Annotation of Net2/arch/i386/isa/fd.c, revision 1.1.1.5

1.1.1.5 ! root        1: /*#define DEBUG 1*/
1.1       root        2: /*-
                      3:  * Copyright (c) 1990 The Regents of the University of California.
                      4:  * All rights reserved.
                      5:  *
                      6:  * This code is derived from software contributed to Berkeley by
                      7:  * Don Ahn.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
                     19:  *     This product includes software developed by the University of
                     20:  *     California, Berkeley and its contributors.
                     21:  * 4. Neither the name of the University nor the names of its contributors
                     22:  *    may be used to endorse or promote products derived from this software
                     23:  *    without specific prior written permission.
                     24:  *
                     25:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     28:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     35:  * SUCH DAMAGE.
                     36:  *
1.1.1.5 ! root       37:  *     from: @(#)fd.c  7.4 (Berkeley) 5/25/91
        !            38:  *     fd.c,v 1.19.2.1 1993/07/28 00:11:21 deraadt Exp
        !            39:  *
        !            40:  * Largely rewritten to handle multiple controllers and drives
        !            41:  * By Julian Elischer, Sun Apr  4 16:34:33 WST 1993
        !            42:  */
        !            43: /*
        !            44:  * fd.c,v
        !            45:  * Revision 1.19.2.1  1993/07/28  00:11:21  deraadt
        !            46:  * wd.c: fixes 1 drive systems
        !            47:  * fd.c: improves reliability
        !            48:  * changes from wolfgang
        !            49:  *
        !            50:  * Revision 1.19  1993/07/16  15:44:22  mycroft
        !            51:  * #include cpufunc,h so inb() and outb() are inlined.
        !            52:  *
        !            53:  * Revision 1.18  1993/07/06  06:06:29  deraadt
        !            54:  * clean up code for timeout/untimeout/wakeup prototypes.
        !            55:  *
        !            56:  * Revision 1.17  1993/06/29  19:12:44  deraadt
        !            57:  * uninitialized variable reported by <[email protected]>
        !            58:  *
        !            59:  * Revision 1.16  1993/06/21  09:39:52  deraadt
        !            60:  * I don't know what I did that was so critical, but now the floppy driver
        !            61:  * works on my machine (it did not before). Big voodoo.
        !            62:  *
        !            63:  * Revision 1.15  1993/06/20  08:42:05  deraadt
        !            64:  * if the floppy does not exist, say nothing.
        !            65:  *
        !            66:  * Revision 1.14  1993/06/18  06:19:16  cgd
        !            67:  * new floppy driver, merged from patchkit patch #153
        !            68:  *
        !            69:  * Revision 1.1.1.1  1993/06/12  14:58:02  rgrimes
        !            70:  * Initial import, 0.1 + pk 0.2.4-B1
        !            71:  *
        !            72:  * Revision 1.10  93/04/13  16:53:29  root
        !            73:  * make sure turning off a drive motor doesn't deselect another
        !            74:  * drive active at the time.
        !            75:  * Also added a pointer from the fd_data to it's fd_type.
        !            76:  * 
        !            77:  * Revision 1.9  93/04/13  15:31:02  root
        !            78:  * make all seeks go through DOSEEK state so are sure of being done right.
        !            79:  * 
        !            80:  * Revision 1.8  93/04/12  21:20:13  root
        !            81:  * only check if old fd is the one we are working on if there IS
        !            82:  * an old fd pointer. (in fdstate())
        !            83:  * 
        !            84:  * Revision 1.7  93/04/11  17:05:35  root
        !            85:  * cleanup timeouts etc.
        !            86:  * also fix bug to select teh correct drive when running > 1 drive
        !            87:  * at a time.
        !            88:  * 
        !            89:  * Revision 1.6  93/04/05  00:48:45  root
        !            90:  * change a timeout and add version to banner message
        !            91:  * 
        !            92:  * Revision 1.5  93/04/04  16:39:08  root
        !            93:  * first working version.. some floppy controllers don't seem to
        !            94:  * like 2 int. status inquiries in a row.
        !            95:  * 
1.1       root       96:  */
                     97: 
                     98: #include "fd.h"
1.1.1.4   root       99: #if NFDC > 0
1.1       root      100: 
                    101: #include "param.h"
                    102: #include "dkbad.h"
                    103: #include "systm.h"
                    104: #include "conf.h"
                    105: #include "file.h"
                    106: #include "ioctl.h"
                    107: #include "buf.h"
                    108: #include "uio.h"
1.1.1.5 ! root      109: #include "machine/cpufunc.h"
        !           110: #include "i386/isa/isa.h"
1.1       root      111: #include "i386/isa/isa_device.h"
                    112: #include "i386/isa/fdreg.h"
                    113: #include "i386/isa/icu.h"
1.1.1.3   root      114: #include "i386/isa/rtc.h"
1.1       root      115: 
1.1.1.2   root      116: #define        FDUNIT(s)       ((s>>3)&1)
                    117: #define        FDTYPE(s)       ((s)&7)
1.1       root      118: 
                    119: #define b_cylin b_resid
                    120: #define FDBLK 512
                    121: 
                    122: struct fd_type {
                    123:        int     sectrac;                /* sectors per track         */
                    124:        int     secsize;                /* size code for sectors     */
                    125:        int     datalen;                /* data len when secsize = 0 */
                    126:        int     gap;                    /* gap len between sectors   */
                    127:        int     tracks;                 /* total num of tracks       */
                    128:        int     size;                   /* size of disk in sectors   */
                    129:        int     steptrac;               /* steps per cylinder        */
                    130:        int     trans;                  /* transfer speed code       */
1.1.1.5 ! root      131:        int     heads;                  /* number of heads           */
1.1       root      132: };
                    133: 
1.1.1.5 ! root      134: struct fd_type fd_types[] =
        !           135: {
        !           136:        { 18,2,0xFF,0x1B,80,2880,1,0,2 }, /* 1.44 meg HD 3.5in floppy    */
        !           137:        { 15,2,0xFF,0x1B,80,2400,1,0,2 }, /* 1.2 meg HD floppy           */
        !           138:        { 9,2,0xFF,0x23,40,720,2,1,2 }, /* 360k floppy in 1.2meg drive */
        !           139:        { 9,2,0xFF,0x2A,40,720,1,1,2 }, /* 360k floppy in DD drive     */
        !           140:        { 9,2,0xFF,0x2A,80,1440,1,0 },  /* 720K drive. PROBABLY WRONG   */
1.1       root      141: };
                    142: 
1.1.1.5 ! root      143: #define DRVS_PER_CTLR 2
        !           144: /***********************************************************************\
        !           145: * Per controller structure.                                            *
        !           146: \***********************************************************************/
        !           147: struct fdc_data
        !           148: {
        !           149:        int     fdcu;           /* our unit number */
        !           150:        int     baseport;
        !           151:        int     dmachan;
        !           152:        int     flags;
        !           153: #define FDC_ATTACHED   0x01
        !           154:        struct  fd_data *fd;
        !           155:        int fdu;                /* the active drive     */
1.1       root      156:        struct buf head;        /* Head of buf chain      */
                    157:        struct buf rhead;       /* Raw head of buf chain  */
1.1.1.5 ! root      158:        int state;
        !           159:        int retry;
        !           160:        int status[7];          /* copy of the registers */
        !           161: }fdc_data[NFDC];
        !           162: 
        !           163: /***********************************************************************\
        !           164: * Per drive structure.                                                 *
        !           165: * N per controller (presently 2) (DRVS_PER_CTLR)                       *
        !           166: \***********************************************************************/
        !           167: struct fd_data {
        !           168:        struct  fdc_data *fdc;
        !           169:        int     fdu;            /* this unit number */
        !           170:        int     fdsu;           /* this units number on this controller */
        !           171:        int     type;           /* Drive type (HD, DD     */
        !           172:        struct  fd_type *ft;    /* pointer to the type descriptor */
        !           173:        int     flags;
        !           174: #define        FD_OPEN         0x01    /* it's open            */
        !           175: #define        FD_ACTIVE       0x02    /* it's active          */
        !           176: #define        FD_MOTOR        0x04    /* motor should be on   */
        !           177: #define        FD_MOTOR_WAIT   0x08    /* motor coming up      */
        !           178:        int skip;
        !           179:        int hddrv;
        !           180:        int track;              /* where we think the head is */
        !           181: } fd_data[NFD];
        !           182: 
        !           183: /***********************************************************************\
        !           184: * Throughout this file the following conventions will be used:         *
        !           185: * fd is a pointer to the fd_data struct for the drive in question      *
        !           186: * fdc is a pointer to the fdc_data struct for the controller           *
        !           187: * fdu is the floppy drive unit number                                  *
        !           188: * fdcu is the floppy controller unit number                            *
        !           189: * fdsu is the floppy drive unit number on that controller. (sub-unit)  *
        !           190: \***********************************************************************/
        !           191: typedef int    fdu_t;
        !           192: typedef int    fdcu_t;
        !           193: typedef int    fdsu_t;
        !           194: typedef        struct fd_data *fd_p;
        !           195: typedef struct fdc_data *fdc_p;
        !           196: 
        !           197: #define DEVIDLE                0
        !           198: #define FINDWORK       1
        !           199: #define        DOSEEK          2
        !           200: #define SEEKCOMPLETE   3
        !           201: #define        IOCOMPLETE      4
        !           202: #define RECALCOMPLETE  5
        !           203: #define        STARTRECAL      6
        !           204: #define        RESETCTLR       7
        !           205: #define        SEEKWAIT        8
        !           206: #define        RECALWAIT       9
        !           207: #define        MOTORWAIT       10
        !           208: #define        IOTIMEDOUT      11
        !           209: 
        !           210: #ifdef DEBUG
        !           211: char *fdstates[] =
        !           212: {
        !           213: "DEVIDLE",
        !           214: "FINDWORK",
        !           215: "DOSEEK",
        !           216: "SEEKCOMPLETE",
        !           217: "IOCOMPLETE",
        !           218: "RECALCOMPLETE",
        !           219: "STARTRECAL",
        !           220: "RESETCTLR",
        !           221: "SEEKWAIT",
        !           222: "RECALWAIT",
        !           223: "MOTORWAIT",
        !           224: "IOTIMEDOUT"
        !           225: };
1.1       root      226: 
                    227: 
1.1.1.5 ! root      228: int    fd_debug = 1;
        !           229: #define TRACE0(arg) if(fd_debug) printf(arg)
        !           230: #define TRACE1(arg1,arg2) if(fd_debug) printf(arg1,arg2)
        !           231: #else  DEBUG
        !           232: #define TRACE0(arg)
        !           233: #define TRACE1(arg1,arg2)
        !           234: #endif DEBUG
1.1       root      235: 
1.1.1.5 ! root      236: extern int hz;
1.1       root      237: /* state needed for current transfer */
                    238: 
                    239: /****************************************************************************/
                    240: /*                      autoconfiguration stuff                             */
                    241: /****************************************************************************/
1.1.1.5 ! root      242: int fdprobe(), fdattach(), fd_turnoff();
1.1       root      243: 
1.1.1.4   root      244: struct isa_driver fdcdriver = {
                    245:        fdprobe, fdattach, "fdc",
1.1       root      246: };
                    247: 
1.1.1.3   root      248: /*
                    249:  * probe for existance of controller
                    250:  */
1.1.1.5 ! root      251: fdprobe(dev)
        !           252: struct isa_device *dev;
1.1       root      253: {
1.1.1.5 ! root      254:        fdc_p fdc = &fdc_data[dev->id_unit];
        !           255:        int fdcu = dev->id_unit;
1.1.1.3   root      256: 
1.1.1.5 ! root      257:        fdc->baseport = dev->id_iobase;
        !           258: 
        !           259:        /* Try a reset, don't change motor on */
        !           260:        set_motor(fdcu,0,1);
        !           261:        DELAY(100);
        !           262:        set_motor(fdcu,0,0);
1.1.1.3   root      263:        /* see if it can handle a command */
1.1.1.5 ! root      264:        if (out_fdc(fdcu,NE7CMD_SPECIFY) < 0)
        !           265:        {
1.1.1.3   root      266:                return(0);
                    267:        }
1.1.1.5 ! root      268:        out_fdc(fdcu,0xDF);
        !           269:        out_fdc(fdcu,2);
        !           270: 
        !           271:        fdc->dmachan = dev->id_drq;
        !           272:        fdc->fdcu = dev->id_unit;
        !           273:        fdc->flags |= FDC_ATTACHED;
        !           274:        fdc->state = DEVIDLE;
        !           275: 
        !           276:        /*
        !           277:         * tdr: I've put this here, because with the new way for
        !           278:         * attach() being called it cannot go there.
        !           279:         */
        !           280:        /* Set transfer to 500kbps */
        !           281:        outb(fdc->baseport+fdctl,0); /*XXX*/
        !           282: 
        !           283:        return (IO_FDCSIZE);
1.1       root      284: }
                    285: 
1.1.1.3   root      286: /*
                    287:  * wire controller into system, look for floppy units
                    288:  */
1.1.1.5 ! root      289: fdattach(dev)
        !           290: struct isa_device *dev;
1.1.1.3   root      291: {
1.1.1.5 ! root      292:        unsigned fdt=0,st0, cyl;
        !           293:        fdu_t   fdu = dev->id_unit;
        !           294:        fdcu_t  fdcu = dev->id_masunit;
        !           295:        fdc_p   fdc = &fdc_data[dev->id_masunit];
        !           296:        fd_p    fd = &fd_data[dev->id_unit];
        !           297:        int     fdsu = dev->id_physid;
        !           298: 
        !           299:        if(dev->id_physid < 0 || dev->id_physid > 1) {
        !           300:                printf("fdc%d: cannot support physical unit %d\n",
        !           301:                        dev->id_masunit, dev->id_physid);
        !           302:                return 0;
        !           303:        }
        !           304:        if(dev->id_masunit==0)
        !           305:                fdt = rtcin(RTC_FDISKETTE);
        !           306:        else
        !           307:                fdt = 0xff;     /* cmos only knows two floppies */
        !           308: 
        !           309:        if(dev->id_physid == 1)
        !           310:                fdt <<= 4;
        !           311: 
        !           312: #ifdef notyet
        !           313:        /* select it */
        !           314:        fd_turnon1(fdu);
        !           315:        spinwait(1000); /* 1 sec */
        !           316:        out_fdc(fdcu,NE7CMD_RECAL);     /* Recalibrate Function */
        !           317:        out_fdc(fdcu,fdsu);
        !           318:        spinwait(1000); /* 1 sec */
        !           319: 
        !           320:        /* anything responding */
        !           321:        out_fdc(fdcu,NE7CMD_SENSEI);
        !           322:        st0 = in_fdc(fdcu);
        !           323:        cyl = in_fdc(fdcu);
        !           324:        if (st0 & 0xd0)
        !           325:                continue;
        !           326: #endif
        !           327:        fd->track = -2;
        !           328:        fd->fdc = fdc;
        !           329:        fd->fdsu = fdsu;
        !           330: 
        !           331:        switch(fdt & 0xf0) {
        !           332:        case RTCFDT_NONE:
        !           333:                /*printf("fd%d at fdc%d targ %d: nonexistant device\n",
        !           334:                        dev->id_unit, dev->id_masunit, dev->id_physid);*/
        !           335:                return 0;
        !           336:                break;
        !           337:        case RTCFDT_12M:
        !           338:                printf("fd%d at fdc%d targ %d: 1.2MB 80 cyl, 2 head, 15 sec\n",
        !           339:                        dev->id_unit, dev->id_masunit, dev->id_physid);
        !           340:                fd->type = 1;
        !           341:                break;
        !           342:        case RTCFDT_144M:
        !           343:                printf("fd%d at fdc%d targ %d: 1.44MB 80 cyl, 2 head, 18 sec\n",
        !           344:                        dev->id_unit, dev->id_masunit, dev->id_physid);
        !           345:                fd->type = 0;
        !           346:                break;
        !           347:        case RTCFDT_360K:
        !           348:                printf("fd%d at fdc%d targ %d: 360KB 40 cyl, 2 head, 9 sec\n",
        !           349:                        dev->id_unit, dev->id_masunit, dev->id_physid);
        !           350:                fd->type = 3;
        !           351:                break;
        !           352:        case RTCFDT_720K:
        !           353:                printf("fd%d at fdc%d targ %d: 720KB 80 cyl, 2 head, 9 sec\n",
        !           354:                        dev->id_unit, dev->id_masunit, dev->id_physid);
        !           355:                fd->type = 4;
        !           356:                break;
        !           357:        default:
        !           358:                printf("fd%d at fdc%d targ %d: unknown device type 0x%x\n",
        !           359:                        dev->id_unit, dev->id_masunit, dev->id_physid,
        !           360:                        fdt & 0xf0);
        !           361:                return 0;
        !           362:                break;
1.1.1.4   root      363:        }
1.1.1.5 ! root      364: 
        !           365:        fd->ft = &fd_types[fd->type];
        !           366:        fd_turnoff(fdu);
        !           367:        return 1;
1.1       root      368: }
                    369: 
                    370: int
                    371: fdsize(dev)
                    372: dev_t  dev;
                    373: {
1.1.1.3   root      374:        return(0);
1.1       root      375: }
                    376: 
                    377: /****************************************************************************/
                    378: /*                               fdstrategy                                 */
                    379: /****************************************************************************/
                    380: fdstrategy(bp)
                    381:        register struct buf *bp;        /* IO operation to perform */
                    382: {
                    383:        register struct buf *dp,*dp0,*dp1;
                    384:        long nblocks,blknum;
1.1.1.5 ! root      385:        int     s;
        !           386:        fdcu_t  fdcu;
        !           387:        fdu_t   fdu;
        !           388:        fdc_p   fdc;
        !           389:        fd_p    fd;
        !           390: 
        !           391:        fdu = FDUNIT(minor(bp->b_dev));
        !           392:        fd = &fd_data[fdu];
        !           393:        fdc = fd->fdc;
        !           394:        fdcu = fdc->fdcu;
1.1.1.3   root      395:        /*type = FDTYPE(minor(bp->b_dev));*/
1.1       root      396: 
1.1.1.5 ! root      397:        if ((fdu >= NFD) || (bp->b_blkno < 0)) {
        !           398:                printf("fdstrat: fdu = %d, blkno = %d, bcount = %d\n",
        !           399:                        fdu, bp->b_blkno, bp->b_bcount);
1.1       root      400:                pg("fd:error in fdstrategy");
                    401:                bp->b_error = EINVAL;
                    402:                bp->b_flags |= B_ERROR;
                    403:                goto bad;
                    404:        }
                    405:        /*
                    406:         * Set up block calculations.
                    407:         */
                    408:        blknum = (unsigned long) bp->b_blkno * DEV_BSIZE/FDBLK;
1.1.1.5 ! root      409:        nblocks = fd->ft->size;
1.1       root      410:        if (blknum + (bp->b_bcount / FDBLK) > nblocks) {
                    411:                if (blknum == nblocks) {
                    412:                        bp->b_resid = bp->b_bcount;
                    413:                } else {
                    414:                        bp->b_error = ENOSPC;
                    415:                        bp->b_flags |= B_ERROR;
                    416:                }
                    417:                goto bad;
                    418:        }
1.1.1.5 ! root      419:        bp->b_cylin = blknum / (fd->ft->sectrac * fd->ft->heads);
        !           420:        dp = &(fdc->head);
1.1       root      421:        s = splbio();
                    422:        disksort(dp, bp);
1.1.1.5 ! root      423:        untimeout((timeout_t)fd_turnoff, (caddr_t)fdu); /* a good idea */
        !           424:        fdstart(fdcu);
1.1       root      425:        splx(s);
                    426:        return;
                    427: 
                    428: bad:
                    429:        biodone(bp);
                    430: }
                    431: 
                    432: /****************************************************************************/
                    433: /*                            motor control stuff                           */
1.1.1.5 ! root      434: /*             remember to not deselect the drive we're working on         */
1.1       root      435: /****************************************************************************/
1.1.1.5 ! root      436: set_motor(fdcu_t fdcu, fdu_t fdu, int reset)
1.1       root      437: {
                    438:        int m0,m1;
1.1.1.5 ! root      439:        int selunit;
        !           440:        fd_p fd;
        !           441:        if(fd = fdc_data[fdcu].fd)/* yes an assign! */
        !           442:        {
        !           443:                selunit =  fd->fdsu;
        !           444:        }
        !           445:        else
        !           446:        {
        !           447:                selunit = 0;
        !           448:        }
        !           449:        m0 = fd_data[fdcu * DRVS_PER_CTLR + 0].flags & FD_MOTOR;
        !           450:        m1 = fd_data[fdcu * DRVS_PER_CTLR + 1].flags & FD_MOTOR;
        !           451:        outb(fdc_data[fdcu].baseport+fdout,
        !           452:                selunit
1.1.1.3   root      453:                | (reset ? 0 : (FDO_FRST|FDO_FDMAEN))
                    454:                | (m0 ? FDO_MOEN0 : 0)
                    455:                | (m1 ? FDO_MOEN1 : 0));
1.1.1.5 ! root      456:        TRACE1("[0x%x->fdout]",(
        !           457:                selunit
        !           458:                | (reset ? 0 : (FDO_FRST|FDO_FDMAEN))
        !           459:                | (m0 ? FDO_MOEN0 : 0)
        !           460:                | (m1 ? FDO_MOEN1 : 0)));
        !           461: }
        !           462: 
        !           463: fd_turnoff(fdu_t fdu)
        !           464: {
        !           465:        fd_p fd = fd_data + fdu;
        !           466:        fd->flags &= ~FD_MOTOR;
        !           467:        set_motor(fd->fdc->fdcu,fd->fdsu,0);
        !           468: }
        !           469: 
        !           470: fd_motor_on(fdu_t fdu)
        !           471: {
        !           472:        fd_p fd = fd_data + fdu;
        !           473:        fd->flags &= ~FD_MOTOR_WAIT;
        !           474:        if((fd->fdc->fd == fd) && (fd->fdc->state == MOTORWAIT))
        !           475:        {
        !           476:                fd_pseudointr(fd->fdc->fdcu);
        !           477:        }
1.1       root      478: }
                    479: 
1.1.1.5 ! root      480: fd_turnon(fdu_t fdu) 
1.1       root      481: {
1.1.1.5 ! root      482:        fd_p fd = fd_data + fdu;
        !           483:        if(!(fd->flags & FD_MOTOR))
        !           484:        {
        !           485:                fd_turnon1(fdu);
        !           486:                fd->flags |= FD_MOTOR_WAIT;
        !           487:                timeout((timeout_t)fd_motor_on, (caddr_t)fdu, hz); /* in 1 sec its ok */
        !           488:        }
1.1       root      489: }
                    490: 
1.1.1.5 ! root      491: fd_turnon1(fdu_t fdu) 
1.1       root      492: {
1.1.1.5 ! root      493:        fd_p fd = fd_data + fdu;
        !           494:        fd->flags |= FD_MOTOR;
        !           495:        set_motor(fd->fdc->fdcu,fd->fdsu,0);
1.1       root      496: }
                    497: 
                    498: /****************************************************************************/
                    499: /*                             fdc in/out                                   */
                    500: /****************************************************************************/
                    501: int
1.1.1.5 ! root      502: in_fdc(fdcu_t fdcu)
1.1       root      503: {
1.1.1.5 ! root      504:        int baseport = fdc_data[fdcu].baseport;
1.1.1.3   root      505:        int i, j = 100000;
1.1.1.5 ! root      506:        while ((i = inb(baseport+fdsts) & (NE7_DIO|NE7_RQM))
        !           507:                != (NE7_DIO|NE7_RQM) && j-- > 0)
1.1       root      508:                if (i == NE7_RQM) return -1;
1.1.1.3   root      509:        if (j <= 0)
                    510:                return(-1);
1.1.1.5 ! root      511: #ifdef DEBUG
        !           512:        i = inb(baseport+fddata);
        !           513:        TRACE1("[fddata->0x%x]",(unsigned char)i);
        !           514:        return(i);
        !           515: #else
        !           516:        return inb(baseport+fddata);
        !           517: #endif
1.1       root      518: }
                    519: 
1.1.1.5 ! root      520: out_fdc(fdcu_t fdcu,int x)
1.1       root      521: {
1.1.1.5 ! root      522:        int baseport = fdc_data[fdcu].baseport;
1.1.1.3   root      523:        int i = 100000;
1.1       root      524: 
1.1.1.5 ! root      525:        while ((inb(baseport+fdsts) & NE7_DIO) && i-- > 0);
        !           526:        while ((inb(baseport+fdsts) & NE7_RQM) == 0 && i-- > 0);
1.1.1.3   root      527:        if (i <= 0) return (-1);
1.1.1.5 ! root      528:        outb(baseport+fddata,x);
        !           529:        TRACE1("[0x%x->fddata]",x);
1.1.1.3   root      530:        return (0);
1.1       root      531: }
                    532: 
1.1.1.3   root      533: static fdopenf;
1.1       root      534: /****************************************************************************/
                    535: /*                           fdopen/fdclose                                 */
                    536: /****************************************************************************/
                    537: Fdopen(dev, flags)
                    538:        dev_t   dev;
                    539:        int     flags;
                    540: {
1.1.1.5 ! root      541:        fdu_t fdu = FDUNIT(minor(dev));
        !           542:        /*int type = FDTYPE(minor(dev));*/
1.1       root      543:        int s;
                    544: 
                    545:        /* check bounds */
1.1.1.5 ! root      546:        if (fdu >= NFD) return(ENXIO);
        !           547:        /*if (type >= sizeof(fd_types)/sizeof(fd_types[0]) ) return(ENXIO);*/
        !           548:        fd_data[fdu].flags |= FD_OPEN;
1.1       root      549: 
                    550:        return 0;
                    551: }
                    552: 
                    553: fdclose(dev, flags)
                    554:        dev_t dev;
                    555: {
1.1.1.5 ! root      556:        fdu_t fdu = FDUNIT(minor(dev));
        !           557:        fd_data[fdu].flags &= ~FD_OPEN;
1.1.1.2   root      558:        return(0);
1.1       root      559: }
                    560: 
                    561: 
1.1.1.5 ! root      562: /***************************************************************\
        !           563: *                              fdstart                         *
        !           564: * We have just queued something.. if the controller is not busy        *
        !           565: * then simulate the case where it has just finished a command  *
        !           566: * So that it (the interrupt routine) looks on the queue for more*
        !           567: * work to do and picks up what we just added.                  *
        !           568: * If the controller is already busy, we need do nothing, as it *
        !           569: * will pick up our work when the present work completes                *
        !           570: \***************************************************************/
        !           571: fdstart(fdcu_t fdcu)
1.1       root      572: {
                    573:        register struct buf *dp,*bp;
                    574:        int s;
1.1.1.5 ! root      575:        fdu_t fdu;
1.1       root      576: 
                    577:        s = splbio();
1.1.1.5 ! root      578:        if(fdc_data[fdcu].state == DEVIDLE)
        !           579:        {
        !           580:                fdintr(fdcu);
1.1       root      581:        }
                    582:        splx(s);
                    583: }
                    584: 
1.1.1.5 ! root      585: fd_timeout(fdcu_t fdcu)
1.1       root      586: {
1.1.1.5 ! root      587:        fdu_t fdu = fdc_data[fdcu].fdu;
1.1.1.3   root      588:        int st0, st3, cyl;
1.1       root      589:        struct buf *dp,*bp;
                    590: 
1.1.1.5 ! root      591:        dp = &fdc_data[fdcu].head;
1.1       root      592:        bp = dp->b_actf;
                    593: 
1.1.1.5 ! root      594:        out_fdc(fdcu,NE7CMD_SENSED);
        !           595:        out_fdc(fdcu,fd_data[fdu].hddrv);
        !           596:        st3 = in_fdc(fdcu);
        !           597: 
        !           598:        out_fdc(fdcu,NE7CMD_SENSEI);
        !           599:        st0 = in_fdc(fdcu);
        !           600:        cyl = in_fdc(fdcu);
        !           601:        printf("fd%d: Operation timeout ST0 %b cyl %d ST3 %b\n",
        !           602:                        fdu,
        !           603:                        st0,
        !           604:                        NE7_ST0BITS,
        !           605:                        cyl,
        !           606:                        st3,
        !           607:                        NE7_ST3BITS);
        !           608: 
        !           609:        if (bp)
        !           610:        {
        !           611:                retrier(fdcu);
        !           612:                fdc_data[fdcu].status[0] = 0xc0;
        !           613:                fdc_data[fdcu].state = IOTIMEDOUT;
        !           614:                if( fdc_data[fdcu].retry < 6)
        !           615:                        fdc_data[fdcu].retry = 6;
        !           616:        }
        !           617:        else
        !           618:        {
        !           619:                fdc_data[fdcu].fd = (fd_p) 0;
        !           620:                fdc_data[fdcu].fdu = -1;
        !           621:                fdc_data[fdcu].state = DEVIDLE;
1.1.1.3   root      622:        }
1.1.1.5 ! root      623:        fd_pseudointr(fdcu);
1.1       root      624: }
                    625: 
1.1.1.5 ! root      626: /* just ensure it has the right spl */
        !           627: fd_pseudointr(fdcu_t fdcu)
        !           628: {
        !           629:        int     s;
        !           630:        s = splbio();
        !           631:        fdintr(fdcu);
        !           632:        splx(s);
        !           633: }
        !           634: 
        !           635: /***********************************************************************\
        !           636: *                                 fdintr                               *
        !           637: * keep calling the state machine until it returns a 0                  *
        !           638: * ALWAYS called at SPLBIO                                              *
        !           639: \***********************************************************************/
        !           640: fdintr(fdcu_t fdcu)
        !           641: {
        !           642:        fdc_p fdc = fdc_data + fdcu;
        !           643:        while(fdstate(fdcu, fdc));
        !           644: }
        !           645: 
        !           646: /***********************************************************************\
        !           647: * The controller state machine.                                                *
        !           648: * if it returns a non zero value, it should be called again immediatly *
        !           649: \***********************************************************************/
        !           650: int fdstate(fdcu_t fdcu, fdc_p fdc)
1.1       root      651: {
1.1.1.3   root      652:        int read,head,trac,sec,i,s,sectrac,cyl,st0;
1.1       root      653:        unsigned long blknum;
1.1.1.5 ! root      654:        fdu_t fdu = fdc->fdu;
        !           655:        fd_p fd;
        !           656:        register struct buf *dp,*bp;
1.1       root      657: 
1.1.1.5 ! root      658:        dp = &(fdc->head);
1.1       root      659:        bp = dp->b_actf;
1.1.1.5 ! root      660:        if(!bp) 
        !           661:        {
        !           662:                /***********************************************\
        !           663:                * nothing left for this controller to do        *
        !           664:                * Force into the IDLE state,                    *
        !           665:                \***********************************************/
        !           666:                fdc->state = DEVIDLE;
        !           667:                if(fdc->fd)
        !           668:                {
        !           669:                        printf("unexpected valid fd pointer (fdu = %d)\n"
        !           670:                                                ,fdc->fdu);
        !           671:                        fdc->fd = (fd_p) 0;
        !           672:                        fdc->fdu = -1;
        !           673:                }
        !           674:                TRACE1("[fdc%d IDLE]",fdcu);
        !           675:                return(0);
        !           676:        }
        !           677:        fdu = FDUNIT(minor(bp->b_dev));
        !           678:        fd = fd_data + fdu;
        !           679:        if (fdc->fd && (fd != fdc->fd))
        !           680:        {
        !           681:                printf("confused fd pointers\n");
        !           682:        }
1.1       root      683:        read = bp->b_flags & B_READ;
1.1.1.5 ! root      684:        TRACE1("fd%d",fdu);
        !           685:        TRACE1("[%s]",fdstates[fdc->state]);
        !           686:        TRACE1("(0x%x)",fd->flags);
        !           687:        untimeout((timeout_t)fd_turnoff, (caddr_t)fdu);
        !           688:        timeout((timeout_t)fd_turnoff, (caddr_t)fdu, 4 * hz);
        !           689:        switch (fdc->state)
        !           690:        {
        !           691:        case DEVIDLE:
        !           692:        case FINDWORK:  /* we have found new work */
        !           693:                fdc->retry = 0;
        !           694:                fd->skip = 0;
        !           695:                fdc->fd = fd;
        !           696:                fdc->fdu = fdu;
        !           697:                /*******************************************************\
        !           698:                * If the next drive has a motor startup pending, then   *
        !           699:                * it will start up in it's own good time                *
        !           700:                \*******************************************************/
        !           701:                if(fd->flags & FD_MOTOR_WAIT)
        !           702:                {
        !           703:                        fdc->state = MOTORWAIT;
        !           704:                        return(0); /* come back later */
        !           705:                }
        !           706:                /*******************************************************\
        !           707:                * Maybe if it's not starting, it SHOULD be starting     *
        !           708:                \*******************************************************/
        !           709:                if (!(fd->flags & FD_MOTOR))
        !           710:                {
        !           711:                        fdc->state = MOTORWAIT;
        !           712:                        fd_turnon(fdu);
        !           713:                        return(0);
        !           714:                }
        !           715:                else    /* at least make sure we are selected */
        !           716:                {
        !           717:                        set_motor(fdcu,fd->fdsu,0);
        !           718:                }
        !           719:                fdc->state = DOSEEK;
        !           720:                break;
        !           721:        case DOSEEK:
        !           722:                if (bp->b_cylin == fd->track)
        !           723:                {
        !           724:                        fdc->state = SEEKCOMPLETE;
        !           725:                        break;
        !           726:                }
        !           727:                out_fdc(fdcu,NE7CMD_SEEK);      /* Seek function */
        !           728:                out_fdc(fdcu,fd->fdsu);         /* Drive number */
        !           729:                out_fdc(fdcu,bp->b_cylin * fd->ft->steptrac);
        !           730:                fd->track = -2;
        !           731:                fdc->state = SEEKWAIT;
        !           732:                return(0);      /* will return later */
        !           733:        case SEEKWAIT:
        !           734:                /* allow heads to settle */
        !           735:                timeout((timeout_t)fd_pseudointr, (caddr_t)fdcu, hz/50);
        !           736:                fdc->state = SEEKCOMPLETE;
        !           737:                return(0);      /* will return later */
        !           738:                break;
        !           739:                
        !           740:        case SEEKCOMPLETE : /* SEEK DONE, START DMA */
1.1       root      741:                /* Make sure seek really happened*/
1.1.1.5 ! root      742:                if(fd->track == -2)
        !           743:                {
        !           744:                        int descyl = bp->b_cylin * fd->ft->steptrac;
        !           745:                        out_fdc(fdcu,NE7CMD_SENSEI);
        !           746:                        i = in_fdc(fdcu);
        !           747:                        cyl = in_fdc(fdcu);
        !           748:                        if (cyl != descyl)
        !           749:                        {
        !           750:                                printf("fd%d: Seek to cyl %d failed; am at cyl %d (ST0 = 0x%x)\n", fdu,
        !           751:                                descyl, cyl, i, NE7_ST0BITS);
        !           752:                                return(retrier(fdcu));
1.1       root      753:                        }
                    754:                }
                    755: 
1.1.1.5 ! root      756:                fd->track = bp->b_cylin;
        !           757:                isa_dmastart(bp->b_flags, bp->b_un.b_addr+fd->skip,
        !           758:                        FDBLK, fdc->dmachan);
1.1       root      759:                blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK
1.1.1.5 ! root      760:                        + fd->skip/FDBLK;
        !           761:                sectrac = fd->ft->sectrac;
        !           762:                sec = blknum %  (sectrac * fd->ft->heads);
1.1       root      763:                head = sec / sectrac;
                    764:                sec = sec % sectrac + 1;
1.1.1.5 ! root      765: /*XXX*/                fd->hddrv = ((head&1)<<2)+fdu;
1.1       root      766: 
1.1.1.5 ! root      767:                if (read)
        !           768:                {
        !           769:                        out_fdc(fdcu,NE7CMD_READ);      /* READ */
        !           770:                }
        !           771:                else
        !           772:                {
        !           773:                        out_fdc(fdcu,NE7CMD_WRITE);     /* WRITE */
        !           774:                }
        !           775:                out_fdc(fdcu,head << 2 | fdu);  /* head & unit */
        !           776:                out_fdc(fdcu,fd->track);                /* track */
        !           777:                out_fdc(fdcu,head);
        !           778:                out_fdc(fdcu,sec);                      /* sector XXX +1? */
        !           779:                out_fdc(fdcu,fd->ft->secsize);          /* sector size */
        !           780:                out_fdc(fdcu,sectrac);          /* sectors/track */
        !           781:                out_fdc(fdcu,fd->ft->gap);              /* gap size */
        !           782:                out_fdc(fdcu,fd->ft->datalen);          /* data length */
        !           783:                fdc->state = IOCOMPLETE;
        !           784:                timeout((timeout_t)fd_timeout, (caddr_t)fdcu, 2 * hz);
        !           785:                return(0);      /* will return later */
        !           786:        case IOCOMPLETE: /* IO DONE, post-analyze */
        !           787:                untimeout((timeout_t)fd_timeout, (caddr_t)fdcu);
        !           788:                for(i=0;i<7;i++)
        !           789:                {
        !           790:                        fdc->status[i] = in_fdc(fdcu);
        !           791:                }
        !           792:        case IOTIMEDOUT: /*XXX*/
        !           793:                isa_dmadone(bp->b_flags, bp->b_un.b_addr+fd->skip,
        !           794:                        FDBLK, fdc->dmachan);
        !           795:                if (fdc->status[0]&0xF8)
        !           796:                {
        !           797:                        return(retrier(fdcu));
1.1       root      798:                }
                    799:                /* All OK */
1.1.1.5 ! root      800:                fd->skip += FDBLK;
        !           801:                if (fd->skip < bp->b_bcount)
        !           802:                {
        !           803:                        /* set up next transfer */
        !           804:                        blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK
        !           805:                                + fd->skip/FDBLK;
        !           806:                        bp->b_cylin = (blknum / (fd->ft->sectrac * fd->ft->heads));
        !           807:                        fdc->state = DOSEEK;
        !           808:                }
        !           809:                else
        !           810:                {
1.1       root      811:                        /* ALL DONE */
1.1.1.5 ! root      812:                        fd->skip = 0;
1.1       root      813:                        bp->b_resid = 0;
                    814:                        dp->b_actf = bp->av_forw;
                    815:                        biodone(bp);
1.1.1.5 ! root      816:                        fdc->fd = (fd_p) 0;
        !           817:                        fdc->fdu = -1;
        !           818:                        fdc->state = FINDWORK;
1.1       root      819:                }
1.1.1.5 ! root      820:                return(1);
        !           821:        case RESETCTLR:
1.1       root      822:                /* Try a reset, keep motor on */
1.1.1.5 ! root      823:                set_motor(fdcu,fd->fdsu,1);
1.1.1.3   root      824:                DELAY(100);
1.1.1.5 ! root      825:                set_motor(fdcu,fd->fdsu,0);
        !           826:                outb(fdc->baseport+fdctl,fd->ft->trans);
        !           827:                TRACE1("[0x%x->fdctl]",fd->ft->trans);
        !           828:                fdc->retry++;
        !           829:                fdc->state = STARTRECAL;
1.1       root      830:                break;
1.1.1.5 ! root      831:        case STARTRECAL:
        !           832:                out_fdc(fdcu,NE7CMD_SPECIFY); /* specify command */
        !           833:                out_fdc(fdcu,0xDF);
        !           834:                out_fdc(fdcu,2);
        !           835:                out_fdc(fdcu,NE7CMD_RECAL);     /* Recalibrate Function */
        !           836:                out_fdc(fdcu,fdu);
        !           837:                fdc->state = RECALWAIT;
        !           838:                return(0);      /* will return later */
        !           839:        case RECALWAIT:
1.1.1.3   root      840:                /* allow heads to settle */
1.1.1.5 ! root      841:                timeout((timeout_t)fd_pseudointr, (caddr_t)fdcu, hz/30);
        !           842:                fdc->state = RECALCOMPLETE;
        !           843:                return(0);      /* will return later */
        !           844:        case RECALCOMPLETE:
        !           845:                out_fdc(fdcu,NE7CMD_SENSEI);
        !           846:                st0 = in_fdc(fdcu);
        !           847:                cyl = in_fdc(fdcu);
        !           848:                if (cyl != 0)
        !           849:                {
        !           850:                        printf("fd%d: recal failed ST0 %b cyl %d\n", fdu,
        !           851:                                st0, NE7_ST0BITS, cyl);
        !           852:                        return(retrier(fdcu));
        !           853:                }
        !           854:                fd->track = 0;
        !           855:                /* Seek (probably) necessary */
        !           856:                fdc->state = DOSEEK;
        !           857:                return(1);      /* will return immediatly */
        !           858:        case    MOTORWAIT:
        !           859:                if(fd->flags & FD_MOTOR_WAIT)
        !           860:                {
        !           861:                        return(0); /* time's not up yet */
        !           862:                }
        !           863:                fdc->state = DOSEEK;
        !           864:                return(1);      /* will return immediatly */
1.1       root      865:        default:
                    866:                printf("Unexpected FD int->");
1.1.1.5 ! root      867:                out_fdc(fdcu,NE7CMD_SENSEI);
        !           868:                st0 = in_fdc(fdcu);
        !           869:                cyl = in_fdc(fdcu);
1.1       root      870:                printf("ST0 = %lx, PCN = %lx\n",i,sec);
1.1.1.5 ! root      871:                out_fdc(fdcu,0x4A); 
        !           872:                out_fdc(fdcu,fd->fdsu);
1.1       root      873:                for(i=0;i<7;i++) {
1.1.1.5 ! root      874:                        fdc->status[i] = in_fdc(fdcu);
1.1       root      875:                }
                    876:        printf("intr status :%lx %lx %lx %lx %lx %lx %lx ",
1.1.1.5 ! root      877:                fdc->status[0],
        !           878:                fdc->status[1],
        !           879:                fdc->status[2],
        !           880:                fdc->status[3],
        !           881:                fdc->status[4],
        !           882:                fdc->status[5],
        !           883:                fdc->status[6] );
        !           884:                return(0);
1.1       root      885:        }
1.1.1.5 ! root      886:        return(1); /* Come back immediatly to new state */
        !           887: }
        !           888: 
        !           889: retrier(fdcu_t fdcu)
        !           890: {
        !           891:        fdc_p fdc = fdc_data + fdcu;
        !           892:        register struct buf *dp,*bp;
        !           893: 
        !           894:        dp = &(fdc->head);
        !           895:        bp = dp->b_actf;
        !           896: 
        !           897:        switch(fdc->retry)
        !           898:        {
        !           899:        case 0: case 1: case 2:
        !           900:                fdc->state = SEEKCOMPLETE;
        !           901:                break;
        !           902:        case 3: case 4: case 5:
        !           903:                fdc->state = STARTRECAL;
        !           904:                break;
1.1.1.3   root      905:        case 6:
1.1.1.5 ! root      906:                fdc->state = RESETCTLR;
        !           907:                break;
1.1.1.3   root      908:        case 7:
1.1       root      909:                break;
                    910:        default:
1.1.1.5 ! root      911:                {
        !           912:                        printf("fd%d: hard error (ST0 %b ",
        !           913:                                 fdc->fdu, fdc->status[0], NE7_ST0BITS);
        !           914:                        printf(" ST1 %b ", fdc->status[1], NE7_ST1BITS);
        !           915:                        printf(" ST2 %b ", fdc->status[2], NE7_ST2BITS);
        !           916:                        printf(" ST3 %b ", fdc->status[3], NE7_ST3BITS);
        !           917:                        printf("cyl %d hd %d sec %d)\n",
        !           918:                                 fdc->status[4], fdc->status[5], fdc->status[6]);
        !           919:                }
        !           920:                bp->b_flags |= B_ERROR;
        !           921:                bp->b_error = EIO;
        !           922:                bp->b_resid = bp->b_bcount - fdc->fd->skip;
        !           923:                dp->b_actf = bp->av_forw;
        !           924:                fdc->fd->skip = 0;
        !           925:                biodone(bp);
        !           926:                fdc->state = FINDWORK;
        !           927:                fdc->fd = (fd_p) 0;
        !           928:                fdc->fdu = -1;
        !           929:                return(1);
1.1       root      930:        }
1.1.1.5 ! root      931:        fdc->retry++;
        !           932:        return(1);
1.1       root      933: }
1.1.1.5 ! root      934: 
1.1       root      935: #endif
1.1.1.5 ! root      936: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.