Annotation of lucent/sys/src/9/next/f002520, revision 1.1

1.1     ! root        1: #include       "u.h"
        !             2: #include       "../port/lib.h"
        !             3: #include       "mem.h"
        !             4: #include       "dat.h"
        !             5: #include       "fns.h"
        !             6: #include       "io.h"
        !             7: #include       "../port/error.h"
        !             8: 
        !             9: /* Intel 82077A (8272A compatible) floppy controller */
        !            10: 
        !            11: typedef        struct Drive            Drive;
        !            12: typedef        struct Controller       Controller;
        !            13: typedef struct Type            Type;
        !            14: typedef struct Device          Device;
        !            15: 
        !            16: /* registers on the 82077 */
        !            17: struct Device
        !            18: {
        !            19:        uchar           sra;    /* (R/O) status register A */           
        !            20:        uchar           srb;    /* (R/O) status register B */
        !            21:        uchar           dor;    /* (R/W) digital output register */
        !            22:        uchar           rsvd3;  /* reserved */
        !            23:        uchar           msr;    /* (R/O) main status register */
        !            24: #define dsr    msr
        !            25:        uchar           fifo;   /* (R/W) data FIFO */
        !            26:        uchar           rsvd6;  /* reserved */
        !            27:        uchar           dir;    /* (R/O) digital input register */
        !            28: #define ccr    dir
        !            29:        uchar           flpctl; /* (W/O) control (not in 82077) */
        !            30: };
        !            31: 
        !            32: /* bits in the registers */
        !            33: enum
        !            34: {
        !            35:        /* status register A */
        !            36:        Fintpend=       0x80,   /* interrupt pending */
        !            37: 
        !            38:        /* digital output register */
        !            39:        Fintena=        0x8,    /* enable floppy interrupt */
        !            40:        Fena=           0x4,    /* 0 == reset controller */
        !            41: 
        !            42:        /* main status register */
        !            43:        Fready=         0x80,   /* ready to be touched */
        !            44:        Ffrom=          0x40,   /* data from controller */
        !            45:        Fbusy=          0x10,   /* operation not over */
        !            46: 
        !            47:        /* data register */
        !            48:        Frecal=         0x07,   /* recalibrate cmd */
        !            49:        Fseek=          0x0f,   /* seek cmd */
        !            50:        Fsense=         0x08,   /* sense cmd */
        !            51:        Fread=          0x66,   /* read cmd */
        !            52:        Freadid=        0x4a,   /* read track id */
        !            53:        Fspec=          0x03,   /* set hold times */
        !            54:        Fwrite=         0x45,   /* write cmd */
        !            55:        Fmulti=         0x80,   /* or'd with Fread or Fwrite for multi-head */
        !            56:        Fdumpreg=       0x0e,   /* dump internal registers */
        !            57: 
        !            58:        /* disk changed register */
        !            59:        Fchange=        0x80,   /* disk has changed */
        !            60: 
        !            61:        /* floppy control register (not part of 82077) */
        !            62:        Eject_disc      = 0x80,         /* Eject the floppy */
        !            63:        Sel_82077       = 0x40,         /* Scsi/82077 select */
        !            64:        Drv_id          = 0x04,         /* Drive present flag */
        !            65:        Mid             = 0x03,         /* Media id bits */
        !            66: 
        !            67:        /* status 0 byte */
        !            68:        Drivemask=      3<<0,
        !            69:        Seekend=        1<<5,
        !            70:        Codemask=       (3<<6)|(3<<3),
        !            71: 
        !            72:        /* file types */
        !            73:        Qdir=           0,
        !            74:        Qdata=          (1<<2),
        !            75:        Qctl=           (2<<2),
        !            76:        Qmask=          (3<<2),
        !            77: };
        !            78: 
        !            79: /*
        !            80:  *  floppy types
        !            81:  */
        !            82: struct Type
        !            83: {
        !            84:        char    *name;
        !            85:        int     bytes;          /* bytes/sector */
        !            86:        int     sectors;        /* sectors/track */
        !            87:        int     heads;          /* number of heads */
        !            88:        int     steps;          /* steps per cylinder */
        !            89:        int     tracks;         /* tracks/disk */
        !            90:        int     gpl;            /* intersector gap length for read/write */     
        !            91:        int     fgpl;           /* intersector gap length for format */
        !            92: 
        !            93:        /*
        !            94:         *  these depend on previous entries and are set filled in
        !            95:         *  by floppyinit
        !            96:         */
        !            97:        int     bcode;          /* coded version of bytes for the controller */
        !            98:        long    cap;            /* drive capacity in bytes */
        !            99:        long    tsize;          /* track size in bytes */
        !           100: };
        !           101: Type floppytype[] =
        !           102: {
        !           103:        { "MF2HD",      512,    18,     2,      1,      80,     0x1B,   0x54, },
        !           104:        { "MF1DD",      512,    9,      2,      1,      80,     0x1B,   0x54, },
        !           105:        { "MF4HD",      1024,   18,     2,      1,      80,     0x1B,   0x54, },
        !           106:        { "F2HD",       512,    15,     2,      1,      80,     0x2A,   0x50, },
        !           107:        { "F2DD",       512,    8,      2,      2,      40,     0x2A,   0x50, },
        !           108:        { "F1DD",       512,    8,      1,      2,      40,     0x2A,   0x50, },
        !           109: };
        !           110: #define NTYPES (sizeof(floppytype)/sizeof(Type))
        !           111: 
        !           112: /*
        !           113:  *  bytes per sector encoding for the controller.
        !           114:  *  - index for b2c is is (bytes per sector/128).
        !           115:  *  - index for c2b is code from b2c
        !           116:  */
        !           117: static int b2c[] =
        !           118: {
        !           119: [1]    0,
        !           120: [2]    1,
        !           121: [4]    2,
        !           122: [8]    3,
        !           123: };
        !           124: static int c2b[] =
        !           125: {
        !           126:        128,
        !           127:        256,
        !           128:        512,
        !           129:        1024,
        !           130: };
        !           131: 
        !           132: /*
        !           133:  *  a floppy drive
        !           134:  */
        !           135: struct Drive
        !           136: {
        !           137:        Type    *t;
        !           138:        int     dev;
        !           139: 
        !           140:        ulong   lasttouched;    /* time last touched */
        !           141:        int     cyl;            /* current cylinder */
        !           142:        int     confused;       /* needs to be recalibrated */
        !           143:        int     vers;
        !           144: 
        !           145:        int     tcyl;           /* target cylinder */
        !           146:        int     thead;          /* target head */
        !           147:        int     tsec;           /* target sector */
        !           148:        long    len;            /* size of xfer */
        !           149: 
        !           150:        uchar   *virtual;       /* track cache */
        !           151:        uchar   *physical;      /* ... */
        !           152:        int     ccyl;
        !           153:        int     chead;
        !           154: 
        !           155:        Rendez  r;              /* waiting here for motor to spin up */
        !           156: };
        !           157: 
        !           158: /*
        !           159:  *  controller for 4 floppys
        !           160:  */
        !           161: struct Controller
        !           162: {
        !           163:        QLock;                  /* exclusive access to the contoller */
        !           164: 
        !           165:        Drive   *d;             /* the floppy drives */
        !           166:        uchar   cmd[14];        /* command */
        !           167:        int     ncmd;             /* # command bytes */
        !           168:        uchar   stat[14];       /* command status */
        !           169:        int     nstat;            /* # status bytes */
        !           170:        int     confused;       /* controler needs to be reset */
        !           171:        Rendez  r;              /* wait here for command termination */
        !           172:        int     motor;          /* bit mask of spinning disks */
        !           173: 
        !           174:        uchar   *virtual;       /* kernel buffer for DMA (output) */
        !           175:        uchar   *physical;      /* ... */
        !           176: 
        !           177:        Rendez  kr;             /* for motor watcher */
        !           178: };
        !           179: 
        !           180: Controller     fl;
        !           181: 
        !           182: #define MOTORBIT(i)    (1<<((i)+4))
        !           183: 
        !           184: /*
        !           185:  *  predeclared
        !           186:  */
        !           187: static int     floppycmd(void);
        !           188: static void    floppyeject(Drive*);
        !           189: static void    floppykproc(void*);
        !           190: static void    floppyon(Drive*);
        !           191: static void    floppyoff(Drive*);
        !           192: static void    floppypos(Drive*,long);
        !           193: static int     floppyrecal(Drive*);
        !           194: static int     floppyresult(void);
        !           195: static void    floppyrevive(void);
        !           196: static long    floppyseek(Drive*, long);
        !           197: static int     floppysense(void);
        !           198: static void    floppywait(void);
        !           199: static long    floppyxfer(Drive*, int, void*, long, long);
        !           200: static long    floppythrice(Drive*, int, void*, long, long);
        !           201: static int     cmddone(void*);
        !           202: 
        !           203: Dirtab floppydir[]={
        !           204:        "fd0disk",              {Qdata + 0},    0,      0666,
        !           205:        "fd0ctl",               {Qctl + 0},     0,      0666,
        !           206:        "fd1disk",              {Qdata + 1},    0,      0666,
        !           207:        "fd1ctl",               {Qctl + 1},     0,      0666,
        !           208:        "fd2disk",              {Qdata + 2},    0,      0666,
        !           209:        "fd2ctl",               {Qctl + 2},     0,      0666,
        !           210:        "fd3disk",              {Qdata + 3},    0,      0666,
        !           211:        "fd3ctl",               {Qctl + 3},     0,      0666,
        !           212: };
        !           213: #define NFDIR  2       /* directory entries/drive */
        !           214: 
        !           215: /*
        !           216:  *  grab DMA from SCSI
        !           217:  */
        !           218: #define GETDMA\
        !           219: {\
        !           220:        qlock(&dmalock);\
        !           221:        dmaowner = Ofloppy;\
        !           222:        ((Device*)(FDCTLRL))->flpctl = Sel_82077;\
        !           223:        if(waserror()){\
        !           224:                ((Device*)(FDCTLRL))->flpctl = 0;\
        !           225:                qunlock(&dmalock);\
        !           226:                nexterror();\
        !           227:        }\
        !           228: }
        !           229: 
        !           230: /*
        !           231:  *  let SCSI have DMA
        !           232:  */
        !           233: #define PUTDMA\
        !           234: {\
        !           235:        ((Device*)(FDCTLRL))->flpctl = 0;\
        !           236:        dmaowner = Oscsi;\
        !           237:        qunlock(&dmalock);\
        !           238:        poperror();\
        !           239: }
        !           240: 
        !           241: void
        !           242: nextfloppyreset(void)
        !           243: {
        !           244:        Device *devp = (Device*)(FDCTLRL);
        !           245:        Drive *dp;
        !           246:        Type *t;
        !           247:        ulong p;
        !           248:        long l;
        !           249: 
        !           250:        /*
        !           251:         *  init dependent parameters
        !           252:         */
        !           253:        for(t = floppytype; t < &floppytype[NTYPES]; t++){
        !           254:                t->cap = t->bytes * t->heads * t->sectors * t->tracks;
        !           255:                t->bcode = b2c[t->bytes/128];
        !           256:                t->tsize = t->bytes * t->sectors;
        !           257:        }
        !           258: 
        !           259:        /*
        !           260:         *  allocate the drive storage
        !           261:         */
        !           262:        fl.d = xalloc(conf.nfloppy*sizeof(Drive));
        !           263: 
        !           264:        /*
        !           265:         *  allocate a page for dma
        !           266:         */
        !           267:        p = (ulong)xspanalloc(BY2PG, BY2PG, 0);
        !           268:        fl.virtual = (uchar *)kmappa(p);
        !           269:        fl.physical = (uchar*)p;
        !           270: 
        !           271:        /*
        !           272:         *  reset the chip, leave it off
        !           273:         */
        !           274:        fl.motor = 0;
        !           275:        devp->flpctl = Sel_82077;
        !           276:        devp->dor = 0;
        !           277:        devp->flpctl = 0;
        !           278: 
        !           279:        /*
        !           280:         *  init drives
        !           281:         */
        !           282:        for(dp = fl.d; dp < &fl.d[conf.nfloppy]; dp++){
        !           283:                dp->dev = dp - fl.d;
        !           284:                dp->t = &floppytype[0];         /* default type */
        !           285:                floppydir[NFDIR*dp->dev].length = dp->t->cap;
        !           286:                dp->cyl = -1;           /* because we don't know */
        !           287:                p = (ulong)xspanalloc(dp->t->tsize, BY2PG, 0);
        !           288:                dp->virtual = (uchar *)kmappa(p);
        !           289:                for(l = BY2PG; l < dp->t->tsize; l += BY2PG)
        !           290:                        kmappa(p+l);
        !           291:                dp->physical = (uchar*)p;
        !           292:                dp->ccyl = -1;
        !           293:                dp->vers = 1;
        !           294:        }
        !           295: 
        !           296:        /*
        !           297:         *  first operation will recalibrate
        !           298:         */
        !           299:        fl.confused = 1;
        !           300: }
        !           301: 
        !           302: void
        !           303: nextfloppyinit(void)
        !           304: {
        !           305: }
        !           306: 
        !           307: Chan*
        !           308: nextfloppyattach(char *spec)
        !           309: {
        !           310:        static int kstarted;
        !           311: 
        !           312:        if(kstarted == 0){
        !           313:                /*
        !           314:                 *  watchdog to turn off the motors
        !           315:                 */
        !           316:                kstarted = 1;
        !           317:                kproc("floppy", floppykproc, 0);
        !           318:        }
        !           319:        return devattach('f', spec);
        !           320: }
        !           321: 
        !           322: Chan*
        !           323: nextfloppyclone(Chan *c, Chan *nc)
        !           324: {
        !           325:        return devclone(c, nc);
        !           326: }
        !           327: 
        !           328: int
        !           329: nextfloppywalk(Chan *c, char *name)
        !           330: {
        !           331:        return devwalk(c, name, floppydir, conf.nfloppy*NFDIR, devgen);
        !           332: }
        !           333: 
        !           334: void
        !           335: nextfloppystat(Chan *c, char *dp)
        !           336: {
        !           337:        devstat(c, dp, floppydir, conf.nfloppy*NFDIR, devgen);
        !           338: }
        !           339: 
        !           340: Chan*
        !           341: nextfloppyopen(Chan *c, int omode)
        !           342: {
        !           343:        return devopen(c, omode, floppydir, conf.nfloppy*NFDIR, devgen);
        !           344: }
        !           345: 
        !           346: void
        !           347: nextfloppycreate(Chan *c, char *name, int omode, ulong perm)
        !           348: {
        !           349:        USED(c, name, omode, perm);
        !           350:        error(Eperm);
        !           351: }
        !           352: 
        !           353: void
        !           354: nextfloppyclose(Chan *c)
        !           355: {
        !           356:        USED(c);
        !           357: }
        !           358: 
        !           359: void
        !           360: nextfloppyremove(Chan *c)
        !           361: {
        !           362:        USED(c);
        !           363:        error(Eperm);
        !           364: }
        !           365: 
        !           366: void
        !           367: nextfloppywstat(Chan *c, char *dp)
        !           368: {
        !           369:        USED(c, dp);
        !           370:        error(Eperm);
        !           371: }
        !           372: 
        !           373: static void
        !           374: islegal(Chan *c, long n, Drive *dp)
        !           375: {
        !           376:        if(c->offset % dp->t->bytes)
        !           377:                error(Ebadarg);
        !           378:        if(n % dp->t->bytes)
        !           379:                error(Ebadarg);
        !           380:        if(c->qid.vers!=0 && c->qid.vers!=dp->vers){
        !           381:                c->qid.vers = dp->vers;
        !           382:                error(Eio);
        !           383:        } else
        !           384:                c->qid.vers = dp->vers;
        !           385: }
        !           386: 
        !           387: static void
        !           388: changed(Chan *c, Drive *dp)
        !           389: {
        !           390:        ulong old;
        !           391: 
        !           392:        old = c->qid.vers;
        !           393:        c->qid.vers = dp->vers;
        !           394:        if(old && old!=dp->vers)
        !           395:                error(Eio);
        !           396: }
        !           397: 
        !           398: long
        !           399: nextfloppyread(Chan *c, void *a, long n)
        !           400: {
        !           401:        Drive *dp;
        !           402:        long rv, i;
        !           403:        int nn, sec, head, cyl;
        !           404:        long len;
        !           405:        uchar *aa;
        !           406: 
        !           407:        if(c->qid.path == CHDIR)
        !           408:                return devdirread(c, a, n, floppydir, conf.nfloppy*NFDIR, devgen);
        !           409: 
        !           410:        rv = 0;
        !           411:        dp = &fl.d[c->qid.path & ~Qmask];
        !           412: 
        !           413:        switch ((int)(c->qid.path & Qmask)) {
        !           414:        case Qdata:
        !           415:                islegal(c, n, dp);
        !           416:                aa = a;
        !           417:                nn = dp->t->tsize;
        !           418: 
        !           419:                qlock(&fl);
        !           420:                if(waserror()){
        !           421:                        qunlock(&fl);
        !           422:                        fl.confused = 1;
        !           423:                        CLRCTL(Cpu_dma);
        !           424:                        nexterror();
        !           425:                }
        !           426:                GETDMA;
        !           427:                floppyon(dp);
        !           428:                changed(c, dp);
        !           429:                for(rv = 0; rv < n; rv += len){
        !           430:                        /*
        !           431:                         *  truncate xfer at track boundary
        !           432:                         */
        !           433:                        dp->len = n - rv;
        !           434:                        floppypos(dp, c->offset+rv);
        !           435:                        cyl = dp->tcyl;
        !           436:                        head = dp->thead;
        !           437:                        len = dp->len;
        !           438:                        sec = dp->tsec;
        !           439: 
        !           440:                        /*
        !           441:                         *  read the track
        !           442:                         */
        !           443:                        if(dp->ccyl!=cyl || dp->chead!=head){
        !           444:                                dp->ccyl = -1;
        !           445:                                i = floppythrice(dp, Fread,0,(cyl*dp->t->heads+head)*nn,nn);
        !           446:                                if(i != nn){
        !           447:                                        if(i == 0)
        !           448:                                                break;
        !           449:                                        error(Eio);
        !           450:                                }
        !           451:                                dp->ccyl = cyl;
        !           452:                                dp->chead = head;
        !           453:                        }
        !           454:                        memmove(aa+rv, dp->virtual + (sec-1)*dp->t->bytes, len);
        !           455:                }
        !           456:                PUTDMA;
        !           457:                qunlock(&fl);
        !           458:                poperror();
        !           459:                break;
        !           460:        case Qctl:
        !           461:                break;
        !           462:        default:
        !           463:                panic("floppyread: bad qid");
        !           464:        }
        !           465: 
        !           466:        return rv;
        !           467: }
        !           468: 
        !           469: #define SNCMP(a, b) strncmp(a, b, sizeof(b)-1)
        !           470: long
        !           471: nextfloppywrite(Chan *c, void *a, long n)
        !           472: {
        !           473:        Drive *dp;
        !           474:        long rv, i;
        !           475:        char *aa = a;
        !           476: 
        !           477:        rv = 0;
        !           478:        dp = &fl.d[c->qid.path & ~Qmask];
        !           479: 
        !           480:        switch ((int)(c->qid.path & Qmask)) {
        !           481:        case Qdata:
        !           482:                islegal(c, n, dp);
        !           483:                qlock(&fl);
        !           484:                if(waserror()){
        !           485:                        qunlock(&fl);
        !           486:                        fl.confused = 1;
        !           487:                        CLRCTL(Cpu_dma);
        !           488:                        nexterror();
        !           489:                }
        !           490:                GETDMA;
        !           491:                floppyon(dp);
        !           492:                changed(c, dp);
        !           493:                for(rv = 0; rv < n; rv += i){
        !           494:                        floppypos(dp, c->offset+rv);
        !           495:                        if(dp->tcyl == dp->ccyl)
        !           496:                                dp->ccyl = -1;
        !           497:                        i = floppythrice(dp, Fwrite, aa+rv, c->offset+rv,
        !           498:                                n-rv);
        !           499:                        if(i <= 0)
        !           500:                                break;
        !           501:                }
        !           502:                PUTDMA;
        !           503:                qunlock(&fl);
        !           504:                poperror();
        !           505:                break;
        !           506:        case Qctl:
        !           507:                if(SNCMP(aa, "eject") == 0){
        !           508:                        qlock(&fl);
        !           509:                        GETDMA;
        !           510:                        floppyeject(dp);
        !           511:                        PUTDMA;
        !           512:                        qunlock(&fl);
        !           513:                } else if(SNCMP(aa, "reset") == 0){
        !           514:                        qlock(&fl);
        !           515:                        GETDMA;
        !           516:                        floppyon(dp);
        !           517:                        PUTDMA;
        !           518:                        qunlock(&fl);
        !           519:                }
        !           520:                break;
        !           521:        default:
        !           522:                panic("floppywrite: bad qid");
        !           523:        }
        !           524: 
        !           525:        return rv;
        !           526: }
        !           527: 
        !           528: static void
        !           529: floppykproc(void *a)
        !           530: {
        !           531:        Drive *dp;
        !           532: 
        !           533:        USED(a);
        !           534: 
        !           535:        while(waserror())
        !           536:                ;
        !           537:        for(;;){
        !           538:                for(dp = fl.d; dp < &fl.d[conf.nfloppy]; dp++){
        !           539:                        if((fl.motor&MOTORBIT(dp->dev))
        !           540:                        && TK2SEC(m->ticks - dp->lasttouched) > 5
        !           541:                        && canqlock(&fl)){
        !           542:                                GETDMA;
        !           543:                                if(TK2SEC(m->ticks - dp->lasttouched) > 5)
        !           544:                                        floppyoff(dp);
        !           545:                                qunlock(&fl);
        !           546:                                PUTDMA;
        !           547:                        }
        !           548:                }
        !           549:                tsleep(&fl.kr, return0, 0, 5*1000);
        !           550:        }
        !           551: }
        !           552: 
        !           553: /*
        !           554:  *  start a floppy drive's motor.
        !           555:  */
        !           556: static void
        !           557: floppyon(Drive *dp)
        !           558: {
        !           559:        Device *devp = (Device*)(FDCTLRL);
        !           560:        int alreadyon;
        !           561:        int tries;
        !           562: 
        !           563:        for(tries = 0; tries < 4; tries++){
        !           564:                if(fl.confused)
        !           565:                        floppyrevive();
        !           566:        
        !           567:                /* start motor and select drive */
        !           568:                alreadyon = fl.motor & MOTORBIT(dp->dev);
        !           569:                fl.motor |= MOTORBIT(dp->dev);
        !           570:                devp->dor = fl.motor | Fintena | Fena | dp->dev;
        !           571:                if(!alreadyon)
        !           572:                        tsleep(&dp->r, return0, 0, 750);
        !           573:        
        !           574:                /* get drive to a known cylinder */
        !           575:                if(dp->confused)
        !           576:                        if(floppyrecal(dp) >= 0)
        !           577:                                break;
        !           578:                else
        !           579:                        break;
        !           580:        }
        !           581:        dp->lasttouched = m->ticks;
        !           582: }
        !           583: 
        !           584: /*
        !           585:  *  stop the floppy if it hasn't been used in 5 seconds
        !           586:  */
        !           587: static void
        !           588: floppyoff(Drive *dp)
        !           589: {
        !           590:        Device *devp = (Device*)(FDCTLRL);
        !           591: 
        !           592:        fl.motor &= ~MOTORBIT(dp->dev);
        !           593:        devp->dor = fl.motor | Fintena | Fena | dp->dev;
        !           594: }
        !           595: 
        !           596: /*
        !           597:  *  eject disk
        !           598:  */
        !           599: static void
        !           600: floppyeject(Drive *dp)
        !           601: {
        !           602:        Device *devp = (Device*)(FDCTLRL);
        !           603: 
        !           604:        dp->vers++;
        !           605:        floppyon(dp);
        !           606:        delay(1);
        !           607:        devp->flpctl = Eject_disc|Sel_82077;
        !           608:        delay(1);
        !           609:        devp->flpctl = Sel_82077;
        !           610:        delay(1);
        !           611:        floppyoff(dp);
        !           612: }
        !           613: 
        !           614: /*
        !           615:  *  send a command to the floppy
        !           616:  */
        !           617: static int
        !           618: floppycmd(void)
        !           619: {
        !           620:        Device *devp = (Device*)(FDCTLRL);
        !           621:        int i;
        !           622:        int tries;
        !           623: 
        !           624:        for(i = 0; i < fl.ncmd; i++){
        !           625:                for(tries = 0; ; tries++){
        !           626:                        if(tries > 1000){
        !           627: print("cmd %ux can't be sent (%d %ux)\n", fl.cmd[0], i, devp->msr);
        !           628:                                fl.confused = 1;
        !           629:                                return -1;
        !           630:                        }
        !           631:                        if((devp->msr&(Ffrom|Fready)) == Fready)
        !           632:                                break;
        !           633:                }
        !           634:                devp->fifo = fl.cmd[i];
        !           635:        }
        !           636:        return 0;
        !           637: }
        !           638: 
        !           639: /*
        !           640:  *  get a command result from the floppy
        !           641:  *
        !           642:  *  when the controller goes ready waiting for a command
        !           643:  *  (instead of sending results), we're done
        !           644:  * 
        !           645:  */
        !           646: static int
        !           647: floppyresult(void)
        !           648: {
        !           649:        Device *devp = (Device*)(FDCTLRL);
        !           650:        int i, s;
        !           651:        int tries;
        !           652: 
        !           653:        for(i = 0; i < sizeof(fl.stat); i++){
        !           654:                for(tries = 0; ; tries++){
        !           655:                        if(tries > 1000){
        !           656:                                fl.confused = 1;
        !           657:                                return -1;
        !           658:                        }
        !           659:                        s = devp->msr&(Ffrom|Fready);
        !           660:                        if(s == Fready){
        !           661:                                fl.nstat = i;
        !           662:                                return i;
        !           663:                        }
        !           664:                        if(s == (Ffrom|Fready))
        !           665:                                break;
        !           666:                }
        !           667:                fl.stat[i] = devp->fifo;
        !           668:        }
        !           669:        fl.nstat = i;
        !           670:        return i;
        !           671: }
        !           672: 
        !           673: /*
        !           674:  *  calculate physical address of a logical byte offset into the disk
        !           675:  *
        !           676:  *  truncate dp->length if it crosses a track boundary
        !           677:  */
        !           678: static void
        !           679: floppypos(Drive *dp, long off)
        !           680: {
        !           681:        int lsec;
        !           682:        int ltrack;
        !           683:        int end;
        !           684: 
        !           685:        lsec = off/dp->t->bytes;
        !           686:        ltrack = lsec/dp->t->sectors;
        !           687:        dp->tcyl = ltrack/dp->t->heads;
        !           688:        dp->tsec = (lsec % dp->t->sectors) + 1;
        !           689:        dp->thead = (lsec/dp->t->sectors) % dp->t->heads;
        !           690: 
        !           691:        /*
        !           692:         *  can't read across track boundaries.
        !           693:         *  if so, decrement the bytes to be read.
        !           694:         */
        !           695:        end = (ltrack+1)*dp->t->sectors*dp->t->bytes;
        !           696:        if(off+dp->len > end)
        !           697:                dp->len = end - off;
        !           698: }
        !           699: 
        !           700: /*
        !           701:  *  get the interrupt cause from the floppy.
        !           702:  */
        !           703: static int
        !           704: floppysense(void)
        !           705: {
        !           706:        fl.ncmd = 0;
        !           707:        fl.cmd[fl.ncmd++] = Fsense;
        !           708:        if(floppycmd() < 0)
        !           709:                return -1;
        !           710:        if(floppyresult() < 2){
        !           711: print("can't read sense response\n");
        !           712:                fl.confused = 1;
        !           713:                return -1;
        !           714:        }
        !           715:        return 0;
        !           716: }
        !           717: 
        !           718: static int
        !           719: cmddone(void *a)
        !           720: {
        !           721:        USED(a);
        !           722:        return fl.ncmd == 0;
        !           723: }
        !           724: 
        !           725: /*
        !           726:  *  wait for a floppy interrupt
        !           727:  */
        !           728: static void
        !           729: floppywait(void)
        !           730: {
        !           731:        tsleep(&fl.r, cmddone, 0, 2000);
        !           732: }
        !           733: 
        !           734: /*
        !           735:  *  we've lost the floppy position, go to cylinder 0.
        !           736:  */
        !           737: static int
        !           738: floppyrecal(Drive *dp)
        !           739: {
        !           740:        Device *devp = (Device*)(FDCTLRL);
        !           741:        int type;
        !           742: 
        !           743:        dp->ccyl = -1;
        !           744: 
        !           745:        type = devp->flpctl & Mid;
        !           746:        switch(type){
        !           747:        case 0:
        !           748:                print("no diskette %d\n", dp->dev);
        !           749:                return -1;
        !           750:        case 1:
        !           751:                devp->dsr = 3;
        !           752:                devp->ccr = 3;
        !           753:                dp->t = &floppytype[2];
        !           754:                return -1;
        !           755:        case 2:
        !           756:                dp->t = &floppytype[0];
        !           757:                break;
        !           758:        case 3:
        !           759:                devp->dsr = 0;
        !           760:                devp->ccr = 0;
        !           761:                dp->t = &floppytype[1];
        !           762:                break;
        !           763:        }
        !           764:        
        !           765:        fl.ncmd = 0;
        !           766:        fl.cmd[fl.ncmd++] = Frecal;
        !           767:        fl.cmd[fl.ncmd++] = dp->dev;
        !           768:        if(floppycmd() < 0)
        !           769:                return -1;
        !           770:        floppywait();
        !           771:        if(fl.nstat < 2){
        !           772:                fl.confused = 1;
        !           773:                return -1;
        !           774:        }
        !           775:        if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
        !           776:                dp->confused = 1;
        !           777:                return -1;
        !           778:        }
        !           779:        dp->cyl = fl.stat[1]/dp->t->steps;
        !           780:        if(dp->cyl != 0){
        !           781:                print("recalibrate went to wrong cylinder %d\n", dp->cyl);
        !           782:                dp->confused = 1;
        !           783:                return -1;
        !           784:        }
        !           785: 
        !           786:        dp->confused = 0;
        !           787:        return 0;
        !           788: }
        !           789: 
        !           790: /*
        !           791:  *  if the controller or a specific drive is in a confused state,
        !           792:  *  reset it and get back to a kown state
        !           793:  */
        !           794: void
        !           795: floppyrevive(void)
        !           796: {
        !           797:        Device *devp = (Device*)(FDCTLRL);
        !           798:        Drive *dp;
        !           799: 
        !           800:        /*
        !           801:         *  reset the controller if it's confused
        !           802:         */
        !           803:        if(fl.confused){
        !           804:                /* reset controller and turn all motors off */
        !           805:                splhi();
        !           806:                fl.cmd[0] = 0;
        !           807:                devp->dor = 0;
        !           808:                delay(1);
        !           809:                devp->dor = Fintena|Fena;
        !           810:                spllo();
        !           811:                for(dp = fl.d; dp < &fl.d[conf.nfloppy]; dp++)
        !           812:                        dp->confused = 1;
        !           813:                fl.motor = 0;
        !           814:                floppywait();
        !           815:                fl.confused = 0;
        !           816:                devp->dsr = 0;
        !           817:                devp->ccr = 0;
        !           818:        }
        !           819: }
        !           820: 
        !           821: /*
        !           822:  *  seek to the target cylinder
        !           823:  *
        !           824:  *     interrupt, no results
        !           825:  */
        !           826: static long
        !           827: floppyseek(Drive *dp, long off)
        !           828: {
        !           829:        floppypos(dp, off);
        !           830:        if(dp->cyl == dp->tcyl)
        !           831:                return dp->cyl;
        !           832: 
        !           833: /* print("seeking tcyl %d, thead %d\n", dp->tcyl, dp->thead); /**/
        !           834:        fl.ncmd = 0;
        !           835:        fl.cmd[fl.ncmd++] = Fseek;
        !           836:        fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
        !           837:        fl.cmd[fl.ncmd++] = dp->tcyl * dp->t->steps;
        !           838:        if(floppycmd() < 0){
        !           839:                print("seek cmd failed\n");
        !           840:                return -1;
        !           841:        }
        !           842:        floppywait();
        !           843:        if(fl.nstat < 2){
        !           844:                fl.confused = 1;
        !           845:                return -1;
        !           846:        }
        !           847:        if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
        !           848:                print("seek failed\n");
        !           849:                dp->confused = 1;
        !           850:                return -1;
        !           851:        }
        !           852: 
        !           853:        dp->cyl = dp->tcyl;
        !           854:        return dp->cyl;
        !           855: }
        !           856: 
        !           857: /*
        !           858:  *  since floppies are so flakey, try 3 times before giving up
        !           859:  */
        !           860: static long
        !           861: floppythrice(Drive *dp, int cmd, void *a, long off, long n)
        !           862: {
        !           863:        int tries;
        !           864:        long rv;
        !           865: 
        !           866:        for(tries = 0; ; tries++){
        !           867:                if(waserror()){
        !           868:                        if(strcmp(u->error, Eintr)==0 || tries > 3)
        !           869:                                nexterror();
        !           870:                } else {
        !           871:                        rv = floppyxfer(dp, cmd, a, off, n);
        !           872:                        poperror();
        !           873:                        return rv;
        !           874:                }
        !           875:        }
        !           876: }
        !           877: 
        !           878: static long
        !           879: floppyxfer(Drive *dp, int cmd, void *a, long off, long n)
        !           880: {
        !           881:        Device *devp = (Device*)(FDCTLRL);
        !           882:        SCSIdma *dma = (SCSIdma *)SCSIDMA;
        !           883:        long offset;
        !           884:        ulong up;
        !           885: 
        !           886:        if(off >= dp->t->cap)
        !           887:                return 0;
        !           888:        if(off + n > dp->t->cap)
        !           889:                n = dp->t->cap - off;
        !           890: 
        !           891:        /*
        !           892:         *  calculate new position and seek to it (dp->len may be trimmed)
        !           893:         */
        !           894:        dp->len = n;
        !           895:        if(floppyseek(dp, off) < 0)
        !           896:                error(Eio);
        !           897:        
        !           898: /*print("tcyl %d, thead %d, tsec %d, addr %lux, buf %lux, n %d\n",
        !           899:        dp->tcyl, dp->thead, dp->tsec, a, fl.physical, dp->len);/**/
        !           900: 
        !           901:        /*
        !           902:         *  turn off any previous dma, set up new one
        !           903:         */
        !           904:        dma->csr = Dinit | Dcreset;
        !           905:        if(cmd == Fread){
        !           906:                up = (ulong)dp->physical;
        !           907:        } else {
        !           908:                memmove(fl.virtual, a, dp->len);
        !           909:                up = (ulong)fl.physical;
        !           910:        }
        !           911:        dma->base = up;
        !           912:        if(cmd == Fread){
        !           913:                dma->limit = up + dp->len;
        !           914:                SETCTL(Dmadir);
        !           915:                dma->csr = Dseten | Dsetread | Dinit;
        !           916:        } else {
        !           917:                dma->limit = up + dp->len + 16;
        !           918:                CLRCTL(Dmadir);
        !           919:                dma->csr = Dseten | Dinit;
        !           920:        }
        !           921: 
        !           922:        /*
        !           923:         *  start operation
        !           924:         */
        !           925: /*     cmd = cmd | (dp->t->heads > 1 ? Fmulti : 0);/**/
        !           926:        fl.ncmd = 0;
        !           927:        fl.cmd[fl.ncmd++] = cmd;
        !           928:        fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
        !           929:        fl.cmd[fl.ncmd++] = dp->tcyl * dp->t->steps;
        !           930:        fl.cmd[fl.ncmd++] = dp->thead;
        !           931:        fl.cmd[fl.ncmd++] = dp->tsec;
        !           932:        fl.cmd[fl.ncmd++] = dp->t->bcode;
        !           933:        fl.cmd[fl.ncmd++] = dp->tsec + dp->len/dp->t->bytes - 1;
        !           934:        fl.cmd[fl.ncmd++] = dp->t->gpl;
        !           935:        fl.cmd[fl.ncmd++] = 0xFF;
        !           936:        splhi();
        !           937:        if(floppycmd() < 0){
        !           938:                spllo();
        !           939:                print("xfer cmd failed\n");
        !           940:                error(Eio);
        !           941:        }
        !           942: 
        !           943:        /*
        !           944:         *  give bus to DMA, floppyintr() will read result
        !           945:         */
        !           946:        SETCTL(Cpu_dma);
        !           947:        spllo();
        !           948:        floppywait();
        !           949: 
        !           950:        /*
        !           951:         *  check for errors
        !           952:         */
        !           953:        if(fl.nstat < 7){
        !           954:                print("xfer result failed %lux\n", devp->msr);
        !           955:                fl.confused = 1;
        !           956:                error(Eio);
        !           957:        }
        !           958:        if((fl.stat[0] & Codemask)!=0 || fl.stat[1] || fl.stat[2]){
        !           959:                if(fl.stat[1] != 0x80){
        !           960:                        print("xfer failed %lux %lux %lux\n", fl.stat[0],
        !           961:                                fl.stat[1], fl.stat[2]);
        !           962:                        print("offset %lud len %d\n", off, dp->len);
        !           963:                        dp->confused = 1;
        !           964:                        error(Eio);
        !           965:                } else
        !           966:                        fl.stat[5]++;
        !           967:        }
        !           968: 
        !           969:        /*
        !           970:         *  check for correct cylinder
        !           971:         */
        !           972:        offset = (fl.stat[3]/dp->t->steps) * dp->t->heads + fl.stat[4];
        !           973:        offset = offset*dp->t->sectors + fl.stat[5] - 1;
        !           974:        offset = offset * c2b[fl.stat[6]];
        !           975:        if(offset != off+dp->len){
        !           976:                print("new offset %d instead of %d\n", offset, off+dp->len);
        !           977:                dp->confused = 1;
        !           978:                error(Eio);
        !           979:        }
        !           980: 
        !           981:        dp->lasttouched = m->ticks;
        !           982:        return dp->len;
        !           983: }
        !           984: 
        !           985: void
        !           986: floppyintr(void)
        !           987: {
        !           988:        SCSIdma *dma = (SCSIdma *)SCSIDMA;
        !           989:        Device *devp = (Device*)(FDCTLRL);
        !           990: 
        !           991:        switch(fl.cmd[0]&~Fmulti){
        !           992:        case Fread:
        !           993:        case Fwrite:
        !           994:                if(dma->base != dma->limit)
        !           995:                        crankfifo(dma->limit - dma->base);
        !           996:                CLRCTL(Cpu_dma);
        !           997:                floppyresult();
        !           998:                break;
        !           999:        case Freadid:
        !          1000:                floppyresult();
        !          1001:                break;
        !          1002:        case Fseek:
        !          1003:        case Frecal:
        !          1004:        default:
        !          1005:                if(dmaowner != Ofloppy)
        !          1006:                        devp->flpctl = Sel_82077;
        !          1007:                floppysense();  /* to clear interrupt */
        !          1008:                if(dmaowner != Ofloppy)
        !          1009:                        devp->flpctl = 0;
        !          1010:                break;
        !          1011:        }
        !          1012:        fl.ncmd = 0;
        !          1013:        wakeup(&fl.r);
        !          1014: }

unix.superglobalmegacorp.com

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