summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>1998-04-18 13:25:49 +0000
committerobrien <obrien@FreeBSD.org>1998-04-18 13:25:49 +0000
commitfd66256f3f5e5ed27e2606aa2fdbca79f3adce7e (patch)
tree7391dd237aa049c6749fe81bade5479b6ef4ee75
parent116081d5f2f15798830c767e3781af1616223bfd (diff)
downloadFreeBSD-src-fd66256f3f5e5ed27e2606aa2fdbca79f3adce7e.zip
FreeBSD-src-fd66256f3f5e5ed27e2606aa2fdbca79f3adce7e.tar.gz
MFC (reduce diff w/-CUR, with hopes of getting DMA support into -STABLE)
1.128 (FUNCTIONAL: better sleep handling) 1.131 (STYLE: labels w/o stmt) 1.132 (STYLE: remove unused #includes) 1.141 (FUNCTIONAL: devfs bug, 2nd controler not showing) 1.144 (STYLE: dont shadow other vars) 1.150 (FUNCTIONAL: fix search bug)
-rw-r--r--sys/i386/isa/wd.c416
1 files changed, 98 insertions, 318 deletions
diff --git a/sys/i386/isa/wd.c b/sys/i386/isa/wd.c
index 13119bb..674211d 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.155 1998/04/10 08:00:24 sos Exp $
+ * $Id: wd.c,v 1.119.2.10 1998/01/16 22:28:44 pst Exp $
*/
/* TODO:
@@ -61,15 +61,11 @@
#endif
#include "wdc.h"
+#include "opt_wd.h"
+#include "opt_atapi.h"
#if NWDC > 0
-#include "opt_atapi.h"
-#include "opt_devfs.h"
-#include "opt_hw_wdog.h"
-#include "opt_wd.h"
-#include "pci.h"
-
#include <sys/param.h>
#include <sys/dkbad.h>
#include <sys/systm.h>
@@ -114,8 +110,6 @@ extern void wdstart(int ctrlr);
/* can't handle that in all cases */
#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
@@ -162,13 +156,11 @@ struct disk {
#endif
int dk_unit; /* physical unit number */
int dk_lunit; /* logical unit number */
- int dk_interface; /* interface (two ctrlrs per interface) */
char dk_state; /* control state */
u_char dk_status; /* copy of status reg. */
u_char dk_error; /* copy of error reg. */
u_char dk_timeout; /* countdown to next timeout */
int dk_port; /* i/o port base */
- int dk_altport; /* altstatus port base */
#ifdef DEVFS
void *dk_bdev; /* devfs token for whole disk */
void *dk_cdev; /* devfs token for raw whole disk */
@@ -181,18 +173,12 @@ struct disk {
#define DKFL_32BIT 0x00100 /* use 32-bit i/o mode */
#define DKFL_MULTI 0x00200 /* use multi-i/o mode */
#define DKFL_BADSCAN 0x00400 /* report all errors */
-#define DKFL_USEDMA 0x00800 /* use DMA for data transfers */
-#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 */
int dk_currentiosize; /* current io size */
struct diskgeom dk_dd; /* device configuration data */
struct diskslices *dk_slices; /* virtual drives */
- void *dk_dmacookie; /* handle for DMA services */
};
#define WD_COUNT_RETRIES
@@ -201,6 +187,7 @@ static int wdtest = 0;
static struct disk *wddrives[NWD]; /* table of units */
static struct buf_queue_head drive_queue[NWD]; /* head of queue per drive */
static struct {
+ int b_errcnt;
int b_active;
} wdutab[NWD];
/*
@@ -212,7 +199,7 @@ static struct {
int b_active;
} wdtab[NWDC];
-struct wddma wddma[NWDC];
+struct wddma wddma;
#ifdef notyet
static struct buf rwdbuf[NWD]; /* buffers for raw IO */
@@ -228,7 +215,6 @@ static int wdsetctlr(struct disk *du);
#if 0
static int wdwsetctlr(struct disk *du);
#endif
-static int wdsetmode(int mode, void *wdinfo);
static int wdgetctlr(struct disk *du);
static void wderror(struct buf *bp, struct disk *du, char *mesg);
static void wdflushirq(struct disk *du, int old_ipl);
@@ -255,7 +241,7 @@ static d_psize_t wdsize;
static struct cdevsw wd_cdevsw;
static struct bdevsw wd_bdevsw =
{ wdopen, wdclose, wdstrategy, wdioctl, /*0*/
- wddump, wdsize, D_DISK, "wd", &wd_cdevsw, -1 };
+ wddump, wdsize, 0, "wd", &wd_cdevsw, -1 };
#ifdef CMD640
static int atapictrlr;
@@ -284,7 +270,6 @@ static int
wdprobe(struct isa_device *dvp)
{
int unit = dvp->id_unit;
- int interface;
struct disk *du;
if (unit >= NWDC)
@@ -295,21 +280,8 @@ wdprobe(struct isa_device *dvp)
return (0);
bzero(du, sizeof *du);
du->dk_ctrlr = dvp->id_unit;
- interface = du->dk_ctrlr / 2;
- du->dk_interface = interface;
-#if !defined(DISABLE_PCI_IDE) && (NPCI > 0)
- if (wddma[interface].wdd_candma) {
- du->dk_dmacookie = wddma[interface].wdd_candma(dvp->id_iobase, du->dk_ctrlr);
- du->dk_port = dvp->id_iobase;
- du->dk_altport = wddma[interface].wdd_altiobase(du->dk_dmacookie);
- } else {
- du->dk_port = dvp->id_iobase;
- du->dk_altport = du->dk_port + wd_ctlr;
- }
-#else
du->dk_port = dvp->id_iobase;
- du->dk_altport = du->dk_port + wd_ctlr;
-#endif
+
/* check if we have registers that work */
outb(du->dk_port + wd_sdh, WDSD_IBM); /* set unit 0 */
@@ -339,16 +311,14 @@ wdprobe(struct isa_device *dvp)
goto reset_ok;
#endif
DELAY(RECOVERYTIME);
- if (wdreset(du) != 0) {
+ if (wdreset(du) != 0)
goto nodevice;
- }
reset_ok:
/* execute a controller only command */
if (wdcommand(du, 0, 0, 0, 0, WDCC_DIAGNOSE) != 0
- || wdwait(du, 0, TIMEOUT) < 0) {
+ || wdwait(du, 0, TIMEOUT) < 0)
goto nodevice;
- }
/*
* drive(s) did not time out during diagnostic :
@@ -362,6 +332,7 @@ reset_ok:
* drive 2. (This seems to contradict the ATA spec.)
*/
du->dk_error = inb(du->dk_port + wd_error);
+ /* printf("Error : %x\n", du->dk_error); */
if(du->dk_error != 0x01 && du->dk_error != 0) {
if(du->dk_error & 0x80) { /* drive 1 failure */
@@ -410,7 +381,6 @@ wdattach(struct isa_device *dvp)
int unit, lunit;
struct isa_device *wdup;
struct disk *du;
- struct wdparams *wp;
if (dvp->id_unit >= NWDC)
return (0);
@@ -419,13 +389,13 @@ wdattach(struct isa_device *dvp)
if (eide_quirks & Q_CMD640B) {
if (dvp->id_unit == PRIMARY) {
printf("wdc0: CMD640B workaround enabled\n");
- bufq_init(&wdtab[PRIMARY].controller_queue);
+ TAILQ_INIT( &wdtab[PRIMARY].controller_queue);
}
} else
- bufq_init(&wdtab[dvp->id_unit].controller_queue);
+ TAILQ_INIT( &wdtab[dvp->id_unit].controller_queue);
#else
- bufq_init(&wdtab[dvp->id_unit].controller_queue);
+ TAILQ_INIT( &wdtab[dvp->id_unit].controller_queue);
#endif
for (wdup = isa_biotab_wdc; wdup->id_driver != 0; wdup++) {
@@ -443,7 +413,7 @@ wdattach(struct isa_device *dvp)
if (wddrives[lunit] != NULL)
panic("drive attached twice");
wddrives[lunit] = du;
- bufq_init(&drive_queue[lunit]);
+ TAILQ_INIT( &drive_queue[lunit]);
bzero(du, sizeof *du);
du->dk_ctrlr = dvp->id_unit;
#ifdef CMD640
@@ -457,7 +427,6 @@ wdattach(struct isa_device *dvp)
du->dk_lunit = lunit;
du->dk_port = dvp->id_iobase;
- du->dk_altport = du->dk_port + wd_ctlr;
/*
* Use the individual device flags or the controller
* flags.
@@ -474,10 +443,6 @@ 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)
printf(", 32-bit");
if (du->dk_multi > 1)
@@ -500,17 +465,6 @@ wdattach(struct isa_device *dvp)
du->dk_dd.d_nsectors,
du->dk_dd.d_secsize);
- if (bootverbose) {
- wp = &du->dk_params;
- printf(
-"wd%d: ATA INQUIRE valid = %04x, dmamword = %04x, apio = %04x, udma = %04x\n",
- du->dk_lunit,
- wp->wdp_atavalid,
- wp->wdp_dmamword,
- wp->wdp_eidepiomodes,
- wp->wdp_udmamode);
- }
-
/*
* Start timeout routine for this drive.
* XXX timeout should be per controller.
@@ -518,15 +472,15 @@ wdattach(struct isa_device *dvp)
wdtimeout(du);
#ifdef DEVFS
- mynor = dkmakeminor(lunit, WHOLE_DISK_SLICE, RAW_PART);
+ mynor = dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART);
du->dk_bdev = devfs_add_devswf(&wd_bdevsw, mynor,
DV_BLK, UID_ROOT,
GID_OPERATOR, 0640,
- "wd%d", lunit);
+ "wd%d", unit);
du->dk_cdev = devfs_add_devswf(&wd_cdevsw, mynor,
DV_CHR, UID_ROOT,
GID_OPERATOR, 0640,
- "rwd%d", lunit);
+ "rwd%d", unit);
#endif
if (dk_ndrive < DK_NDRIVE) {
@@ -642,7 +596,7 @@ wdstrategy(register struct buf *bp)
/* queue transfer on drive, activate drive and controller if idle */
s = splbio();
- bufqdisksort(&drive_queue[lunit], bp);
+ tqdisksort(&drive_queue[lunit], bp);
if (wdutab[lunit].b_active == 0)
wdustart(du); /* start drive */
@@ -716,14 +670,14 @@ wdustart(register struct disk *du)
return;
- bp = bufq_first(&drive_queue[du->dk_lunit]);
+ bp = drive_queue[du->dk_lunit].tqh_first;
if (bp == NULL) { /* yes, an assign */
return;
}
- bufq_remove(&drive_queue[du->dk_lunit], bp);
+ TAILQ_REMOVE( &drive_queue[du->dk_lunit], bp, b_act);
/* link onto controller queue */
- bufq_insert_tail(&wdtab[ctrlr].controller_queue, bp);
+ TAILQ_INSERT_TAIL( &wdtab[ctrlr].controller_queue, bp, b_act);
/* mark the drive unit as busy */
wdutab[du->dk_lunit].b_active = 1;
@@ -765,7 +719,7 @@ wdstart(int ctrlr)
return;
#endif
/* is there a drive for the controller to do a transfer with? */
- bp = bufq_first(&wdtab[ctrlr].controller_queue);
+ bp = wdtab[ctrlr].controller_queue.tqh_first;
if (bp == NULL) {
#ifdef ATAPI
#ifdef CMD640
@@ -803,7 +757,7 @@ wdstart(int ctrlr)
(bp->b_flags & B_READ) ? "read" : "write",
bp->b_bcount, blknum);
else
- printf(" %d)%x", du->dk_skip, inb(du->dk_altport));
+ printf(" %d)%x", du->dk_skip, inb(du->dk_port + wd_altsts));
#endif
lp = &du->dk_dd;
@@ -840,23 +794,12 @@ wdstart(int ctrlr)
u_int count1;
long cylin, head, sector;
- 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.
- */
+ cylin = blknum / secpercyl;
+ head = (blknum % secpercyl) / secpertrk;
+ sector = blknum % secpertrk;
+
if (wdtab[ctrlr].b_errcnt && (bp->b_flags & B_READ) == 0)
du->dk_bc += DEV_BSIZE;
-
count1 = howmany( du->dk_bc, DEV_BSIZE);
du->dk_flags &= ~DKFL_MULTI;
@@ -876,19 +819,7 @@ wdstart(int ctrlr)
count1 = 1;
du->dk_currentiosize = 1;
} else {
- if((du->dk_flags & DKFL_USEDMA) &&
- wddma[du->dk_interface].wdd_dmaverify(du->dk_dmacookie,
- (void *)((int)bp->b_data +
- du->dk_skip * DEV_BSIZE),
- du->dk_bc,
- bp->b_flags & B_READ)) {
- du->dk_flags |= DKFL_DMA;
- if( bp->b_flags & B_READ)
- command = WDCC_READ_DMA;
- else
- command = WDCC_WRITE_DMA;
- du->dk_currentiosize = count1;
- } else if( (count1 > 1) && (du->dk_multi > 1)) {
+ if( (count1 > 1) && (du->dk_multi > 1)) {
du->dk_flags |= DKFL_MULTI;
if( bp->b_flags & B_READ) {
command = WDCC_READ_MULTI;
@@ -924,14 +855,6 @@ wdstart(int ctrlr)
if(du->dk_dkunit >= 0) {
dk_busy |= 1 << du->dk_dkunit;
}
-
- if ((du->dk_flags & (DKFL_DMA|DKFL_SINGLE)) == DKFL_DMA) {
- wddma[du->dk_interface].wdd_dmaprep(du->dk_dmacookie,
- (void *)((int)bp->b_data +
- du->dk_skip * DEV_BSIZE),
- du->dk_bc,
- bp->b_flags & B_READ);
- }
while (wdcommand(du, cylin, head, sector, count1, command)
!= 0) {
wderror(bp, du,
@@ -941,8 +864,8 @@ wdstart(int ctrlr)
#ifdef WDDEBUG
printf("cylin %ld head %ld sector %ld addr %x sts %x\n",
cylin, head, sector,
- (int)bp->b_data + du->dk_skip * DEV_BSIZE,
- inb(du->dk_altport));
+ (int)bp->b_un.b_addr + du->dk_skip * DEV_BSIZE,
+ inb(du->dk_port + wd_altsts));
#endif
}
@@ -951,9 +874,6 @@ wdstart(int ctrlr)
* unmarked bad blocks can take 3 seconds! Then it is not good that
* we retry 5 times.
*
- * On the first try, we give it 10 seconds, for drives that may need
- * to spin up.
- *
* XXX wdtimeout() doesn't increment the error count so we may loop
* forever. More seriously, the loop isn't forever but causes a
* crash.
@@ -963,16 +883,7 @@ wdstart(int ctrlr)
* think). Discarding them would be OK if the (special) file offset
* was not advanced.
*/
- if (wdtab[ctrlr].b_errcnt == 0)
- du->dk_timeout = 1 + 10;
- else
- du->dk_timeout = 1 + 3;
-
- /* if this is a DMA op, start DMA and go away until it's done. */
- if ((du->dk_flags & (DKFL_DMA|DKFL_SINGLE)) == DKFL_DMA) {
- wddma[du->dk_interface].wdd_dmastart(du->dk_dmacookie);
- return;
- }
+ du->dk_timeout = 1 + 3;
/* If this is a read operation, just go away until it's done. */
if (bp->b_flags & B_READ)
@@ -1004,11 +915,11 @@ wdstart(int ctrlr)
if (du->dk_flags & DKFL_32BIT)
outsl(du->dk_port + wd_data,
- (void *)((int)bp->b_data + du->dk_skip * DEV_BSIZE),
+ (void *)((int)bp->b_un.b_addr + du->dk_skip * DEV_BSIZE),
(count * DEV_BSIZE) / sizeof(long));
else
outsw(du->dk_port + wd_data,
- (void *)((int)bp->b_data + du->dk_skip * DEV_BSIZE),
+ (void *)((int)bp->b_un.b_addr + du->dk_skip * DEV_BSIZE),
(count * DEV_BSIZE) / sizeof(short));
du->dk_bc -= DEV_BSIZE * count;
if (du->dk_dkunit >= 0) {
@@ -1028,13 +939,11 @@ wdstart(int ctrlr)
* the next request. Also check for a partially done transfer, and
* continue with the next chunk if so.
*/
-
void
wdintr(int unit)
{
register struct disk *du;
register struct buf *bp;
- int dmastat = 0; /* Shut up GCC */
#ifdef CMD640
int ctrlr_atapi;
@@ -1076,21 +985,10 @@ wdintr(int unit)
return;
}
#endif
- bp = bufq_first(&wdtab[unit].controller_queue);
+ bp = wdtab[unit].controller_queue.tqh_first;
du = wddrives[dkunit(bp->b_dev)];
-
- /* finish off DMA */
- if (du->dk_flags & (DKFL_DMA|DKFL_USEDMA)) {
- /* XXX SMP boxes sometimes generate an early intr. Why? */
- if ((wddma[du->dk_interface].wdd_dmastatus(du->dk_dmacookie) & WDDS_INTERRUPT)
- == 0)
- return;
- dmastat = wddma[du->dk_interface].wdd_dmadone(du->dk_dmacookie);
- }
-
du->dk_timeout = 0;
- /* check drive status/failure */
if (wdwait(du, 0, TIMEOUT) < 0) {
wderror(bp, du, "wdintr: timeout waiting for status");
du->dk_status |= WDCS_ERR; /* XXX */
@@ -1111,32 +1009,16 @@ wdintr(int unit)
}
/* have we an error? */
- if ((du->dk_status & (WDCS_ERR | WDCS_ECCCOR))
- || (((du->dk_flags & (DKFL_DMA|DKFL_SINGLE)) == DKFL_DMA)
- && dmastat != WDDS_INTERRUPT)) {
-
- unsigned int errstat;
+ if (du->dk_status & (WDCS_ERR | WDCS_ECCCOR)) {
oops:
/*
- * XXX bogus inb() here
+ * XXX bogus inb() here, register 0 is assumed and intr status
+ * is reset.
*/
- errstat = inb(du->dk_port + wd_error);
-
- if(((du->dk_flags & (DKFL_DMA|DKFL_SINGLE)) == DKFL_DMA) &&
- (errstat & WDERR_ABORT)) {
- wderror(bp, du, "reverting to PIO mode");
- du->dk_flags &= ~DKFL_USEDMA;
- } else if((du->dk_flags & DKFL_MULTI) &&
- (errstat & WDERR_ABORT)) {
+ if( (du->dk_flags & DKFL_MULTI) && (inb(du->dk_port) & WDERR_ABORT)) {
wderror(bp, du, "reverting to non-multi sector mode");
du->dk_multi = 1;
}
-
- if (!(du->dk_status & (WDCS_ERR | WDCS_ECCCOR)) &&
- (((du->dk_flags & (DKFL_DMA|DKFL_SINGLE)) == DKFL_DMA) &&
- (dmastat != WDDS_INTERRUPT)))
- printf("wd%d: DMA failure, DMA status %b\n",
- du->dk_lunit, dmastat, WDDS_BITS);
#ifdef WDDEBUG
wderror(bp, du, "wdintr");
#endif
@@ -1163,7 +1045,7 @@ oops:
bp->b_error = EIO;
bp->b_flags |= B_ERROR; /* flag the error */
}
- } else if (du->dk_status & WDCS_ECCCOR)
+ } else
wderror(bp, du, "soft ecc");
}
@@ -1171,7 +1053,6 @@ oops:
* If this was a successful read operation, fetch the data.
*/
if (((bp->b_flags & (B_READ | B_ERROR)) == B_READ)
- && !((du->dk_flags & (DKFL_DMA|DKFL_SINGLE)) == DKFL_DMA)
&& wdtab[unit].b_active) {
int chk, dummy, multisize;
multisize = chk = du->dk_currentiosize * DEV_BSIZE;
@@ -1195,11 +1076,11 @@ oops:
/* suck in data */
if( du->dk_flags & DKFL_32BIT)
insl(du->dk_port + wd_data,
- (void *)((int)bp->b_data + du->dk_skip * DEV_BSIZE),
+ (void *)((int)bp->b_un.b_addr + du->dk_skip * DEV_BSIZE),
chk / sizeof(long));
else
insw(du->dk_port + wd_data,
- (void *)((int)bp->b_data + du->dk_skip * DEV_BSIZE),
+ (void *)((int)bp->b_un.b_addr + du->dk_skip * DEV_BSIZE),
chk / sizeof(short));
du->dk_bc -= chk;
@@ -1213,20 +1094,6 @@ oops:
dk_wds[du->dk_dkunit] += chk >> 6;
}
- /* final cleanup on DMA */
- if (((bp->b_flags & B_ERROR) == 0)
- && ((du->dk_flags & (DKFL_DMA|DKFL_SINGLE)) == DKFL_DMA)
- && wdtab[unit].b_active) {
- int iosize;
-
- iosize = du->dk_currentiosize * DEV_BSIZE;
-
- du->dk_bc -= iosize;
-
- if (du->dk_dkunit >= 0)
- dk_wds[du->dk_dkunit] += iosize >> 6;
- }
-
outt:
if (wdtab[unit].b_active) {
if ((bp->b_flags & B_ERROR) == 0) {
@@ -1258,11 +1125,12 @@ outt:
done: ;
/* done with this transfer, with or without error */
- du->dk_flags &= ~(DKFL_SINGLE|DKFL_DMA);
- bufq_remove( &wdtab[unit].controller_queue, bp);
+ du->dk_flags &= ~DKFL_SINGLE;
+ TAILQ_REMOVE(&wdtab[unit].controller_queue, bp, b_act);
wdtab[unit].b_errcnt = 0;
bp->b_resid = bp->b_bcount - du->dk_skip * DEV_BSIZE;
wdutab[du->dk_lunit].b_active = 0;
+ wdutab[du->dk_lunit].b_errcnt = 0;
du->dk_skip = 0;
biodone(bp);
}
@@ -1279,7 +1147,7 @@ done: ;
/* anything more for controller to do? */
#ifndef ATAPI
/* This is not valid in ATAPI mode. */
- if (bufq_first(&wdtab[unit].controller_queue) != NULL)
+ if (wdtab[unit].controller_queue.tqh_first)
#endif
wdstart(unit);
}
@@ -1312,7 +1180,6 @@ wdopen(dev_t dev, int flags, int fmt, struct proc *p)
du->dk_flags &= ~DKFL_BADSCAN;
- /* spin waiting for anybody else reading the disk label */
while (du->dk_flags & DKFL_LABELLING)
tsleep((caddr_t)&du->dk_flags, PZERO - 1, "wdopen", 1);
#if 1
@@ -1567,20 +1434,15 @@ wdcommand(struct disk *du, u_int cylinder, u_int head, u_int sector,
return (1);
if( command == WDCC_FEATURES) {
outb(wdc + wd_features, count);
- if ( count == WDFEA_SETXFER )
- outb(wdc + wd_seccnt, sector);
} else {
outb(wdc + wd_precomp, du->dk_dd.d_precompcyl / 4);
outb(wdc + wd_cyl_lo, cylinder);
outb(wdc + wd_cyl_hi, cylinder >> 8);
outb(wdc + wd_sdh, WDSD_IBM | (du->dk_unit << 4) | head);
- 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);
}
- if (wdwait(du, (command == WDCC_DIAGNOSE || command == WDCC_IDC)
+ if (wdwait(du, command == WDCC_DIAGNOSE || command == WDCC_IDC
? 0 : WDCS_READY, TIMEOUT) < 0)
return (1);
outb(wdc + wd_command, command);
@@ -1624,44 +1486,42 @@ wdsetctlr(struct disk *du)
du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks,
du->dk_dd.d_nsectors);
#endif
- 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;
- }
+ 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_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;
+ else {
+ printf("(truncating to 16)\n");
+ du->dk_dd.d_ntracks = 16;
}
- 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
- 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);
@@ -1698,26 +1558,6 @@ wdwsetctlr(struct disk *du)
#endif
/*
- * gross little callback function for wdddma interface. returns 1 for
- * success, 0 for failure.
- */
-static int
-wdsetmode(int mode, void *wdinfo)
-{
- int i;
- struct disk *du;
-
- du = wdinfo;
- if (bootverbose)
- printf("wd%d: wdsetmode() setting transfer mode to %02x\n",
- du->dk_lunit, mode);
- i = wdcommand(du, 0, 0, mode, WDFEA_SETXFER,
- WDCC_FEATURES) == 0 &&
- wdwait(du, WDCS_READY, TIMEOUT) == 0;
- return i;
-}
-
-/*
* issue READP to drive to ask it what it is.
*/
static int
@@ -1872,23 +1712,6 @@ failed:
du->dk_multi = wp->wdp_nsecperint & 0xff;
wdsetmulti(du);
- /*
- * check drive's DMA capability
- */
- if (wddma[du->dk_interface].wdd_candma) {
- du->dk_dmacookie = wddma[du->dk_interface].wdd_candma(du->dk_port, du->dk_ctrlr);
- /* does user want this? */
- if ((du->cfg_flags & WDOPT_DMA) &&
- /* have we got a DMA controller? */
- du->dk_dmacookie &&
- /* can said drive do DMA? */
- wddma[du->dk_interface].wdd_dmainit(du->dk_dmacookie, wp, wdsetmode, du)) {
- du->dk_flags |= DKFL_USEDMA;
- }
- } else {
- du->dk_dmacookie = NULL;
- }
-
#ifdef WDDEBUG
printf(
"\nwd(%d,%d): wdgetctlr: gc %x cyl %d trk %d sec %d type %d sz %d model %s\n",
@@ -1899,40 +1722,11 @@ failed:
/* update disklabel given drive information */
du->dk_dd.d_secsize = DEV_BSIZE;
- if ((du->cfg_flags & WDOPT_LBA) && wp->wdp_lbasize) {
- du->dk_dd.d_nsectors = 63;
- if (wp->wdp_lbasize < 16*63*1024) { /* <=528.4 MB */
- du->dk_dd.d_ntracks = 16;
- }
- 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;
- }
+ 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 =
@@ -1976,7 +1770,7 @@ wdioctl(dev_t dev, int cmd, caddr_t addr, int flags, struct proc *p)
wdsleep(du->dk_ctrlr, "wdioct");
error = dsioctl("wd", dev, cmd, addr, flags, &du->dk_slices,
wdstrategy1, (ds_setgeom_t *)NULL);
- if (error != ENOIOCTL)
+ if (error != -1)
return (error);
switch (cmd) {
@@ -2279,28 +2073,25 @@ wdflushirq(struct disk *du, int old_ipl)
static int
wdreset(struct disk *du)
{
- int err = 0;
-
- if ((du->dk_flags & (DKFL_DMA|DKFL_USEDMA)) && du->dk_dmacookie)
- wddma[du->dk_interface].wdd_dmadone(du->dk_dmacookie);
+ int wdc, err = 0;
+ wdc = du->dk_port;
(void)wdwait(du, 0, TIMEOUT);
- outb(du->dk_altport, WDCTL_IDS | WDCTL_RST);
+ outb(wdc + wd_ctlr, WDCTL_IDS | WDCTL_RST);
DELAY(10 * 1000);
- outb(du->dk_altport, WDCTL_IDS);
+ outb(wdc + wd_ctlr, WDCTL_IDS);
#ifdef ATAPI
if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0)
err = 1; /* no IDE drive found */
- du->dk_error = inb(du->dk_port + wd_error);
+ du->dk_error = inb(wdc + wd_error);
if (du->dk_error != 0x01)
err = 1; /* the drive is incompatible */
#else
- if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0) {
- printf("wdreset: error1: 0x%x\n", du->dk_error);
+ if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0
+ || (du->dk_error = inb(wdc + wd_error)) != 0x01)
return (1);
- }
#endif
- outb(du->dk_altport, WDCTL_4BIT);
+ outb(wdc + wd_ctlr, WDCTL_4BIT);
return (err);
}
@@ -2332,19 +2123,11 @@ wdtimeout(void *cdu)
du = (struct disk *)cdu;
x = splbio();
if (du->dk_timeout != 0 && --du->dk_timeout == 0) {
- if(timeouts++ <= 5) {
- char *msg;
-
- msg = (timeouts > 5) ?
-"Last time I say: interrupt timeout. Probably a portable PC." :
-"interrupt timeout";
- wderror((struct buf *)NULL, du, msg);
- if (du->dk_dmacookie)
- printf("wd%d: wdtimeout() DMA status %b\n",
- du->dk_lunit,
- wddma[du->dk_interface].wdd_dmastatus(du->dk_dmacookie),
- WDDS_BITS);
- }
+ if(timeouts++ == 5)
+ wderror((struct buf *)NULL, du,
+ "Last time I say: interrupt timeout. Probably a portable PC.");
+ else if(timeouts++ < 5)
+ wderror((struct buf *)NULL, du, "interrupt timeout");
wdunwedge(du);
wdflushirq(du, x);
du->dk_skip = 0;
@@ -2453,9 +2236,8 @@ wdwait(struct disk *du, u_char bits_wanted, int timeout)
* command completion.
*/
}
- if ((status & bits_wanted) == bits_wanted) {
+ if ((status & bits_wanted) == bits_wanted)
return (status & WDCS_ERR);
- }
}
if (timeout < TIMEOUT)
/*
@@ -2477,8 +2259,6 @@ static void wd_drvinit(void *unused)
{
if( ! wd_devsw_installed ) {
- if (wd_bdevsw.d_maxio == 0)
- wd_bdevsw.d_maxio = 248 * 512;
bdevsw_add_generic(BDEV_MAJOR,CDEV_MAJOR, &wd_bdevsw);
wd_devsw_installed = 1;
}
OpenPOWER on IntegriCloud