diff options
author | nyan <nyan@FreeBSD.org> | 2003-01-06 13:43:15 +0000 |
---|---|---|
committer | nyan <nyan@FreeBSD.org> | 2003-01-06 13:43:15 +0000 |
commit | 1eceeaf8c6dcbda5f4137c3cfd3e414f23c04b04 (patch) | |
tree | ca6a0e75a96f625d14910f4c3a41f63ae4a9b68d /sys/boot | |
parent | 266526442d75736b6f9ba0af867862398750359a (diff) | |
download | FreeBSD-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.S | 186 | ||||
-rw-r--r-- | sys/boot/pc98/boot2/boot.c | 9 | ||||
-rw-r--r-- | sys/boot/pc98/boot2/disk.c | 11 | ||||
-rw-r--r-- | sys/boot/pc98/boot2/sys.c | 10 | ||||
-rw-r--r-- | sys/boot/pc98/libpc98/biosdisk.c | 38 |
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; |