Use TAILQ_*() to maintain the drive activation queues.
This commit is contained in:
parent
1ffc6c23e3
commit
893be926ec
@ -35,7 +35,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)fd.c 7.4 (Berkeley) 5/25/91
|
||||
* $Id: fd.c,v 1.39 1994/04/09 02:57:14 mycroft Exp $
|
||||
* $Id: fd.c,v 1.40 1994/04/20 07:23:52 mycroft Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -52,6 +52,7 @@
|
||||
#include <sys/buf.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/pio.h>
|
||||
@ -102,8 +103,7 @@ struct fdc_softc {
|
||||
u_short sc_drq;
|
||||
|
||||
struct fd_softc *sc_fd[4]; /* pointers to children */
|
||||
struct fd_softc *sc_afd; /* active drive */
|
||||
struct buf sc_q;
|
||||
TAILQ_HEAD(drivehead, fd_softc) sc_drives;
|
||||
enum fdc_state sc_state;
|
||||
int sc_retry; /* number of retries so far */
|
||||
u_char sc_status[7]; /* copy of registers */
|
||||
@ -159,6 +159,7 @@ struct fd_softc {
|
||||
#endif
|
||||
|
||||
struct fd_type *sc_deftype; /* default type descriptor */
|
||||
TAILQ_ENTRY(fd_softc) sc_drivechain;
|
||||
struct buf sc_q; /* head of buf chain */
|
||||
int sc_drive; /* unit number on this controller */
|
||||
int sc_flags;
|
||||
@ -186,6 +187,7 @@ struct dkdriver fddkdriver = { fdstrategy };
|
||||
#endif
|
||||
|
||||
struct fd_type *fd_nvtotype __P((char *, int, int));
|
||||
void fdstart __P((struct fd_softc *fd));
|
||||
void fd_set_motor __P((struct fdc_softc *fdc, int reset));
|
||||
void fd_motor_off __P((struct fd_softc *fd));
|
||||
void fd_motor_on __P((struct fd_softc *fd));
|
||||
@ -197,6 +199,7 @@ void fdctimeout __P((struct fdc_softc *fdc));
|
||||
void fdcpseudointr __P((struct fdc_softc *fdc));
|
||||
int fdcintr __P((struct fdc_softc *fdc));
|
||||
void fdcretry __P((struct fdc_softc *fdc));
|
||||
void fdfinish __P((struct fd_softc *fd, struct buf *bp));
|
||||
|
||||
int
|
||||
fdcprobe(parent, self, aux)
|
||||
@ -294,6 +297,8 @@ fdcattach(parent, self, aux)
|
||||
fdc->sc_iobase = ia->ia_iobase;
|
||||
fdc->sc_drq = ia->ia_drq;
|
||||
fdc->sc_state = DEVIDLE;
|
||||
TAILQ_INIT(&fdc->sc_drives);
|
||||
|
||||
printf("\n");
|
||||
|
||||
#ifdef NEWCONFIG
|
||||
@ -512,38 +517,39 @@ fdstrategy(bp)
|
||||
bp->b_blkno, bp->b_bcount, fd->sc_blkno, bp->b_cylin, nblks);
|
||||
#endif
|
||||
s = splbio();
|
||||
dp = &fd->sc_q;
|
||||
disksort(dp, bp);
|
||||
disksort(&fd->sc_q, bp);
|
||||
untimeout((timeout_t)fd_motor_off, (caddr_t)fd); /* a good idea */
|
||||
if (!dp->b_active) {
|
||||
register struct buf *cp;
|
||||
dp->b_forw = NULL;
|
||||
dp->b_active = 1;
|
||||
cp = &fdc->sc_q;
|
||||
if (!cp->b_forw)
|
||||
cp->b_forw = dp;
|
||||
else
|
||||
cp->b_back->b_forw = dp;
|
||||
cp->b_back = dp;
|
||||
if (!cp->b_active) {
|
||||
cp->b_active = 1;
|
||||
fdcstart(fdc);
|
||||
}
|
||||
}
|
||||
if (!fd->sc_q.b_active)
|
||||
fdstart(fd);
|
||||
#ifdef DIAGNOSTIC
|
||||
else if (!fdc->sc_q.b_active) {
|
||||
else if (fdc->sc_state == DEVIDLE) {
|
||||
printf("fdstrategy: controller inactive\n");
|
||||
fdc->sc_q.b_active = 1;
|
||||
fdcstart(fdc);
|
||||
}
|
||||
#endif
|
||||
splx(s);
|
||||
return;
|
||||
|
||||
bad:
|
||||
bad:
|
||||
biodone(bp);
|
||||
}
|
||||
|
||||
void
|
||||
fdstart(fd)
|
||||
struct fd_softc *fd;
|
||||
{
|
||||
struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
|
||||
int active = fdc->sc_drives.tqh_first != 0;
|
||||
|
||||
/* Link into controller queue. */
|
||||
fd->sc_q.b_active = 1;
|
||||
TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain);
|
||||
|
||||
/* If controller not already active, start it. */
|
||||
if (!active)
|
||||
fdcstart(fdc);
|
||||
}
|
||||
|
||||
void
|
||||
fd_set_motor(fdc, reset)
|
||||
struct fdc_softc *fdc;
|
||||
@ -553,7 +559,7 @@ fd_set_motor(fdc, reset)
|
||||
u_char status;
|
||||
int n;
|
||||
|
||||
if (fd = fdc->sc_afd)
|
||||
if (fd = fdc->sc_drives.tqh_first)
|
||||
status = fd->sc_drive;
|
||||
else
|
||||
status = 0;
|
||||
@ -584,7 +590,7 @@ fd_motor_on(fd)
|
||||
int s = splbio();
|
||||
|
||||
fd->sc_flags &= ~FD_MOTOR_WAIT;
|
||||
if ((fdc->sc_afd == fd) && (fdc->sc_state == MOTORWAIT))
|
||||
if ((fdc->sc_drives.tqh_first == fd) && (fdc->sc_state == MOTORWAIT))
|
||||
(void) fdcintr(fdc);
|
||||
splx(s);
|
||||
}
|
||||
@ -718,17 +724,17 @@ void
|
||||
fdctimeout(fdc)
|
||||
struct fdc_softc *fdc;
|
||||
{
|
||||
struct fd_softc *fd = fdc->sc_afd;
|
||||
struct fd_softc *fd;
|
||||
int s = splbio();
|
||||
|
||||
fd = fdc->sc_drives.tqh_first;
|
||||
|
||||
fdcstatus(&fd->sc_dev, 0, "timeout");
|
||||
|
||||
if (fd->sc_q.b_actf) {
|
||||
if (fd->sc_q.b_actf)
|
||||
fdc->sc_state++;
|
||||
} else {
|
||||
fdc->sc_afd = NULL;
|
||||
else
|
||||
fdc->sc_state = DEVIDLE;
|
||||
}
|
||||
|
||||
(void) fdcintr(fdc);
|
||||
splx(s);
|
||||
@ -752,43 +758,29 @@ fdcintr(fdc)
|
||||
#define st0 fdc->sc_status[0]
|
||||
#define cyl fdc->sc_status[1]
|
||||
struct fd_softc *fd;
|
||||
struct buf *dp, *bp;
|
||||
struct buf *bp;
|
||||
u_short iobase = fdc->sc_iobase;
|
||||
int read, head, trac, sec, i, s, sectrac, blkno, nblks;
|
||||
struct fd_type *type;
|
||||
|
||||
again:
|
||||
dp = fdc->sc_q.b_forw;
|
||||
if (!dp) {
|
||||
fd = fdc->sc_drives.tqh_first;
|
||||
if (!fd) {
|
||||
/* no drives waiting; end */
|
||||
fdc->sc_state = DEVIDLE;
|
||||
fdc->sc_q.b_active = 0;
|
||||
#ifdef DIAGNOSTIC
|
||||
if (fd = fdc->sc_afd) {
|
||||
printf("%s: stray afd %s\n", fdc->sc_dev.dv_xname,
|
||||
fd->sc_dev.dv_xname);
|
||||
fdc->sc_afd = NULL;
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
bp = dp->b_actf;
|
||||
bp = fd->sc_q.b_actf;
|
||||
if (!bp) {
|
||||
/* nothing queued on this drive; try next */
|
||||
fdc->sc_q.b_forw = dp->b_forw;
|
||||
dp->b_active = 0;
|
||||
TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain);
|
||||
fd->sc_q.b_active = 0;
|
||||
goto again;
|
||||
}
|
||||
fd = fdcd.cd_devs[FDUNIT(bp->b_dev)];
|
||||
#ifdef DIAGNOSTIC
|
||||
if (fdc->sc_afd && (fd != fdc->sc_afd))
|
||||
printf("%s: confused fd pointers\n", fdc->sc_dev.dv_xname);
|
||||
#endif
|
||||
|
||||
switch (fdc->sc_state) {
|
||||
case DEVIDLE:
|
||||
fdc->sc_retry = 0;
|
||||
fdc->sc_afd = fd;
|
||||
fd->sc_skip = 0;
|
||||
fd->sc_blkno = bp->b_blkno * DEV_BSIZE / FDC_BSIZE;
|
||||
untimeout((timeout_t)fd_motor_off, (caddr_t)fd);
|
||||
@ -954,14 +946,7 @@ again:
|
||||
bp->b_cylin = (blkno / (type->sectrac * type->heads)) * type->step;
|
||||
goto doseek;
|
||||
} else {
|
||||
bp->b_resid = 0;
|
||||
fd->sc_q.b_actf = bp->b_actf;
|
||||
biodone(bp);
|
||||
/* turn off motor 5s from now */
|
||||
timeout((timeout_t)fd_motor_off, (caddr_t)fd, hz*5);
|
||||
fd->sc_skip = 0;
|
||||
fdc->sc_afd = NULL;
|
||||
fdc->sc_state = DEVIDLE;
|
||||
fdfinish(fd, bp);
|
||||
goto again;
|
||||
}
|
||||
|
||||
@ -1027,9 +1012,10 @@ void
|
||||
fdcretry(fdc)
|
||||
struct fdc_softc *fdc;
|
||||
{
|
||||
register struct buf *bp;
|
||||
struct fd_softc *fd = fdc->sc_afd;
|
||||
struct fd_softc *fd;
|
||||
struct buf *bp;
|
||||
|
||||
fd = fdc->sc_drives.tqh_first;
|
||||
bp = fd->sc_q.b_actf;
|
||||
|
||||
switch (fdc->sc_retry) {
|
||||
@ -1049,8 +1035,6 @@ fdcretry(fdc)
|
||||
break;
|
||||
|
||||
default:
|
||||
fd = fdc->sc_afd;
|
||||
|
||||
diskerr(bp, "fd", "hard error", LOG_PRINTF,
|
||||
fd->sc_skip, (struct disklabel *)NULL);
|
||||
printf(" (st0 %b ", fdc->sc_status[0], NE7_ST0BITS);
|
||||
@ -1061,18 +1045,45 @@ fdcretry(fdc)
|
||||
|
||||
bp->b_flags |= B_ERROR;
|
||||
bp->b_error = EIO;
|
||||
bp->b_resid = bp->b_bcount - fd->sc_skip;
|
||||
fd->sc_q.b_actf = bp->b_actf;
|
||||
biodone(bp);
|
||||
/* turn off motor 5s from now */
|
||||
timeout((timeout_t)fd_motor_off, (caddr_t)fd, hz*5);
|
||||
fd->sc_skip = 0;
|
||||
fdc->sc_afd = NULL;
|
||||
fdc->sc_state = DEVIDLE;
|
||||
fdfinish(fd, bp);
|
||||
}
|
||||
fdc->sc_retry++;
|
||||
}
|
||||
|
||||
void
|
||||
fdfinish(fd, bp)
|
||||
struct fd_softc *fd;
|
||||
struct buf *bp;
|
||||
{
|
||||
struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* This might seem like a good idea, but each drive switch takes .25
|
||||
* second because we can't keep both motors running at the same time
|
||||
* and we have to wait for the new one to stabilize for each I/O.
|
||||
*/
|
||||
/*
|
||||
* Move this drive to the end of the queue to give others a `fair'
|
||||
* chance.
|
||||
*/
|
||||
if (fd->sc_drivechain.tqe_next) {
|
||||
TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain);
|
||||
if (bp->b_actf) {
|
||||
TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain);
|
||||
} else
|
||||
fd->sc_q.b_active = 0;
|
||||
}
|
||||
#endif
|
||||
bp->b_resid = bp->b_bcount - fd->sc_skip;
|
||||
fd->sc_skip = 0;
|
||||
fd->sc_q.b_actf = bp->b_actf;
|
||||
biodone(bp);
|
||||
/* turn off motor 5s from now */
|
||||
timeout((timeout_t)fd_motor_off, (caddr_t)fd, hz*5);
|
||||
fdc->sc_state = DEVIDLE;
|
||||
}
|
||||
|
||||
int
|
||||
fdioctl(dev, cmd, addr, flag)
|
||||
dev_t dev;
|
||||
|
@ -35,7 +35,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)wd.c 7.2 (Berkeley) 5/9/91
|
||||
* $Id: wd.c,v 1.77 1994/04/09 03:43:36 mycroft Exp $
|
||||
* $Id: wd.c,v 1.78 1994/04/20 07:23:54 mycroft Exp $
|
||||
*/
|
||||
|
||||
#define INSTRUMENT /* instrumentation stuff by Brad Parker */
|
||||
@ -122,6 +122,7 @@ struct wd_softc {
|
||||
#define WDF_BSDLABEL 0x00010 /* has a BSD disk label */
|
||||
#define WDF_BADSECT 0x00020 /* has a bad144 badsector table */
|
||||
#define WDF_WRITEPROT 0x00040 /* manual unit write protect */
|
||||
TAILQ_ENTRY(wd_softc) sc_drivechain;
|
||||
struct buf sc_q;
|
||||
struct wdparams sc_params; /* ESDI/IDE drive/controller parameters */
|
||||
struct disklabel sc_label; /* device configuration data */
|
||||
@ -133,14 +134,16 @@ struct wdc_softc {
|
||||
struct device sc_dev;
|
||||
struct intrhand sc_ih;
|
||||
|
||||
struct buf sc_q;
|
||||
u_char sc_flags;
|
||||
#define WDCF_ACTIVE 0x00001 /* controller is active */
|
||||
#define WDCF_SINGLE 0x00004 /* sector at a time mode */
|
||||
#define WDCF_ERROR 0x00008 /* processing a disk error */
|
||||
u_char sc_status; /* copy of status register */
|
||||
u_char sc_error; /* copy of error register */
|
||||
u_short sc_iobase; /* i/o port base */
|
||||
int sc_timeout; /* timeout counter */
|
||||
int sc_errors; /* count of errors during current transfer */
|
||||
TAILQ_HEAD(drivehead, wd_softc) sc_drives;
|
||||
};
|
||||
|
||||
int wdcprobe(), wdprobe(), wdcintr();
|
||||
@ -254,6 +257,7 @@ wdcattach(parent, self, aux)
|
||||
for (wa.wa_drive = 0; wa.wa_drive < 2; wa.wa_drive++)
|
||||
(void)config_found(self, &wa, wdprint);
|
||||
|
||||
TAILQ_INIT(&wdc->sc_drives);
|
||||
wdctimeout(wdc);
|
||||
wdc->sc_ih.ih_fun = wdcintr;
|
||||
wdc->sc_ih.ih_arg = wdc;
|
||||
@ -333,7 +337,6 @@ void
|
||||
wdstrategy(bp)
|
||||
struct buf *bp;
|
||||
{
|
||||
struct buf *dp;
|
||||
struct wd_softc *wd; /* disk unit to do the IO */
|
||||
struct wdc_softc *wdc;
|
||||
int lunit = WDUNIT(bp->b_dev);
|
||||
@ -371,14 +374,16 @@ wdstrategy(bp)
|
||||
bp->b_cylin = 0;
|
||||
|
||||
/* Queue transfer on drive, activate drive and controller if idle. */
|
||||
dp = &wd->sc_q;
|
||||
s = splbio();
|
||||
wddisksort(dp, bp);
|
||||
if (dp->b_active == 0)
|
||||
wddisksort(&wd->sc_q, bp);
|
||||
if (!wd->sc_q.b_active)
|
||||
wdstart(wd); /* Start drive. */
|
||||
wdc = (void *)wd->sc_dev.dv_parent;
|
||||
if (wdc->sc_q.b_active == 0)
|
||||
wdcstart(wdc); /* Start controller. */
|
||||
#ifdef DIAGNOSTIC
|
||||
else if ((wdc->sc_flags & WDCF_ACTIVE) == 0) {
|
||||
printf("wdstrategy: controller inactive\n");
|
||||
wdcstart(wdc);
|
||||
}
|
||||
#endif
|
||||
splx(s);
|
||||
return;
|
||||
|
||||
@ -410,29 +415,16 @@ static void
|
||||
wdstart(wd)
|
||||
struct wd_softc *wd;
|
||||
{
|
||||
struct buf *dp;
|
||||
struct wdc_softc *wdc;
|
||||
struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
|
||||
int active = wdc->sc_drives.tqh_first != 0;
|
||||
|
||||
dp = &wd->sc_q;
|
||||
|
||||
/* Unit already active? */
|
||||
if (dp->b_active)
|
||||
return;
|
||||
/* Anything to start? */
|
||||
if (dp->b_actf == NULL)
|
||||
return;
|
||||
|
||||
/* Link onto controller queue. */
|
||||
dp->b_forw = NULL;
|
||||
wdc = (void *)wd->sc_dev.dv_parent;
|
||||
if (wdc->sc_q.b_forw == NULL)
|
||||
wdc->sc_q.b_forw = dp;
|
||||
else
|
||||
wdc->sc_q.b_actl->b_forw = dp;
|
||||
wdc->sc_q.b_actl = dp;
|
||||
wd->sc_q.b_active = 1;
|
||||
TAILQ_INSERT_TAIL(&wdc->sc_drives, wd, sc_drivechain);
|
||||
|
||||
/* Mark the drive unit as busy. */
|
||||
dp->b_active = 1;
|
||||
/* If controller not already active, start it. */
|
||||
if (!active)
|
||||
wdcstart(wdc);
|
||||
}
|
||||
|
||||
void
|
||||
@ -446,22 +438,26 @@ wdfinish(wd, bp)
|
||||
dk_busy &= ~(1 << wd->sc_drive);
|
||||
#endif
|
||||
wdc->sc_flags &= ~(WDCF_SINGLE | WDCF_ERROR);
|
||||
wdc->sc_q.b_errcnt = 0;
|
||||
wdc->sc_errors = 0;
|
||||
/*
|
||||
* If this is the only buf or the last buf in the transfer (taking into
|
||||
* account any residual, in case we erred)...
|
||||
*/
|
||||
wd->sc_mbcount -= wd->sc_bcount;
|
||||
if (wd->sc_mbcount == 0) {
|
||||
wd->sc_mskip = 0;
|
||||
/*
|
||||
* ...then move this drive to the end of the queue to give
|
||||
* others a `fair' chance.
|
||||
*/
|
||||
wdc->sc_q.b_forw = wd->sc_q.b_forw;
|
||||
wd->sc_mskip = 0;
|
||||
wd->sc_q.b_active = 0;
|
||||
if (wd->sc_q.b_actf)
|
||||
wdstart(wd);
|
||||
if (wd->sc_drivechain.tqe_next) {
|
||||
TAILQ_REMOVE(&wdc->sc_drives, wd, sc_drivechain);
|
||||
if (bp->b_actf) {
|
||||
TAILQ_INSERT_TAIL(&wdc->sc_drives, wd,
|
||||
sc_drivechain);
|
||||
} else
|
||||
wd->sc_q.b_active = 0;
|
||||
}
|
||||
}
|
||||
bp->b_resid = wd->sc_bcount;
|
||||
bp->b_flags &= ~B_XXX;
|
||||
@ -484,42 +480,34 @@ wdcstart(wdc)
|
||||
struct wd_softc *wd; /* disk unit for IO */
|
||||
struct buf *bp;
|
||||
struct disklabel *lp;
|
||||
struct buf *dp;
|
||||
long blknum, cylin, head, sector;
|
||||
long secpertrk, secpercyl;
|
||||
int xfrblknum;
|
||||
int lunit;
|
||||
|
||||
loop:
|
||||
/* Is there a drive for the controller to do a transfer with? */
|
||||
dp = wdc->sc_q.b_forw;
|
||||
if (dp == NULL) {
|
||||
wdc->sc_q.b_active = 0;
|
||||
wd = wdc->sc_drives.tqh_first;
|
||||
if (wd == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Is there a transfer to this drive? If not, deactivate drive. */
|
||||
bp = dp->b_actf;
|
||||
bp = wd->sc_q.b_actf;
|
||||
if (bp == NULL) {
|
||||
dp->b_active = 0;
|
||||
wdc->sc_q.b_forw = dp->b_forw;
|
||||
TAILQ_REMOVE(&wdc->sc_drives, wd, sc_drivechain);
|
||||
wd->sc_q.b_active = 0;
|
||||
goto loop;
|
||||
}
|
||||
|
||||
/* Obtain controller and drive information */
|
||||
lunit = WDUNIT(bp->b_dev);
|
||||
wd = wdcd.cd_devs[lunit];
|
||||
|
||||
if (wdc->sc_q.b_errcnt >= WDIORETRIES) {
|
||||
if (wdc->sc_errors >= WDIORETRIES) {
|
||||
wderror(wd, bp, "hard error");
|
||||
bp->b_error = EIO;
|
||||
bp->b_flags |= B_ERROR;
|
||||
wdfinish(wd, bp);
|
||||
goto loop;
|
||||
}
|
||||
|
||||
/* Mark controller active and set a timeout. */
|
||||
wdc->sc_q.b_active = 1;
|
||||
|
||||
/* Mark the controller active and set a timeout. */
|
||||
wdc->sc_flags |= WDCF_ACTIVE;
|
||||
wdc->sc_timeout = 4;
|
||||
|
||||
/* Do control operations specially. */
|
||||
@ -551,7 +539,7 @@ loop:
|
||||
blknum = bp->b_blkno + wd->sc_skip;
|
||||
#ifdef WDDEBUG
|
||||
if (wd->sc_skip == 0)
|
||||
printf("\nwdcstart %d: %s %d@%d; map ", lunit,
|
||||
printf("\nwdcstart %s: %s %d@%d; map ", wd->sc_dev.dv_xname,
|
||||
(bp->b_flags & B_READ) ? "read" : "write", bp->b_bcount,
|
||||
blknum);
|
||||
else
|
||||
@ -680,7 +668,7 @@ loop:
|
||||
cylin, head, bp->b_un.b_addr, inb(wd->sc_iobase+wd_altsts));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* If this is a read operation, just go away until it's done. */
|
||||
if (bp->b_flags & B_READ)
|
||||
return;
|
||||
@ -712,13 +700,12 @@ wdcintr(wdc)
|
||||
/* Clear the pending interrupt. */
|
||||
(void) inb(wdc->sc_iobase+wd_status);
|
||||
|
||||
if (!wdc->sc_q.b_active)
|
||||
if ((wdc->sc_flags & WDCF_ACTIVE) == 0)
|
||||
return 0;
|
||||
|
||||
bp = wdc->sc_q.b_forw->b_actf;
|
||||
wd = wdcd.cd_devs[WDUNIT(bp->b_dev)];
|
||||
wdc->sc_timeout = 0;
|
||||
|
||||
|
||||
wd = wdc->sc_drives.tqh_first;
|
||||
bp = wd->sc_q.b_actf;
|
||||
|
||||
#ifdef WDDEBUG
|
||||
printf("I%d ", ctrlr);
|
||||
#endif
|
||||
@ -734,6 +721,9 @@ wdcintr(wdc)
|
||||
wdcstart(wdc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
wdc->sc_flags &= ~WDCF_ACTIVE;
|
||||
wdc->sc_timeout = 0;
|
||||
|
||||
/* Have we an error? */
|
||||
if (wdc->sc_status & (WDCS_ERR | WDCS_ECCCOR)) {
|
||||
@ -755,7 +745,7 @@ wdcintr(wdc)
|
||||
|
||||
/* Error or error correction? */
|
||||
if (wdc->sc_status & WDCS_ERR) {
|
||||
if (++wdc->sc_q.b_errcnt >= WDIORETRIES) {
|
||||
if (++wdc->sc_errors >= WDIORETRIES) {
|
||||
wderror(wd, bp, "hard error");
|
||||
bp->b_error = EIO;
|
||||
bp->b_flags |= B_ERROR; /* Flag the error. */
|
||||
@ -782,9 +772,9 @@ wdcintr(wdc)
|
||||
}
|
||||
|
||||
/* If we encountered any abnormalities, flag it as a soft error. */
|
||||
if (wdc->sc_q.b_errcnt) {
|
||||
if (wdc->sc_errors) {
|
||||
wderror(wd, bp, "soft error");
|
||||
wdc->sc_q.b_errcnt = 0;
|
||||
wdc->sc_errors = 0;
|
||||
}
|
||||
|
||||
/* Ready for the next block, if any. */
|
||||
@ -970,7 +960,7 @@ wdcontrol(wd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
wdc->sc_q.b_errcnt = 0;
|
||||
wdc->sc_errors = 0;
|
||||
wd->sc_state = OPEN;
|
||||
/*
|
||||
* The rest of the initialization can be done by normal means.
|
||||
@ -1498,7 +1488,6 @@ wdcrestart(wdc)
|
||||
{
|
||||
int s = splbio();
|
||||
|
||||
wdc->sc_q.b_active = 0;
|
||||
wdcstart(wdc);
|
||||
splx(s);
|
||||
}
|
||||
@ -1529,7 +1518,7 @@ wdcunwedge(wdc)
|
||||
}
|
||||
|
||||
wdc->sc_flags |= WDCF_ERROR;
|
||||
++wdc->sc_q.b_errcnt;
|
||||
++wdc->sc_errors;
|
||||
|
||||
/* Wake up in a little bit and restart the operation. */
|
||||
timeout((timeout_t)wdcrestart, (caddr_t)wdc, RECOVERYTIME);
|
||||
|
121
sys/dev/ata/wd.c
121
sys/dev/ata/wd.c
@ -35,7 +35,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)wd.c 7.2 (Berkeley) 5/9/91
|
||||
* $Id: wd.c,v 1.77 1994/04/09 03:43:36 mycroft Exp $
|
||||
* $Id: wd.c,v 1.78 1994/04/20 07:23:54 mycroft Exp $
|
||||
*/
|
||||
|
||||
#define INSTRUMENT /* instrumentation stuff by Brad Parker */
|
||||
@ -122,6 +122,7 @@ struct wd_softc {
|
||||
#define WDF_BSDLABEL 0x00010 /* has a BSD disk label */
|
||||
#define WDF_BADSECT 0x00020 /* has a bad144 badsector table */
|
||||
#define WDF_WRITEPROT 0x00040 /* manual unit write protect */
|
||||
TAILQ_ENTRY(wd_softc) sc_drivechain;
|
||||
struct buf sc_q;
|
||||
struct wdparams sc_params; /* ESDI/IDE drive/controller parameters */
|
||||
struct disklabel sc_label; /* device configuration data */
|
||||
@ -133,14 +134,16 @@ struct wdc_softc {
|
||||
struct device sc_dev;
|
||||
struct intrhand sc_ih;
|
||||
|
||||
struct buf sc_q;
|
||||
u_char sc_flags;
|
||||
#define WDCF_ACTIVE 0x00001 /* controller is active */
|
||||
#define WDCF_SINGLE 0x00004 /* sector at a time mode */
|
||||
#define WDCF_ERROR 0x00008 /* processing a disk error */
|
||||
u_char sc_status; /* copy of status register */
|
||||
u_char sc_error; /* copy of error register */
|
||||
u_short sc_iobase; /* i/o port base */
|
||||
int sc_timeout; /* timeout counter */
|
||||
int sc_errors; /* count of errors during current transfer */
|
||||
TAILQ_HEAD(drivehead, wd_softc) sc_drives;
|
||||
};
|
||||
|
||||
int wdcprobe(), wdprobe(), wdcintr();
|
||||
@ -254,6 +257,7 @@ wdcattach(parent, self, aux)
|
||||
for (wa.wa_drive = 0; wa.wa_drive < 2; wa.wa_drive++)
|
||||
(void)config_found(self, &wa, wdprint);
|
||||
|
||||
TAILQ_INIT(&wdc->sc_drives);
|
||||
wdctimeout(wdc);
|
||||
wdc->sc_ih.ih_fun = wdcintr;
|
||||
wdc->sc_ih.ih_arg = wdc;
|
||||
@ -333,7 +337,6 @@ void
|
||||
wdstrategy(bp)
|
||||
struct buf *bp;
|
||||
{
|
||||
struct buf *dp;
|
||||
struct wd_softc *wd; /* disk unit to do the IO */
|
||||
struct wdc_softc *wdc;
|
||||
int lunit = WDUNIT(bp->b_dev);
|
||||
@ -371,14 +374,16 @@ wdstrategy(bp)
|
||||
bp->b_cylin = 0;
|
||||
|
||||
/* Queue transfer on drive, activate drive and controller if idle. */
|
||||
dp = &wd->sc_q;
|
||||
s = splbio();
|
||||
wddisksort(dp, bp);
|
||||
if (dp->b_active == 0)
|
||||
wddisksort(&wd->sc_q, bp);
|
||||
if (!wd->sc_q.b_active)
|
||||
wdstart(wd); /* Start drive. */
|
||||
wdc = (void *)wd->sc_dev.dv_parent;
|
||||
if (wdc->sc_q.b_active == 0)
|
||||
wdcstart(wdc); /* Start controller. */
|
||||
#ifdef DIAGNOSTIC
|
||||
else if ((wdc->sc_flags & WDCF_ACTIVE) == 0) {
|
||||
printf("wdstrategy: controller inactive\n");
|
||||
wdcstart(wdc);
|
||||
}
|
||||
#endif
|
||||
splx(s);
|
||||
return;
|
||||
|
||||
@ -410,29 +415,16 @@ static void
|
||||
wdstart(wd)
|
||||
struct wd_softc *wd;
|
||||
{
|
||||
struct buf *dp;
|
||||
struct wdc_softc *wdc;
|
||||
struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
|
||||
int active = wdc->sc_drives.tqh_first != 0;
|
||||
|
||||
dp = &wd->sc_q;
|
||||
|
||||
/* Unit already active? */
|
||||
if (dp->b_active)
|
||||
return;
|
||||
/* Anything to start? */
|
||||
if (dp->b_actf == NULL)
|
||||
return;
|
||||
|
||||
/* Link onto controller queue. */
|
||||
dp->b_forw = NULL;
|
||||
wdc = (void *)wd->sc_dev.dv_parent;
|
||||
if (wdc->sc_q.b_forw == NULL)
|
||||
wdc->sc_q.b_forw = dp;
|
||||
else
|
||||
wdc->sc_q.b_actl->b_forw = dp;
|
||||
wdc->sc_q.b_actl = dp;
|
||||
wd->sc_q.b_active = 1;
|
||||
TAILQ_INSERT_TAIL(&wdc->sc_drives, wd, sc_drivechain);
|
||||
|
||||
/* Mark the drive unit as busy. */
|
||||
dp->b_active = 1;
|
||||
/* If controller not already active, start it. */
|
||||
if (!active)
|
||||
wdcstart(wdc);
|
||||
}
|
||||
|
||||
void
|
||||
@ -446,22 +438,26 @@ wdfinish(wd, bp)
|
||||
dk_busy &= ~(1 << wd->sc_drive);
|
||||
#endif
|
||||
wdc->sc_flags &= ~(WDCF_SINGLE | WDCF_ERROR);
|
||||
wdc->sc_q.b_errcnt = 0;
|
||||
wdc->sc_errors = 0;
|
||||
/*
|
||||
* If this is the only buf or the last buf in the transfer (taking into
|
||||
* account any residual, in case we erred)...
|
||||
*/
|
||||
wd->sc_mbcount -= wd->sc_bcount;
|
||||
if (wd->sc_mbcount == 0) {
|
||||
wd->sc_mskip = 0;
|
||||
/*
|
||||
* ...then move this drive to the end of the queue to give
|
||||
* others a `fair' chance.
|
||||
*/
|
||||
wdc->sc_q.b_forw = wd->sc_q.b_forw;
|
||||
wd->sc_mskip = 0;
|
||||
wd->sc_q.b_active = 0;
|
||||
if (wd->sc_q.b_actf)
|
||||
wdstart(wd);
|
||||
if (wd->sc_drivechain.tqe_next) {
|
||||
TAILQ_REMOVE(&wdc->sc_drives, wd, sc_drivechain);
|
||||
if (bp->b_actf) {
|
||||
TAILQ_INSERT_TAIL(&wdc->sc_drives, wd,
|
||||
sc_drivechain);
|
||||
} else
|
||||
wd->sc_q.b_active = 0;
|
||||
}
|
||||
}
|
||||
bp->b_resid = wd->sc_bcount;
|
||||
bp->b_flags &= ~B_XXX;
|
||||
@ -484,42 +480,34 @@ wdcstart(wdc)
|
||||
struct wd_softc *wd; /* disk unit for IO */
|
||||
struct buf *bp;
|
||||
struct disklabel *lp;
|
||||
struct buf *dp;
|
||||
long blknum, cylin, head, sector;
|
||||
long secpertrk, secpercyl;
|
||||
int xfrblknum;
|
||||
int lunit;
|
||||
|
||||
loop:
|
||||
/* Is there a drive for the controller to do a transfer with? */
|
||||
dp = wdc->sc_q.b_forw;
|
||||
if (dp == NULL) {
|
||||
wdc->sc_q.b_active = 0;
|
||||
wd = wdc->sc_drives.tqh_first;
|
||||
if (wd == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Is there a transfer to this drive? If not, deactivate drive. */
|
||||
bp = dp->b_actf;
|
||||
bp = wd->sc_q.b_actf;
|
||||
if (bp == NULL) {
|
||||
dp->b_active = 0;
|
||||
wdc->sc_q.b_forw = dp->b_forw;
|
||||
TAILQ_REMOVE(&wdc->sc_drives, wd, sc_drivechain);
|
||||
wd->sc_q.b_active = 0;
|
||||
goto loop;
|
||||
}
|
||||
|
||||
/* Obtain controller and drive information */
|
||||
lunit = WDUNIT(bp->b_dev);
|
||||
wd = wdcd.cd_devs[lunit];
|
||||
|
||||
if (wdc->sc_q.b_errcnt >= WDIORETRIES) {
|
||||
if (wdc->sc_errors >= WDIORETRIES) {
|
||||
wderror(wd, bp, "hard error");
|
||||
bp->b_error = EIO;
|
||||
bp->b_flags |= B_ERROR;
|
||||
wdfinish(wd, bp);
|
||||
goto loop;
|
||||
}
|
||||
|
||||
/* Mark controller active and set a timeout. */
|
||||
wdc->sc_q.b_active = 1;
|
||||
|
||||
/* Mark the controller active and set a timeout. */
|
||||
wdc->sc_flags |= WDCF_ACTIVE;
|
||||
wdc->sc_timeout = 4;
|
||||
|
||||
/* Do control operations specially. */
|
||||
@ -551,7 +539,7 @@ loop:
|
||||
blknum = bp->b_blkno + wd->sc_skip;
|
||||
#ifdef WDDEBUG
|
||||
if (wd->sc_skip == 0)
|
||||
printf("\nwdcstart %d: %s %d@%d; map ", lunit,
|
||||
printf("\nwdcstart %s: %s %d@%d; map ", wd->sc_dev.dv_xname,
|
||||
(bp->b_flags & B_READ) ? "read" : "write", bp->b_bcount,
|
||||
blknum);
|
||||
else
|
||||
@ -680,7 +668,7 @@ loop:
|
||||
cylin, head, bp->b_un.b_addr, inb(wd->sc_iobase+wd_altsts));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* If this is a read operation, just go away until it's done. */
|
||||
if (bp->b_flags & B_READ)
|
||||
return;
|
||||
@ -712,13 +700,12 @@ wdcintr(wdc)
|
||||
/* Clear the pending interrupt. */
|
||||
(void) inb(wdc->sc_iobase+wd_status);
|
||||
|
||||
if (!wdc->sc_q.b_active)
|
||||
if ((wdc->sc_flags & WDCF_ACTIVE) == 0)
|
||||
return 0;
|
||||
|
||||
bp = wdc->sc_q.b_forw->b_actf;
|
||||
wd = wdcd.cd_devs[WDUNIT(bp->b_dev)];
|
||||
wdc->sc_timeout = 0;
|
||||
|
||||
|
||||
wd = wdc->sc_drives.tqh_first;
|
||||
bp = wd->sc_q.b_actf;
|
||||
|
||||
#ifdef WDDEBUG
|
||||
printf("I%d ", ctrlr);
|
||||
#endif
|
||||
@ -734,6 +721,9 @@ wdcintr(wdc)
|
||||
wdcstart(wdc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
wdc->sc_flags &= ~WDCF_ACTIVE;
|
||||
wdc->sc_timeout = 0;
|
||||
|
||||
/* Have we an error? */
|
||||
if (wdc->sc_status & (WDCS_ERR | WDCS_ECCCOR)) {
|
||||
@ -755,7 +745,7 @@ wdcintr(wdc)
|
||||
|
||||
/* Error or error correction? */
|
||||
if (wdc->sc_status & WDCS_ERR) {
|
||||
if (++wdc->sc_q.b_errcnt >= WDIORETRIES) {
|
||||
if (++wdc->sc_errors >= WDIORETRIES) {
|
||||
wderror(wd, bp, "hard error");
|
||||
bp->b_error = EIO;
|
||||
bp->b_flags |= B_ERROR; /* Flag the error. */
|
||||
@ -782,9 +772,9 @@ wdcintr(wdc)
|
||||
}
|
||||
|
||||
/* If we encountered any abnormalities, flag it as a soft error. */
|
||||
if (wdc->sc_q.b_errcnt) {
|
||||
if (wdc->sc_errors) {
|
||||
wderror(wd, bp, "soft error");
|
||||
wdc->sc_q.b_errcnt = 0;
|
||||
wdc->sc_errors = 0;
|
||||
}
|
||||
|
||||
/* Ready for the next block, if any. */
|
||||
@ -970,7 +960,7 @@ wdcontrol(wd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
wdc->sc_q.b_errcnt = 0;
|
||||
wdc->sc_errors = 0;
|
||||
wd->sc_state = OPEN;
|
||||
/*
|
||||
* The rest of the initialization can be done by normal means.
|
||||
@ -1498,7 +1488,6 @@ wdcrestart(wdc)
|
||||
{
|
||||
int s = splbio();
|
||||
|
||||
wdc->sc_q.b_active = 0;
|
||||
wdcstart(wdc);
|
||||
splx(s);
|
||||
}
|
||||
@ -1529,7 +1518,7 @@ wdcunwedge(wdc)
|
||||
}
|
||||
|
||||
wdc->sc_flags |= WDCF_ERROR;
|
||||
++wdc->sc_q.b_errcnt;
|
||||
++wdc->sc_errors;
|
||||
|
||||
/* Wake up in a little bit and restart the operation. */
|
||||
timeout((timeout_t)wdcrestart, (caddr_t)wdc, RECOVERYTIME);
|
||||
|
121
sys/dev/isa/wd.c
121
sys/dev/isa/wd.c
@ -35,7 +35,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)wd.c 7.2 (Berkeley) 5/9/91
|
||||
* $Id: wd.c,v 1.77 1994/04/09 03:43:36 mycroft Exp $
|
||||
* $Id: wd.c,v 1.78 1994/04/20 07:23:54 mycroft Exp $
|
||||
*/
|
||||
|
||||
#define INSTRUMENT /* instrumentation stuff by Brad Parker */
|
||||
@ -122,6 +122,7 @@ struct wd_softc {
|
||||
#define WDF_BSDLABEL 0x00010 /* has a BSD disk label */
|
||||
#define WDF_BADSECT 0x00020 /* has a bad144 badsector table */
|
||||
#define WDF_WRITEPROT 0x00040 /* manual unit write protect */
|
||||
TAILQ_ENTRY(wd_softc) sc_drivechain;
|
||||
struct buf sc_q;
|
||||
struct wdparams sc_params; /* ESDI/IDE drive/controller parameters */
|
||||
struct disklabel sc_label; /* device configuration data */
|
||||
@ -133,14 +134,16 @@ struct wdc_softc {
|
||||
struct device sc_dev;
|
||||
struct intrhand sc_ih;
|
||||
|
||||
struct buf sc_q;
|
||||
u_char sc_flags;
|
||||
#define WDCF_ACTIVE 0x00001 /* controller is active */
|
||||
#define WDCF_SINGLE 0x00004 /* sector at a time mode */
|
||||
#define WDCF_ERROR 0x00008 /* processing a disk error */
|
||||
u_char sc_status; /* copy of status register */
|
||||
u_char sc_error; /* copy of error register */
|
||||
u_short sc_iobase; /* i/o port base */
|
||||
int sc_timeout; /* timeout counter */
|
||||
int sc_errors; /* count of errors during current transfer */
|
||||
TAILQ_HEAD(drivehead, wd_softc) sc_drives;
|
||||
};
|
||||
|
||||
int wdcprobe(), wdprobe(), wdcintr();
|
||||
@ -254,6 +257,7 @@ wdcattach(parent, self, aux)
|
||||
for (wa.wa_drive = 0; wa.wa_drive < 2; wa.wa_drive++)
|
||||
(void)config_found(self, &wa, wdprint);
|
||||
|
||||
TAILQ_INIT(&wdc->sc_drives);
|
||||
wdctimeout(wdc);
|
||||
wdc->sc_ih.ih_fun = wdcintr;
|
||||
wdc->sc_ih.ih_arg = wdc;
|
||||
@ -333,7 +337,6 @@ void
|
||||
wdstrategy(bp)
|
||||
struct buf *bp;
|
||||
{
|
||||
struct buf *dp;
|
||||
struct wd_softc *wd; /* disk unit to do the IO */
|
||||
struct wdc_softc *wdc;
|
||||
int lunit = WDUNIT(bp->b_dev);
|
||||
@ -371,14 +374,16 @@ wdstrategy(bp)
|
||||
bp->b_cylin = 0;
|
||||
|
||||
/* Queue transfer on drive, activate drive and controller if idle. */
|
||||
dp = &wd->sc_q;
|
||||
s = splbio();
|
||||
wddisksort(dp, bp);
|
||||
if (dp->b_active == 0)
|
||||
wddisksort(&wd->sc_q, bp);
|
||||
if (!wd->sc_q.b_active)
|
||||
wdstart(wd); /* Start drive. */
|
||||
wdc = (void *)wd->sc_dev.dv_parent;
|
||||
if (wdc->sc_q.b_active == 0)
|
||||
wdcstart(wdc); /* Start controller. */
|
||||
#ifdef DIAGNOSTIC
|
||||
else if ((wdc->sc_flags & WDCF_ACTIVE) == 0) {
|
||||
printf("wdstrategy: controller inactive\n");
|
||||
wdcstart(wdc);
|
||||
}
|
||||
#endif
|
||||
splx(s);
|
||||
return;
|
||||
|
||||
@ -410,29 +415,16 @@ static void
|
||||
wdstart(wd)
|
||||
struct wd_softc *wd;
|
||||
{
|
||||
struct buf *dp;
|
||||
struct wdc_softc *wdc;
|
||||
struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
|
||||
int active = wdc->sc_drives.tqh_first != 0;
|
||||
|
||||
dp = &wd->sc_q;
|
||||
|
||||
/* Unit already active? */
|
||||
if (dp->b_active)
|
||||
return;
|
||||
/* Anything to start? */
|
||||
if (dp->b_actf == NULL)
|
||||
return;
|
||||
|
||||
/* Link onto controller queue. */
|
||||
dp->b_forw = NULL;
|
||||
wdc = (void *)wd->sc_dev.dv_parent;
|
||||
if (wdc->sc_q.b_forw == NULL)
|
||||
wdc->sc_q.b_forw = dp;
|
||||
else
|
||||
wdc->sc_q.b_actl->b_forw = dp;
|
||||
wdc->sc_q.b_actl = dp;
|
||||
wd->sc_q.b_active = 1;
|
||||
TAILQ_INSERT_TAIL(&wdc->sc_drives, wd, sc_drivechain);
|
||||
|
||||
/* Mark the drive unit as busy. */
|
||||
dp->b_active = 1;
|
||||
/* If controller not already active, start it. */
|
||||
if (!active)
|
||||
wdcstart(wdc);
|
||||
}
|
||||
|
||||
void
|
||||
@ -446,22 +438,26 @@ wdfinish(wd, bp)
|
||||
dk_busy &= ~(1 << wd->sc_drive);
|
||||
#endif
|
||||
wdc->sc_flags &= ~(WDCF_SINGLE | WDCF_ERROR);
|
||||
wdc->sc_q.b_errcnt = 0;
|
||||
wdc->sc_errors = 0;
|
||||
/*
|
||||
* If this is the only buf or the last buf in the transfer (taking into
|
||||
* account any residual, in case we erred)...
|
||||
*/
|
||||
wd->sc_mbcount -= wd->sc_bcount;
|
||||
if (wd->sc_mbcount == 0) {
|
||||
wd->sc_mskip = 0;
|
||||
/*
|
||||
* ...then move this drive to the end of the queue to give
|
||||
* others a `fair' chance.
|
||||
*/
|
||||
wdc->sc_q.b_forw = wd->sc_q.b_forw;
|
||||
wd->sc_mskip = 0;
|
||||
wd->sc_q.b_active = 0;
|
||||
if (wd->sc_q.b_actf)
|
||||
wdstart(wd);
|
||||
if (wd->sc_drivechain.tqe_next) {
|
||||
TAILQ_REMOVE(&wdc->sc_drives, wd, sc_drivechain);
|
||||
if (bp->b_actf) {
|
||||
TAILQ_INSERT_TAIL(&wdc->sc_drives, wd,
|
||||
sc_drivechain);
|
||||
} else
|
||||
wd->sc_q.b_active = 0;
|
||||
}
|
||||
}
|
||||
bp->b_resid = wd->sc_bcount;
|
||||
bp->b_flags &= ~B_XXX;
|
||||
@ -484,42 +480,34 @@ wdcstart(wdc)
|
||||
struct wd_softc *wd; /* disk unit for IO */
|
||||
struct buf *bp;
|
||||
struct disklabel *lp;
|
||||
struct buf *dp;
|
||||
long blknum, cylin, head, sector;
|
||||
long secpertrk, secpercyl;
|
||||
int xfrblknum;
|
||||
int lunit;
|
||||
|
||||
loop:
|
||||
/* Is there a drive for the controller to do a transfer with? */
|
||||
dp = wdc->sc_q.b_forw;
|
||||
if (dp == NULL) {
|
||||
wdc->sc_q.b_active = 0;
|
||||
wd = wdc->sc_drives.tqh_first;
|
||||
if (wd == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Is there a transfer to this drive? If not, deactivate drive. */
|
||||
bp = dp->b_actf;
|
||||
bp = wd->sc_q.b_actf;
|
||||
if (bp == NULL) {
|
||||
dp->b_active = 0;
|
||||
wdc->sc_q.b_forw = dp->b_forw;
|
||||
TAILQ_REMOVE(&wdc->sc_drives, wd, sc_drivechain);
|
||||
wd->sc_q.b_active = 0;
|
||||
goto loop;
|
||||
}
|
||||
|
||||
/* Obtain controller and drive information */
|
||||
lunit = WDUNIT(bp->b_dev);
|
||||
wd = wdcd.cd_devs[lunit];
|
||||
|
||||
if (wdc->sc_q.b_errcnt >= WDIORETRIES) {
|
||||
if (wdc->sc_errors >= WDIORETRIES) {
|
||||
wderror(wd, bp, "hard error");
|
||||
bp->b_error = EIO;
|
||||
bp->b_flags |= B_ERROR;
|
||||
wdfinish(wd, bp);
|
||||
goto loop;
|
||||
}
|
||||
|
||||
/* Mark controller active and set a timeout. */
|
||||
wdc->sc_q.b_active = 1;
|
||||
|
||||
/* Mark the controller active and set a timeout. */
|
||||
wdc->sc_flags |= WDCF_ACTIVE;
|
||||
wdc->sc_timeout = 4;
|
||||
|
||||
/* Do control operations specially. */
|
||||
@ -551,7 +539,7 @@ loop:
|
||||
blknum = bp->b_blkno + wd->sc_skip;
|
||||
#ifdef WDDEBUG
|
||||
if (wd->sc_skip == 0)
|
||||
printf("\nwdcstart %d: %s %d@%d; map ", lunit,
|
||||
printf("\nwdcstart %s: %s %d@%d; map ", wd->sc_dev.dv_xname,
|
||||
(bp->b_flags & B_READ) ? "read" : "write", bp->b_bcount,
|
||||
blknum);
|
||||
else
|
||||
@ -680,7 +668,7 @@ loop:
|
||||
cylin, head, bp->b_un.b_addr, inb(wd->sc_iobase+wd_altsts));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* If this is a read operation, just go away until it's done. */
|
||||
if (bp->b_flags & B_READ)
|
||||
return;
|
||||
@ -712,13 +700,12 @@ wdcintr(wdc)
|
||||
/* Clear the pending interrupt. */
|
||||
(void) inb(wdc->sc_iobase+wd_status);
|
||||
|
||||
if (!wdc->sc_q.b_active)
|
||||
if ((wdc->sc_flags & WDCF_ACTIVE) == 0)
|
||||
return 0;
|
||||
|
||||
bp = wdc->sc_q.b_forw->b_actf;
|
||||
wd = wdcd.cd_devs[WDUNIT(bp->b_dev)];
|
||||
wdc->sc_timeout = 0;
|
||||
|
||||
|
||||
wd = wdc->sc_drives.tqh_first;
|
||||
bp = wd->sc_q.b_actf;
|
||||
|
||||
#ifdef WDDEBUG
|
||||
printf("I%d ", ctrlr);
|
||||
#endif
|
||||
@ -734,6 +721,9 @@ wdcintr(wdc)
|
||||
wdcstart(wdc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
wdc->sc_flags &= ~WDCF_ACTIVE;
|
||||
wdc->sc_timeout = 0;
|
||||
|
||||
/* Have we an error? */
|
||||
if (wdc->sc_status & (WDCS_ERR | WDCS_ECCCOR)) {
|
||||
@ -755,7 +745,7 @@ wdcintr(wdc)
|
||||
|
||||
/* Error or error correction? */
|
||||
if (wdc->sc_status & WDCS_ERR) {
|
||||
if (++wdc->sc_q.b_errcnt >= WDIORETRIES) {
|
||||
if (++wdc->sc_errors >= WDIORETRIES) {
|
||||
wderror(wd, bp, "hard error");
|
||||
bp->b_error = EIO;
|
||||
bp->b_flags |= B_ERROR; /* Flag the error. */
|
||||
@ -782,9 +772,9 @@ wdcintr(wdc)
|
||||
}
|
||||
|
||||
/* If we encountered any abnormalities, flag it as a soft error. */
|
||||
if (wdc->sc_q.b_errcnt) {
|
||||
if (wdc->sc_errors) {
|
||||
wderror(wd, bp, "soft error");
|
||||
wdc->sc_q.b_errcnt = 0;
|
||||
wdc->sc_errors = 0;
|
||||
}
|
||||
|
||||
/* Ready for the next block, if any. */
|
||||
@ -970,7 +960,7 @@ wdcontrol(wd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
wdc->sc_q.b_errcnt = 0;
|
||||
wdc->sc_errors = 0;
|
||||
wd->sc_state = OPEN;
|
||||
/*
|
||||
* The rest of the initialization can be done by normal means.
|
||||
@ -1498,7 +1488,6 @@ wdcrestart(wdc)
|
||||
{
|
||||
int s = splbio();
|
||||
|
||||
wdc->sc_q.b_active = 0;
|
||||
wdcstart(wdc);
|
||||
splx(s);
|
||||
}
|
||||
@ -1529,7 +1518,7 @@ wdcunwedge(wdc)
|
||||
}
|
||||
|
||||
wdc->sc_flags |= WDCF_ERROR;
|
||||
++wdc->sc_q.b_errcnt;
|
||||
++wdc->sc_errors;
|
||||
|
||||
/* Wake up in a little bit and restart the operation. */
|
||||
timeout((timeout_t)wdcrestart, (caddr_t)wdc, RECOVERYTIME);
|
||||
|
Loading…
Reference in New Issue
Block a user