diff options
-rw-r--r-- | sys/dev/fdc/fdc.c | 117 | ||||
-rw-r--r-- | sys/i386/isa/fd.c | 117 | ||||
-rw-r--r-- | sys/i386/isa/fdc.h | 3 | ||||
-rw-r--r-- | sys/isa/fd.c | 117 | ||||
-rw-r--r-- | sys/isa/fdc.h | 3 |
5 files changed, 187 insertions, 170 deletions
diff --git a/sys/dev/fdc/fdc.c b/sys/dev/fdc/fdc.c index f432e51..bf39b9b 100644 --- a/sys/dev/fdc/fdc.c +++ b/sys/dev/fdc/fdc.c @@ -1,4 +1,3 @@ - /* * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. @@ -44,7 +43,7 @@ * SUCH DAMAGE. * * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $Id: fd.c,v 1.118 1998/07/15 09:59:30 bde Exp $ + * $Id: fd.c,v 1.119 1998/07/18 03:15:33 bde Exp $ * */ @@ -241,7 +240,7 @@ static void fd_turnon(fdu_t); static void fdc_reset(fdc_p); static int fd_in(fdcu_t, int *); static void fdstart(fdcu_t); -static timeout_t fd_timeout; +static timeout_t fd_iotimeout; static timeout_t fd_pseudointr; static int fdstate(fdcu_t, fdc_p); static int retrier(fdcu_t); @@ -266,6 +265,7 @@ static int fifo_threshold = 8; /* XXX: should be accessible via sysctl */ #define RECALWAIT 9 #define MOTORWAIT 10 #define IOTIMEDOUT 11 +#define RESETCOMPLETE 12 #ifdef FDC_DEBUG static char const * const fdstates[] = @@ -281,7 +281,8 @@ static char const * const fdstates[] = "SEEKWAIT", "RECALWAIT", "MOTORWAIT", -"IOTIMEDOUT" +"IOTIMEDOUT", +"RESETCOMPLETE", }; /* CAUTION: fd_debug causes huge amounts of logging output */ @@ -1382,15 +1383,15 @@ fdstart(fdcu_t fdcu) } static void -fd_timeout(void *arg1) +fd_iotimeout(void *arg1) { - fdcu_t fdcu = (fdcu_t)arg1; - fdu_t fdu = fdc_data[fdcu].fdu; - int baseport = fdc_data[fdcu].baseport; - struct buf *bp; + fdc_p fdc; + fdcu_t fdcu; int s; - bp = bufq_first(&fdc_data[fdcu].head); + fdcu = (fdcu_t)arg1; + fdc = fdc_data + fdcu; + TRACE1("fd%d[fd_iotimeout()]", fdc->fdu); /* * Due to IBM's brain-dead design, the FDC has a faked ready @@ -1398,34 +1399,15 @@ fd_timeout(void *arg1) * issued if there's no diskette in the drive will _never_ * complete, and must be aborted by resetting the FDC. * Many thanks, Big Blue! + * The FDC must not be reset directly, since that would + * interfere with the state machine. Instead, pretend that + * the command completed but was invalid. The state machine + * will reset the FDC and retry once. */ - s = splbio(); - - TRACE1("fd%d[fd_timeout()]", fdu); - /* See if the controller is still busy (patiently awaiting data) */ - if(((inb(baseport + FDSTS)) & (NE7_CB|NE7_RQM)) == NE7_CB) - { - TRACE1("[FDSTS->0x%x]", inb(baseport + FDSTS)); - /* yup, it is; kill it now */ - fdc_reset(&fdc_data[fdcu]); - printf("fd%d: Operation timeout\n", fdu); - } - - if (bp) - { - retrier(fdcu); - fdc_data[fdcu].status[0] = NE7_ST0_IC_RC; - fdc_data[fdcu].state = IOTIMEDOUT; - if( fdc_data[fdcu].retry < 6) - fdc_data[fdcu].retry = 6; - } - else - { - fdc_data[fdcu].fd = (fd_p) 0; - fdc_data[fdcu].fdu = -1; - fdc_data[fdcu].state = DEVIDLE; - } + fdc->status[0] = NE7_ST0_IC_IV; + fdc->flags &= ~FDC_STAT_VALID; + fdc->state = IOTIMEDOUT; fdintr(fdcu); splx(s); } @@ -1470,7 +1452,7 @@ static int fdstate(fdcu_t fdcu, fdc_p fdc) { struct subdev *sd; - int read, format, head, sec = 0, sectrac, st0, cyl, st3; + int read, format, head, i, sec = 0, sectrac, st0, cyl, st3; unsigned blknum = 0, b_cylinder = 0; fdu_t fdu = fdc->fdu; fd_p fd; @@ -1557,7 +1539,11 @@ fdstate(fdcu_t fdcu, fdc_p fdc) { set_motor(fdcu, fd->fdsu, TURNON); } - fdc->state = DOSEEK; + if (fdc->flags & FDC_NEEDS_RESET) { + fdc->state = RESETCTLR; + fdc->flags &= ~FDC_NEEDS_RESET; + } else + fdc->state = DOSEEK; break; case DOSEEK: if (b_cylinder == (unsigned)fd->track) @@ -1669,6 +1655,9 @@ fdstate(fdcu_t fdcu, fdc_p fdc) if(fd_sense_drive_status(fdc, &st3) != 0) { /* stuck controller? */ + isa_dmadone(bp->b_flags, bp->b_data + fd->skip, + format ? bp->b_bcount : fdblk, + fdc->dmachan); fdc->retry = 6; /* reset the beast */ return(retrier(fdcu)); } @@ -1706,6 +1695,9 @@ fdstate(fdcu_t fdcu, fdc_p fdc) 0)) { /* controller fell over */ + isa_dmadone(bp->b_flags, bp->b_data + fd->skip, + format ? bp->b_bcount : fdblk, + fdc->dmachan); fdc->retry = 6; return(retrier(fdcu)); } @@ -1725,18 +1717,24 @@ fdstate(fdcu_t fdcu, fdc_p fdc) 0)) { /* the beast is sleeping again */ + isa_dmadone(bp->b_flags, bp->b_data + fd->skip, + format ? bp->b_bcount : fdblk, + fdc->dmachan); fdc->retry = 6; return(retrier(fdcu)); } } fdc->state = IOCOMPLETE; - fd->tohandle = timeout(fd_timeout, (caddr_t)fdcu, hz); + fd->tohandle = timeout(fd_iotimeout, (caddr_t)fdcu, hz); return(0); /* will return later */ case IOCOMPLETE: /* IO DONE, post-analyze */ - untimeout(fd_timeout, (caddr_t)fdcu, fd->tohandle); + untimeout(fd_iotimeout, (caddr_t)fdcu, fd->tohandle); if (fd_read_status(fdc, fd->fdsu)) { + isa_dmadone(bp->b_flags, bp->b_data + fd->skip, + format ? bp->b_bcount : fdblk, + fdc->dmachan); if (fdc->retry < 6) fdc->retry = 6; /* force a reset */ return retrier(fdcu); @@ -1747,7 +1745,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) /* FALLTHROUGH */ case IOTIMEDOUT: - isa_dmadone(bp->b_flags, bp->b_data+fd->skip, + isa_dmadone(bp->b_flags, bp->b_data + fd->skip, format ? bp->b_bcount : fdblk, fdc->dmachan); if (fdc->status[0] & NE7_ST0_IC) { @@ -1793,16 +1791,18 @@ fdstate(fdcu_t fdcu, fdc_p fdc) case RESETCTLR: fdc_reset(fdc); fdc->retry++; + fdc->state = RESETCOMPLETE; + return (0); + case RESETCOMPLETE: + /* + * Discard all the results from the reset so that they + * can't cause an unexpected interrupt later. + */ + for (i = 0; i < 4; i++) + (void)fd_sense_int(fdc, &st0, &cyl); fdc->state = STARTRECAL; - break; + /* Fall through. */ case STARTRECAL: - /* XXX clear the fdc results from the last reset, if any. */ - { - int i; - for (i = 0; i < 4; i++) - (void)fd_sense_int(fdc, &st0, &cyl); - } - if(fd_cmd(fdcu, 2, NE7CMD_RECAL, fdu, 0)) /* Recalibrate Function */ @@ -1854,12 +1854,17 @@ fdstate(fdcu_t fdcu, fdc_p fdc) { return(0); /* time's not up yet */ } - /* - * since the controller was off, it has lost its - * idea about the current track it were; thus, - * recalibrate the bastard - */ - fdc->state = STARTRECAL; + if (fdc->flags & FDC_NEEDS_RESET) { + fdc->state = RESETCTLR; + fdc->flags &= ~FDC_NEEDS_RESET; + } else { + /* + * If all motors were off, then the controller was + * reset, so it has lost track of the current + * cylinder. Recalibrate to handle this case. + */ + fdc->state = STARTRECAL; + } return(1); /* will return immediatly */ default: printf("fdc%d: Unexpected FD int->", fdcu); @@ -1959,9 +1964,9 @@ retrier(fdcu) fdc->fd->skip = 0; biodone(bp); fdc->state = FINDWORK; + fdc->flags |= FDC_NEEDS_RESET; fdc->fd = (fd_p) 0; fdc->fdu = -1; - /* XXX abort current command, if any. */ return(1); } fdc->retry++; diff --git a/sys/i386/isa/fd.c b/sys/i386/isa/fd.c index f432e51..bf39b9b 100644 --- a/sys/i386/isa/fd.c +++ b/sys/i386/isa/fd.c @@ -1,4 +1,3 @@ - /* * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. @@ -44,7 +43,7 @@ * SUCH DAMAGE. * * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $Id: fd.c,v 1.118 1998/07/15 09:59:30 bde Exp $ + * $Id: fd.c,v 1.119 1998/07/18 03:15:33 bde Exp $ * */ @@ -241,7 +240,7 @@ static void fd_turnon(fdu_t); static void fdc_reset(fdc_p); static int fd_in(fdcu_t, int *); static void fdstart(fdcu_t); -static timeout_t fd_timeout; +static timeout_t fd_iotimeout; static timeout_t fd_pseudointr; static int fdstate(fdcu_t, fdc_p); static int retrier(fdcu_t); @@ -266,6 +265,7 @@ static int fifo_threshold = 8; /* XXX: should be accessible via sysctl */ #define RECALWAIT 9 #define MOTORWAIT 10 #define IOTIMEDOUT 11 +#define RESETCOMPLETE 12 #ifdef FDC_DEBUG static char const * const fdstates[] = @@ -281,7 +281,8 @@ static char const * const fdstates[] = "SEEKWAIT", "RECALWAIT", "MOTORWAIT", -"IOTIMEDOUT" +"IOTIMEDOUT", +"RESETCOMPLETE", }; /* CAUTION: fd_debug causes huge amounts of logging output */ @@ -1382,15 +1383,15 @@ fdstart(fdcu_t fdcu) } static void -fd_timeout(void *arg1) +fd_iotimeout(void *arg1) { - fdcu_t fdcu = (fdcu_t)arg1; - fdu_t fdu = fdc_data[fdcu].fdu; - int baseport = fdc_data[fdcu].baseport; - struct buf *bp; + fdc_p fdc; + fdcu_t fdcu; int s; - bp = bufq_first(&fdc_data[fdcu].head); + fdcu = (fdcu_t)arg1; + fdc = fdc_data + fdcu; + TRACE1("fd%d[fd_iotimeout()]", fdc->fdu); /* * Due to IBM's brain-dead design, the FDC has a faked ready @@ -1398,34 +1399,15 @@ fd_timeout(void *arg1) * issued if there's no diskette in the drive will _never_ * complete, and must be aborted by resetting the FDC. * Many thanks, Big Blue! + * The FDC must not be reset directly, since that would + * interfere with the state machine. Instead, pretend that + * the command completed but was invalid. The state machine + * will reset the FDC and retry once. */ - s = splbio(); - - TRACE1("fd%d[fd_timeout()]", fdu); - /* See if the controller is still busy (patiently awaiting data) */ - if(((inb(baseport + FDSTS)) & (NE7_CB|NE7_RQM)) == NE7_CB) - { - TRACE1("[FDSTS->0x%x]", inb(baseport + FDSTS)); - /* yup, it is; kill it now */ - fdc_reset(&fdc_data[fdcu]); - printf("fd%d: Operation timeout\n", fdu); - } - - if (bp) - { - retrier(fdcu); - fdc_data[fdcu].status[0] = NE7_ST0_IC_RC; - fdc_data[fdcu].state = IOTIMEDOUT; - if( fdc_data[fdcu].retry < 6) - fdc_data[fdcu].retry = 6; - } - else - { - fdc_data[fdcu].fd = (fd_p) 0; - fdc_data[fdcu].fdu = -1; - fdc_data[fdcu].state = DEVIDLE; - } + fdc->status[0] = NE7_ST0_IC_IV; + fdc->flags &= ~FDC_STAT_VALID; + fdc->state = IOTIMEDOUT; fdintr(fdcu); splx(s); } @@ -1470,7 +1452,7 @@ static int fdstate(fdcu_t fdcu, fdc_p fdc) { struct subdev *sd; - int read, format, head, sec = 0, sectrac, st0, cyl, st3; + int read, format, head, i, sec = 0, sectrac, st0, cyl, st3; unsigned blknum = 0, b_cylinder = 0; fdu_t fdu = fdc->fdu; fd_p fd; @@ -1557,7 +1539,11 @@ fdstate(fdcu_t fdcu, fdc_p fdc) { set_motor(fdcu, fd->fdsu, TURNON); } - fdc->state = DOSEEK; + if (fdc->flags & FDC_NEEDS_RESET) { + fdc->state = RESETCTLR; + fdc->flags &= ~FDC_NEEDS_RESET; + } else + fdc->state = DOSEEK; break; case DOSEEK: if (b_cylinder == (unsigned)fd->track) @@ -1669,6 +1655,9 @@ fdstate(fdcu_t fdcu, fdc_p fdc) if(fd_sense_drive_status(fdc, &st3) != 0) { /* stuck controller? */ + isa_dmadone(bp->b_flags, bp->b_data + fd->skip, + format ? bp->b_bcount : fdblk, + fdc->dmachan); fdc->retry = 6; /* reset the beast */ return(retrier(fdcu)); } @@ -1706,6 +1695,9 @@ fdstate(fdcu_t fdcu, fdc_p fdc) 0)) { /* controller fell over */ + isa_dmadone(bp->b_flags, bp->b_data + fd->skip, + format ? bp->b_bcount : fdblk, + fdc->dmachan); fdc->retry = 6; return(retrier(fdcu)); } @@ -1725,18 +1717,24 @@ fdstate(fdcu_t fdcu, fdc_p fdc) 0)) { /* the beast is sleeping again */ + isa_dmadone(bp->b_flags, bp->b_data + fd->skip, + format ? bp->b_bcount : fdblk, + fdc->dmachan); fdc->retry = 6; return(retrier(fdcu)); } } fdc->state = IOCOMPLETE; - fd->tohandle = timeout(fd_timeout, (caddr_t)fdcu, hz); + fd->tohandle = timeout(fd_iotimeout, (caddr_t)fdcu, hz); return(0); /* will return later */ case IOCOMPLETE: /* IO DONE, post-analyze */ - untimeout(fd_timeout, (caddr_t)fdcu, fd->tohandle); + untimeout(fd_iotimeout, (caddr_t)fdcu, fd->tohandle); if (fd_read_status(fdc, fd->fdsu)) { + isa_dmadone(bp->b_flags, bp->b_data + fd->skip, + format ? bp->b_bcount : fdblk, + fdc->dmachan); if (fdc->retry < 6) fdc->retry = 6; /* force a reset */ return retrier(fdcu); @@ -1747,7 +1745,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) /* FALLTHROUGH */ case IOTIMEDOUT: - isa_dmadone(bp->b_flags, bp->b_data+fd->skip, + isa_dmadone(bp->b_flags, bp->b_data + fd->skip, format ? bp->b_bcount : fdblk, fdc->dmachan); if (fdc->status[0] & NE7_ST0_IC) { @@ -1793,16 +1791,18 @@ fdstate(fdcu_t fdcu, fdc_p fdc) case RESETCTLR: fdc_reset(fdc); fdc->retry++; + fdc->state = RESETCOMPLETE; + return (0); + case RESETCOMPLETE: + /* + * Discard all the results from the reset so that they + * can't cause an unexpected interrupt later. + */ + for (i = 0; i < 4; i++) + (void)fd_sense_int(fdc, &st0, &cyl); fdc->state = STARTRECAL; - break; + /* Fall through. */ case STARTRECAL: - /* XXX clear the fdc results from the last reset, if any. */ - { - int i; - for (i = 0; i < 4; i++) - (void)fd_sense_int(fdc, &st0, &cyl); - } - if(fd_cmd(fdcu, 2, NE7CMD_RECAL, fdu, 0)) /* Recalibrate Function */ @@ -1854,12 +1854,17 @@ fdstate(fdcu_t fdcu, fdc_p fdc) { return(0); /* time's not up yet */ } - /* - * since the controller was off, it has lost its - * idea about the current track it were; thus, - * recalibrate the bastard - */ - fdc->state = STARTRECAL; + if (fdc->flags & FDC_NEEDS_RESET) { + fdc->state = RESETCTLR; + fdc->flags &= ~FDC_NEEDS_RESET; + } else { + /* + * If all motors were off, then the controller was + * reset, so it has lost track of the current + * cylinder. Recalibrate to handle this case. + */ + fdc->state = STARTRECAL; + } return(1); /* will return immediatly */ default: printf("fdc%d: Unexpected FD int->", fdcu); @@ -1959,9 +1964,9 @@ retrier(fdcu) fdc->fd->skip = 0; biodone(bp); fdc->state = FINDWORK; + fdc->flags |= FDC_NEEDS_RESET; fdc->fd = (fd_p) 0; fdc->fdu = -1; - /* XXX abort current command, if any. */ return(1); } fdc->retry++; diff --git a/sys/i386/isa/fdc.h b/sys/i386/isa/fdc.h index 8524123..fdaf694 100644 --- a/sys/i386/isa/fdc.h +++ b/sys/i386/isa/fdc.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $Id: fdc.h,v 1.9 1997/09/17 20:16:16 tegge Exp $ + * $Id: fdc.h,v 1.10 1998/07/11 06:35:39 bde Exp $ * */ @@ -55,6 +55,7 @@ struct fdc_data #define FDC_TAPE_BUSY 0x04 #define FDC_STAT_VALID 0x08 #define FDC_HAS_FIFO 0x10 +#define FDC_NEEDS_RESET 0x20 struct fd_data *fd; int fdu; /* the active drive */ int state; diff --git a/sys/isa/fd.c b/sys/isa/fd.c index f432e51..bf39b9b 100644 --- a/sys/isa/fd.c +++ b/sys/isa/fd.c @@ -1,4 +1,3 @@ - /* * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. @@ -44,7 +43,7 @@ * SUCH DAMAGE. * * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $Id: fd.c,v 1.118 1998/07/15 09:59:30 bde Exp $ + * $Id: fd.c,v 1.119 1998/07/18 03:15:33 bde Exp $ * */ @@ -241,7 +240,7 @@ static void fd_turnon(fdu_t); static void fdc_reset(fdc_p); static int fd_in(fdcu_t, int *); static void fdstart(fdcu_t); -static timeout_t fd_timeout; +static timeout_t fd_iotimeout; static timeout_t fd_pseudointr; static int fdstate(fdcu_t, fdc_p); static int retrier(fdcu_t); @@ -266,6 +265,7 @@ static int fifo_threshold = 8; /* XXX: should be accessible via sysctl */ #define RECALWAIT 9 #define MOTORWAIT 10 #define IOTIMEDOUT 11 +#define RESETCOMPLETE 12 #ifdef FDC_DEBUG static char const * const fdstates[] = @@ -281,7 +281,8 @@ static char const * const fdstates[] = "SEEKWAIT", "RECALWAIT", "MOTORWAIT", -"IOTIMEDOUT" +"IOTIMEDOUT", +"RESETCOMPLETE", }; /* CAUTION: fd_debug causes huge amounts of logging output */ @@ -1382,15 +1383,15 @@ fdstart(fdcu_t fdcu) } static void -fd_timeout(void *arg1) +fd_iotimeout(void *arg1) { - fdcu_t fdcu = (fdcu_t)arg1; - fdu_t fdu = fdc_data[fdcu].fdu; - int baseport = fdc_data[fdcu].baseport; - struct buf *bp; + fdc_p fdc; + fdcu_t fdcu; int s; - bp = bufq_first(&fdc_data[fdcu].head); + fdcu = (fdcu_t)arg1; + fdc = fdc_data + fdcu; + TRACE1("fd%d[fd_iotimeout()]", fdc->fdu); /* * Due to IBM's brain-dead design, the FDC has a faked ready @@ -1398,34 +1399,15 @@ fd_timeout(void *arg1) * issued if there's no diskette in the drive will _never_ * complete, and must be aborted by resetting the FDC. * Many thanks, Big Blue! + * The FDC must not be reset directly, since that would + * interfere with the state machine. Instead, pretend that + * the command completed but was invalid. The state machine + * will reset the FDC and retry once. */ - s = splbio(); - - TRACE1("fd%d[fd_timeout()]", fdu); - /* See if the controller is still busy (patiently awaiting data) */ - if(((inb(baseport + FDSTS)) & (NE7_CB|NE7_RQM)) == NE7_CB) - { - TRACE1("[FDSTS->0x%x]", inb(baseport + FDSTS)); - /* yup, it is; kill it now */ - fdc_reset(&fdc_data[fdcu]); - printf("fd%d: Operation timeout\n", fdu); - } - - if (bp) - { - retrier(fdcu); - fdc_data[fdcu].status[0] = NE7_ST0_IC_RC; - fdc_data[fdcu].state = IOTIMEDOUT; - if( fdc_data[fdcu].retry < 6) - fdc_data[fdcu].retry = 6; - } - else - { - fdc_data[fdcu].fd = (fd_p) 0; - fdc_data[fdcu].fdu = -1; - fdc_data[fdcu].state = DEVIDLE; - } + fdc->status[0] = NE7_ST0_IC_IV; + fdc->flags &= ~FDC_STAT_VALID; + fdc->state = IOTIMEDOUT; fdintr(fdcu); splx(s); } @@ -1470,7 +1452,7 @@ static int fdstate(fdcu_t fdcu, fdc_p fdc) { struct subdev *sd; - int read, format, head, sec = 0, sectrac, st0, cyl, st3; + int read, format, head, i, sec = 0, sectrac, st0, cyl, st3; unsigned blknum = 0, b_cylinder = 0; fdu_t fdu = fdc->fdu; fd_p fd; @@ -1557,7 +1539,11 @@ fdstate(fdcu_t fdcu, fdc_p fdc) { set_motor(fdcu, fd->fdsu, TURNON); } - fdc->state = DOSEEK; + if (fdc->flags & FDC_NEEDS_RESET) { + fdc->state = RESETCTLR; + fdc->flags &= ~FDC_NEEDS_RESET; + } else + fdc->state = DOSEEK; break; case DOSEEK: if (b_cylinder == (unsigned)fd->track) @@ -1669,6 +1655,9 @@ fdstate(fdcu_t fdcu, fdc_p fdc) if(fd_sense_drive_status(fdc, &st3) != 0) { /* stuck controller? */ + isa_dmadone(bp->b_flags, bp->b_data + fd->skip, + format ? bp->b_bcount : fdblk, + fdc->dmachan); fdc->retry = 6; /* reset the beast */ return(retrier(fdcu)); } @@ -1706,6 +1695,9 @@ fdstate(fdcu_t fdcu, fdc_p fdc) 0)) { /* controller fell over */ + isa_dmadone(bp->b_flags, bp->b_data + fd->skip, + format ? bp->b_bcount : fdblk, + fdc->dmachan); fdc->retry = 6; return(retrier(fdcu)); } @@ -1725,18 +1717,24 @@ fdstate(fdcu_t fdcu, fdc_p fdc) 0)) { /* the beast is sleeping again */ + isa_dmadone(bp->b_flags, bp->b_data + fd->skip, + format ? bp->b_bcount : fdblk, + fdc->dmachan); fdc->retry = 6; return(retrier(fdcu)); } } fdc->state = IOCOMPLETE; - fd->tohandle = timeout(fd_timeout, (caddr_t)fdcu, hz); + fd->tohandle = timeout(fd_iotimeout, (caddr_t)fdcu, hz); return(0); /* will return later */ case IOCOMPLETE: /* IO DONE, post-analyze */ - untimeout(fd_timeout, (caddr_t)fdcu, fd->tohandle); + untimeout(fd_iotimeout, (caddr_t)fdcu, fd->tohandle); if (fd_read_status(fdc, fd->fdsu)) { + isa_dmadone(bp->b_flags, bp->b_data + fd->skip, + format ? bp->b_bcount : fdblk, + fdc->dmachan); if (fdc->retry < 6) fdc->retry = 6; /* force a reset */ return retrier(fdcu); @@ -1747,7 +1745,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) /* FALLTHROUGH */ case IOTIMEDOUT: - isa_dmadone(bp->b_flags, bp->b_data+fd->skip, + isa_dmadone(bp->b_flags, bp->b_data + fd->skip, format ? bp->b_bcount : fdblk, fdc->dmachan); if (fdc->status[0] & NE7_ST0_IC) { @@ -1793,16 +1791,18 @@ fdstate(fdcu_t fdcu, fdc_p fdc) case RESETCTLR: fdc_reset(fdc); fdc->retry++; + fdc->state = RESETCOMPLETE; + return (0); + case RESETCOMPLETE: + /* + * Discard all the results from the reset so that they + * can't cause an unexpected interrupt later. + */ + for (i = 0; i < 4; i++) + (void)fd_sense_int(fdc, &st0, &cyl); fdc->state = STARTRECAL; - break; + /* Fall through. */ case STARTRECAL: - /* XXX clear the fdc results from the last reset, if any. */ - { - int i; - for (i = 0; i < 4; i++) - (void)fd_sense_int(fdc, &st0, &cyl); - } - if(fd_cmd(fdcu, 2, NE7CMD_RECAL, fdu, 0)) /* Recalibrate Function */ @@ -1854,12 +1854,17 @@ fdstate(fdcu_t fdcu, fdc_p fdc) { return(0); /* time's not up yet */ } - /* - * since the controller was off, it has lost its - * idea about the current track it were; thus, - * recalibrate the bastard - */ - fdc->state = STARTRECAL; + if (fdc->flags & FDC_NEEDS_RESET) { + fdc->state = RESETCTLR; + fdc->flags &= ~FDC_NEEDS_RESET; + } else { + /* + * If all motors were off, then the controller was + * reset, so it has lost track of the current + * cylinder. Recalibrate to handle this case. + */ + fdc->state = STARTRECAL; + } return(1); /* will return immediatly */ default: printf("fdc%d: Unexpected FD int->", fdcu); @@ -1959,9 +1964,9 @@ retrier(fdcu) fdc->fd->skip = 0; biodone(bp); fdc->state = FINDWORK; + fdc->flags |= FDC_NEEDS_RESET; fdc->fd = (fd_p) 0; fdc->fdu = -1; - /* XXX abort current command, if any. */ return(1); } fdc->retry++; diff --git a/sys/isa/fdc.h b/sys/isa/fdc.h index 8524123..fdaf694 100644 --- a/sys/isa/fdc.h +++ b/sys/isa/fdc.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $Id: fdc.h,v 1.9 1997/09/17 20:16:16 tegge Exp $ + * $Id: fdc.h,v 1.10 1998/07/11 06:35:39 bde Exp $ * */ @@ -55,6 +55,7 @@ struct fdc_data #define FDC_TAPE_BUSY 0x04 #define FDC_STAT_VALID 0x08 #define FDC_HAS_FIFO 0x10 +#define FDC_NEEDS_RESET 0x20 struct fd_data *fd; int fdu; /* the active drive */ int state; |