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

1.1       root        1: /*-
                      2:  * Copyright (c) 1990 The Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * This code is derived from software contributed to Berkeley by
                      6:  * Don Ahn.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *     This product includes software developed by the University of
                     19:  *     California, Berkeley and its contributors.
                     20:  * 4. Neither the name of the University nor the names of its contributors
                     21:  *    may be used to endorse or promote products derived from this software
                     22:  *    without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     34:  * SUCH DAMAGE.
                     35:  *
                     36:  *     @(#)fd.c        7.4 (Berkeley) 5/25/91
                     37:  */
                     38: 
                     39: #include "fd.h"
1.1.1.4 ! root       40: #if NFDC > 0
1.1       root       41: 
                     42: #include "param.h"
                     43: #include "dkbad.h"
                     44: #include "systm.h"
                     45: #include "conf.h"
                     46: #include "file.h"
                     47: #include "ioctl.h"
                     48: #include "buf.h"
                     49: #include "uio.h"
                     50: #include "i386/isa/isa_device.h"
                     51: #include "i386/isa/fdreg.h"
                     52: #include "i386/isa/icu.h"
1.1.1.3   root       53: #include "i386/isa/rtc.h"
1.1       root       54: 
1.1.1.2   root       55: #define        FDUNIT(s)       ((s>>3)&1)
                     56: #define        FDTYPE(s)       ((s)&7)
1.1       root       57: 
                     58: #define b_cylin b_resid
                     59: #define b_step b_resid
                     60: #define FDBLK 512
1.1.1.4 ! root       61: #define NUMTYPES 4+1
1.1       root       62: 
                     63: struct fd_type {
                     64:        int     sectrac;                /* sectors per track         */
                     65:        int     secsize;                /* size code for sectors     */
                     66:        int     datalen;                /* data len when secsize = 0 */
                     67:        int     gap;                    /* gap len between sectors   */
                     68:        int     tracks;                 /* total num of tracks       */
                     69:        int     size;                   /* size of disk in sectors   */
                     70:        int     steptrac;               /* steps per cylinder        */
                     71:        int     trans;                  /* transfer speed code       */
                     72: };
                     73: 
                     74: struct fd_type fd_types[NUMTYPES] = {
1.1.1.4 ! root       75:        { 0 },                          /* non-existant */
1.1       root       76:        { 18,2,0xFF,0x1B,80,2880,1,0 }, /* 1.44 meg HD 3.5in floppy    */
                     77:        { 15,2,0xFF,0x1B,80,2400,1,0 }, /* 1.2 meg HD floppy           */
                     78:        { 9,2,0xFF,0x23,40,720,2,1 },   /* 360k floppy in 1.2meg drive */
                     79:        { 9,2,0xFF,0x2A,40,720,1,1 },   /* 360k floppy in DD drive     */
                     80: };
                     81: 
                     82: struct fd_u {
                     83:        int type;               /* Drive type (HD, DD     */
                     84:        int active;             /* Drive activity boolean */
                     85:        int motor;              /* Motor on flag          */
                     86:        struct buf head;        /* Head of buf chain      */
                     87:        struct buf rhead;       /* Raw head of buf chain  */
                     88:        int reset;
                     89: } fd_unit[NFD];
                     90: 
                     91: 
1.1.1.3   root       92: struct buf fdtab, fdutab[NFD]; /* controller activity */
1.1       root       93: extern int hz;
                     94: 
                     95: /* state needed for current transfer */
                     96: static fdc;    /* floppy disk controller io base register */
1.1.1.3   root       97: int    fd_dmachan;
1.1       root       98: static int fd_skip;
                     99: static int fd_state;
                    100: static int fd_retry;
                    101: static int fd_drive;
1.1.1.3   root      102: static int fd_hddrv;
1.1       root      103: static int fd_track = -1;
                    104: static int fd_status[7];
                    105: 
                    106: /****************************************************************************/
                    107: /*                      autoconfiguration stuff                             */
                    108: /****************************************************************************/
1.1.1.4 ! root      109: int fdprobe(struct isa_device *);
        !           110: int fdattach(struct isa_device *);
        !           111: int fd_turnoff(int);
1.1       root      112: 
1.1.1.4 ! root      113: struct isa_driver fdcdriver = {
        !           114:        fdprobe, fdattach, "fdc",
1.1       root      115: };
                    116: 
1.1.1.3   root      117: /*
                    118:  * probe for existance of controller
                    119:  */
1.1.1.4 ! root      120: fdprobe(struct isa_device *dev)
1.1       root      121: {
1.1.1.3   root      122:        fdc = dev->id_iobase;
                    123: 
                    124:        /* see if it can handle a command */
                    125:        if (out_fdc(NE7CMD_SPECIFY) < 0) {
                    126:                fdc = 0;
                    127:                return(0);
                    128:        }
                    129:        out_fdc(0xDF);
                    130:        out_fdc(2);
1.1.1.4 ! root      131:        return 8;
1.1       root      132: }
                    133: 
1.1.1.3   root      134: /*
                    135:  * wire controller into system, look for floppy units
                    136:  */
1.1.1.4 ! root      137: fdattach(struct isa_device *dev)
1.1.1.3   root      138: {
1.1.1.4 ! root      139:        unsigned fdt, unit, fddrive, fdunit;
        !           140:        extern struct isa_device isa_biotab_fdc[];
        !           141:        struct isa_device *fdutab;
        !           142:        unsigned st0, cyl;
1.1.1.3   root      143: 
                    144:        fd_dmachan = dev->id_drq;
                    145: 
                    146:        fdt = rtcin(RTC_FDISKETTE);
1.1.1.4 ! root      147:        unit = dev->id_unit;
        !           148:        if (unit >= NFDC)
        !           149:                return;
1.1.1.3   root      150: 
1.1.1.4 ! root      151:        for (fdutab = isa_biotab_fdc; fdutab->id_driver != 0; fdutab++) {
        !           152:                fdunit = fdutab->id_unit;
        !           153:                if (fdunit >= NFD)
        !           154:                        continue;
        !           155:                fddrive = fdutab->id_physid;
        !           156:                if (fddrive == 1)
        !           157:                        fdt <<= 4;
        !           158:        
1.1.1.3   root      159:                /* is there a unit? */
1.1.1.4 ! root      160:                if ((fdt & 0xf0) == RTCFDT_NONE) {
        !           161:                        /*printf("fd%d: <no drive> on fdc%d slave %d\n", fddrive,
        !           162:                                dev->id_unit, fdunit);*/
1.1.1.3   root      163:                        continue;
1.1.1.4 ! root      164:                }
1.1.1.3   root      165: 
1.1.1.4 ! root      166:                fd_turnon(fddrive);
1.1.1.3   root      167:                DELAY(10000);
                    168:                out_fdc(NE7CMD_RECAL);  /* Recalibrate Function */
1.1.1.4 ! root      169:                out_fdc(fddrive);
        !           170:                DELAY(30000);
        !           171:                out_fdc(NE7CMD_SENSEI); /* anything responding */
1.1.1.3   root      172:                st0 = in_fdc();
                    173:                cyl = in_fdc();
                    174:                if (st0 & 0xd0)
                    175:                        continue;
                    176: 
                    177:                if ((fdt & 0xf0) == RTCFDT_12M) {
1.1.1.4 ! root      178:                        printf("fd%d at fdc%d slave %d: <1.2M>\n", fddrive,
        !           179:                                dev->id_unit, fdunit);
        !           180:                        fd_unit[fdunit].type = 2;
1.1.1.3   root      181:                }
                    182:                if ((fdt & 0xf0) == RTCFDT_144M) {
1.1.1.4 ! root      183:                        printf("fd%d at fdc%d slave %d: <1.44M>\n", fddrive,
        !           184:                                dev->id_unit, fdunit);
        !           185:                        fd_unit[fdunit].type = 1;
1.1.1.3   root      186:                }
                    187: 
1.1.1.4 ! root      188:                outb(fdc+fdctl,0);      /* Set transfer to 500kbps */
1.1       root      189: 
1.1.1.4 ! root      190:                fd_turnoff(fddrive);
        !           191:        }
1.1       root      192: }
                    193: 
                    194: int
                    195: fdsize(dev)
                    196: dev_t  dev;
                    197: {
1.1.1.3   root      198:        return(0);
1.1       root      199: }
                    200: 
                    201: /****************************************************************************/
                    202: /*                               fdstrategy                                 */
                    203: /****************************************************************************/
                    204: fdstrategy(bp)
                    205:        register struct buf *bp;        /* IO operation to perform */
                    206: {
                    207:        register struct buf *dp,*dp0,*dp1;
                    208:        long nblocks,blknum;
                    209:        int     unit, type, s;
                    210: 
                    211:        unit = FDUNIT(minor(bp->b_dev));
1.1.1.3   root      212:        /*type = FDTYPE(minor(bp->b_dev));*/
                    213:        type = fd_unit[unit].type;
1.1.1.4 ! root      214:        if(type == 0) {
        !           215:                bp->b_error = EINVAL;
        !           216:                bp->b_flags |= B_ERROR;
        !           217:                goto bad;
        !           218:        }
1.1       root      219: 
                    220: #ifdef FDTEST
                    221: printf("fdstrat%d, blk = %d, bcount = %d, addr = %x|",
                    222:        unit, bp->b_blkno, bp->b_bcount,bp->b_un.b_addr);
                    223: #endif
                    224:        if ((unit >= NFD) || (bp->b_blkno < 0)) {
                    225:                printf("fdstrat: unit = %d, blkno = %d, bcount = %d\n",
                    226:                        unit, bp->b_blkno, bp->b_bcount);
                    227:                pg("fd:error in fdstrategy");
                    228:                bp->b_error = EINVAL;
                    229:                bp->b_flags |= B_ERROR;
                    230:                goto bad;
                    231:        }
                    232:        /*
                    233:         * Set up block calculations.
                    234:         */
                    235:        blknum = (unsigned long) bp->b_blkno * DEV_BSIZE/FDBLK;
                    236:        nblocks = fd_types[type].size;
                    237:        if (blknum + (bp->b_bcount / FDBLK) > nblocks) {
                    238:                if (blknum == nblocks) {
                    239:                        bp->b_resid = bp->b_bcount;
                    240:                } else {
                    241:                        bp->b_error = ENOSPC;
                    242:                        bp->b_flags |= B_ERROR;
                    243:                }
                    244:                goto bad;
                    245:        }
                    246:        bp->b_cylin = blknum / (fd_types[type].sectrac * 2);
                    247:        dp = &fd_unit[unit].head;
                    248:        dp->b_step = (fd_types[fd_unit[unit].type].steptrac);
                    249:        s = splbio();
                    250:        disksort(dp, bp);
1.1.1.3   root      251:        if (dp->b_active == 0) {
1.1       root      252: #ifdef FDDEBUG
                    253: printf("T|");
                    254: #endif
                    255:                dp->b_active = 1;
                    256:                fd_drive = unit;
                    257:                fd_track = -1;  /* force seek on first xfer */
                    258:                untimeout(fd_turnoff,unit);
                    259:                fdstart(unit);          /* start drive if idle */
                    260:        }
                    261:        splx(s);
                    262:        return;
                    263: 
                    264: bad:
                    265:        biodone(bp);
                    266: }
                    267: 
                    268: /****************************************************************************/
                    269: /*                            motor control stuff                           */
                    270: /****************************************************************************/
                    271: set_motor(unit,reset)
                    272: int unit,reset;
                    273: {
                    274:        int m0,m1;
                    275:        m0 = fd_unit[0].motor;
                    276:        m1 = fd_unit[1].motor;
1.1.1.3   root      277:        outb(fdc+fdout, (unit&FDO_FDSEL)
                    278:                | (reset ? 0 : (FDO_FRST|FDO_FDMAEN))
                    279:                | (m0 ? FDO_MOEN0 : 0)
                    280:                | (m1 ? FDO_MOEN1 : 0));
1.1       root      281: }
                    282: 
                    283: fd_turnoff(unit)
                    284: int unit;
                    285: {
                    286:        fd_unit[unit].motor = 0;
                    287:        if (unit) set_motor(0,0);
                    288:        else set_motor(1,0);
                    289: }
                    290: 
                    291: fd_turnon(unit)
                    292: int unit;
                    293: {
                    294:        fd_unit[unit].motor = 1;
                    295:        set_motor(unit,0);
                    296: }
                    297: 
                    298: /****************************************************************************/
                    299: /*                             fdc in/out                                   */
                    300: /****************************************************************************/
                    301: int
                    302: in_fdc()
                    303: {
1.1.1.3   root      304:        int i, j = 100000;
                    305:        while ((i = inb(fdc+fdsts) & (NE7_DIO|NE7_RQM)) != (NE7_DIO|NE7_RQM) && j-- > 0)
1.1       root      306:                if (i == NE7_RQM) return -1;
1.1.1.3   root      307:        if (j <= 0)
                    308:                return(-1);
1.1       root      309:        return inb(fdc+fddata);
                    310: }
                    311: 
                    312: out_fdc(x)
                    313: int x;
                    314: {
1.1.1.3   root      315:        int i = 100000;
1.1       root      316: 
1.1.1.3   root      317:        while ((inb(fdc+fdsts) & NE7_DIO) && i-- > 0);
                    318:        while ((inb(fdc+fdsts) & NE7_RQM) == 0 && i-- > 0);
                    319:        if (i <= 0) return (-1);
                    320:        outb(fdc+fddata,x);
                    321:        return (0);
1.1       root      322: }
                    323: 
1.1.1.3   root      324: static fdopenf;
1.1       root      325: /****************************************************************************/
                    326: /*                           fdopen/fdclose                                 */
                    327: /****************************************************************************/
                    328: Fdopen(dev, flags)
                    329:        dev_t   dev;
                    330:        int     flags;
                    331: {
                    332:        int unit = FDUNIT(minor(dev));
1.1.1.4 ! root      333:        int type = fd_unit[unit].type;
1.1       root      334:        int s;
                    335: 
1.1.1.3   root      336:        fdopenf = 1;
1.1       root      337:        /* check bounds */
                    338:        if (unit >= NFD) return(ENXIO);
1.1.1.4 ! root      339:        if (type >= NUMTYPES || type==0)
        !           340:                return ENXIO;
1.1       root      341: 
                    342:        /* Set proper disk type, only allow one type */
                    343:        return 0;
                    344: }
                    345: 
                    346: fdclose(dev, flags)
                    347:        dev_t dev;
                    348: {
1.1.1.2   root      349:        return(0);
1.1       root      350: }
                    351: 
                    352: 
                    353: /****************************************************************************/
                    354: /*                                 fdstart                                  */
                    355: /****************************************************************************/
                    356: fdstart(unit)
                    357: int unit;
                    358: {
                    359:        register struct buf *dp,*bp;
                    360:        int s;
                    361: 
                    362: #ifdef FDTEST
                    363: printf("st%d|",unit);
                    364: #endif 
1.1.1.3   root      365:        dp = &fd_unit[unit].head;
                    366:        bp = dp->b_actf;
1.1       root      367:        s = splbio();
                    368:        if (!fd_unit[unit].motor) {
                    369:                fd_turnon(unit);
1.1.1.3   root      370: #ifdef notdef
                    371:                if ((bp->b_flags & B_READ) == 0) {
                    372:                        /* Wait for 1 sec */
                    373: #endif
                    374:                        timeout(fdstart,unit,hz);
                    375:                /*}*/
                    376:        } else
1.1       root      377:                 {
                    378:                /* make sure drive is selected as well as on */
                    379: 
                    380:                fd_retry = 0;
                    381:                if (fd_unit[unit].reset) fd_state = 1;
                    382:                else {
                    383:                        /* DO a RESET */
                    384:                        fd_unit[unit].reset = 1;
                    385:                        fd_state = 5;
                    386:                }
                    387:                fd_skip = 0;
                    388: #ifdef FDDEBUG
                    389: printf("Seek %d %d\n", bp->b_cylin, dp->b_step);
                    390: #endif
                    391:                if (bp->b_cylin != fd_track) {
                    392:                /* Seek necessary, never quite sure where head is at! */
1.1.1.3   root      393:                out_fdc(NE7CMD_SEEK);   /* Seek function */
1.1       root      394:                out_fdc(unit);  /* Drive number */
                    395:                out_fdc(bp->b_cylin * dp->b_step);
1.1.1.3   root      396:                fd_state = 6;
                    397:                } else {
                    398:                fd_state = 1;
                    399:                fdintr(0xff);
                    400:                }
1.1       root      401:        }
                    402:        splx(s);
                    403: }
                    404: 
                    405: fd_timeout(x)
                    406: int x;
                    407: {
1.1.1.3   root      408:        int st0, st3, cyl;
1.1       root      409:        struct buf *dp,*bp;
                    410: 
                    411:        dp = &fd_unit[fd_drive].head;
                    412:        bp = dp->b_actf;
                    413: 
1.1.1.3   root      414:        out_fdc(NE7CMD_SENSED);
                    415:        out_fdc(fd_hddrv);
                    416:        st3 = in_fdc();
                    417: 
                    418:        out_fdc(NE7CMD_SENSEI);
                    419:        st0 = in_fdc();
                    420:        cyl = in_fdc();
                    421: printf("fd%d: Operation timeout ST0 %b cyl %d ST3 %b\n", fd_drive,
                    422: st0, NE7_ST0BITS, cyl, st3, NE7_ST3BITS);
1.1       root      423: 
1.1.1.3   root      424:        if (bp) {
                    425:                fd_state = 4;
                    426:                fdintr(fd_drive);
                    427:        }
1.1       root      428: }
                    429: 
                    430: /****************************************************************************/
                    431: /*                                 fdintr                                   */
                    432: /****************************************************************************/
                    433: fdintr(unit)
                    434: {
                    435:        register struct buf *dp,*bp;
                    436:        struct buf *dpother;
1.1.1.3   root      437:        int read,head,trac,sec,i,s,sectrac,cyl,st0;
1.1       root      438:        unsigned long blknum;
                    439:        struct fd_type *ft;
                    440: 
                    441: #ifdef FDTEST
                    442:        printf("state %d, unit %d, dr %d|",fd_state,unit,fd_drive);
                    443: #endif
                    444: 
1.1.1.3   root      445:        if (!fdopenf) return;
1.1       root      446:        dp = &fd_unit[fd_drive].head;
                    447:        bp = dp->b_actf;
                    448:        read = bp->b_flags & B_READ;
1.1.1.3   root      449:        /*ft = &fd_types[FDTYPE(bp->b_dev)];*/
                    450:        ft = &fd_types[fd_unit[fd_drive].type];
1.1       root      451: 
                    452:        switch (fd_state) {
                    453:        case 1 : /* SEEK DONE, START DMA */
                    454:                /* Make sure seek really happened*/
                    455:                if (unit != 0xff) {
1.1.1.3   root      456:                        int descyl = bp->b_cylin * dp->b_step;
                    457:                        out_fdc(NE7CMD_SENSEI);
1.1       root      458:                        i = in_fdc();
                    459:                        cyl = in_fdc();
1.1.1.3   root      460:                        if (cyl != descyl) {
                    461: printf("fd%d: Seek to cyl %d failed; am at cyl %d (ST0 = %b)\n", fd_drive,
                    462: descyl, cyl, i, NE7_ST0BITS);
                    463: fd_state = 4;
1.1       root      464:                                return;
                    465:                        }
                    466:                }
                    467: 
                    468:                fd_track = bp->b_cylin;
1.1.1.3   root      469:                isa_dmastart(bp->b_flags, bp->b_un.b_addr+fd_skip,
                    470:                        FDBLK, fd_dmachan);
1.1       root      471:                blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK
                    472:                        + fd_skip/FDBLK;
                    473:                sectrac = ft->sectrac;
                    474:                sec = blknum %  (sectrac * 2);
                    475:                head = sec / sectrac;
                    476:                sec = sec % sectrac + 1;
1.1.1.3   root      477: fd_hddrv = ((head&1)<<2)+fd_drive;
1.1       root      478: 
1.1.1.3   root      479:                if (read)  out_fdc(NE7CMD_READ);        /* READ */
                    480:                else out_fdc(NE7CMD_WRITE);             /* WRITE */
1.1       root      481:                out_fdc(head << 2 | fd_drive);  /* head & unit */
                    482:                out_fdc(fd_track);              /* track */
                    483:                out_fdc(head);
                    484:                out_fdc(sec);                   /* sector XXX +1? */
                    485:                out_fdc(ft->secsize);           /* sector size */
                    486:                out_fdc(sectrac);               /* sectors/track */
                    487:                out_fdc(ft->gap);               /* gap size */
                    488:                out_fdc(ft->datalen);           /* data length */
                    489:                fd_state = 2;
                    490:                break;
                    491:        case 2 : /* IO DONE, post-analyze */
                    492:                untimeout(fd_timeout,2);
                    493:                for(i=0;i<7;i++) {
                    494:                        fd_status[i] = in_fdc();
                    495:                }
                    496:                if (fd_status[0]&0xF8) {
                    497: #ifdef FDOTHER
                    498: printf("status0 err %d:",fd_status[0]);
                    499: #endif
                    500:                        goto retry;
                    501:                }
                    502:                /* All OK */
1.1.1.3   root      503:                isa_dmadone(bp->b_flags, bp->b_un.b_addr+fd_skip,
                    504:                        FDBLK, fd_dmachan);
1.1       root      505:                fd_skip += FDBLK;
                    506:                if (fd_skip >= bp->b_bcount) {
                    507: #ifdef FDTEST
                    508: printf("DONE %d|", bp->b_blkno);
                    509: #endif
                    510:                        /* ALL DONE */
                    511:                        fd_skip = 0;
                    512:                        bp->b_resid = 0;
                    513:                        dp->b_actf = bp->av_forw;
                    514:                        biodone(bp);
                    515:                        nextstate(dp);
                    516: 
                    517:                } else {
                    518: #ifdef FDDEBUG
                    519: printf("next|");
                    520: #endif
                    521:                        /* set up next transfer */
                    522:                        blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK
                    523:                                + fd_skip/FDBLK;
                    524:                        fd_state = 1;
                    525:                        bp->b_cylin = (blknum / (ft->sectrac * 2));
                    526:                        if (bp->b_cylin != fd_track) {
                    527: #ifdef FDTEST
                    528: printf("Seek|");
                    529: #endif
                    530:                                /* SEEK Necessary */
1.1.1.3   root      531:                                out_fdc(NE7CMD_SEEK);   /* Seek function */
1.1       root      532:                                out_fdc(fd_drive);/* Drive number */
                    533:                                out_fdc(bp->b_cylin * dp->b_step);
1.1.1.3   root      534:                        fd_state = 6;
1.1       root      535:                                break;
                    536:                        } else fdintr(0xff);
                    537:                }
                    538:                break;
                    539:        case 3:
1.1.1.3   root      540:                out_fdc(NE7CMD_SENSEI);
                    541:                st0 = in_fdc();
                    542:                cyl = in_fdc();
                    543:                if (cyl != 0)
                    544:                        printf("fd%d: recal failed ST0 %b cyl %d\n", fd_drive,
                    545:                                st0, NE7_ST0BITS, cyl);
                    546: 
1.1       root      547:                /* Seek necessary */
1.1.1.3   root      548:                out_fdc(NE7CMD_SEEK);   /* Seek function */
1.1       root      549:                out_fdc(fd_drive);/* Drive number */
                    550:                out_fdc(bp->b_cylin * dp->b_step);
1.1.1.3   root      551:                fd_state = 6;
1.1       root      552:                break;
                    553:        case 4:
1.1.1.3   root      554:                out_fdc(NE7CMD_SPECIFY); /* specify command */
1.1       root      555:                out_fdc(0xDF);
                    556:                out_fdc(2);
1.1.1.3   root      557:                out_fdc(NE7CMD_RECAL);  /* Recalibrate Function */
1.1       root      558:                out_fdc(fd_drive);
1.1.1.3   root      559:                fd_state = 7;
1.1       root      560:                break;
                    561:        case 5:
                    562: #ifdef FDOTHER
                    563:                printf("**RESET**\n");
                    564: #endif
                    565:                /* Try a reset, keep motor on */
                    566:                set_motor(fd_drive,1);
1.1.1.3   root      567:                DELAY(100);
1.1       root      568:                set_motor(fd_drive,0);
                    569:                outb(fdc+fdctl,ft->trans);
                    570:                fd_retry++;
                    571:                fd_state = 4;
                    572:                break;
1.1.1.3   root      573:        case 6:
                    574:                /* allow heads to settle */
                    575:                timeout(fdintr,fd_drive,hz/30);
                    576:                fd_state = 1;
                    577:                return;
                    578:                break;
                    579:                
                    580:        case 7:
                    581:                /* allow heads to settle */
                    582:                timeout(fdintr,fd_drive,hz/3);
                    583:                fd_state = 3;
                    584:                return;
                    585:                break;
                    586:                
1.1       root      587:        default:
                    588:                printf("Unexpected FD int->");
1.1.1.3   root      589:                out_fdc(NE7CMD_SENSEI);
                    590:                st0 = in_fdc();
                    591:                cyl = in_fdc();
1.1       root      592:                printf("ST0 = %lx, PCN = %lx\n",i,sec);
                    593:                out_fdc(0x4A); 
                    594:                out_fdc(fd_drive);
                    595:                for(i=0;i<7;i++) {
                    596:                        fd_status[i] = in_fdc();
                    597:                }
                    598:        printf("intr status :%lx %lx %lx %lx %lx %lx %lx ",
                    599:                fd_status[0], fd_status[1], fd_status[2], fd_status[3],
                    600:                fd_status[4], fd_status[5], fd_status[6] );
                    601:                break;
                    602:        }
                    603:        return;
                    604: retry:
                    605:        switch(fd_retry) {
                    606:        case 0: case 1:
1.1.1.3   root      607:        case 2:
1.1       root      608:                break;
1.1.1.3   root      609:        case 3:
1.1       root      610:        case 4:
1.1.1.3   root      611:        case 5:
                    612:                fd_retry++;
                    613:                fd_state = 4;
                    614:                fdintr(0xff);
                    615:                return;
                    616:        case 6:
1.1       root      617:                fd_retry++;
                    618:                fd_state = 5;
                    619:                fdintr(0xff);
                    620:                return;
1.1.1.3   root      621:        case 7:
1.1       root      622:                break;
                    623:        default:
1.1.1.3   root      624: /*printf("fd%d: hard error (ST0 %b ST1 %b ST2 %b ST3 %b cyl %d hd %d sec %d)\n",
                    625:                fd_drive, fd_status[0], NE7_ST0BITS, fd_status[1], NE7_ST1BITS,
                    626:                fd_status[2], NE7_ST2BITS,  fd_status[3], NE7_ST3BITS, 
                    627:                fd_status[4], fd_status[5], fd_status[6]);*/
                    628: printf("fd%d: hard error (ST0 %b ", fd_drive, fd_status[0], NE7_ST0BITS);
                    629: printf(" ST1 %b ", fd_status[1], NE7_ST1BITS);
                    630: printf(" ST2 %b ", fd_status[2], NE7_ST2BITS);
                    631: printf(" ST3 %b ", fd_status[3], NE7_ST3BITS);
                    632: printf("cyl %d hd %d sec %d)\n", fd_status[4], fd_status[5], fd_status[6]);
1.1       root      633:                badtrans(dp,bp);
                    634:                return;
                    635:        }
                    636:        fd_state = 1;
                    637:        fd_retry++;
                    638:        fdintr(0xff);
                    639: }
                    640: 
                    641: badtrans(dp,bp)
                    642: struct buf *dp,*bp;
                    643: {
                    644: 
                    645:        bp->b_flags |= B_ERROR;
                    646:        bp->b_error = EIO;
                    647:        bp->b_resid = bp->b_bcount - fd_skip;
                    648:        dp->b_actf = bp->av_forw;
                    649:        fd_skip = 0;
                    650:        biodone(bp);
                    651:        nextstate(dp);
                    652: 
                    653: }
                    654: 
                    655: /*
                    656:        nextstate : After a transfer is done, continue processing
                    657:        requests on the current drive queue.  If empty, go to
                    658:        the other drives queue.  If that is empty too, timeout
                    659:        to turn off the current drive in 5 seconds, and go
                    660:        to state 0 (not expecting any interrupts).
                    661: */
                    662: 
                    663: nextstate(dp)
                    664: struct buf *dp;
                    665: {
                    666:        struct buf *dpother;
                    667:        
                    668:        if (dp->b_actf) fdstart(fd_drive);
1.1.1.3   root      669:        else {
1.1       root      670:                untimeout(fd_turnoff,fd_drive);
1.1.1.3   root      671:                timeout(fd_turnoff,fd_drive,hz);
1.1       root      672:                fd_state = 0;
                    673:                dp->b_active = 0;
                    674:        }
                    675: }
                    676: #endif

unix.superglobalmegacorp.com

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