diff options
-rw-r--r-- | sys/i386/isa/wd.c | 111 | ||||
-rw-r--r-- | sys/i386/isa/wdreg.h | 3 |
2 files changed, 71 insertions, 43 deletions
diff --git a/sys/i386/isa/wd.c b/sys/i386/isa/wd.c index 2bf2367..552f1e3 100644 --- a/sys/i386/isa/wd.c +++ b/sys/i386/isa/wd.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)wd.c 7.2 (Berkeley) 5/9/91 - * $Id: wd.c,v 1.151 1998/02/16 23:57:41 eivind Exp $ + * $Id: wd.c,v 1.152 1998/04/02 02:10:47 eivind Exp $ */ /* TODO: @@ -115,6 +115,7 @@ extern void wdstart(int ctrlr); #define WDOPT_32BIT 0x8000 #define WDOPT_SLEEPHACK 0x4000 #define WDOPT_DMA 0x2000 +#define WDOPT_LBA 0x1000 #define WDOPT_FORCEHD(x) (((x)&0x0f00)>>8) #define WDOPT_MULTIMASK 0x00ff @@ -184,6 +185,7 @@ struct disk { #define DKFL_DMA 0x01000 /* using DMA on this transfer-- DKFL_SINGLE * overrides this */ +#define DKFL_LBA 0x02000 /* use LBA for data transfers */ struct wdparams dk_params; /* ESDI/IDE drive/controller parameters */ int dk_dkunit; /* disk stats unit number */ int dk_multi; /* multi transfers */ @@ -472,6 +474,8 @@ wdattach(struct isa_device *dvp) dvp->id_unit, unit, lunit, sizeof du->dk_params.wdp_model, du->dk_params.wdp_model); + if (du->dk_flags & DKFL_LBA) + printf(", LBA"); if (du->dk_flags & DKFL_USEDMA) printf(", DMA"); if (du->dk_flags & DKFL_32BIT) @@ -836,10 +840,16 @@ wdstart(int ctrlr) u_int count1; long cylin, head, sector; - cylin = blknum / secpercyl; - head = (blknum % secpercyl) / secpertrk; - sector = blknum % secpertrk; - + if (du->dk_flags & DKFL_LBA) { + sector = (blknum >> 0) & 0xff; + 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 * on write. @@ -1564,7 +1574,10 @@ wdcommand(struct disk *du, u_int cylinder, u_int head, u_int sector, outb(wdc + wd_cyl_lo, cylinder); outb(wdc + wd_cyl_hi, cylinder >> 8); outb(wdc + wd_sdh, WDSD_IBM | (du->dk_unit << 4) | head); - outb(wdc + wd_sector, sector + 1); + if (head &= WDSD_LBA) + outb(wdc + wd_sector, sector); + else + outb(wdc + wd_sector, sector + 1); outb(wdc + wd_seccnt, count); } if (wdwait(du, (command == WDCC_DIAGNOSE || command == WDCC_IDC) @@ -1611,42 +1624,44 @@ wdsetctlr(struct disk *du) du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks, du->dk_dd.d_nsectors); #endif - 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); - /* obtain parameters */ - wp = &du->dk_params; - if (wp->wdp_heads > 0 && wp->wdp_heads <= 16) { - printf("(controller value %u restored)\n", - wp->wdp_heads); - du->dk_dd.d_ntracks = wp->wdp_heads; + if (!(du->dk_flags &= DKFL_LBA)) { + 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); + /* obtain parameters */ + wp = &du->dk_params; + if (wp->wdp_heads > 0 && wp->wdp_heads <= 16) { + printf("(controller value %u restored)\n", + 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"); - du->dk_dd.d_ntracks = 16; + + 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 (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) { + if (error) { #ifdef CMD640 - wdtab[du->dk_ctrlr_cmd640].b_errcnt += RETRIES; + wdtab[du->dk_ctrlr_cmd640].b_errcnt += RETRIES; #else - wdtab[du->dk_ctrlr].b_errcnt += RETRIES; + wdtab[du->dk_ctrlr].b_errcnt += RETRIES; #endif - return (1); - } - if (wdcommand(du, du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks - 1, 0, - du->dk_dd.d_nsectors, WDCC_IDC) != 0 - || wdwait(du, WDCS_READY, TIMEOUT) < 0) { - wderror((struct buf *)NULL, du, "wdsetctlr failed"); - return (1); + return (1); + } + if (wdcommand(du, du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks - 1, 0, + du->dk_dd.d_nsectors, WDCC_IDC) != 0 + || wdwait(du, WDCS_READY, TIMEOUT) < 0) { + wderror((struct buf *)NULL, du, "wdsetctlr failed"); + return (1); + } } wdsetmulti(du); @@ -1884,11 +1899,23 @@ failed: /* update disklabel given drive information */ du->dk_dd.d_secsize = DEV_BSIZE; - 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 ((du->cfg_flags & WDOPT_LBA) && wp->wdp_lbasize) { + du->dk_dd.d_nsectors = 63; + du->dk_dd.d_ntracks = 64; + du->dk_dd.d_ncylinders = wp->wdp_lbasize / (63*64); + du->dk_dd.d_secpercyl= 63*64; + 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)) { du->dk_dd.d_ntracks = WDOPT_FORCEHD(du->cfg_flags); du->dk_dd.d_secpercyl = diff --git a/sys/i386/isa/wdreg.h b/sys/i386/isa/wdreg.h index 22c07d8..f8520bf 100644 --- a/sys/i386/isa/wdreg.h +++ b/sys/i386/isa/wdreg.h @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)wdreg.h 7.1 (Berkeley) 5/9/91 - * $Id: wdreg.h,v 1.20 1997/09/20 07:41:45 dyson Exp $ + * $Id: wdreg.h,v 1.21 1998/01/14 08:08:42 kato Exp $ */ /* @@ -137,6 +137,7 @@ #define WD_STEP 0 /* winchester- default 35us step */ #define WDSD_IBM 0xa0 /* forced to 512 byte sector, ecc */ +#define WDSD_LBA 0x40 /* use Logical Block Adressing */ #ifdef KERNEL /* |