Annotation of lucent/sys/src/boot/pc/hard.c, revision 1.1.1.1

1.1       root        1: #include       "u.h"
                      2: #include       "lib.h"
                      3: #include       "mem.h"
                      4: #include       "dat.h"
                      5: #include       "fns.h"
                      6: #include       "io.h"
                      7: 
                      8: #define DPRINT if(0)print
                      9: 
                     10: typedef        struct Drive            Drive;
                     11: typedef        struct Ident            Ident;
                     12: typedef        struct Controller       Controller;
                     13: 
                     14: enum
                     15: {
                     16:        /* ports */
                     17:        Pbase=          0x1F0,
                     18:        Pdata=          0,      /* data port (16 bits) */
                     19:        Perror=         1,      /* error port (read) */
                     20:        Pprecomp=       1,      /* buffer mode port (write) */
                     21:        Pcount=         2,      /* sector count port */
                     22:        Psector=        3,      /* sector number port */
                     23:        Pcyllsb=        4,      /* least significant byte cylinder # */
                     24:        Pcylmsb=        5,      /* most significant byte cylinder # */
                     25:        Pdh=            6,      /* drive/head port */
                     26:        Pstatus=        7,      /* status port (read) */
                     27:         Sbusy=          (1<<7),
                     28:         Sready=         (1<<6),
                     29:         Sdrq=           (1<<3),
                     30:         Serr=           (1<<0),
                     31:        Pcmd=           7,      /* cmd port (write) */
                     32: 
                     33:        /* commands */
                     34:        Crecal=         0x10,
                     35:        Cread=          0x20,
                     36:        Cwrite=         0x30,
                     37:        Cident=         0xEC,
                     38:        Cident2=        0xFF,   /* pseudo command for post Cident interrupt */
                     39:        Csetbuf=        0xEF,
                     40: 
                     41:        /* file types */
                     42:        Qdir=           0,
                     43: 
                     44:        /* magic bit in drive head register */
                     45:        Dmagic=         (1<<5),
                     46: 
                     47:        Timeout=        4,              /* seconds to wait for things to complete */
                     48: };
                     49: 
                     50: /*
                     51:  *  ident sector from drive.  this is from ANSI X3.221-1994
                     52:  */
                     53: struct Ident
                     54: {
                     55:        ushort  config;         /* general configuration info */
                     56:        ushort  cyls;           /* # of cylinders (default) */
                     57:        ushort  reserved0;
                     58:        ushort  heads;          /* # of heads (default) */
                     59:        ushort  b2t;            /* unformatted bytes/track */
                     60:        ushort  b2s;            /* unformated bytes/sector */
                     61:        ushort  s2t;            /* sectors/track (default) */
                     62:        ushort  reserved1[3];
                     63: /* 10 */
                     64:        ushort  serial[10];     /* serial number */
                     65:        ushort  type;           /* buffer type */
                     66:        ushort  bsize;          /* buffer size/512 */
                     67:        ushort  ecc;            /* ecc bytes returned by read long */
                     68:        ushort  firm[4];        /* firmware revision */
                     69:        ushort  model[20];      /* model number */
                     70: /* 47 */
                     71:        ushort  s2i;            /* number of sectors/interrupt */
                     72:        ushort  dwtf;           /* double word transfer flag */
                     73:        ushort  capabilities;
                     74:        ushort  reserved2;
                     75:        ushort  piomode;
                     76:        ushort  dmamode;
                     77:        ushort  cvalid;         /* (cvald&1) if next 4 words are valid */
                     78:        ushort  ccyls;          /* current # cylinders */
                     79:        ushort  cheads;         /* current # heads */
                     80:        ushort  cs2t;           /* current sectors/track */
                     81:        ushort  ccap[2];        /* current capacity in sectors */
                     82:        ushort  cs2i;           /* current number of sectors/interrupt */
                     83: /* 60 */
                     84:        ushort  lbasecs[2];     /* # LBA user addressable sectors */
                     85:        ushort  dmasingle;
                     86:        ushort  dmadouble;
                     87: /* 64 */
                     88:        ushort  reserved3[64];
                     89:        ushort  vendor[32];     /* vendor specific */
                     90:        ushort  reserved4[96];
                     91: };
                     92: 
                     93: /*
                     94:  *  a hard drive
                     95:  */
                     96: struct Drive
                     97: {
                     98:        Controller *cp;
                     99:        int     drive;
                    100:        int     confused;       /* needs to be recalibrated (or worse) */
                    101: 
                    102:        Disc;
                    103: };
                    104: 
                    105: /*
                    106:  *  a controller for 2 drives
                    107:  */
                    108: struct Controller
                    109: {
                    110:        int     confused;       /* needs to be recalibrated (or worse) */
                    111:        int     pbase;          /* base port */
                    112: 
                    113:        /*
                    114:         *  current operation
                    115:         */
                    116:        int     cmd;            /* current command */
                    117:        char    *buf;           /* xfer buffer */
                    118:        int     tcyl;           /* target cylinder */
                    119:        int     thead;          /* target head */
                    120:        int     tsec;           /* target sector */
                    121:        int     tbyte;          /* target byte */
                    122:        int     nsecs;          /* length of transfer (sectors) */
                    123:        int     sofar;          /* bytes transferred so far */
                    124:        int     status;
                    125:        int     error;
                    126:        Drive   *dp;            /* drive being accessed */
                    127: };
                    128: 
                    129: Controller     *hardc;
                    130: Drive          *hard;
                    131: 
                    132: static void    hardintr(Ureg*, void*);
                    133: static long    hardxfer(Drive*, Partition*, int, long, long);
                    134: static int     hardident(Drive*);
                    135: static void    hardsetbuf(Drive*, int);
                    136: static void    hardpart(Drive*);
                    137: static int     hardparams(Drive*);
                    138: static void    hardrecal(Drive*);
                    139: static int     hardprobe(Drive*, int, int, int);
                    140: 
                    141: /*
                    142:  *  we assume drives 0 and 1 are on the first controller, 2 and 3 on the
                    143:  *  second, etc.  Discover drive parameters.  BUG! we are only guessing about
                    144:  *  the port locations for disks other than 0 and 1.
                    145:  */
                    146: int
                    147: hardinit(void)
                    148: {
                    149:        Drive *dp;
                    150:        Controller *cp;
                    151:        uchar equip;
                    152:        int mask, nhard;
                    153: 
                    154:        equip = nvramread(0x12);
                    155:        if(equip == 0)
                    156:                equip = 0x10;           /* the Globalyst 250 lies */
                    157: 
                    158:        hard = ialloc(2 * sizeof(Drive), 0);
                    159:        hardc = ialloc(sizeof(Controller), 0);
                    160: 
                    161:        cp = hardc;
                    162:        cp->buf = ialloc(Maxxfer, 0);
                    163:        cp->cmd = 0;
                    164:        cp->pbase = Pbase;
                    165:        /*
                    166:         *  clear any pending intr from drive
                    167:         */
                    168:        inb(cp->pbase+Pstatus);
                    169:        setvec(Hardvec, hardintr, cp);
                    170:        
                    171:        dp = hard;
                    172:        if(equip & 0xf0){
                    173:                dp->drive = 0;
                    174:                dp->online = 0;
                    175:                dp->cp = cp;
                    176:                dp++;
                    177:        }
                    178:        if(equip & 0x0f){
                    179:                dp->drive = 1;
                    180:                dp->online = 0;
                    181:                dp->cp = cp;
                    182:                dp++;
                    183:        }
                    184:        nhard = dp-hard;
                    185: 
                    186:        mask = 0;
                    187:        for(dp = hard; dp < &hard[nhard]; dp++){
                    188:                if(hardparams(dp) == 0){
                    189:                        print("hd%d: %d cylinders %d heads %d sectors/track %d bytes\n",
                    190:                                dp->drive, dp->cyl, dp->heads, dp->sectors, dp->cap);
                    191:                        dp->online = 1;
                    192:                        hardpart(dp);
                    193:                        hardsetbuf(dp, 1);
                    194:                        mask |= 1<<dp->drive;
                    195:                } else
                    196:                        dp->online = 0;
                    197:        }
                    198:        return mask;
                    199: }
                    200: 
                    201: long
                    202: hardseek(int dev, long off)
                    203: {
                    204:        hard[dev].offset = off;
                    205:        return off;
                    206: }
                    207: 
                    208: /*
                    209:  *  did an interrupt happen?
                    210:  */
                    211: static void
                    212: hardwait(Controller *cp)
                    213: {
                    214:        ulong start;
                    215:        int x;
                    216: 
                    217:        x = spllo();
                    218:        for(start = m->ticks; TK2SEC(m->ticks - start) < Timeout && cp->cmd;)
                    219:                if(cp->cmd == Cident2 && TK2SEC(m->ticks - start) >= 1)
                    220:                        break;
                    221:        if(TK2SEC(m->ticks - start) >= Timeout){
                    222:                DPRINT("hardwait timed out %ux\n", inb(cp->pbase+Pstatus));
                    223:                hardintr(0, cp);
                    224:        }
                    225:        splx(x);
                    226: }
                    227: 
                    228: Partition*
                    229: sethardpart(int dev, char *p)
                    230: {
                    231:        Partition *pp;
                    232:        Drive *dp;
                    233: 
                    234:        dp = &hard[dev];
                    235:        for(pp = dp->p; pp < &dp->p[dp->npart]; pp++)
                    236:                if(strcmp(pp->name, p) == 0){
                    237:                        dp->current = pp;
                    238:                        return pp;
                    239:                }
                    240:        return 0;
                    241: }
                    242: 
                    243: long
                    244: hardread(int dev, void *a, long n)
                    245: {
                    246:        Drive *dp;
                    247:        long rv, i;
                    248:        int skip;
                    249:        uchar *aa = a;
                    250:        Partition *pp;
                    251:        Controller *cp;
                    252: 
                    253:        dp = &hard[dev];
                    254:        pp = dp->current;
                    255:        if(pp == 0)
                    256:                return -1;
                    257:        cp = dp->cp;
                    258: 
                    259:        skip = dp->offset % dp->bytes;
                    260:        for(rv = 0; rv < n; rv += i){
                    261:                i = hardxfer(dp, pp, Cread, dp->offset+rv-skip, n-rv+skip);
                    262:                if(i == 0)
                    263:                        break;
                    264:                if(i < 0)
                    265:                        return -1;
                    266:                i -= skip;
                    267:                if(i > n - rv)
                    268:                        i = n - rv;
                    269:                memmove(aa+rv, cp->buf + skip, i);
                    270:                skip = 0;
                    271:        }
                    272:        dp->offset += rv;
                    273: 
                    274:        return rv;
                    275: }
                    276: 
                    277: /*
                    278:  *  wait for the controller to be ready to accept a command
                    279:  */
                    280: static int
                    281: cmdreadywait(Controller *cp)
                    282: {
                    283:        long start;
                    284: 
                    285:        start = m->ticks;
                    286:        while((inb(cp->pbase+Pstatus) & (Sready|Sbusy)) != Sready)
                    287:                if(TK2MS(m->ticks - start) > Timeout){
                    288:                        DPRINT("cmdreadywait failed 0x%lux\n", inb(cp->pbase+Pstatus));
                    289:                        return -1;
                    290:                }
                    291:        return 0;
                    292: }
                    293: 
                    294: /*
                    295:  *  transfer a number of sectors.  hardintr will perform all the iterative
                    296:  *  parts.
                    297:  */
                    298: static long
                    299: hardxfer(Drive *dp, Partition *pp, int cmd, long start, long len)
                    300: {
                    301:        Controller *cp;
                    302:        long lsec;
                    303:        int loop;
                    304: 
                    305:        if(dp->online == 0){
                    306:                DPRINT("disk not on line\n");
                    307:                return -1;
                    308:        }
                    309: 
                    310:        /*
                    311:         *  cut transfer size down to disk buffer size
                    312:         */
                    313:        start = start / dp->bytes;
                    314:        if(len > Maxxfer)
                    315:                len = Maxxfer;
                    316:        len = (len + dp->bytes - 1) / dp->bytes;
                    317: 
                    318:        /*
                    319:         *  calculate physical address
                    320:         */
                    321:        cp = dp->cp;
                    322:        lsec = start + pp->start;
                    323:        if(lsec >= pp->end){
                    324:                DPRINT("read past end of partition\n");
                    325:                return 0;
                    326:        }
                    327:        if(dp->lba){
                    328:                cp->tsec = lsec & 0xff;
                    329:                cp->tcyl = (lsec>>8) & 0xffff;
                    330:                cp->thead = (lsec>>24) & 0xf;
                    331:        } else {
                    332:                cp->tcyl = lsec/(dp->sectors*dp->heads);
                    333:                cp->tsec = (lsec % dp->sectors) + 1;
                    334:                cp->thead = (lsec/dp->sectors) % dp->heads;
                    335:        }
                    336: 
                    337:        /*
                    338:         *  can't xfer past end of disk
                    339:         */
                    340:        if(lsec+len > pp->end)
                    341:                len = pp->end - lsec;
                    342:        cp->nsecs = len;
                    343: 
                    344:        if(cmdreadywait(cp) < 0)
                    345:                return -1;
                    346: 
                    347:        /*
                    348:         *  start the transfer
                    349:         */
                    350:        cp->cmd = cmd;
                    351:        cp->dp = dp;
                    352:        cp->sofar = 0;
                    353:        cp->status = 0;
                    354:        DPRINT("xfer:\ttcyl %d, tsec %d, thead %d\n", cp->tcyl, cp->tsec, cp->thead);
                    355:        DPRINT("\tnsecs %d, sofar %d\n", cp->nsecs, cp->sofar);
                    356:        outb(cp->pbase+Pcount, cp->nsecs);
                    357:        outb(cp->pbase+Psector, cp->tsec);
                    358:        outb(cp->pbase+Pdh, Dmagic | (dp->drive<<4) | (dp->lba<<6) | cp->thead);
                    359:        outb(cp->pbase+Pcyllsb, cp->tcyl);
                    360:        outb(cp->pbase+Pcylmsb, cp->tcyl>>8);
                    361:        outb(cp->pbase+Pcmd, cmd);
                    362: 
                    363:        if(cmd == Cwrite){
                    364:                loop = 0;
                    365:                while((inb(cp->pbase+Pstatus) & Sdrq) == 0)
                    366:                        if(++loop > 10000)
                    367:                                panic("hardxfer");
                    368:                outss(cp->pbase+Pdata, cp->buf, dp->bytes/2);
                    369:        }
                    370: 
                    371:        hardwait(cp);
                    372: 
                    373:        if(cp->status & Serr){
                    374:                DPRINT("hd%d err: status %lux, err %lux\n",
                    375:                        dp-hard, cp->status, cp->error);
                    376:                DPRINT("\ttcyl %d, tsec %d, thead %d\n",
                    377:                        cp->tcyl, cp->tsec, cp->thead);
                    378:                DPRINT("\tnsecs %d, sofar %d\n", cp->nsecs, cp->sofar);
                    379:                return -1;
                    380:        }
                    381: 
                    382:        return cp->nsecs*dp->bytes;
                    383: }
                    384: 
                    385: /*
                    386:  *  set read ahead mode (1 == on, 0 == off)
                    387:  */
                    388: static void
                    389: hardsetbuf(Drive *dp, int on)
                    390: {
                    391:        Controller *cp = dp->cp;
                    392: 
                    393:        if(cmdreadywait(cp) < 0)
                    394:                return;
                    395: 
                    396:        cp->cmd = Csetbuf;
                    397:        /* BUG: precomp varies by hard drive...this is safari-specific? */
                    398:        outb(cp->pbase+Pprecomp, on ? 0xAA : 0x55);
                    399:        outb(cp->pbase+Pdh, Dmagic | (dp->drive<<4));
                    400:        outb(cp->pbase+Pcmd, Csetbuf);
                    401: 
                    402:        hardwait(cp);
                    403: }
                    404: 
                    405: /*
                    406:  *  get parameters from the drive
                    407:  */
                    408: static int
                    409: hardident(Drive *dp)
                    410: {
                    411:        Controller *cp;
                    412:        Ident *ip;
                    413: 
                    414:        dp->bytes = 512;
                    415:        cp = dp->cp;
                    416: 
                    417:        if(cmdreadywait(cp) < 0)
                    418:                return -1;
                    419: 
                    420:        cp->nsecs = 1;
                    421:        cp->sofar = 0;
                    422:        cp->cmd = Cident;
                    423:        cp->dp = dp;
                    424:        outb(cp->pbase+Pdh, Dmagic | (dp->drive<<4));
                    425:        outb(cp->pbase+Pcmd, Cident);
                    426: 
                    427:        hardwait(cp);
                    428: 
                    429:        if(cp->status & Serr)
                    430:                return -1;
                    431:        
                    432:        hardwait(cp);
                    433: 
                    434:        ip = (Ident*)cp->buf;
                    435:        if(ip->capabilities & (1<<9)){
                    436:                dp->lba = 1;
                    437:                dp->sectors = (ip->lbasecs[0]) | (ip->lbasecs[1]<<16);
                    438:                dp->cap = dp->bytes * dp->sectors;
                    439: /*print("\nata%d model %s with %d lba sectors\n", dp->drive, id, dp->sectors);/**/
                    440:        } else {
                    441:                dp->lba = 0;
                    442: 
                    443:                /* use default (unformatted) settings */
                    444:                dp->cyl = ip->cyls;
                    445:                dp->heads = ip->heads;
                    446:                dp->sectors = ip->s2t;
                    447: /*print("\nata%d model %s with default %d cyl %d head %d sec\n", dp->drive,
                    448:                        id, dp->cyl, dp->heads, dp->sectors);/**/
                    449: 
                    450:                if(ip->cvalid&(1<<0)){
                    451:                        /* use current settings */
                    452:                        dp->cyl = ip->ccyls;
                    453:                        dp->heads = ip->cheads;
                    454:                        dp->sectors = ip->cs2t;
                    455: /*print("\tchanged to %d cyl %d head %d sec\n", dp->cyl, dp->heads, dp->sectors);/**/
                    456:                }
                    457:                dp->cap = dp->bytes * dp->cyl * dp->heads * dp->sectors;
                    458:        }
                    459: 
                    460:        return 0;
                    461: }
                    462: 
                    463: /*
                    464:  *  probe the given sector to see if it exists
                    465:  */
                    466: static int
                    467: hardprobe(Drive *dp, int cyl, int sec, int head)
                    468: {
                    469:        Controller *cp;
                    470: 
                    471:        cp = dp->cp;
                    472:        if(cmdreadywait(cp) < 0)
                    473:                return -1;
                    474: 
                    475:        /*
                    476:         *  start the transfer
                    477:         */
                    478:        cp->cmd = Cread;
                    479:        cp->dp = dp;
                    480:        cp->sofar = 0;
                    481:        cp->nsecs = 1;
                    482:        cp->status = 0;
                    483:        outb(cp->pbase+Pcount, 1);
                    484:        outb(cp->pbase+Psector, sec+1);
                    485:        outb(cp->pbase+Pdh, Dmagic | head | (dp->lba<<6) | (dp->drive<<4));
                    486:        outb(cp->pbase+Pcyllsb, cyl);
                    487:        outb(cp->pbase+Pcylmsb, cyl>>8);
                    488:        outb(cp->pbase+Pcmd, Cread);
                    489: 
                    490:        hardwait(cp);
                    491: 
                    492:        if(cp->status & Serr)
                    493:                return -1;
                    494: 
                    495:        return 0;
                    496: }
                    497: 
                    498: /*
                    499:  *  figure out the drive parameters
                    500:  */
                    501: static int
                    502: hardparams(Drive *dp)
                    503: {
                    504:        int i, hi, lo;
                    505: 
                    506:        /*
                    507:         *  first try the easy way, ask the drive and make sure it
                    508:         *  isn't lying.
                    509:         */
                    510:        dp->bytes = 512;
                    511:        if(hardident(dp) < 0)
                    512:                return -1;
                    513:        if(dp->lba){
                    514:                i = dp->sectors - 1;
                    515:                if(hardprobe(dp, (i>>8)&0xffff, (i&0xff)-1, (i>>24)&0xf) == 0)
                    516:                        return 0;
                    517:        } else {
                    518:                if(hardprobe(dp, dp->cyl-1, dp->sectors-1, dp->heads-1) == 0)
                    519:                        return 0;
                    520:        }
                    521: 
                    522:        DPRINT("hardparam: cyl %d sectors %d heads %d\n", dp->cyl, dp->sectors, dp->heads);
                    523:        /*
                    524:         *  the drive lied, determine parameters by seeing which ones
                    525:         *  work to read sectors.
                    526:         */
                    527:        for(i = 0; i < 32; i++)
                    528:                if(hardprobe(dp, 0, 0, i) < 0)
                    529:                        break;
                    530:        dp->heads = i;
                    531:        for(i = 0; i < 128; i++)
                    532:                if(hardprobe(dp, 0, i, 0) < 0)
                    533:                        break;
                    534:        dp->sectors = i;
                    535:        for(i = 512; ; i += 512)
                    536:                if(hardprobe(dp, i, dp->sectors-1, dp->heads-1) < 0)
                    537:                        break;
                    538:        lo = i - 512;
                    539:        hi = i;
                    540:        for(; hi-lo > 1;){
                    541:                i = lo + (hi - lo)/2;
                    542:                if(hardprobe(dp, i, dp->sectors-1, dp->heads-1) < 0)
                    543:                        hi = i;
                    544:                else
                    545:                        lo = i;
                    546:        }
                    547:        dp->cyl = lo + 1;
                    548:        dp->cap = dp->bytes * dp->cyl * dp->heads * dp->sectors;
                    549: 
                    550:        if(dp->cyl == 0 || dp->heads == 0 || dp->sectors == 0 || dp->cap == 0)
                    551:                return -1;
                    552: 
                    553:        return 0;
                    554: }
                    555: 
                    556: /*
                    557:  *  read partition table.  The partition table is just ascii strings.
                    558:  */
                    559: #define MAGIC "plan9 partitions"
                    560: static void
                    561: hardpart(Drive *dp)
                    562: {
                    563:        Partition *pp;
                    564:        Controller *cp;
                    565:        char *line[Npart+1];
                    566:        char *field[3];
                    567:        ulong n;
                    568:        int i;
                    569: 
                    570:        cp = dp->cp;
                    571: 
                    572:        /*
                    573:         *  we always have a partition for the whole disk
                    574:         *  and one for the partition table
                    575:         */
                    576:        pp = &dp->p[0];
                    577:        strcpy(pp->name, "disk");
                    578:        pp->start = 0;
                    579:        pp->end = dp->cap / dp->bytes;
                    580:        pp++;
                    581:        strcpy(pp->name, "partition");
                    582:        pp->start = dp->p[0].end - 1;
                    583:        pp->end = dp->p[0].end;
                    584:        dp->npart = 2;
                    585: 
                    586:        /*
                    587:         *  read last sector from disk, null terminate.  This used
                    588:         *  to be the sector we used for the partition tables.
                    589:         *  However, this sector is special on some PC's so we've
                    590:         *  started to use the second last sector as the partition
                    591:         *  table instead.  To avoid reconfiguring all our old systems
                    592:         *  we first look to see if there is a valid partition
                    593:         *  table in the last sector.  If so, we use it.  Otherwise
                    594:         *  we switch to the second last.
                    595:         */
                    596:        hardxfer(dp, pp, Cread, 0, dp->bytes);
                    597:        cp->buf[dp->bytes-1] = 0;
                    598:        n = getfields(cp->buf, line, Npart+1, '\n');
                    599:        if(n == 0 || strncmp(line[0], MAGIC, sizeof(MAGIC)-1)){
                    600:                dp->p[0].end--;
                    601:                dp->p[1].start--;
                    602:                dp->p[1].end--;
                    603:                hardxfer(dp, pp, Cread, 0, dp->bytes);
                    604:                cp->buf[dp->bytes-1] = 0;
                    605:                n = getfields(cp->buf, line, Npart+1, '\n');
                    606:        }
                    607: 
                    608:        /*
                    609:         *  parse partition table.
                    610:         */
                    611:        if(n && strncmp(line[0], MAGIC, sizeof(MAGIC)-1) == 0){
                    612:                for(i = 1; i < n; i++){
                    613:                        pp++;
                    614:                        if(getfields(line[i], field, 3, ' ') != 3)
                    615:                                break;
                    616:                        strncpy(pp->name, field[0], NAMELEN);
                    617:                        pp->start = strtoul(field[1], 0, 0);
                    618:                        pp->end = strtoul(field[2], 0, 0);
                    619:                        if(pp->start > pp->end || pp->start >= dp->p[0].end)
                    620:                                break;
                    621:                        dp->npart++;
                    622:                }
                    623:        }
                    624:        return;
                    625: }
                    626: 
                    627: /*
                    628:  *  we get an interrupt for every sector transferred
                    629:  */
                    630: static void
                    631: hardintr(Ureg*, void *arg)
                    632: {
                    633:        Controller *cp;
                    634:        Drive *dp;
                    635:        long loop;
                    636: 
                    637:        cp = arg;
                    638:        dp = cp->dp;
                    639: 
                    640:        loop = 0;
                    641:        while((cp->status = inb(cp->pbase+Pstatus)) & Sbusy)
                    642:                if(++loop > 100000){
                    643:                        print("hardintr 0x%lux\n", cp->status);
                    644:                        break;
                    645:                }
                    646:        switch(cp->cmd){
                    647:        case Cwrite:
                    648:                if(cp->status & Serr){
                    649:                        cp->error = inb(cp->pbase+Perror);
                    650:                        cp->cmd = 0;
                    651:                        return;
                    652:                }
                    653:                cp->sofar++;
                    654:                if(cp->sofar < cp->nsecs){
                    655:                        loop = 0;
                    656:                        while((inb(cp->pbase+Pstatus) & Sdrq) == 0)
                    657:                                if(++loop > 10000){
                    658:                                        print("hardintr 1");
                    659:                                        cp->cmd = 0;
                    660:                                        return;
                    661:                                }
                    662:                        outss(cp->pbase+Pdata, &cp->buf[cp->sofar*dp->bytes],
                    663:                                dp->bytes/2);
                    664:                } else{
                    665:                        cp->cmd = 0;
                    666:                }
                    667:                break;
                    668:        case Cread:
                    669:        case Cident:
                    670:                if(cp->status & Serr){
                    671:                        cp->cmd = 0;
                    672:                        cp->error = inb(cp->pbase+Perror);
                    673:                        return;
                    674:                }
                    675:                loop = 0;
                    676:                while((inb(cp->pbase+Pstatus) & Sdrq) == 0)
                    677:                        if(++loop > 100000){
                    678:                                print("hardintr 2 cmd %ux status %ux",
                    679:                                        cp->cmd, inb(cp->pbase+Pstatus));
                    680:                                cp->cmd = 0;
                    681:                                return;
                    682:                        }
                    683:                inss(cp->pbase+Pdata, &cp->buf[cp->sofar*dp->bytes],
                    684:                        dp->bytes/2);
                    685:                cp->sofar++;
                    686:                if(cp->sofar >= cp->nsecs){
                    687:                        if (cp->cmd == Cread)
                    688:                                cp->cmd = 0;
                    689:                        else
                    690:                                cp->cmd = Cident2; /* sometimes we get a second intr */
                    691:                }
                    692:                break;
                    693:        case Csetbuf:
                    694:        case Cident2:
                    695:                cp->cmd = 0;
                    696:                break;
                    697:        default:
                    698:                cp->cmd = 0;
                    699:                break;
                    700:        }
                    701: }

unix.superglobalmegacorp.com

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