summaryrefslogtreecommitdiffstats
path: root/sys/boot
diff options
context:
space:
mode:
authornyan <nyan@FreeBSD.org>2003-01-06 13:43:15 +0000
committernyan <nyan@FreeBSD.org>2003-01-06 13:43:15 +0000
commit1eceeaf8c6dcbda5f4137c3cfd3e414f23c04b04 (patch)
treeca6a0e75a96f625d14910f4c3a41f63ae4a9b68d /sys/boot
parent266526442d75736b6f9ba0af867862398750359a (diff)
downloadFreeBSD-src-1eceeaf8c6dcbda5f4137c3cfd3e414f23c04b04.zip
FreeBSD-src-1eceeaf8c6dcbda5f4137c3cfd3e414f23c04b04.tar.gz
Add SCSI MO device support.
Submitted by: Kawanobe Koh <kawanobe@st.rim.or.jp>
Diffstat (limited to 'sys/boot')
-rw-r--r--sys/boot/pc98/boot2/bios.S186
-rw-r--r--sys/boot/pc98/boot2/boot.c9
-rw-r--r--sys/boot/pc98/boot2/disk.c11
-rw-r--r--sys/boot/pc98/boot2/sys.c10
-rw-r--r--sys/boot/pc98/libpc98/biosdisk.c38
5 files changed, 156 insertions, 98 deletions
diff --git a/sys/boot/pc98/boot2/bios.S b/sys/boot/pc98/boot2/bios.S
index 0c0aa74..8a884d6 100644
--- a/sys/boot/pc98/boot2/bios.S
+++ b/sys/boot/pc98/boot2/bios.S
@@ -94,6 +94,26 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#ifndef CDBOOT
/*
+ * PC-9801/PC-9821 SCSI MO booting
+ * 2002/06/05-07/03 Kawanobe Koh <kawanobe@st.rim.or.jp>
+ *
+ */
+scsi_hd:
+ .code16
+ push %cx
+ push %ds
+ mov %bl, %cl /* UA */
+ and $0x0F, %cl
+ xor %ax, %ax
+ mov %ax, %ds
+ mov (0x0482), %al /* SCSI HD equipment bits */
+ shr %cl, %al
+ pop %ds
+ pop %cx
+ test $1, %al
+ ret
+
+/*
* biosread(dev, cyl, head, sec, nsec, offset)
* Read "nsec" sectors from disk to offset "offset" in boot segment
* BIOS call "INT 0x1B Function 0xn6" to read sectors from disk into memory
@@ -118,54 +138,58 @@ ENTRY(biosread)
push %esi
push %edi
- movb 0x14(%ebp), %dl /* sector */
- movb 0x10(%ebp), %dh /* head */
- movw 0x0c(%ebp), %cx /* cylinder */
- movb 0x08(%ebp), %al /* DA/UA */
- movb $0x06, %ah
- andb $0xf0, %al
- cmpb $0x30, %al
- jz fd
- cmpb $0x90, %al
- jnz 1f
-fd:
- incb %dl
- movb $0x02, %ch
- movb $0xd6, %ah
-1:
- movb 0x08(%ebp), %al
- movl %eax, %ebx
+ mov 0x08(%ebp), %bl /* (byte) DA/UA */
+ mov 0x0C(%ebp), %ecx /* (word) cylinder */
+ mov 0x10(%ebp), %dh /* (byte) head */
+ mov 0x14(%ebp), %dl /* (byte) sector */
+ mov 0x18(%ebp), %esi /* (byte) number of sectors */
+ mov 0x1C(%ebp), %edi /* (word) destination offset */
/* prot_to_real will set %es to BOOTSEG */
call EXT(prot_to_real) /* enter real mode */
- mov %ebx, %eax
- xor %ebx, %ebx
- addr32
- movb 0x18(%ebp), %bl /* number of sectors */
.code16
- shl $9, %ebx
- push %ebx
- .code32
- addr32
- data32
- mov 0x1c(%ebp), %ebx
- .code16
- mov %ebx, %ebp
- pop %ebx
+ mov $0x06, %bh /* read data function */
+ mov %bl, %al /* DA */
+ and $0xF0, %al
+ cmp $0x30, %al /* 1440KB FD */
+ jz read_floppy
+ cmp $0x90, %al /* 1200KB FD */
+ jz read_floppy
+ cmp $0xA0, %al /* SCSI HD or MO */
+ jnz read_next
+ call scsi_hd
+ jnz read_next
+read_linear:
+ mov %dh, %al /* change to linear sector */
+ shl $5, %al /* multiply by 32 sector per track */
+ add %dl, %al
+ xor %dh, %dh /* higher 16 bits into %dx */
+ mov %ch, %dl
+ mov %cl, %ch /* lower 16 bits into %cx */
+ mov %al, %cl
+ and $0x7F, %bl /* linear access DA/UA */
+ jmp read_next
+read_floppy:
+ inc %dx /* sector address begins from one */
+ mov $0x02, %ch /* 512 bytes sector */
+ mov $0xD6, %bh /* MT MFM retry seek */
+read_next:
+ mov %si, %ax /* number of sectors */
+ shl $9, %ax /* multiply by 512 bytes */
+ xchg %bx, %ax
+ mov %di, %bp /* destination offset */
+ int $0x1B /* disk bios call */
+ jc read_end
+ xor %ax, %ax
+read_end:
+ mov %ax, %bx /* save return value */
- int $0x1b
- jc 1f
.code32
- xor %eax, %eax
-1:
- /* save return value (actually movw %ax, %bx) */
- mov %eax, %ebx
-
data32
call EXT(real_to_prot) /* back to protected mode */
xor %eax, %eax
- movb %bh, %al /* return value in %ax */
+ mov %bh, %al /* return value in %eax */
pop %edi
pop %esi
@@ -360,46 +384,61 @@ ENTRY(get_diskinfo)
push %ebp
mov %esp, %ebp
push %ebx
- push %esi
- push %edi
- movb 0x8(%ebp), %dl /* diskinfo(drive #) */
+ mov 0x08(%ebp), %bl /* (byte) DA/UA */
+
call EXT(prot_to_real) /* enter real mode */
.code16
-
- movb %dl, %al /* ask for disk info */
- andb $0xf0, %al
- cmpb $0x30, %al
- jz fdd4
- cmpb $0x90, %al
- jz fdd
-
- movb %dl, %al
- movb $0x84, %ah
-
+ mov %bl, %al /* DA */
+ and $0xf0, %al
+ mov $18, %dl /* 1440KB FD sectors per track */
+ cmp $0x30, %al
+ jz floppy
+ mov $15, %dl /* 1200KB FD sectors per track */
+ cmp $0x90, %al
+ jz floppy
+ cmp $0xA0, %al /* SCSI HD or MO */
+ jnz sense
+ call scsi_hd
+ jnz sense
+
+ push %ds /* SCSI MO or CD ? */
+ xor %ax, %ax
+ mov %ax, %ds
+ and $0x0F, %bx /* UA */
+ shl $2, %bx /* parameter offset */
+ add $0x0460, %bx
+ mov (%bx), %al /* SCSI equipment parameter[0] */
+ and $0x1F, %al /* peripheral device type */
+ cmp $7, %al /* SCSI MO */
+ jnz good
+ add $3, %bx
+ mov (%bx), %al /* SCSI equipment parameter[3] */
+ test $0x30, %al /* sector length from 256 to 2048 */
+ jnz good
+ or $0x10, %al /* forced set 512 bytes sector */
+ mov %al, (%bx)
+ mov $0xA100, %dx /* refered by C language */
+ mov %dx, %ds
+ mov %al, (%bx)
+good:
+ pop %ds
+
+ mov $0xFFFE, %cx /* virtual 65535 cylinders setting */
+ mov $0x0820, %dx /* standard 8 heads and 32 sectors */
+ jmp ok
+sense:
+ mov $0x84, %ah /* ask for disk info */
+ mov %bl, %al
int $0x1b
-
- jnc ok
+ jnc ok /* use %cx and %dx after */
/*
* Urk. Call failed. It is not supported for floppies by old BIOS's.
* Guess it's a 15-sector floppy.
*/
-fdd4:
- movb $18, %dl
- jmp 1f
-fdd:
- movb $15, %dl /* max sector */
-1:
- subb %ah, %ah /* %ax = 0 */
- movb %al, %al
- movb %ah, %bh /* %bh = 0 */
- movb $2, %bl /* %bl bits 0-3 = drive type,
- bit 2 = 1.2M */
- movb $79, %ch /* max track */
- movb $1, %cl /* # floppy drives installed */
- movb $2, %dh /* max head */
- /* es:di = parameter table */
- /* carry = 0 */
+floppy:
+ mov $79, %cx /* 80 cylinders 1200K and 1440K FD */
+ mov $2, %dh /* 2 heads as double side */
ok:
.code32
data32
@@ -412,12 +451,9 @@ ok:
* 8 bit sector
*/
mov %ecx, %eax
- sall $16,%eax /* << 16 */
- movb %dh, %ah /* max head */
- movb %dl, %al /* max sector (and # sectors) */
+ sal $16, %eax /* max cylinder number from zero */
+ mov %dx, %ax /* number of heads and sectors */
- pop %edi
- pop %esi
pop %ebx
pop %ebp
ret
diff --git a/sys/boot/pc98/boot2/boot.c b/sys/boot/pc98/boot2/boot.c
index cfd6fe2..bc639a2 100644
--- a/sys/boot/pc98/boot2/boot.c
+++ b/sys/boot/pc98/boot2/boot.c
@@ -118,11 +118,16 @@ boot(int drive)
dosdev = drive;
#ifdef PC98
maj = (drive&0x70) >> 3; /* a good first bet */
- if (maj == 4) { /* sd */
+ if (maj == 4) { /* da */
disk_equips = *(unsigned char *)V(0xA1482);
unit = 0;
for (i=0; i<(drive&0x0f); i++) {
- unit += (disk_equips >> i) & 1;
+ int media = ((unsigned *)V(0xA1460))[i] & 0x1F;
+
+ if ((disk_equips >> i) & 1) /* HD */
+ unit++;
+ else if (media == 7) /* MO */
+ unit++;
}
} else {
unit = drive & 0x0f;
diff --git a/sys/boot/pc98/boot2/disk.c b/sys/boot/pc98/boot2/disk.c
index e878258..f0eaf67 100644
--- a/sys/boot/pc98/boot2/disk.c
+++ b/sys/boot/pc98/boot2/disk.c
@@ -129,17 +129,6 @@ devopen(void)
printf("bad disklabel\n");
return 1;
}
- if( (maj == 4) || (maj == 0) || (maj == 1))
- {
- if (dl->d_type == DTYPE_SCSI)
- {
- maj = 4; /* use scsi as boot dev */
- }
- else
- {
- maj = 0; /* must be ESDI/IDE */
- }
- }
/* This little trick is for OnTrack DiskManager disks */
boff = dl->d_partitions[part].p_offset -
dl->d_partitions[2].p_offset + sector;
diff --git a/sys/boot/pc98/boot2/sys.c b/sys/boot/pc98/boot2/sys.c
index 1b138b3..eb65d33 100644
--- a/sys/boot/pc98/boot2/sys.c
+++ b/sys/boot/pc98/boot2/sys.c
@@ -275,8 +275,8 @@ openrd(void)
switch(maj)
{
#ifdef PC98
- case 4: /* sd */
- dosdev_copy = biosdrive | 0xa0;
+ case 4: /* da */
+ dosdev_copy = biosdrive | 0xA0; /* SCSI HD or MO */
#else /* IBM-PC */
case 0:
case 4:
@@ -284,8 +284,8 @@ openrd(void)
#endif
break;
#ifdef PC98
- case 0:
- case 2:
+ case 0: /* wd */
+ case 2: /* 1200KB fd */
dosdev_copy = (maj << 3) | unit | 0x80;
#else
case 2:
@@ -293,7 +293,7 @@ openrd(void)
#endif
break;
#ifdef PC98
- case 6:/* 1.44MB FD */
+ case 6: /* 1440KB fd */
dosdev_copy = (maj << 3) | unit;
break;
#endif
diff --git a/sys/boot/pc98/libpc98/biosdisk.c b/sys/boot/pc98/libpc98/biosdisk.c
index 9606a11..d5c0a65 100644
--- a/sys/boot/pc98/libpc98/biosdisk.c
+++ b/sys/boot/pc98/libpc98/biosdisk.c
@@ -81,6 +81,9 @@ struct open_disk {
#define BD_FLOPPY 0x0004
#define BD_LABELOK 0x0008
#define BD_PARTTABOK 0x0010
+#ifdef PC98
+#define BD_OPTICAL 0x0020
+#endif
struct disklabel od_disklabel;
int od_nslices; /* slice count */
struct pc98_partition od_slicetab[MAX_SLICES];
@@ -198,7 +201,7 @@ bd_init(void)
}
}
else {
- if ((unit & 0xa0) == 0xa0)
+ if ((unit & 0xF0) == 0xA0) /* SCSI HD or MO */
bdinfo[nbdinfo].bd_da_unit = da_drive++;
}
/* XXX we need "disk aliases" to make this simpler */
@@ -257,6 +260,14 @@ bd_int13probe(struct bdinfo *bd)
bd->bd_flags |= BD_MODEINT13;
return(1);
}
+ if ((bd->bd_unit & 0xF0) == 0xA0) {
+ int media = ((unsigned *)PTOV(0xA1460))[bd->bd_unit & 0x0F] & 0x1F;
+
+ if (media == 7) { /* MO */
+ bd->bd_flags |= BD_MODEINT13 | BD_OPTICAL;
+ return(1);
+ }
+ }
return(0);
#else
v86.ctl = V86_FLAGS;
@@ -1081,7 +1092,13 @@ bd_read(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest)
v86.eax = 0x0600 | od->od_unit;
v86.ecx = cyl;
}
- v86.edx = (hd << 8) | sec;
+ if (od->od_flags & BD_OPTICAL) {
+ v86.eax &= 0xFF7F;
+ v86.ecx = dblk & 0xFFFF;
+ v86.edx = dblk >> 16;
+ } else {
+ v86.edx = (hd << 8) | sec;
+ }
v86.ebx = x * BIOSDISK_SECSIZE;
v86.es = VTOPSEG(xp);
v86.ebp = VTOPOFF(xp);
@@ -1362,6 +1379,10 @@ bd_getgeom(struct open_disk *od)
od->od_cyl = 79;
od->od_hds = 2;
od->od_sec = (od->od_unit & 0xf0) == 0x30 ? 18 : 15;
+ } else if (od->od_flags & BD_OPTICAL) {
+ od->od_cyl = 0xFFFE;
+ od->od_hds = 8;
+ od->od_sec = 32;
} else {
v86.ctl = V86_FLAGS;
v86.addr = 0x1b;
@@ -1423,19 +1444,26 @@ bd_getbigeom(int bunit)
if (*(u_char *)PTOV(addr) & (1 << (unit & 0x0f)))
if (hds++ == bunit)
break;
+
+ if (unit >= 0xA0) {
+ int media = ((unsigned *)PTOV(0xA1460))[unit & 0x0F] & 0x1F;
+
+ if (media == 7 && hds++ == bunit) /* SCSI MO */
+ return(0xFFFE0820); /* C:65535 H:8 S:32 */
+ }
if (++unit == 0x84) {
- unit = 0xa0; /* SCSI HDD */
+ unit = 0xA0; /* SCSI HDD */
addr = 0xA1482;
}
}
if (unit == 0xa7)
- return 0x4f010f;
+ return 0x4F020F; /* 1200KB FD C:80 H:2 S:15 */
v86.ctl = V86_FLAGS;
v86.addr = 0x1b;
v86.eax = 0x8400 | unit;
v86int();
if (v86.efl & 0x1)
- return 0x4f010f;
+ return 0x4F020F; /* 1200KB FD C:80 H:2 S:15 */
return ((v86.ecx & 0xffff) << 16) | (v86.edx & 0xffff);
#else
v86.ctl = V86_FLAGS;
OpenPOWER on IntegriCloud