|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.