diff options
Diffstat (limited to 'sys/isa/fd.c')
-rw-r--r-- | sys/isa/fd.c | 977 |
1 files changed, 0 insertions, 977 deletions
diff --git a/sys/isa/fd.c b/sys/isa/fd.c deleted file mode 100644 index c287ef1..0000000 --- a/sys/isa/fd.c +++ /dev/null @@ -1,977 +0,0 @@ -/*#define DEBUG 1*/ -/*- - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Don Ahn. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $Id: fd.c,v 1.5 1993/09/15 23:27:45 rgrimes Exp $ - * - */ - -#include "fd.h" -#if NFD > 0 - -#include "param.h" -#include "dkbad.h" -#include "systm.h" -#include "conf.h" -#include "file.h" -#include "ioctl.h" -#include "disklabel.h" -#include "buf.h" -#include "uio.h" -#include "syslog.h" -#include "i386/isa/isa.h" -#include "i386/isa/isa_device.h" -#include "i386/isa/fdreg.h" -#include "i386/isa/icu.h" -#include "i386/isa/rtc.h" -#undef NFD -#define NFD 2 - -#define FDUNIT(s) ((s>>3)&1) -#define FDTYPE(s) ((s)&7) - -#define b_cylin b_resid -#define FDBLK 512 -#define NUMTYPES 4 - -struct fd_type { - int sectrac; /* sectors per track */ - int secsize; /* size code for sectors */ - int datalen; /* data len when secsize = 0 */ - int gap; /* gap len between sectors */ - int tracks; /* total num of tracks */ - int size; /* size of disk in sectors */ - int steptrac; /* steps per cylinder */ - int trans; /* transfer speed code */ - int heads; /* number of heads */ -}; - -struct fd_type fd_types[NUMTYPES] = -{ - { 18,2,0xFF,0x1B,80,2880,1,0,2 }, /* 1.44 meg HD 3.5in floppy */ - { 15,2,0xFF,0x1B,80,2400,1,0,2 }, /* 1.2 meg HD floppy */ - { 9,2,0xFF,0x23,40,720,2,1,2 }, /* 360k floppy in 1.2meg drive */ - { 9,2,0xFF,0x2A,40,720,1,1,2 }, /* 360k floppy in DD drive */ -}; - -#define DRVS_PER_CTLR 2 -/***********************************************************************\ -* Per controller structure. * -\***********************************************************************/ -struct fdc_data -{ - int fdcu; /* our unit number */ - int baseport; - int dmachan; - int flags; -#define FDC_ATTACHED 0x01 - struct fd_data *fd; - int fdu; /* the active drive */ - struct buf head; /* Head of buf chain */ - struct buf rhead; /* Raw head of buf chain */ - int state; - int retry; - int status[7]; /* copy of the registers */ -}fdc_data[(NFD+1)/DRVS_PER_CTLR]; - -/***********************************************************************\ -* Per drive structure. * -* N per controller (presently 2) (DRVS_PER_CTLR) * -\***********************************************************************/ -struct fd_data { - struct fdc_data *fdc; - int fdu; /* this unit number */ - int fdsu; /* this units number on this controller */ - int type; /* Drive type (HD, DD */ - struct fd_type *ft; /* pointer to the type descriptor */ - int flags; -#define FD_OPEN 0x01 /* it's open */ -#define FD_ACTIVE 0x02 /* it's active */ -#define FD_MOTOR 0x04 /* motor should be on */ -#define FD_MOTOR_WAIT 0x08 /* motor coming up */ - int skip; - int hddrv; - int track; /* where we think the head is */ -} fd_data[NFD]; - -/***********************************************************************\ -* Throughout this file the following conventions will be used: * -* fd is a pointer to the fd_data struct for the drive in question * -* fdc is a pointer to the fdc_data struct for the controller * -* fdu is the floppy drive unit number * -* fdcu is the floppy controller unit number * -* fdsu is the floppy drive unit number on that controller. (sub-unit) * -\***********************************************************************/ -typedef int fdu_t; -typedef int fdcu_t; -typedef int fdsu_t; -typedef struct fd_data *fd_p; -typedef struct fdc_data *fdc_p; - -#define DEVIDLE 0 -#define FINDWORK 1 -#define DOSEEK 2 -#define SEEKCOMPLETE 3 -#define IOCOMPLETE 4 -#define RECALCOMPLETE 5 -#define STARTRECAL 6 -#define RESETCTLR 7 -#define SEEKWAIT 8 -#define RECALWAIT 9 -#define MOTORWAIT 10 -#define IOTIMEDOUT 11 - -#ifdef DEBUG -char *fdstates[] = -{ -"DEVIDLE", -"FINDWORK", -"DOSEEK", -"SEEKCOMPLETE", -"IOCOMPLETE", -"RECALCOMPLETE", -"STARTRECAL", -"RESETCTLR", -"SEEKWAIT", -"RECALWAIT", -"MOTORWAIT", -"IOTIMEDOUT" -}; - - -int fd_debug = 1; -#define TRACE0(arg) if(fd_debug) printf(arg) -#define TRACE1(arg1,arg2) if(fd_debug) printf(arg1,arg2) -#else DEBUG -#define TRACE0(arg) -#define TRACE1(arg1,arg2) -#endif DEBUG - -extern int hz; -/* state needed for current transfer */ - -/****************************************************************************/ -/* autoconfiguration stuff */ -/****************************************************************************/ -int fdprobe(), fdattach(), fd_turnoff(); - -struct isa_driver fddriver = { - fdprobe, fdattach, "fd", -}; - -/* - * probe for existance of controller - */ -fdprobe(dev) -struct isa_device *dev; -{ - fdcu_t fdcu = dev->id_unit; - if(fdc_data[fdcu].flags & FDC_ATTACHED) - { - printf("fdc: same unit (%d) used multiple times\n",fdcu); - return 0; - } - - fdc_data[fdcu].baseport = dev->id_iobase; - - /* see if it can handle a command */ - if (out_fdc(fdcu,NE7CMD_SPECIFY) < 0) - { - return(0); - } - out_fdc(fdcu,0xDF); - out_fdc(fdcu,2); - return (IO_FDCSIZE); -} - -/* - * wire controller into system, look for floppy units - */ -fdattach(dev) -struct isa_device *dev; -{ - unsigned fdt,st0, cyl; - int hdr; - fdu_t fdu; - fdcu_t fdcu = dev->id_unit; - fdc_p fdc = fdc_data + fdcu; - fd_p fd; - int fdsu; - - fdc->fdcu = fdcu; - fdc->flags |= FDC_ATTACHED; - fdc->dmachan = dev->id_drq; - fdc->state = DEVIDLE; - - fdt = rtcin(RTC_FDISKETTE); - hdr = 0; - - /* check for each floppy drive */ - for (fdu = (fdcu * DRVS_PER_CTLR),fdsu = 0; - ((fdu < NFD) && (fdsu < DRVS_PER_CTLR)); - fdu++,fdsu++) - { - /* is there a unit? */ - if ((fdt & 0xf0) == RTCFDT_NONE) { -#define NO_TYPE NUMTYPES - fd_data[fdu].type = NO_TYPE; - continue; - } - -#ifdef notyet - /* select it */ - fd_turnon1(fdu); - spinwait(1000); /* 1 sec */ - out_fdc(fdcu,NE7CMD_RECAL); /* Recalibrate Function */ - out_fdc(fdcu,fdsu); - spinwait(1000); /* 1 sec */ - - /* anything responding */ - out_fdc(fdcu,NE7CMD_SENSEI); - st0 = in_fdc(fdcu); - cyl = in_fdc(fdcu); - if (st0 & 0xd0) - continue; - -#endif - fd_data[fdu].track = -2; - fd_data[fdu].fdc = fdc; - fd_data[fdu].fdsu = fdsu; - printf("fd%d: unit %d type ", fdcu, fdu); - - if ((fdt & 0xf0) == RTCFDT_12M) { - printf("1.2MB 5.25in\n"); - fd_data[fdu].type = 1; - fd_data[fdu].ft = fd_types + 1; - - } - if ((fdt & 0xf0) == RTCFDT_144M) { - printf("1.44MB 3.5in\n"); - fd_data[fdu].type = 0; - fd_data[fdu].ft = fd_types + 0; - } - - fdt <<= 4; - fd_turnoff(fdu); - hdr = 1; - } - - /* Set transfer to 500kbps */ - outb(fdc->baseport+fdctl,0); /*XXX*/ -} - -int -fdsize(dev) -dev_t dev; -{ - return(0); -} - -/****************************************************************************/ -/* fdstrategy */ -/****************************************************************************/ -fdstrategy(bp) - register struct buf *bp; /* IO operation to perform */ -{ - register struct buf *dp,*dp0,*dp1; - long nblocks,blknum; - int s; - fdcu_t fdcu; - fdu_t fdu; - fdc_p fdc; - fd_p fd; - - fdu = FDUNIT(minor(bp->b_dev)); - fd = &fd_data[fdu]; - fdc = fd->fdc; - fdcu = fdc->fdcu; - /*type = FDTYPE(minor(bp->b_dev));*/ - - if ((fdu >= NFD) || (bp->b_blkno < 0)) { - printf("fdstrat: fdu = %d, blkno = %d, bcount = %d\n", - fdu, bp->b_blkno, bp->b_bcount); - pg("fd:error in fdstrategy"); - bp->b_error = EINVAL; - bp->b_flags |= B_ERROR; - goto bad; - } - /* - * Set up block calculations. - */ - blknum = (unsigned long) bp->b_blkno * DEV_BSIZE/FDBLK; - nblocks = fd->ft->size; - if (blknum + (bp->b_bcount / FDBLK) > nblocks) { - if (blknum == nblocks) { - bp->b_resid = bp->b_bcount; - } else { - bp->b_error = ENOSPC; - bp->b_flags |= B_ERROR; - } - goto bad; - } - bp->b_cylin = blknum / (fd->ft->sectrac * fd->ft->heads); - dp = &(fdc->head); - s = splbio(); - disksort(dp, bp); - untimeout(fd_turnoff,fdu); /* a good idea */ - fdstart(fdcu); - splx(s); - return; - -bad: - biodone(bp); -} - -/****************************************************************************/ -/* motor control stuff */ -/* remember to not deselect the drive we're working on */ -/****************************************************************************/ -set_motor(fdcu, fdu, reset) - fdcu_t fdcu; - fdu_t fdu; - int reset; -{ - int m0,m1; - int selunit; - fd_p fd; - if(fd = fdc_data[fdcu].fd)/* yes an assign! */ - { - selunit = fd->fdsu; - } - else - { - selunit = 0; - } - m0 = fd_data[fdcu * DRVS_PER_CTLR + 0].flags & FD_MOTOR; - m1 = fd_data[fdcu * DRVS_PER_CTLR + 1].flags & FD_MOTOR; - outb(fdc_data[fdcu].baseport+fdout, - selunit - | (reset ? 0 : (FDO_FRST|FDO_FDMAEN)) - | (m0 ? FDO_MOEN0 : 0) - | (m1 ? FDO_MOEN1 : 0)); - TRACE1("[0x%x->fdout]",( - selunit - | (reset ? 0 : (FDO_FRST|FDO_FDMAEN)) - | (m0 ? FDO_MOEN0 : 0) - | (m1 ? FDO_MOEN1 : 0))); -} - -fd_turnoff(fdu) - fdu_t fdu; -{ - int s; - - fd_p fd = fd_data + fdu; - s = splbio(); - fd->flags &= ~FD_MOTOR; - set_motor(fd->fdc->fdcu,fd->fdsu,0); - splx(s); -} - -fd_motor_on(fdu) - fdu_t fdu; -{ - int s; - - fd_p fd = fd_data + fdu; - s = splbio(); - fd->flags &= ~FD_MOTOR_WAIT; - if((fd->fdc->fd == fd) && (fd->fdc->state == MOTORWAIT)) - { - fdintr(fd->fdc->fdcu); - } - splx(s); -} - -fd_turnon(fdu) - fdu_t fdu; -{ - fd_p fd = fd_data + fdu; - if(!(fd->flags & FD_MOTOR)) - { - fd_turnon1(fdu); - fd->flags |= FD_MOTOR_WAIT; - timeout(fd_motor_on,fdu,hz); /* in 1 sec its ok */ - } -} - -fd_turnon1(fdu) - fdu_t fdu; -{ - fd_p fd = fd_data + fdu; - fd->flags |= FD_MOTOR; - set_motor(fd->fdc->fdcu,fd->fdsu,0); -} - -/****************************************************************************/ -/* fdc in/out */ -/****************************************************************************/ -int -in_fdc(fdcu) - fdcu_t fdcu; -{ - int baseport = fdc_data[fdcu].baseport; - int i, j = 100000; - while ((i = inb(baseport+fdsts) & (NE7_DIO|NE7_RQM)) - != (NE7_DIO|NE7_RQM) && j-- > 0) - if (i == NE7_RQM) return -1; - if (j <= 0) - return(-1); -#ifdef DEBUG - i = inb(baseport+fddata); - TRACE1("[fddata->0x%x]",(unsigned char)i); - return(i); -#else - return inb(baseport+fddata); -#endif -} - -out_fdc(fdcu, x) - fdcu_t fdcu; - int x; -{ - int baseport = fdc_data[fdcu].baseport; - int i; - - /* Check that the direction bit is set */ - i = 100000; - while ((inb(baseport+fdsts) & NE7_DIO) && i-- > 0); - if (i <= 0) return (-1); /* Floppy timed out */ - - /* Check that the floppy controller is ready for a command */ - i = 100000; - while ((inb(baseport+fdsts) & NE7_RQM) == 0 && i-- > 0); - if (i <= 0) return (-1); /* Floppy timed out */ - - /* Send the command and return */ - outb(baseport+fddata,x); - TRACE1("[0x%x->fddata]",x); - return (0); -} - -/****************************************************************************/ -/* fdopen/fdclose */ -/****************************************************************************/ -Fdopen(dev, flags) - dev_t dev; - int flags; -{ - fdu_t fdu = FDUNIT(minor(dev)); - /*int type = FDTYPE(minor(dev));*/ - int s; - - /* check bounds */ - if (fdu >= NFD || fd_data[fdu].type == NO_TYPE) return(ENXIO); - /*if (type >= NUMTYPES) return(ENXIO);*/ - fd_data[fdu].flags |= FD_OPEN; - - return 0; -} - -fdclose(dev, flags) - dev_t dev; -{ - fdu_t fdu = FDUNIT(minor(dev)); - fd_data[fdu].flags &= ~FD_OPEN; - return(0); -} - - -/***************************************************************\ -* fdstart * -* We have just queued something.. if the controller is not busy * -* then simulate the case where it has just finished a command * -* So that it (the interrupt routine) looks on the queue for more* -* work to do and picks up what we just added. * -* If the controller is already busy, we need do nothing, as it * -* will pick up our work when the present work completes * -\***************************************************************/ -fdstart(fdcu) - fdcu_t fdcu; -{ - register struct buf *dp,*bp; - int s; - fdu_t fdu; - - s = splbio(); - if(fdc_data[fdcu].state == DEVIDLE) - { - fdintr(fdcu); - } - splx(s); -} - -fd_timeout(fdcu) - fdcu_t fdcu; -{ - fdu_t fdu = fdc_data[fdcu].fdu; - int st0, st3, cyl; - struct buf *dp,*bp; - int s; - - dp = &fdc_data[fdcu].head; - s = splbio(); - bp = dp->b_actf; - - out_fdc(fdcu,NE7CMD_SENSED); - out_fdc(fdcu,fd_data[fdu].hddrv); - st3 = in_fdc(fdcu); - - out_fdc(fdcu,NE7CMD_SENSEI); - st0 = in_fdc(fdcu); - cyl = in_fdc(fdcu); - printf("fd%d: Operation timeout ST0 %b cyl %d ST3 %b\n", - fdu, - st0, - NE7_ST0BITS, - cyl, - st3, - NE7_ST3BITS); - - if (bp) - { - retrier(fdcu); - fdc_data[fdcu].status[0] = 0xc0; - 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; - } - fdintr(fdcu); - splx(s); -} - -/* just ensure it has the right spl */ -fd_pseudointr(fdcu) - fdcu_t fdcu; -{ - int s; - s = splbio(); - fdintr(fdcu); - splx(s); -} - -/***********************************************************************\ -* fdintr * -* keep calling the state machine until it returns a 0 * -* ALWAYS called at SPLBIO * -\***********************************************************************/ -fdintr(fdcu) - fdcu_t fdcu; -{ - fdc_p fdc = fdc_data + fdcu; - while(fdstate(fdcu, fdc)); -} - -/***********************************************************************\ -* The controller state machine. * -* if it returns a non zero value, it should be called again immediatly * -\***********************************************************************/ -int fdstate(fdcu, fdc) - fdcu_t fdcu; - fdc_p fdc; -{ - int read,head,trac,sec,i,s,sectrac,cyl,st0; - unsigned long blknum; - fdu_t fdu = fdc->fdu; - fd_p fd; - register struct buf *dp,*bp; - - dp = &(fdc->head); - bp = dp->b_actf; - if(!bp) - { - /***********************************************\ - * nothing left for this controller to do * - * Force into the IDLE state, * - \***********************************************/ - fdc->state = DEVIDLE; - if(fdc->fd) - { - printf("unexpected valid fd pointer (fdu = %d)\n" - ,fdc->fdu); - fdc->fd = (fd_p) 0; - fdc->fdu = -1; - } - TRACE1("[fdc%d IDLE]",fdcu); - return(0); - } - fdu = FDUNIT(minor(bp->b_dev)); - fd = fd_data + fdu; - if (fdc->fd && (fd != fdc->fd)) - { - printf("confused fd pointers\n"); - } - read = bp->b_flags & B_READ; - TRACE1("fd%d",fdu); - TRACE1("[%s]",fdstates[fdc->state]); - TRACE1("(0x%x)",fd->flags); - untimeout(fd_turnoff, fdu); - timeout(fd_turnoff,fdu,4 * hz); - switch (fdc->state) - { - case DEVIDLE: - case FINDWORK: /* we have found new work */ - fdc->retry = 0; - fd->skip = 0; - fdc->fd = fd; - fdc->fdu = fdu; - /*******************************************************\ - * If the next drive has a motor startup pending, then * - * it will start up in it's own good time * - \*******************************************************/ - if(fd->flags & FD_MOTOR_WAIT) - { - fdc->state = MOTORWAIT; - return(0); /* come back later */ - } - /*******************************************************\ - * Maybe if it's not starting, it SHOULD be starting * - \*******************************************************/ - if (!(fd->flags & FD_MOTOR)) - { - fdc->state = MOTORWAIT; - fd_turnon(fdu); - return(0); - } - else /* at least make sure we are selected */ - { - set_motor(fdcu,fd->fdsu,0); - } - fdc->state = DOSEEK; - break; - case DOSEEK: - if (bp->b_cylin == fd->track) - { - fdc->state = SEEKCOMPLETE; - break; - } - out_fdc(fdcu,NE7CMD_SEEK); /* Seek function */ - out_fdc(fdcu,fd->fdsu); /* Drive number */ - out_fdc(fdcu,bp->b_cylin * fd->ft->steptrac); - fd->track = -2; - fdc->state = SEEKWAIT; - timeout(fd_timeout,fdcu,2 * hz); - return(0); /* will return later */ - case SEEKWAIT: - untimeout(fd_timeout,fdcu); - /* allow heads to settle */ - timeout(fd_pseudointr,fdcu,hz/50); - fdc->state = SEEKCOMPLETE; - return(0); /* will return later */ - break; - - case SEEKCOMPLETE : /* SEEK DONE, START DMA */ - /* Make sure seek really happened*/ - if(fd->track == -2) - { - int descyl = bp->b_cylin * fd->ft->steptrac; - out_fdc(fdcu,NE7CMD_SENSEI); - i = in_fdc(fdcu); - cyl = in_fdc(fdcu); - if (cyl != descyl) - { - printf("fd%d: Seek to cyl %d failed; am at cyl %d (ST0 = 0x%x)\n", fdu, - descyl, cyl, i, NE7_ST0BITS); - return(retrier(fdcu)); - } - } - - fd->track = bp->b_cylin; - isa_dmastart(bp->b_flags, bp->b_un.b_addr+fd->skip, - FDBLK, fdc->dmachan); - blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK - + fd->skip/FDBLK; - sectrac = fd->ft->sectrac; - sec = blknum % (sectrac * fd->ft->heads); - head = sec / sectrac; - sec = sec % sectrac + 1; -/*XXX*/ fd->hddrv = ((head&1)<<2)+fdu; - - if (read) - { - out_fdc(fdcu,NE7CMD_READ); /* READ */ - } - else - { - out_fdc(fdcu,NE7CMD_WRITE); /* WRITE */ - } - out_fdc(fdcu,head << 2 | fdu); /* head & unit */ - out_fdc(fdcu,fd->track); /* track */ - out_fdc(fdcu,head); - out_fdc(fdcu,sec); /* sector XXX +1? */ - out_fdc(fdcu,fd->ft->secsize); /* sector size */ - out_fdc(fdcu,sectrac); /* sectors/track */ - out_fdc(fdcu,fd->ft->gap); /* gap size */ - out_fdc(fdcu,fd->ft->datalen); /* data length */ - fdc->state = IOCOMPLETE; - timeout(fd_timeout,fdcu,2 * hz); - return(0); /* will return later */ - case IOCOMPLETE: /* IO DONE, post-analyze */ - untimeout(fd_timeout,fdcu); - for(i=0;i<7;i++) - { - fdc->status[i] = in_fdc(fdcu); - } - case IOTIMEDOUT: /*XXX*/ - isa_dmadone(bp->b_flags, bp->b_un.b_addr+fd->skip, - FDBLK, fdc->dmachan); - if (fdc->status[0]&0xF8) - { - return(retrier(fdcu)); - } - /* All OK */ - fd->skip += FDBLK; - if (fd->skip < bp->b_bcount) - { - /* set up next transfer */ - blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK - + fd->skip/FDBLK; - bp->b_cylin = (blknum / (fd->ft->sectrac * fd->ft->heads)); - fdc->state = DOSEEK; - } - else - { - /* ALL DONE */ - fd->skip = 0; - bp->b_resid = 0; - dp->b_actf = bp->av_forw; - biodone(bp); - fdc->fd = (fd_p) 0; - fdc->fdu = -1; - fdc->state = FINDWORK; - } - return(1); - case RESETCTLR: - /* Try a reset, keep motor on */ - set_motor(fdcu,fd->fdsu,1); - DELAY(100); - set_motor(fdcu,fd->fdsu,0); - outb(fdc->baseport+fdctl,fd->ft->trans); - TRACE1("[0x%x->fdctl]",fd->ft->trans); - fdc->retry++; - fdc->state = STARTRECAL; - break; - case STARTRECAL: - out_fdc(fdcu,NE7CMD_SPECIFY); /* specify command */ - out_fdc(fdcu,0xDF); - out_fdc(fdcu,2); - out_fdc(fdcu,NE7CMD_RECAL); /* Recalibrate Function */ - out_fdc(fdcu,fdu); - fdc->state = RECALWAIT; - return(0); /* will return later */ - case RECALWAIT: - /* allow heads to settle */ - timeout(fd_pseudointr,fdcu,hz/30); - fdc->state = RECALCOMPLETE; - return(0); /* will return later */ - case RECALCOMPLETE: - out_fdc(fdcu,NE7CMD_SENSEI); - st0 = in_fdc(fdcu); - cyl = in_fdc(fdcu); - if (cyl != 0) - { - printf("fd%d: recal failed ST0 %b cyl %d\n", fdu, - st0, NE7_ST0BITS, cyl); - return(retrier(fdcu)); - } - fd->track = 0; - /* Seek (probably) necessary */ - fdc->state = DOSEEK; - return(1); /* will return immediatly */ - case MOTORWAIT: - if(fd->flags & FD_MOTOR_WAIT) - { - return(0); /* time's not up yet */ - } - fdc->state = DOSEEK; - return(1); /* will return immediatly */ - default: - printf("Unexpected FD int->"); - out_fdc(fdcu,NE7CMD_SENSEI); - st0 = in_fdc(fdcu); - cyl = in_fdc(fdcu); - printf("ST0 = %lx, PCN = %lx\n",i,sec); - out_fdc(fdcu,0x4A); - out_fdc(fdcu,fd->fdsu); - for(i=0;i<7;i++) { - fdc->status[i] = in_fdc(fdcu); - } - printf("intr status :%lx %lx %lx %lx %lx %lx %lx ", - fdc->status[0], - fdc->status[1], - fdc->status[2], - fdc->status[3], - fdc->status[4], - fdc->status[5], - fdc->status[6] ); - return(0); - } - return(1); /* Come back immediatly to new state */ -} - -retrier(fdcu) - fdcu_t fdcu; -{ - fdc_p fdc = fdc_data + fdcu; - register struct buf *dp,*bp; - - dp = &(fdc->head); - bp = dp->b_actf; - - switch(fdc->retry) - { - case 0: case 1: case 2: - fdc->state = SEEKCOMPLETE; - break; - case 3: case 4: case 5: - fdc->state = STARTRECAL; - break; - case 6: - fdc->state = RESETCTLR; - break; - case 7: - break; - default: - { - diskerr(bp, "fd", "hard error", LOG_PRINTF, - fdc->fd->skip, (struct disklabel *)NULL); - printf(" (ST0 %b ", fdc->status[0], NE7_ST0BITS); - printf(" ST1 %b ", fdc->status[1], NE7_ST1BITS); - printf(" ST2 %b ", fdc->status[2], NE7_ST2BITS); - printf("cyl %d hd %d sec %d)\n", - fdc->status[3], fdc->status[4], fdc->status[5]); - } - bp->b_flags |= B_ERROR; - bp->b_error = EIO; - bp->b_resid = bp->b_bcount - fdc->fd->skip; - dp->b_actf = bp->av_forw; - fdc->fd->skip = 0; - biodone(bp); - fdc->state = FINDWORK; - fdc->fd = (fd_p) 0; - fdc->fdu = -1; - /* XXX abort current command, if any. */ - return(1); - } - fdc->retry++; - return(1); -} - -/* - * fdioctl() from jc@irbs.UUCP (John Capo) - * i386/i386/conf.c needs to have fdioctl() declared and remove the line that - * defines fdioctl to be enxio. - * - * TODO: Reformat. - * Think about allocating buffer off stack. - * Don't pass uncast 0's and NULL's to read/write/setdisklabel(). - * Watch out for NetBSD's different *disklabel() interface. - */ - -int -fdioctl (dev, cmd, addr, flag) -dev_t dev; -int cmd; -caddr_t addr; -int flag; -{ - struct fd_type *fdt; - struct disklabel *dl; - char buffer[DEV_BSIZE]; - int error; - - error = 0; - - switch (cmd) - { - case DIOCGDINFO: - bzero(buffer, sizeof (buffer)); - dl = (struct disklabel *)buffer; - dl->d_secsize = FDBLK; - fdt = fd_data[FDUNIT(minor(dev))].ft; - dl->d_secpercyl = fdt->size / fdt->tracks; - dl->d_type = DTYPE_FLOPPY; - - if (readdisklabel(dev, fdstrategy, dl, NULL, 0, 0) == NULL) - error = 0; - else - error = EINVAL; - - *(struct disklabel *)addr = *dl; - break; - - case DIOCSDINFO: - - if ((flag & FWRITE) == 0) - error = EBADF; - - break; - - case DIOCWLABEL: - if ((flag & FWRITE) == 0) - error = EBADF; - - break; - - case DIOCWDINFO: - if ((flag & FWRITE) == 0) - { - error = EBADF; - break; - } - - dl = (struct disklabel *)addr; - - if (error = setdisklabel ((struct disklabel *)buffer, dl, 0, NULL)) - break; - - error = writedisklabel(dev, fdstrategy, (struct disklabel *)buffer, NULL); - break; - - default: - error = EINVAL; - break; - } - return (error); -} - -#endif |