summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/i386/isa/wd.c111
-rw-r--r--sys/i386/isa/wdreg.h3
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
/*
OpenPOWER on IntegriCloud