Sync with sys/i386/isa/wd.c revision 1.155.

This commit is contained in:
KATO Takenori 1998-04-12 05:05:19 +00:00
parent 66cc72d13d
commit 44ed0f3748
1 changed files with 85 additions and 41 deletions

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* from: @(#)wd.c 7.2 (Berkeley) 5/9/91 * from: @(#)wd.c 7.2 (Berkeley) 5/9/91
* $Id: wd.c,v 1.44 1998/02/16 23:57:45 eivind Exp $ * $Id: wd.c,v 1.45 1998/04/02 11:06:59 kato Exp $
*/ */
/* TODO: /* TODO:
@ -121,6 +121,7 @@ extern void wdstart(int ctrlr);
#define WDOPT_32BIT 0x8000 #define WDOPT_32BIT 0x8000
#define WDOPT_SLEEPHACK 0x4000 #define WDOPT_SLEEPHACK 0x4000
#define WDOPT_DMA 0x2000 #define WDOPT_DMA 0x2000
#define WDOPT_LBA 0x1000
#define WDOPT_FORCEHD(x) (((x)&0x0f00)>>8) #define WDOPT_FORCEHD(x) (((x)&0x0f00)>>8)
#define WDOPT_MULTIMASK 0x00ff #define WDOPT_MULTIMASK 0x00ff
@ -203,6 +204,7 @@ struct disk {
#define DKFL_DMA 0x01000 /* using DMA on this transfer-- DKFL_SINGLE #define DKFL_DMA 0x01000 /* using DMA on this transfer-- DKFL_SINGLE
* overrides this * overrides this
*/ */
#define DKFL_LBA 0x02000 /* use LBA for data transfers */
struct wdparams dk_params; /* ESDI/IDE drive/controller parameters */ struct wdparams dk_params; /* ESDI/IDE drive/controller parameters */
int dk_dkunit; /* disk stats unit number */ int dk_dkunit; /* disk stats unit number */
int dk_multi; /* multi transfers */ int dk_multi; /* multi transfers */
@ -545,6 +547,8 @@ wdattach(struct isa_device *dvp)
dvp->id_unit, unit, lunit, dvp->id_unit, unit, lunit,
sizeof du->dk_params.wdp_model, sizeof du->dk_params.wdp_model,
du->dk_params.wdp_model); du->dk_params.wdp_model);
if (du->dk_flags & DKFL_LBA)
printf(", LBA");
if (du->dk_flags & DKFL_USEDMA) if (du->dk_flags & DKFL_USEDMA)
printf(", DMA"); printf(", DMA");
if (du->dk_flags & DKFL_32BIT) if (du->dk_flags & DKFL_32BIT)
@ -936,10 +940,16 @@ wdstart(int ctrlr)
u_int count1; u_int count1;
long cylin, head, sector; long cylin, head, sector;
cylin = blknum / secpercyl; if (du->dk_flags & DKFL_LBA) {
head = (blknum % secpercyl) / secpertrk; sector = (blknum >> 0) & 0xff;
sector = blknum % secpertrk; cylin = (blknum >> 8) & 0xffff;
head = ((blknum >> 24) & 0xf) | WDSD_LBA;
}
else {
cylin = blknum / secpercyl;
head = (blknum % secpercyl) / secpertrk;
sector = blknum % secpertrk;
}
/* /*
* XXX this looks like an attempt to skip bad sectors * XXX this looks like an attempt to skip bad sectors
* on write. * on write.
@ -1726,6 +1736,9 @@ wdcommand(struct disk *du, u_int cylinder, u_int head, u_int sector,
#else #else
outb(wdc + wd_sdh, WDSD_IBM | (du->dk_unit<<4) | head); outb(wdc + wd_sdh, WDSD_IBM | (du->dk_unit<<4) | head);
#endif #endif
if (head & WDSD_LBA)
outb(wdc + wd_sector, sector);
else
outb(wdc + wd_sector, sector + 1); outb(wdc + wd_sector, sector + 1);
outb(wdc + wd_seccnt, count); outb(wdc + wd_seccnt, count);
} }
@ -1780,42 +1793,44 @@ wdsetctlr(struct disk *du)
du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks, du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks,
du->dk_dd.d_nsectors); du->dk_dd.d_nsectors);
#endif #endif
if (du->dk_dd.d_ntracks == 0 || du->dk_dd.d_ntracks > 16) { if (!(du->dk_flags &= DKFL_LBA)) {
struct wdparams *wp; if (du->dk_dd.d_ntracks == 0 || du->dk_dd.d_ntracks > 16) {
struct wdparams *wp;
printf("wd%d: can't handle %lu heads from partition table ",
du->dk_lunit, du->dk_dd.d_ntracks); printf("wd%d: can't handle %lu heads from partition table ",
/* obtain parameters */ du->dk_lunit, du->dk_dd.d_ntracks);
wp = &du->dk_params; /* obtain parameters */
if (wp->wdp_heads > 0 && wp->wdp_heads <= 16) { wp = &du->dk_params;
printf("(controller value %u restored)\n", if (wp->wdp_heads > 0 && wp->wdp_heads <= 16) {
wp->wdp_heads); printf("(controller value %u restored)\n",
du->dk_dd.d_ntracks = wp->wdp_heads; wp->wdp_heads);
du->dk_dd.d_ntracks = wp->wdp_heads;
}
else {
printf("(truncating to 16)\n");
du->dk_dd.d_ntracks = 16;
}
} }
else {
printf("(truncating to 16)\n"); if (du->dk_dd.d_nsectors == 0 || du->dk_dd.d_nsectors > 255) {
du->dk_dd.d_ntracks = 16; printf("wd%d: cannot handle %lu sectors (max 255)\n",
du->dk_lunit, du->dk_dd.d_nsectors);
error = 1;
} }
} if (error) {
if (du->dk_dd.d_nsectors == 0 || du->dk_dd.d_nsectors > 255) {
printf("wd%d: cannot handle %lu sectors (max 255)\n",
du->dk_lunit, du->dk_dd.d_nsectors);
error = 1;
}
if (error) {
#ifdef CMD640 #ifdef CMD640
wdtab[du->dk_ctrlr_cmd640].b_errcnt += RETRIES; wdtab[du->dk_ctrlr_cmd640].b_errcnt += RETRIES;
#else #else
wdtab[du->dk_ctrlr].b_errcnt += RETRIES; wdtab[du->dk_ctrlr].b_errcnt += RETRIES;
#endif #endif
return (1); return (1);
} }
if (wdcommand(du, du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks - 1, 0, if (wdcommand(du, du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks - 1, 0,
du->dk_dd.d_nsectors, WDCC_IDC) != 0 du->dk_dd.d_nsectors, WDCC_IDC) != 0
|| wdwait(du, WDCS_READY, TIMEOUT) < 0) { || wdwait(du, WDCS_READY, TIMEOUT) < 0) {
wderror((struct buf *)NULL, du, "wdsetctlr failed"); wderror((struct buf *)NULL, du, "wdsetctlr failed");
return (1); return (1);
}
} }
wdsetmulti(du); wdsetmulti(du);
@ -2096,11 +2111,40 @@ failed:
/* update disklabel given drive information */ /* update disklabel given drive information */
du->dk_dd.d_secsize = DEV_BSIZE; du->dk_dd.d_secsize = DEV_BSIZE;
du->dk_dd.d_ncylinders = wp->wdp_cylinders; /* +- 1 */ if ((du->cfg_flags & WDOPT_LBA) && wp->wdp_lbasize) {
du->dk_dd.d_ntracks = wp->wdp_heads; du->dk_dd.d_nsectors = 63;
du->dk_dd.d_nsectors = wp->wdp_sectors; if (wp->wdp_lbasize < 16*63*1024) { /* <=528.4 MB */
du->dk_dd.d_secpercyl = du->dk_dd.d_ntracks * du->dk_dd.d_nsectors; du->dk_dd.d_ntracks = 16;
du->dk_dd.d_secperunit = du->dk_dd.d_secpercyl * du->dk_dd.d_ncylinders; }
else if (wp->wdp_lbasize < 32*63*1024) { /* <=1.057 GB */
du->dk_dd.d_ntracks = 32;
}
else if (wp->wdp_lbasize < 64*63*1024) { /* <=2.114 GB */
du->dk_dd.d_ntracks = 64;
}
else if (wp->wdp_lbasize < 128*63*1024) { /* <=4.228 GB */
du->dk_dd.d_ntracks = 128;
}
else if (wp->wdp_lbasize < 128*63*1024) { /* <=8.422 GB */
du->dk_dd.d_ntracks = 255;
}
else { /* >8.422 GB */
du->dk_dd.d_ntracks = 255; /* XXX */
}
du->dk_dd.d_secpercyl= du->dk_dd.d_ntracks*du->dk_dd.d_nsectors;
du->dk_dd.d_ncylinders = wp->wdp_lbasize/du->dk_dd.d_secpercyl;
du->dk_dd.d_secperunit = wp->wdp_lbasize;
du->dk_flags |= DKFL_LBA;
}
else {
du->dk_dd.d_ncylinders = wp->wdp_cylinders; /* +- 1 */
du->dk_dd.d_ntracks = wp->wdp_heads;
du->dk_dd.d_nsectors = wp->wdp_sectors;
du->dk_dd.d_secpercyl =
du->dk_dd.d_ntracks * du->dk_dd.d_nsectors;
du->dk_dd.d_secperunit =
du->dk_dd.d_secpercyl * du->dk_dd.d_ncylinders;
}
if (WDOPT_FORCEHD(du->cfg_flags)) { if (WDOPT_FORCEHD(du->cfg_flags)) {
du->dk_dd.d_ntracks = WDOPT_FORCEHD(du->cfg_flags); du->dk_dd.d_ntracks = WDOPT_FORCEHD(du->cfg_flags);
du->dk_dd.d_secpercyl = du->dk_dd.d_secpercyl =