Annotation of lucent/sys/src/boot/pc/floppy.c, revision 1.1

1.1     ! root        1: #include <u.h>
        !             2: 
        !             3: #include       "lib.h"
        !             4: #include       "mem.h"
        !             5: #include       "dat.h"
        !             6: #include       "fns.h"
        !             7: #include       "io.h"
        !             8: #include       "ureg.h"
        !             9: 
        !            10: #define DPRINT if(0)print
        !            11: 
        !            12: typedef        struct Drive    Drive;
        !            13: typedef        struct Floppy   Floppy;
        !            14: typedef struct Type    Type;
        !            15: 
        !            16: enum
        !            17: {
        !            18:        Pdor=           0x3f2,  /* motor port */
        !            19:         Fintena=        0x8,   /* enable floppy interrupt */
        !            20:         Fena=           0x4,   /* 0 == reset controller */
        !            21: 
        !            22:        Pmsr=           0x3f4,  /* controller main status port */
        !            23:         Fready=         0x80,  /* ready to be touched */
        !            24:         Ffrom=          0x40,  /* data from controller */
        !            25:         Fbusy=          0x10,  /* operation not over */
        !            26: 
        !            27:        Pdata=          0x3f5,  /* controller data port */
        !            28:         Frecal=         0x7,   /* recalibrate cmd */
        !            29:         Fseek=          0xf,   /* seek cmd */
        !            30:         Fsense=         0x8,   /* sense cmd */
        !            31:         Fread=          0x66,  /* read cmd */
        !            32:         Fwrite=         0x45,  /* write cmd */
        !            33:         Fmulti=         0x80,  /* or'd with Fread or Fwrite for multi-head */
        !            34: 
        !            35:        /* digital input register */
        !            36:        Pdir=           0x3F7,  /* disk changed port (read only) */
        !            37:        Pdsr=           0x3F7,  /* data rate select port (write only) */
        !            38:        Fchange=        0x80,   /* disk has changed */
        !            39: 
        !            40:        DMAmode0=       0xb,
        !            41:        DMAmode1=       0xc,
        !            42:        DMAaddr=        0x4,
        !            43:        DMAtop=         0x81,
        !            44:        DMAinit=        0xa,
        !            45:        DMAcount=       0x5,
        !            46: 
        !            47:        Maxfloppy=      4,      /* floppies/controller */
        !            48: 
        !            49:        /* sector size encodings */
        !            50:        S128=           0,
        !            51:        S256=           1,
        !            52:        S512=           2,
        !            53:        S1024=          3,
        !            54: 
        !            55:        /* status 0 byte */
        !            56:        Drivemask=      3<<0,
        !            57:        Seekend=        1<<5,
        !            58:        Codemask=       (3<<6)|(3<<3),
        !            59: };
        !            60: 
        !            61: #define MOTORBIT(i)    (1<<((i)+4))
        !            62: 
        !            63: /*
        !            64:  *  types of drive (from PC equipment byte)
        !            65:  */
        !            66: enum
        !            67: {
        !            68:        Tnone=          0,
        !            69:        T360kb=         1,
        !            70:        T1200kb=        2,
        !            71:        T720kb=         3,
        !            72:        T1440kb=        4,
        !            73: };
        !            74: 
        !            75: /*
        !            76:  *  floppy types (all MFM encoding)
        !            77:  */
        !            78: struct Type
        !            79: {
        !            80:        char    *name;
        !            81:        int     dt;             /* compatible drive type */
        !            82:        int     bytes;          /* bytes/sector */
        !            83:        int     sectors;        /* sectors/track */
        !            84:        int     heads;          /* number of heads */
        !            85:        int     steps;          /* steps per cylinder */
        !            86:        int     tracks;         /* tracks/disk */
        !            87:        int     gpl;            /* intersector gap length for read/write */     
        !            88:        int     fgpl;           /* intersector gap length for format */
        !            89:        int     rate;           /* rate code */
        !            90: 
        !            91:        /*
        !            92:         *  these depend on previous entries and are set filled in
        !            93:         *  by floppyinit
        !            94:         */
        !            95:        int     bcode;          /* coded version of bytes for the controller */
        !            96:        long    cap;            /* drive capacity in bytes */
        !            97:        long    tsize;          /* track size in bytes */
        !            98: };
        !            99: Type floppytype[] =
        !           100: {
        !           101:  { "3½HD",    T1440kb, 512, 18, 2, 1, 80, 0x1B, 0x54, 0, },
        !           102:  { "3½DD",    T1440kb, 512,  9, 2, 1, 80, 0x1B, 0x54, 2, },
        !           103:  { "3½DD",    T720kb,  512,  9, 2, 1, 80, 0x1B, 0x54, 2, },
        !           104:  { "5¼HD",    T1200kb, 512, 15, 2, 1, 80, 0x2A, 0x50, 0, },
        !           105:  { "5¼DD",    T1200kb, 512,  9, 2, 2, 40, 0x2A, 0x50, 1, },
        !           106:  { "5¼DD",    T360kb,  512,  9, 2, 1, 40, 0x2A, 0x50, 2, },
        !           107: };
        !           108: #define NTYPES (sizeof(floppytype)/sizeof(Type))
        !           109: 
        !           110: /*
        !           111:  *  bytes per sector encoding for the controller.
        !           112:  *  - index for b2c is is (bytes per sector/128).
        !           113:  *  - index for c2b is code from b2c
        !           114:  */
        !           115: static int b2c[] =
        !           116: {
        !           117: [1]    0,
        !           118: [2]    1,
        !           119: [4]    2,
        !           120: [8]    3,
        !           121: };
        !           122: static int c2b[] =
        !           123: {
        !           124:        128,
        !           125:        256,
        !           126:        512,
        !           127:        1024,
        !           128: };
        !           129: 
        !           130: /*
        !           131:  *  a floppy drive
        !           132:  */
        !           133: struct Drive
        !           134: {
        !           135:        Type    *t;
        !           136:        int     dt;
        !           137:        int     dev;
        !           138: 
        !           139:        ulong   lasttouched;    /* time last touched */
        !           140:        int     cyl;            /* current cylinder */
        !           141:        int     confused;       /* needs to be recalibrated (or worse) */
        !           142:        long    offset;         /* current offset */
        !           143: 
        !           144:        int     tcyl;           /* target cylinder */
        !           145:        int     thead;          /* target head */
        !           146:        int     tsec;           /* target sector */
        !           147:        long    len;
        !           148:        int     maxtries;
        !           149: };
        !           150: 
        !           151: /*
        !           152:  *  NEC PD765A controller for 4 floppys
        !           153:  */
        !           154: struct Floppy
        !           155: {
        !           156:        Drive   d[Maxfloppy];   /* the floppy drives */
        !           157:        int     rw;             /* true if a read or write in progress */
        !           158:        int     seek;           /* one bit for each seek in progress */
        !           159:        uchar   stat[8];        /* status of an operation */
        !           160:        int     intr;
        !           161:        int     confused;
        !           162:        int     motor;
        !           163:        Drive   *selected;
        !           164:        int     rate;
        !           165: 
        !           166:        int     cdev;
        !           167:        uchar   *ccache;        /* cylinder cache */
        !           168:        int     ccyl;
        !           169:        int     chead;
        !           170: };
        !           171: 
        !           172: Floppy fl;
        !           173: 
        !           174: static void    floppyalarm(Alarm*);
        !           175: static int     floppysend(int);
        !           176: static int     floppyrcv(void);
        !           177: static int     floppyrdstat(int);
        !           178: static void    floppypos(Drive*, long);
        !           179: static void    floppywait(char*);
        !           180: static int     floppysense(Drive*);
        !           181: static int     floppyrecal(Drive*);
        !           182: static void    floppyon(Drive*);
        !           183: static long    floppyxfer(Drive*, int, void*, long);
        !           184: static void    floppyrevive(void);
        !           185: static void    floppystop(Drive*);
        !           186: 
        !           187: static void
        !           188: timedsleep(int ms)
        !           189: {
        !           190:        ulong end;
        !           191: 
        !           192:        end = m->ticks + 1 + MS2TK(ms);
        !           193:        while(m->ticks < end)
        !           194:                ;
        !           195: }
        !           196: 
        !           197: /*
        !           198:  *  set floppy drive to its default type
        !           199:  */
        !           200: static void
        !           201: setdef(Drive *dp)
        !           202: {
        !           203:        Type *t;
        !           204: 
        !           205:        for(t = floppytype; t < &floppytype[NTYPES]; t++)
        !           206:                if(dp->dt == t->dt){
        !           207:                        dp->t = t;
        !           208:                        break;
        !           209:                }
        !           210: }
        !           211: 
        !           212: static void
        !           213: floppyintr(Ureg*, void*)
        !           214: {
        !           215:        fl.intr = 1;
        !           216: }
        !           217: 
        !           218: int
        !           219: floppyinit(void)
        !           220: {
        !           221:        Drive *dp;
        !           222:        uchar equip;
        !           223:        int mask;
        !           224:        Type *t;
        !           225:        char debstr[256];
        !           226: 
        !           227:        setvec(Floppyvec, floppyintr, 0);
        !           228: 
        !           229:        /* reset the interface chip */
        !           230:        sprint(debstr, "resetting floppy interface\n");
        !           231:        delay(50);
        !           232:        outb(Pdor, 0);
        !           233:        delay(50);
        !           234:        outb(Pdor, Fintena | Fena);
        !           235:        delay(50);
        !           236:        sprint(debstr, "floppy interface reset\n");
        !           237: 
        !           238:        /*
        !           239:         *  init dependent parameters
        !           240:         */
        !           241:        for(t = floppytype; t < &floppytype[NTYPES]; t++){
        !           242:                t->cap = t->bytes * t->heads * t->sectors * t->tracks;
        !           243:                t->bcode = b2c[t->bytes/128];
        !           244:                t->tsize = t->bytes * t->sectors;
        !           245:        }
        !           246: 
        !           247:        /*
        !           248:         *  init drive parameters
        !           249:         */
        !           250:        for(dp = fl.d; dp < &fl.d[Maxfloppy]; dp++){
        !           251:                dp->cyl = -1;
        !           252:                dp->dev = dp - fl.d;
        !           253:                dp->maxtries = 1;
        !           254:        }
        !           255: 
        !           256:        /*
        !           257:         *  read nvram for types of floppies 0 & 1
        !           258:         */
        !           259:        mask = 0;
        !           260:        equip = nvramread(0x10);
        !           261:        if(Maxfloppy > 0 && (fl.d[0].dt = ((equip>>4) & 0xF))){
        !           262:                setdef(&fl.d[0]);
        !           263:                mask |= 0x01;
        !           264:        }
        !           265:        if(Maxfloppy > 1 && (fl.d[1].dt = (equip & 0xF))){
        !           266:                setdef(&fl.d[1]);
        !           267:                mask |= 0x02;
        !           268:        }
        !           269: 
        !           270:        fl.rate = -1;
        !           271:        fl.motor = 0;
        !           272:        fl.confused = 1;
        !           273:        fl.ccyl = -1;
        !           274:        fl.chead = -1;
        !           275:        fl.cdev = -1;
        !           276:        fl.ccache = (uchar*)ialloc(18*2*512, 1);
        !           277: 
        !           278:        /* to turn the motor off when inactive */
        !           279:        alarm(5*1000, floppyalarm, (void *)0);
        !           280: 
        !           281:        return mask;
        !           282: }
        !           283: 
        !           284: static void
        !           285: floppyon(Drive *dp)
        !           286: {
        !           287:        int alreadyon;
        !           288:        int tries;
        !           289: 
        !           290:        if(fl.confused)
        !           291:                floppyrevive();
        !           292: 
        !           293:        alreadyon = fl.motor & MOTORBIT(dp->dev);
        !           294:        fl.motor |= MOTORBIT(dp->dev);
        !           295:        outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
        !           296: 
        !           297:        /* get motor going */
        !           298:        if(!alreadyon)
        !           299:                timedsleep(750);
        !           300: 
        !           301:        /* set transfer rate */
        !           302:        if(fl.rate != dp->t->rate){
        !           303:                fl.rate = dp->t->rate;
        !           304:                outb(Pdsr, fl.rate);
        !           305:        }
        !           306: 
        !           307:        /* get drive to a known cylinder */
        !           308:        if(dp->confused)
        !           309:                for(tries = 0; tries < 4; tries++)
        !           310:                        if(floppyrecal(dp) >= 0)
        !           311:                                break;
        !           312: 
        !           313:        dp->lasttouched = m->ticks;
        !           314:        fl.selected = dp;
        !           315: }
        !           316: 
        !           317: static void
        !           318: floppyrevive(void)
        !           319: {
        !           320:        Drive *dp;
        !           321: 
        !           322:        /*
        !           323:         *  reset the controller if it's confused
        !           324:         */
        !           325:        if(fl.confused){
        !           326:                /* reset controller and turn all motors off */
        !           327:                fl.intr = 0;
        !           328:                splhi();
        !           329:                outb(Pdor, 0);
        !           330:                delay(1);
        !           331:                outb(Pdor, Fintena|Fena);
        !           332:                spllo();
        !           333:                for(dp = fl.d; dp < &fl.d[Maxfloppy]; dp++)
        !           334:                        dp->confused = 1;
        !           335:                fl.motor = 0;
        !           336:                floppywait("revive");
        !           337:                fl.confused = 0;
        !           338:                outb(Pdsr, 0);
        !           339:        }
        !           340: }
        !           341: 
        !           342: static void
        !           343: floppystop(Drive *dp)
        !           344: {
        !           345:        fl.motor &= ~MOTORBIT(dp->dev);
        !           346:        outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
        !           347:        fl.selected = dp;
        !           348: }
        !           349: 
        !           350: static void
        !           351: floppyalarm(Alarm* a)
        !           352: {
        !           353:        Drive *dp;
        !           354: 
        !           355:        for(dp = fl.d; dp < &fl.d[Maxfloppy]; dp++){
        !           356:                if((fl.motor&MOTORBIT(dp->dev)) && TK2SEC(m->ticks - dp->lasttouched) > 5)
        !           357:                        floppystop(dp);
        !           358:        }
        !           359: 
        !           360:        alarm(5*1000, floppyalarm, 0);
        !           361:        cancel(a);
        !           362: }
        !           363: 
        !           364: static int
        !           365: floppysend(int data)
        !           366: {
        !           367:        int tries;
        !           368:        uchar c;
        !           369: 
        !           370:        for(tries = 0; tries < 100; tries++){
        !           371:                /*
        !           372:                 *  see if its ready for data
        !           373:                 */
        !           374:                c = inb(Pmsr);
        !           375:                if((c&(Ffrom|Fready)) != Fready)
        !           376:                        continue;
        !           377: 
        !           378:                /*
        !           379:                 *  send the data
        !           380:                 */
        !           381:                outb(Pdata, data);
        !           382:                return 0;
        !           383:        }
        !           384:        return -1;
        !           385: }
        !           386: 
        !           387: static int
        !           388: floppyrcv(void)
        !           389: {
        !           390:        int tries;
        !           391:        uchar c;
        !           392: 
        !           393:        for(tries = 0; tries < 100; tries++){
        !           394:                /*
        !           395:                 *  see if its ready for data
        !           396:                 */
        !           397:                c = inb(Pmsr);
        !           398:                if((c&(Ffrom|Fready)) != (Ffrom|Fready))
        !           399:                        continue;
        !           400: 
        !           401:                /*
        !           402:                 *  get data
        !           403:                 */
        !           404:                return inb(Pdata)&0xff;
        !           405:        }
        !           406:        DPRINT("floppyrcv returns -1 status = %lux\n", c);
        !           407:        return -1;
        !           408: }
        !           409: 
        !           410: static int
        !           411: floppyrdstat(int n)
        !           412: {
        !           413:        int i;
        !           414:        int c;
        !           415: 
        !           416:        for(i = 0; i < n; i++){
        !           417:                c = floppyrcv();
        !           418:                if(c < 0)
        !           419:                        return -1;
        !           420:                fl.stat[i] = c;
        !           421:        }
        !           422:        return 0;
        !           423: }
        !           424: 
        !           425: static void
        !           426: floppypos(Drive *dp, long off)
        !           427: {
        !           428:        int lsec;
        !           429:        int cyl;
        !           430: 
        !           431:        lsec = off/dp->t->bytes;
        !           432:        dp->tcyl = lsec/(dp->t->sectors*dp->t->heads);
        !           433:        dp->tsec = (lsec % dp->t->sectors) + 1;
        !           434:        dp->thead = (lsec/dp->t->sectors) % dp->t->heads;
        !           435: 
        !           436:        /*
        !           437:         *  can't read across cylinder boundaries.
        !           438:         *  if so, decrement the bytes to be read.
        !           439:         */
        !           440:        lsec = (off+dp->len)/dp->t->bytes;
        !           441:        cyl = lsec/(dp->t->sectors*dp->t->heads);
        !           442:        if(cyl != dp->tcyl){
        !           443:                dp->len -= (lsec % dp->t->sectors)*dp->t->bytes;
        !           444:                dp->len -= ((lsec/dp->t->sectors) % dp->t->heads)*dp->t->bytes
        !           445:                                *dp->t->sectors;
        !           446:        }
        !           447: 
        !           448:        dp->lasttouched = m->ticks;     
        !           449:        fl.intr = 0;
        !           450: }
        !           451: 
        !           452: static void
        !           453: floppywait(char *cmd)
        !           454: {
        !           455:        ulong start;
        !           456: 
        !           457:        for(start = m->ticks; TK2SEC(m->ticks - start) < 1 && fl.intr == 0;)
        !           458:                ;
        !           459:        if(TK2SEC(m->ticks - start) >= 1)
        !           460:                DPRINT("floppy timed out, cmd=%s\n", cmd);
        !           461:        fl.intr = 0;
        !           462: }
        !           463: 
        !           464: static int
        !           465: floppysense(Drive *dp)
        !           466: {
        !           467:        /*
        !           468:         *  ask for floppy status
        !           469:         */
        !           470:        if(floppysend(Fsense) < 0){
        !           471:                fl.confused = 1;
        !           472:                return -1;
        !           473:        }
        !           474:        if(floppyrdstat(2) < 0){
        !           475:                fl.confused = 1;
        !           476:                dp->confused = 1;
        !           477:                return -1;
        !           478:        }
        !           479: 
        !           480:        /*
        !           481:         *  make sure it's the right drive
        !           482:         */
        !           483:        if((fl.stat[0] & Drivemask) != dp->dev){
        !           484:                DPRINT("sense failed, %lux %lux\n", fl.stat[0], fl.stat[1]);
        !           485:                dp->confused = 1;
        !           486:                return -1;
        !           487:        }
        !           488:        return 0;
        !           489: }
        !           490: 
        !           491: static int
        !           492: floppyrecal(Drive *dp)
        !           493: {
        !           494:        fl.intr = 0;
        !           495:        if(floppysend(Frecal) < 0
        !           496:        || floppysend(dp - fl.d) < 0){
        !           497:                DPRINT("recalibrate rejected\n");
        !           498:                fl.confused = 0;
        !           499:                return -1;
        !           500:        }
        !           501:        floppywait("recal");
        !           502: 
        !           503:        /*
        !           504:         *  get return values
        !           505:         */
        !           506:        if(floppysense(dp) < 0)
        !           507:                return -1;
        !           508: 
        !           509:        /*
        !           510:         *  see what cylinder we got to
        !           511:         */
        !           512:        dp->tcyl = 0;
        !           513:        dp->cyl = fl.stat[1]/dp->t->steps;
        !           514:        if(dp->cyl != dp->tcyl){
        !           515:                DPRINT("recalibrate went to wrong cylinder %d\n", dp->cyl);
        !           516:                dp->confused = 1;
        !           517:                return -1;
        !           518:        }
        !           519: 
        !           520:        dp->confused = 0;
        !           521:        return 0;
        !           522: }
        !           523: 
        !           524: long
        !           525: floppyseek(int dev, long off)
        !           526: {
        !           527:        Drive *dp;
        !           528: 
        !           529:        dp = &fl.d[dev];
        !           530:        floppyon(dp);
        !           531:        floppypos(dp, off);
        !           532:        if(dp->cyl == dp->tcyl){
        !           533:                dp->offset = off;
        !           534:                return off;
        !           535:        }
        !           536: 
        !           537:        /*
        !           538:         *  tell floppy to seek
        !           539:         */
        !           540:        if(floppysend(Fseek) < 0
        !           541:        || floppysend((dp->thead<<2) | dp->dev) < 0
        !           542:        || floppysend(dp->tcyl * dp->t->steps) < 0){
        !           543:                DPRINT("seek cmd failed\n");
        !           544:                fl.confused = 1;
        !           545:                return -1;
        !           546:        }
        !           547: 
        !           548:        /*
        !           549:         *  wait for interrupt
        !           550:         */
        !           551:        floppywait("seek");
        !           552: 
        !           553:        /*
        !           554:         *  get floppy status
        !           555:         */
        !           556:        if(floppysense(dp) < 0)
        !           557:                return -1;
        !           558: 
        !           559:        /*
        !           560:         *  see if it worked
        !           561:         */
        !           562:        if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
        !           563:                DPRINT("seek failed\n");
        !           564:                dp->confused = 1;
        !           565:                return -1;
        !           566:        }
        !           567: 
        !           568:        /*
        !           569:         *  see what cylinder we got to
        !           570:         */
        !           571:        dp->cyl = fl.stat[1]/dp->t->steps;
        !           572:        if(dp->cyl != dp->tcyl){
        !           573:                DPRINT("seek went to wrong cylinder %d instead of %d\n",
        !           574:                        dp->cyl, dp->tcyl);
        !           575:                dp->confused = 1;
        !           576:                return -1;
        !           577:        }
        !           578: 
        !           579:        dp->offset = off;
        !           580:        DPRINT("seek to %d succeeded\n", dp->offset);
        !           581:        return dp->offset;
        !           582: }
        !           583: 
        !           584: static long
        !           585: floppyxfer(Drive *dp, int cmd, void *a, long n)
        !           586: {
        !           587:        ulong addr;
        !           588:        long offset;
        !           589: 
        !           590:        addr = (ulong)a;
        !           591: 
        !           592:        /*
        !           593:         *  dma can't cross 64 k boundaries
        !           594:         */
        !           595:        if((addr & 0xffff0000) != ((addr+n) & 0xffff0000))
        !           596:                n -= (addr+n)&0xffff;
        !           597: 
        !           598:        dp->len = n;
        !           599:        if(floppyseek(dp->dev, dp->offset) < 0){
        !           600:                DPRINT("xfer seek failed\n");
        !           601:                return -1;
        !           602:        }
        !           603: 
        !           604:        DPRINT("floppy %d tcyl %d, thead %d, tsec %d, addr %lux, n %d\n",
        !           605:                dp->dev, dp->tcyl, dp->thead, dp->tsec, addr, n);/**/
        !           606: 
        !           607:        /*
        !           608:         *  set up the dma
        !           609:         */
        !           610:        outb(DMAmode1, cmd==Fread ? 0x46 : 0x4a);
        !           611:        outb(DMAmode0, cmd==Fread ? 0x46 : 0x4a);
        !           612:        outb(DMAaddr, addr);
        !           613:        outb(DMAaddr, addr>>8);
        !           614:        outb(DMAtop, addr>>16);
        !           615:        outb(DMAcount, n-1);
        !           616:        outb(DMAcount, (n-1)>>8);
        !           617:        outb(DMAinit, 2);
        !           618: 
        !           619:        /*
        !           620:         *  tell floppy to go
        !           621:         */
        !           622:        cmd = cmd | (dp->t->heads > 1 ? Fmulti : 0);
        !           623:        if(floppysend(cmd) < 0
        !           624:        || floppysend((dp->thead<<2) | dp->dev) < 0
        !           625:        || floppysend(dp->tcyl * dp->t->steps) < 0
        !           626:        || floppysend(dp->thead) < 0
        !           627:        || floppysend(dp->tsec) < 0
        !           628:        || floppysend(dp->t->bcode) < 0
        !           629:        || floppysend(dp->t->sectors) < 0
        !           630:        || floppysend(dp->t->gpl) < 0
        !           631:        || floppysend(0xFF) < 0){
        !           632:                DPRINT("xfer cmd failed\n");
        !           633:                fl.confused = 1;
        !           634:                return -1;
        !           635:        }
        !           636: 
        !           637:        floppywait("xfer");
        !           638: 
        !           639:        /*
        !           640:         *  get status
        !           641:         */
        !           642:        if(floppyrdstat(7) < 0){
        !           643:                DPRINT("xfer status failed\n");
        !           644:                fl.confused = 1;
        !           645:                return -1;
        !           646:        }
        !           647: 
        !           648:        if((fl.stat[0] & Codemask)!=0 || fl.stat[1] || fl.stat[2]){
        !           649:                DPRINT("xfer failed %lux %lux %lux\n", fl.stat[0],
        !           650:                        fl.stat[1], fl.stat[2]);
        !           651:                dp->confused = 1;
        !           652:                return -1;
        !           653:        }
        !           654: 
        !           655:        offset = (fl.stat[3]/dp->t->steps) * dp->t->heads + fl.stat[4];
        !           656:        offset = offset*dp->t->sectors + fl.stat[5] - 1;
        !           657:        offset = offset * c2b[fl.stat[6]];
        !           658:        if(offset != dp->offset+n){
        !           659:                DPRINT("new offset %d instead of %d\n", offset, dp->offset+dp->len);
        !           660:                dp->confused = 1;
        !           661:                return -1;/**/
        !           662:        }
        !           663:        dp->offset += dp->len;
        !           664:        return dp->len;
        !           665: }
        !           666: 
        !           667: long
        !           668: floppyread(int dev, void *a, long n)
        !           669: {
        !           670:        Drive *dp;
        !           671:        long rv, i, nn, offset, sec;
        !           672:        uchar *aa;
        !           673:        int tries;
        !           674: 
        !           675:        dp = &fl.d[dev];
        !           676: 
        !           677:        dp->len = n;
        !           678:        floppypos(dp, dp->offset);
        !           679:        offset = dp->offset;
        !           680:        sec = dp->tsec + dp->t->sectors*dp->thead;
        !           681:        n = dp->len;
        !           682:        if(fl.ccyl==dp->tcyl && fl.cdev==dev)
        !           683:                goto out;
        !           684: 
        !           685:        fl.ccyl = -1;
        !           686:        fl.cdev = dev;
        !           687:        aa = fl.ccache;
        !           688:        nn = dp->t->bytes*dp->t->sectors*dp->t->heads;
        !           689:        dp->offset = dp->tcyl*nn;
        !           690:        for(rv = 0; rv < nn; rv += i){
        !           691:                i = 0;
        !           692:                for(tries = 0; tries < dp->maxtries; tries++){
        !           693:                        i = floppyxfer(dp, Fread, aa+rv, nn-rv);
        !           694:                        if(i > 0)
        !           695:                                break;
        !           696:                }
        !           697:                if(tries == dp->maxtries)
        !           698:                        break;
        !           699:        }
        !           700:        if(rv != nn){
        !           701:                dp->confused = 1;
        !           702:                return -1;
        !           703:        }
        !           704:        fl.ccyl = dp->tcyl;
        !           705: out:
        !           706:        memmove(a, fl.ccache + dp->t->bytes*(sec-1), n);
        !           707:        dp->offset = offset + n;
        !           708:        dp->maxtries = 3;
        !           709:        return n;
        !           710: }

unix.superglobalmegacorp.com

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