Annotation of lucent/sys/src/9/next/f002520, revision 1.1.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.