Annotation of Net2/arch/i386/isa/fd.c, revision 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.