Add SCSI MO device support.

Submitted by:	Kawanobe Koh <kawanobe@st.rim.or.jp>
This commit is contained in:
Yoshihiro Takahashi 2003-01-06 13:43:15 +00:00
parent f0c093284d
commit 97a45538e4
5 changed files with 154 additions and 96 deletions

View File

@ -93,6 +93,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
@ -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
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
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
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

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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;