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

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"
                     40: #if NFD > 0
                     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"
                     53: 
                     54: #define        FDUNIT(s)       ((s)&1)
                     55: #define        FDTYPE(s)       (((s)>>1)&7)
                     56: 
                     57: #define b_cylin b_resid
                     58: #define b_step b_resid
                     59: #define FDBLK 512
                     60: #define NUMTYPES 4
                     61: 
                     62: struct fd_type {
                     63:        int     sectrac;                /* sectors per track         */
                     64:        int     secsize;                /* size code for sectors     */
                     65:        int     datalen;                /* data len when secsize = 0 */
                     66:        int     gap;                    /* gap len between sectors   */
                     67:        int     tracks;                 /* total num of tracks       */
                     68:        int     size;                   /* size of disk in sectors   */
                     69:        int     steptrac;               /* steps per cylinder        */
                     70:        int     trans;                  /* transfer speed code       */
                     71: };
                     72: 
                     73: struct fd_type fd_types[NUMTYPES] = {
                     74:        { 18,2,0xFF,0x1B,80,2880,1,0 }, /* 1.44 meg HD 3.5in floppy    */
                     75:        { 15,2,0xFF,0x1B,80,2400,1,0 }, /* 1.2 meg HD floppy           */
                     76:        { 9,2,0xFF,0x23,40,720,2,1 },   /* 360k floppy in 1.2meg drive */
                     77:        { 9,2,0xFF,0x2A,40,720,1,1 },   /* 360k floppy in DD drive     */
                     78: };
                     79: 
                     80: struct fd_u {
                     81:        int type;               /* Drive type (HD, DD     */
                     82:        int active;             /* Drive activity boolean */
                     83:        int motor;              /* Motor on flag          */
                     84:        struct buf head;        /* Head of buf chain      */
                     85:        struct buf rhead;       /* Raw head of buf chain  */
                     86:        int reset;
                     87: } fd_unit[NFD];
                     88: 
                     89: 
                     90: extern int hz;
                     91: 
                     92: /* state needed for current transfer */
                     93: static fdc;    /* floppy disk controller io base register */
                     94: int    fd_dmachan = 2;
                     95: static int fd_skip;
                     96: static int fd_state;
                     97: static int fd_retry;
                     98: static int fd_drive;
                     99: static int fd_track = -1;
                    100: static int fd_status[7];
                    101: 
                    102: /*
                    103:        make sure bounce buffer for DMA is aligned since the DMA chip
                    104:        doesn't roll over properly over a 64k boundary
                    105: */
                    106: extern struct buf *dma_bounce[];
                    107: 
                    108: /****************************************************************************/
                    109: /*                      autoconfiguration stuff                             */
                    110: /****************************************************************************/
                    111: int fdprobe(), fdattach(), fd_turnoff();
                    112: 
                    113: struct isa_driver fddriver = {
                    114:        fdprobe, fdattach, "fd",
                    115: };
                    116: 
                    117: fdprobe(dev)
                    118: struct isa_device *dev;
                    119: {
                    120:        return 1;
                    121: }
                    122: 
                    123: fdattach(dev)
                    124: struct isa_device *dev;
                    125: {      int     s;
                    126: 
                    127:        fdc = dev->id_iobase;
                    128:        /* Set transfer to 500kbps */
                    129:        outb(fdc+fdctl,0);
                    130:        fd_turnoff(0);
                    131: }
                    132: 
                    133: int
                    134: fdsize(dev)
                    135: dev_t  dev;
                    136: {
                    137:        return(2400);
                    138: }
                    139: 
                    140: /****************************************************************************/
                    141: /*                               fdstrategy                                 */
                    142: /****************************************************************************/
                    143: fdstrategy(bp)
                    144:        register struct buf *bp;        /* IO operation to perform */
                    145: {
                    146:        register struct buf *dp,*dp0,*dp1;
                    147:        long nblocks,blknum;
                    148:        int     unit, type, s;
                    149: 
                    150:        unit = FDUNIT(minor(bp->b_dev));
                    151:        type = FDTYPE(minor(bp->b_dev));
                    152: 
                    153: #ifdef FDTEST
                    154: printf("fdstrat%d, blk = %d, bcount = %d, addr = %x|",
                    155:        unit, bp->b_blkno, bp->b_bcount,bp->b_un.b_addr);
                    156: #endif
                    157:        if ((unit >= NFD) || (bp->b_blkno < 0)) {
                    158:                printf("fdstrat: unit = %d, blkno = %d, bcount = %d\n",
                    159:                        unit, bp->b_blkno, bp->b_bcount);
                    160:                pg("fd:error in fdstrategy");
                    161:                bp->b_error = EINVAL;
                    162:                bp->b_flags |= B_ERROR;
                    163:                goto bad;
                    164:        }
                    165:        /*
                    166:         * Set up block calculations.
                    167:         */
                    168:        blknum = (unsigned long) bp->b_blkno * DEV_BSIZE/FDBLK;
                    169:        nblocks = fd_types[type].size;
                    170:        if (blknum + (bp->b_bcount / FDBLK) > nblocks) {
                    171:                if (blknum == nblocks) {
                    172:                        bp->b_resid = bp->b_bcount;
                    173:                } else {
                    174:                        bp->b_error = ENOSPC;
                    175:                        bp->b_flags |= B_ERROR;
                    176:                }
                    177:                goto bad;
                    178:        }
                    179:        bp->b_cylin = blknum / (fd_types[type].sectrac * 2);
                    180:        dp = &fd_unit[unit].head;
                    181:        dp0 = &fd_unit[0].head;
                    182:        dp1 = &fd_unit[1].head;
                    183:        dp->b_step = (fd_types[fd_unit[unit].type].steptrac);
                    184:        s = splbio();
                    185:        disksort(dp, bp);
                    186:        if ((dp0->b_active == 0)&&(dp1->b_active == 0)) {
                    187: #ifdef FDDEBUG
                    188: printf("T|");
                    189: #endif
                    190:                dp->b_active = 1;
                    191:                fd_drive = unit;
                    192:                fd_track = -1;  /* force seek on first xfer */
                    193:                untimeout(fd_turnoff,unit);
                    194:                fdstart(unit);          /* start drive if idle */
                    195:        }
                    196:        splx(s);
                    197:        return;
                    198: 
                    199: bad:
                    200:        biodone(bp);
                    201: }
                    202: 
                    203: /****************************************************************************/
                    204: /*                            motor control stuff                           */
                    205: /****************************************************************************/
                    206: set_motor(unit,reset)
                    207: int unit,reset;
                    208: {
                    209:        int m0,m1;
                    210:        m0 = fd_unit[0].motor;
                    211:        m1 = fd_unit[1].motor;
                    212:        outb(fdc+fdout,unit | (reset ? 0 : 0xC)  | (m0 ? 16 : 0) | (m1 ? 32 : 0));
                    213: }
                    214: 
                    215: fd_turnoff(unit)
                    216: int unit;
                    217: {
                    218:        fd_unit[unit].motor = 0;
                    219:        if (unit) set_motor(0,0);
                    220:        else set_motor(1,0);
                    221: }
                    222: 
                    223: fd_turnon(unit)
                    224: int unit;
                    225: {
                    226:        fd_unit[unit].motor = 1;
                    227:        set_motor(unit,0);
                    228: }
                    229: 
                    230: /****************************************************************************/
                    231: /*                             fdc in/out                                   */
                    232: /****************************************************************************/
                    233: int
                    234: in_fdc()
                    235: {
                    236:        int i;
                    237:        while ((i = inb(fdc+fdsts) & (NE7_DIO|NE7_RQM)) != (NE7_DIO|NE7_RQM))
                    238:                if (i == NE7_RQM) return -1;
                    239:        return inb(fdc+fddata);
                    240: }
                    241: 
                    242: dump_stat()
                    243: {
                    244:        int i;
                    245:        for(i=0;i<7;i++) {
                    246:                fd_status[i] = in_fdc();
                    247:                if (fd_status[i] < 0) break;
                    248:        }
                    249: printf("FD bad status :%lx %lx %lx %lx %lx %lx %lx\n",
                    250:        fd_status[0], fd_status[1], fd_status[2], fd_status[3],
                    251:        fd_status[4], fd_status[5], fd_status[6] );
                    252: }
                    253: 
                    254: out_fdc(x)
                    255: int x;
                    256: {
                    257:        int r,errcnt;
                    258:        static int maxcnt = 0;
                    259:        errcnt = 0;
                    260:        do {
                    261:                r = (inb(fdc+fdsts) & (NE7_DIO|NE7_RQM));
                    262:                if (r== NE7_RQM) break;
                    263:                if (r==(NE7_DIO|NE7_RQM)) {
                    264:                        dump_stat(); /* error: direction. eat up output */
                    265: #ifdef FDOTHER
                    266: printf("%lx\n",x);
                    267: #endif
                    268:                }
                    269:                /* printf("Error r = %d:",r); */
                    270:                errcnt++;
                    271:        } while (1);
                    272:        if (errcnt > maxcnt) {
                    273:                maxcnt = errcnt;
                    274: #ifdef FDOTHER
                    275: printf("New MAX = %d\n",maxcnt);
                    276: #endif
                    277:        }
                    278:        outb(fdc+fddata,x);
                    279: }
                    280: 
                    281: /* see if fdc responding */
                    282: int
                    283: check_fdc()
                    284: {
                    285:        int i;
                    286:        for(i=0;i<100;i++) {
                    287:                if (inb(fdc+fdsts)& NE7_RQM) return 0;
                    288:        }
                    289:        return 1;
                    290: }
                    291: 
                    292: /****************************************************************************/
                    293: /*                           fdopen/fdclose                                 */
                    294: /****************************************************************************/
                    295: Fdopen(dev, flags)
                    296:        dev_t   dev;
                    297:        int     flags;
                    298: {
                    299:        int unit = FDUNIT(minor(dev));
                    300:        int type = FDTYPE(minor(dev));
                    301:        int s;
                    302: 
                    303:        /* check bounds */
                    304:        if (unit >= NFD) return(ENXIO);
                    305:        if (type >= NUMTYPES) return(ENXIO);
                    306: /*
                    307:        if (check_fdc()) return(EBUSY);
                    308: */
                    309: 
                    310:        /* Set proper disk type, only allow one type */
                    311:        return 0;
                    312: }
                    313: 
                    314: fdclose(dev, flags)
                    315:        dev_t dev;
                    316: {
                    317: }
                    318: 
                    319: /****************************************************************************/
                    320: /*                            fdread/fdwrite                                */
                    321: /****************************************************************************/
                    322: /*
                    323:  * Routines to do raw IO for a unit.
                    324:  */
                    325: fdread(dev, uio)                       /* character read routine */
                    326: dev_t dev;
                    327: struct uio *uio;
                    328: {
                    329:        int unit = FDUNIT(minor(dev)) ;
                    330:        if (unit >= NFD) return(ENXIO);
                    331:        return(physio(fdstrategy,&fd_unit[unit].rhead,dev,B_READ,minphys,uio));
                    332: }
                    333: 
                    334: fdwrite(dev, uio)                      /* character write routine */
                    335: dev_t dev;
                    336: struct uio *uio;
                    337: {
                    338:        int unit = FDUNIT(minor(dev)) ;
                    339:        if (unit >= NFD) return(ENXIO);
                    340:        return(physio(fdstrategy,&fd_unit[unit].rhead,dev,B_WRITE,minphys,uio));
                    341: }
                    342: 
                    343: /****************************************************************************/
                    344: /*                                 fdstart                                  */
                    345: /****************************************************************************/
                    346: fdstart(unit)
                    347: int unit;
                    348: {
                    349:        register struct buf *dp,*bp;
                    350:        int s;
                    351: 
                    352: #ifdef FDTEST
                    353: printf("st%d|",unit);
                    354: #endif 
                    355:        s = splbio();
                    356:        if (!fd_unit[unit].motor) {
                    357:                fd_turnon(unit);
                    358:                /* Wait for 1 sec */
                    359:                timeout(fdstart,unit,hz);
                    360:                /*DELAY(1000000);*/
                    361:        }else
                    362:                 {
                    363:                /* make sure drive is selected as well as on */
                    364:                /*set_motor(unit,0);*/
                    365: 
                    366:                dp = &fd_unit[unit].head;
                    367:                bp = dp->b_actf;
                    368:                fd_retry = 0;
                    369:                if (fd_unit[unit].reset) fd_state = 1;
                    370:                else {
                    371:                        /* DO a RESET */
                    372:                        fd_unit[unit].reset = 1;
                    373:                        fd_state = 5;
                    374:                }
                    375:                fd_skip = 0;
                    376: #ifdef FDDEBUG
                    377: printf("Seek %d %d\n", bp->b_cylin, dp->b_step);
                    378: #endif
                    379:                if (bp->b_cylin != fd_track) {
                    380:                /* Seek necessary, never quite sure where head is at! */
                    381:                out_fdc(15);    /* Seek function */
                    382:                out_fdc(unit);  /* Drive number */
                    383:                out_fdc(bp->b_cylin * dp->b_step);
                    384:                } else fdintr(0xff);
                    385:        }
                    386:        splx(s);
                    387: }
                    388: 
                    389: fd_timeout(x)
                    390: int x;
                    391: {
                    392:        int i,j;
                    393:        struct buf *dp,*bp;
                    394: 
                    395:        dp = &fd_unit[fd_drive].head;
                    396:        bp = dp->b_actf;
                    397: 
                    398:        out_fdc(0x4);
                    399:        out_fdc(fd_drive);
                    400:        i = in_fdc();
                    401:        printf("Timeout drive status %lx\n",i);
                    402: 
                    403:        out_fdc(0x8);
                    404:        i = in_fdc();
                    405:        j = in_fdc();
                    406:        printf("ST0 = %lx, PCN = %lx\n",i,j);
                    407: 
                    408:        if (bp) badtrans(dp,bp);
                    409: }
                    410: 
                    411: /****************************************************************************/
                    412: /*                                 fdintr                                   */
                    413: /****************************************************************************/
                    414: fdintr(unit)
                    415: {
                    416:        register struct buf *dp,*bp;
                    417:        struct buf *dpother;
                    418:        int read,head,trac,sec,i,s,sectrac,cyl;
                    419:        unsigned long blknum;
                    420:        struct fd_type *ft;
                    421: 
                    422: #ifdef FDTEST
                    423:        printf("state %d, unit %d, dr %d|",fd_state,unit,fd_drive);
                    424: #endif
                    425: 
                    426:        dp = &fd_unit[fd_drive].head;
                    427:        bp = dp->b_actf;
                    428:        read = bp->b_flags & B_READ;
                    429:        ft = &fd_types[FDTYPE(bp->b_dev)];
                    430: 
                    431:        switch (fd_state) {
                    432:        case 1 : /* SEEK DONE, START DMA */
                    433:                /* Make sure seek really happened*/
                    434:                if (unit != 0xff) {
                    435:                        out_fdc(0x8);
                    436:                        i = in_fdc();
                    437:                        cyl = in_fdc();
                    438:                        if (!(i&0x20) || (cyl != bp->b_cylin*dp->b_step)) {
                    439: printf("Stray int ST0 = %lx, PCN = %lx:",i,cyl);
                    440:                                return;
                    441:                        }
                    442:                }
                    443: 
                    444:                fd_track = bp->b_cylin;
                    445:                at_dma(read,bp->b_un.b_addr+fd_skip,FDBLK, fd_dmachan);
                    446:                blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK
                    447:                        + fd_skip/FDBLK;
                    448:                sectrac = ft->sectrac;
                    449:                sec = blknum %  (sectrac * 2);
                    450:                head = sec / sectrac;
                    451:                sec = sec % sectrac + 1;
                    452: 
                    453:                if (read)  out_fdc(0xE6);       /* READ */
                    454:                else out_fdc(0xC5);             /* WRITE */
                    455:                out_fdc(head << 2 | fd_drive);  /* head & unit */
                    456:                out_fdc(fd_track);              /* track */
                    457:                out_fdc(head);
                    458:                out_fdc(sec);                   /* sector XXX +1? */
                    459:                out_fdc(ft->secsize);           /* sector size */
                    460:                out_fdc(sectrac);               /* sectors/track */
                    461:                out_fdc(ft->gap);               /* gap size */
                    462:                out_fdc(ft->datalen);           /* data length */
                    463:                fd_state = 2;
                    464:                /* XXX PARANOIA */
                    465:                untimeout(fd_timeout,2);
                    466:                timeout(fd_timeout,2,hz);
                    467:                break;
                    468:        case 2 : /* IO DONE, post-analyze */
                    469:                untimeout(fd_timeout,2);
                    470:                for(i=0;i<7;i++) {
                    471:                        fd_status[i] = in_fdc();
                    472:                }
                    473:                if (fd_status[0]&0xF8) {
                    474: #ifdef FDOTHER
                    475: printf("status0 err %d:",fd_status[0]);
                    476: #endif
                    477:                        goto retry;
                    478:                }
                    479: /*
                    480:                if (fd_status[1]){
                    481:                        printf("status1 err %d:",fd_status[0]);
                    482:                        goto retry;
                    483:                }
                    484:                if (fd_status[2]){
                    485:                        printf("status2 err %d:",fd_status[0]);
                    486:                        goto retry;
                    487:                }
                    488: */
                    489:                /* All OK */
                    490:                if (!kernel_space(bp->b_un.b_addr+fd_skip)) {
                    491:                        /* RAW transfer */
                    492:                        if (read) bcopy(dma_bounce[fd_dmachan]->b_un.b_addr,
                    493:                                bp->b_un.b_addr+fd_skip, FDBLK);
                    494:                }
                    495:                fd_skip += FDBLK;
                    496:                if (fd_skip >= bp->b_bcount) {
                    497: #ifdef FDTEST
                    498: printf("DONE %d|", bp->b_blkno);
                    499: #endif
                    500:                        /* ALL DONE */
                    501:                        fd_skip = 0;
                    502:                        bp->b_resid = 0;
                    503:                        dp->b_actf = bp->av_forw;
                    504:                        biodone(bp);
                    505:                        nextstate(dp);
                    506: 
                    507:                } else {
                    508: #ifdef FDDEBUG
                    509: printf("next|");
                    510: #endif
                    511:                        /* set up next transfer */
                    512:                        blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK
                    513:                                + fd_skip/FDBLK;
                    514:                        fd_state = 1;
                    515:                        bp->b_cylin = (blknum / (ft->sectrac * 2));
                    516:                        if (bp->b_cylin != fd_track) {
                    517: #ifdef FDTEST
                    518: printf("Seek|");
                    519: #endif
                    520:                                /* SEEK Necessary */
                    521:                                out_fdc(15);    /* Seek function */
                    522:                                out_fdc(fd_drive);/* Drive number */
                    523:                                out_fdc(bp->b_cylin * dp->b_step);
                    524:                                break;
                    525:                        } else fdintr(0xff);
                    526:                }
                    527:                break;
                    528:        case 3:
                    529: #ifdef FDOTHER
                    530: printf("Seek %d %d\n", bp->b_cylin, dp->b_step);
                    531: #endif
                    532:                /* Seek necessary */
                    533:                out_fdc(15);    /* Seek function */
                    534:                out_fdc(fd_drive);/* Drive number */
                    535:                out_fdc(bp->b_cylin * dp->b_step);
                    536:                fd_state = 1;
                    537:                break;
                    538:        case 4:
                    539:                out_fdc(3); /* specify command */
                    540:                out_fdc(0xDF);
                    541:                out_fdc(2);
                    542:                out_fdc(7);     /* Recalibrate Function */
                    543:                out_fdc(fd_drive);
                    544:                fd_state = 3;
                    545:                break;
                    546:        case 5:
                    547: #ifdef FDOTHER
                    548:                printf("**RESET**\n");
                    549: #endif
                    550:                /* Try a reset, keep motor on */
                    551:                set_motor(fd_drive,1);
                    552:                set_motor(fd_drive,0);
                    553:                outb(fdc+fdctl,ft->trans);
                    554:                fd_retry++;
                    555:                fd_state = 4;
                    556:                break;
                    557:        default:
                    558:                printf("Unexpected FD int->");
                    559:                out_fdc(0x8);
                    560:                i = in_fdc();
                    561:                sec = in_fdc();
                    562:                printf("ST0 = %lx, PCN = %lx\n",i,sec);
                    563:                out_fdc(0x4A); 
                    564:                out_fdc(fd_drive);
                    565:                for(i=0;i<7;i++) {
                    566:                        fd_status[i] = in_fdc();
                    567:                }
                    568:        printf("intr status :%lx %lx %lx %lx %lx %lx %lx ",
                    569:                fd_status[0], fd_status[1], fd_status[2], fd_status[3],
                    570:                fd_status[4], fd_status[5], fd_status[6] );
                    571:                break;
                    572:        }
                    573:        return;
                    574: retry:
                    575:        switch(fd_retry) {
                    576:        case 0: case 1:
                    577:        case 2: case 3:
                    578:                break;
                    579:        case 4:
                    580:                fd_retry++;
                    581:                fd_state = 5;
                    582:                fdintr(0xff);
                    583:                return;
                    584:        case 5: case 6: case 7:
                    585:                break;
                    586:        default:
                    587:                printf("FD err %lx %lx %lx %lx %lx %lx %lx\n",
                    588:                fd_status[0], fd_status[1], fd_status[2], fd_status[3],
                    589:                fd_status[4], fd_status[5], fd_status[6] );
                    590:                badtrans(dp,bp);
                    591:                return;
                    592:        }
                    593:        fd_state = 1;
                    594:        fd_retry++;
                    595:        fdintr(0xff);
                    596: }
                    597: 
                    598: badtrans(dp,bp)
                    599: struct buf *dp,*bp;
                    600: {
                    601: 
                    602:        bp->b_flags |= B_ERROR;
                    603:        bp->b_error = EIO;
                    604:        bp->b_resid = bp->b_bcount - fd_skip;
                    605:        dp->b_actf = bp->av_forw;
                    606:        fd_skip = 0;
                    607:        biodone(bp);
                    608:        nextstate(dp);
                    609: 
                    610: }
                    611: 
                    612: /*
                    613:        nextstate : After a transfer is done, continue processing
                    614:        requests on the current drive queue.  If empty, go to
                    615:        the other drives queue.  If that is empty too, timeout
                    616:        to turn off the current drive in 5 seconds, and go
                    617:        to state 0 (not expecting any interrupts).
                    618: */
                    619: 
                    620: nextstate(dp)
                    621: struct buf *dp;
                    622: {
                    623:        struct buf *dpother;
                    624:        
                    625:        dpother = &fd_unit[fd_drive ? 0 : 1].head;
                    626:        if (dp->b_actf) fdstart(fd_drive);
                    627:        else if (dpother->b_actf) {
                    628: #ifdef FDTEST
                    629: printf("switch|");
                    630: #endif
                    631:                untimeout(fd_turnoff,fd_drive);
                    632:                timeout(fd_turnoff,fd_drive,5*hz);
                    633:                fd_drive = 1 - fd_drive;
                    634:                dp->b_active = 0;
                    635:                dpother->b_active = 1;
                    636:                fdstart(fd_drive);
                    637:        } else {
                    638: #ifdef FDTEST
                    639: printf("off|");
                    640: #endif
                    641:                untimeout(fd_turnoff,fd_drive);
                    642:                timeout(fd_turnoff,fd_drive,5*hz);
                    643:                fd_state = 0;
                    644:                dp->b_active = 0;
                    645:        }
                    646: }
                    647: #endif

unix.superglobalmegacorp.com

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