|
|
1.1 ! root 1: /* ! 2: * This is a driver for the IBM AT (286 & up) floppy, using interrupts and DMA ! 3: * on the NEC 756 floppy chip. ! 4: * Handles single/double/quad density drives, 8/9/15/18 sectors per track. ! 5: * ! 6: * Minor device assignments: xxuuhkkk ! 7: * uu - unit = 0/1/2/3 ! 8: * kkk - kind, struct fdata infra. ! 9: * h - alternating head rather than side by side ! 10: * ! 11: */ ! 12: ! 13: #include <sys/coherent.h> ! 14: #include <sys/buf.h> ! 15: #include <sys/con.h> ! 16: #include <sys/stat.h> ! 17: #include <errno.h> ! 18: #include <sys/timeout.h> ! 19: #include <sys/fdioctl.h> ! 20: #include <sys/sched.h> ! 21: #include <sys/dmac.h> ! 22: #include <sys/devices.h> ! 23: ! 24: #ifdef _I386 ! 25: #include <sys/reg.h> ! 26: #else ! 27: #include <sys/i8086.h> ! 28: #endif ! 29: ! 30: #define BIT(n) (1 << (n)) ! 31: ! 32: #include <sys/abios.h> ! 33: static short intimeout; ! 34: static request_block_fl fl_rb; ! 35: ! 36: void floppy_function(); ! 37: void floppy_functionb(); ! 38: static void fl_drive_off(); ! 39: ! 40: /* ! 41: * Patchable parameters (default to IBM PC/XT values). ! 42: */ ! 43: ! 44: int fl_srt = 0xC; /* Floppy seek step rate, in unit 2 millisec */ ! 45: /* NOT DIRECTLY ENCODED */ ! 46: /* COMPAQ wants 0xD */ ! 47: int fl_hlt = 1; /* Floppy head load time, in unit 4 millisec */ ! 48: int fl_hut = 0xF; /* Floppy head unload time, in unit 32 millisec */ ! 49: ! 50: int flload(); ! 51: int flunload(); ! 52: void flreset(); ! 53: int flopen(); ! 54: int flblock(); ! 55: int flread(); ! 56: int flwrite(); ! 57: int flioctl(); ! 58: static void flstart(); ! 59: static void flintr(); ! 60: static void fldone(); ! 61: static void fltimer(); ! 62: static void flstatus(); ! 63: int nulldev(); ! 64: int nonedev(); ! 65: ! 66: CON flcon = { ! 67: DFBLK|DFCHR, /* Flags */ ! 68: FL_MAJOR, /* Major index */ ! 69: flopen, /* Open */ ! 70: nulldev, /* Close */ ! 71: flblock, /* Block */ ! 72: flread, /* Read */ ! 73: flwrite, /* Write */ ! 74: flioctl, /* Ioctl */ ! 75: nulldev, /* Powerfail */ ! 76: fltimer, /* Timeout */ ! 77: flload, /* Load */ ! 78: flunload /* Unload */ ! 79: }; ! 80: ! 81: /* ! 82: * Driver States. ! 83: */ ! 84: #ifdef OLD ! 85: #define SIDLE 0 /* Idle */ ! 86: #define SSEEK 1 /* Need seek */ ! 87: #define SRDWR 2 /* Need read/write command */ ! 88: #define SENDIO 3 /* Need end I/O processing */ ! 89: #define SDELAY 4 /* Delay before next disk operation */ ! 90: #define SHDLY 5 /* Head settling delay before r/w */ ! 91: #define SRESET 6 /* Doing a reset */ ! 92: #else ! 93: #define SIDLE 0 /* controller idle */ ! 94: #define SRETRY 1 /* seeking */ ! 95: #define SREAD 2 /* reading */ ! 96: #define SWRITE 3 /* writing */ ! 97: #define SRESET 4 /* reseting */ ! 98: ! 99: extern char *smsg[]; ! 100: #endif ! 101: ! 102: #define funit(x) (minor(x)>>4) /* Unit/drive number */ ! 103: #define fkind(x) (0x7) /* Kind of format */ ! 104: /* #define fkind(x) (minor(x)&0x7) Kind of format */ ! 105: #define fhbyh(x) (minor(x)&0x8) /* 0=Side by side, 1=Head by head */ ! 106: ! 107: static ! 108: struct fdata { ! 109: int fd_size; /* Blocks per diskette */ ! 110: int fd_nhds; /* Heads per drive */ ! 111: int fd_trks; /* Tracks per side */ ! 112: int fd_offs; /* Sector base */ ! 113: int fd_nspt; /* Sectors per track */ ! 114: char fd_GPL[4]; /* Controller gap param (indexed by rate) */ ! 115: char fd_N; /* Controller size param */ ! 116: char fd_FGPL; /* Format gap length */ ! 117: } fdata[] = { ! 118: /* 8 sectors per track, surface by surface seek. */ ! 119: { 320,1,40,0, 8, { 0x00,0x23,0x2A }, 2,0x50 }, /* Single sided */ ! 120: { 640,2,40,0, 8, { 0x00,0x23,0x2A }, 2,0x50 }, /* Double sided */ ! 121: { 1280,2,80,0, 8, { 0x00,0x23,0x2A }, 2,0x50 }, /* Quad density */ ! 122: /* 9 sectors per track, surface by surface seek. */ ! 123: { 360,1,40,0, 9, { 0x00,0x23,0x2A }, 2,0x50 }, /* Single sided */ ! 124: { 720,2,40,0, 9, { 0x00,0x23,0x2A }, 2,0x50 }, /* Double sided */ ! 125: { 1440,2,80,0, 9, { 0x00,0x23,0x2A }, 2,0x50 }, /* Quad density */ ! 126: /* 15 sectors per track, surface by surface seek. */ ! 127: { 2400,2,80,0,15, { 0x1B,0x00,0x00 }, 2,0x54 }, /* High capacity */ ! 128: /* 18 sectors per track, surface by surface seek. */ ! 129: { 2880,2,80,0,18, { 0x1B,0x00,0x00 }, 2,0x54 } /* 1.44 3.5" */ ! 130: }; ! 131: ! 132: ! 133: static ! 134: struct fl { ! 135: BUF *fl_actf; /* Queue, forward */ ! 136: BUF *fl_actl; /* Queue, backward */ ! 137: paddr_t fl_addr; /* Address */ ! 138: int fl_nsec; /* # of sectors */ ! 139: int fl_secn; /* Current sector */ ! 140: struct fdata fl_fd; /* Disk kind data */ ! 141: int fl_fcyl; /* Floppy cylinder # */ ! 142: char fl_incal[4]; /* Disk in cal flags */ ! 143: char fl_ndsk; /* # of 5 1/4" drives */ ! 144: char fl_unit; /* Unit # */ ! 145: char fl_mask; /* Handy unit mask */ ! 146: char fl_hbyh; /* 0/1 = Side by side/Head by head */ ! 147: char fl_nerr; /* Error count */ ! 148: int fl_ncmdstat; /* Number of cmd status bytes recvd */ ! 149: char fl_cmdstat[8]; /* Command Status buffer */ ! 150: int fl_nintstat; /* Number of intr status bytes recvd */ ! 151: char fl_intstat[4]; /* Interrupt Status buffer */ ! 152: int fl_fsec; /* Floppy sector # */ ! 153: int fl_head; /* Floppy head */ ! 154: char fl_init; /* FDC init done flag */ ! 155: char fl_state; /* Processing state */ ! 156: char fl_mstatus; /* Motor status */ ! 157: char fl_time[4]; /* Motor timeout */ ! 158: char fl_rate; /* Data rate: 500,300,250,?? kbps */ ! 159: char fl_type[4]; /* Type of drive: 2 = HiCap */ ! 160: int fl_wflag; /* Write operation */ ! 161: int fl_recov; /* Recovery initiated */ ! 162: } fl; ! 163: ! 164: ! 165: static BUF flbuf; ! 166: static TIM fltim; ! 167: static TIM flrstlck; ! 168: ! 169: /* ! 170: * The load routine asks the ! 171: * switches how many drives are present ! 172: * in the machine, and sets up the field ! 173: * in the floppy database. It also grabs ! 174: * the level 6 interrupt vector. ! 175: */ ! 176: static ! 177: flload() ! 178: { ! 179: register int eflag; ! 180: register int s; ! 181: ! 182: init_abios(); ! 183: ! 184: /* ! 185: * Read floppy equipment byte from CMOS ram ! 186: * drive 0 is in high nibble, drive 1 is in low nibble. ! 187: */ ! 188: outb( 0x70, 0x10 ); ! 189: /* delay */ ! 190: eflag = inb( 0x71 ); ! 191: ! 192: /* ! 193: * Flag hardware as an IBM AT if neither equipment byte nibble is ! 194: * greater than 4 (since 5 through 15 are reserved nibble values - see ! 195: * IBM AT Technical Reference manual, page 1-50). Note that this ! 196: * relies on the fact that in the XT, this byte will "float" high. ! 197: * NOTE: 1.44 Mbyte 3.5 inch drives are type 4 ! 198: */ ! 199: if ( (eflag & 0x88) == 0 ) { ! 200: ! 201: /* ! 202: * Reinitialize patchable parameters for IBM AT. ! 203: */ ! 204: fl_srt = 0xD; /* Floppy seek step rate, in unit 2 ms */ ! 205: /* NOT DIRECTLY ENCODED */ ! 206: fl_hlt = 25; /* Floppy head load time, in unit 4 ms */ ! 207: ! 208: /* ! 209: * Define AT drive information. ! 210: */ ! 211: fl.fl_type[0] = eflag >> 4; ! 212: fl.fl_type[1] = eflag & 15; ! 213: fl.fl_rate = 1; /* Must not be 2 */ ! 214: ! 215: /* ! 216: * Determine number of AT floppy drives. ! 217: */ ! 218: if ( eflag & 0xF0 ) { ! 219: fl.fl_ndsk++; ! 220: if ( eflag & 0x0F ) ! 221: fl.fl_ndsk++; ! 222: } ! 223: } else { ! 224: /* ! 225: * Define XT drive information. ! 226: */ ! 227: eflag = int11(); ! 228: fl.fl_rate = 2; ! 229: if ( eflag & 1 ) ! 230: fl.fl_ndsk = ((eflag >> 6) & 0x03) + 1; ! 231: } ! 232: ! 233: fl.fl_actf = NULL; /* Start up with this Null to avoid phony calls */ ! 234: ! 235: if ( fl.fl_ndsk ) { ! 236: ! 237: s = sphi(); ! 238: setivec(6, &flintr); ! 239: spl( s ); ! 240: ! 241: fl_rb.length = 0x51; ! 242: fl_rb.logical_id = 3; ! 243: fl_rb.unit = 0; ! 244: fl_rb.function = 3; ! 245: fl_rb.reserved = 0L; ! 246: fl_rb.ret_code = 0xffff; ! 247: d1_func(&fl_rb, START_P); ! 248: if (fl_rb.ret_code) ! 249: printf("\nfloppy function 3 returned = %d\n", ! 250: fl_rb.ret_code); ! 251: flreset(); ! 252: } ! 253: } ! 254: ! 255: /* ! 256: * Release resources. ! 257: */ ! 258: flunload() ! 259: { ! 260: /* ! 261: * Clear interrupt vector. ! 262: */ ! 263: if ( fl.fl_ndsk ) ! 264: clrivec(6); ! 265: ! 266: /* ! 267: * Cancel timed function. ! 268: */ ! 269: timeout( &fltim, 0, NULL, NULL ); ! 270: ! 271: /* ! 272: * Cancel periodic [1 second] invocation. ! 273: */ ! 274: drvl[FL_MAJOR].d_time = 0; ! 275: ! 276: /* ! 277: * Turn motors off. ! 278: */ ! 279: /* outb(FDCDOR, DORNMR | DORIEN );*/ ! 280: } ! 281: ! 282: ! 283: /** ! 284: * void ! 285: * flreset() -- reset floppy disk controller. ! 286: */ ! 287: static void ! 288: flreset() ! 289: { ! 290: register int s; ! 291: ! 292: fl.fl_state = SRESET; ! 293: fl_rb.length = 0x51; ! 294: fl_rb.logical_id = 3; ! 295: fl_rb.unit = 0; ! 296: fl_rb.function = 5; ! 297: fl_rb.reserved = 0L; ! 298: fl_rb.ret_code = 0xffff; ! 299: fl_rb.vars.f5.reserved = 0; ! 300: ! 301: floppy_function(START_P); ! 302: ! 303: while ((fl_rb.ret_code == 1) || (fl_rb.ret_code == 2)) ! 304: { ! 305: long i; ! 306: for (i=0;i<50000L;i++) ! 307: ; ! 308: } ! 309: ! 310: ! 311: fl.fl_state = SIDLE; ! 312: if (fl_rb.ret_code != 0) ! 313: printf("FL: reset failed - %u\n", fl_rb.ret_code); ! 314: } ! 315: ! 316: ! 317: /* ! 318: * The open routine screens out ! 319: * opens of illegal minor devices and ! 320: * performs the NEC specify command if ! 321: * this is the very first floppy disk ! 322: * open call. ! 323: */ ! 324: ! 325: static ! 326: flopen( dev, mode ) ! 327: dev_t dev; ! 328: int mode; ! 329: ! 330: { ! 331: /* ! 332: * Validate existence and data rate [Gap length != 0]. ! 333: */ ! 334: if ( funit(dev) >= fl.fl_ndsk ) ! 335: { ! 336: u.u_error = ENXIO; ! 337: return; ! 338: } ! 339: } ! 340: ! 341: /* ! 342: * The read routine just calls ! 343: * off to the common raw I/O processing ! 344: * code, using a static buffer header in ! 345: * the driver. ! 346: */ ! 347: ! 348: static ! 349: flread( dev, iop ) ! 350: dev_t dev; ! 351: IO *iop; ! 352: { ! 353: ioreq(&flbuf, iop, dev, BREAD); ! 354: } ! 355: ! 356: /* ! 357: * The write routine is just like the ! 358: * read routine, except that the function code ! 359: * is write instead of read. ! 360: */ ! 361: ! 362: static ! 363: flwrite( dev, iop ) ! 364: ! 365: dev_t dev; ! 366: IO *iop; ! 367: ! 368: { ! 369: ioreq(&flbuf, iop, dev, BWRITE); ! 370: } ! 371: ! 372: /* ! 373: * The only valid command is to format a track. ! 374: * The parameter block contains the header records supplied to the controller. ! 375: */ ! 376: ! 377: static ! 378: flioctl( dev, com, par ) ! 379: ! 380: dev_t dev; ! 381: int com; ! 382: char *par; ! 383: { ! 384: register unsigned s; ! 385: register struct fdata *fdp; ! 386: unsigned hd, cyl; ! 387: ! 388: if (com != FDFORMAT) { ! 389: u.u_error = EINVAL; ! 390: return; ! 391: } ! 392: ! 393: fdp = &fdata[ fkind(dev) ]; ! 394: cyl = getubd(par); ! 395: hd = getubd(par+1); ! 396: ! 397: if (hd > 1 || cyl >= fdp->fd_trks) { ! 398: u.u_error = EINVAL; ! 399: return; ! 400: } ! 401: ! 402: fl_rb.length = 0x51; ! 403: fl_rb.logical_id = 3; ! 404: fl_rb.unit = 0; ! 405: fl_rb.reserved = 0L; ! 406: fl_rb.ret_code = 0xffff; ! 407: ! 408: /* Note that the items below are set up the same way for a ! 409: * read or a write. */ ! 410: fl_rb.vars.f8.reserved = 0; ! 411: fl_rb.vars.f8.reserved1 = 0L; ! 412: fl_rb.vars.f8.dptr = fl.fl_addr; ! 413: fl_rb.vars.f8.reserved2 = 0; ! 414: fl_rb.vars.f8.cylinder = fl.fl_fcyl; ! 415: fl_rb.vars.f8.head = fl.fl_head; ! 416: fl_rb.vars.f8.sector = fl.fl_secn; ! 417: fl_rb.vars.f8.sectors_read = fl.fl_nsec; ! 418: ! 419: if (fl.fl_actf->b_req == BWRITE) { ! 420: fl_rb.function = 9; ! 421: fl.fl_state = SWRITE; ! 422: } ! 423: ! 424: /* ! 425: * The following may need some explanation. ! 426: * dmareq will: ! 427: * claim the buffer, ! 428: * bounds check the parameter buffer, ! 429: * lock the parameter buffer in memory, ! 430: * convert io_seek to b_bno, ! 431: * dispatch the request, ! 432: * wait for completion, ! 433: * and unlock the parameter buffer. ! 434: * The b_bno is reconverted to hd, cyl in flfsm. ! 435: */ ! 436: ! 437: s = fhbyh(dev) ? (cyl * fdp->fd_nhds + hd) : (hd * fdp->fd_trks + cyl); ! 438: s *= fdp->fd_nspt; ! 439: u.u_io.io_seek = ((long)s) * BSIZE; ! 440: #ifdef _I386 ! 441: u.u_io.io.vbase = par; ! 442: #else ! 443: u.u_io.io_base = par; ! 444: #endif ! 445: u.u_io.io_ioc = fdp->fd_nspt * 4; ! 446: dmareq(&flbuf, &u.u_io, dev, FDFORMAT); ! 447: } ! 448: ! 449: /* ! 450: * Start up block I/O on a ! 451: * buffer. Check that the block number ! 452: * is not out of range, given the style of ! 453: * the disk. Put the buffer header into the ! 454: * device queue. Start up the disk if the ! 455: * device is idle. ! 456: */ ! 457: ! 458: static ! 459: flblock( bp ) ! 460: ! 461: register BUF *bp; ! 462: { ! 463: register unsigned bno; ! 464: ! 465: intimeout = 0; ! 466: ! 467: bno = bp->b_bno + (bp->b_count >> 9) - 1; ! 468: if ((unsigned)bp->b_bno > fdata[ fkind(bp->b_dev) ].fd_size) { ! 469: bp->b_flag |= BFERR; ! 470: bdone(bp); ! 471: return; ! 472: } ! 473: ! 474: if (bp->b_req != FDFORMAT && bno>=fdata[ fkind(bp->b_dev) ].fd_size) { ! 475: bp->b_resid = bp->b_count; ! 476: if (bp->b_flag & BFRAW) ! 477: bp->b_flag |= BFERR; ! 478: bdone(bp); /* return w/ b_resid != 0 */ ! 479: return; ! 480: } ! 481: ! 482: if ((bp->b_count&0x1FF) != 0) { ! 483: if (bp->b_req != FDFORMAT) { ! 484: bp->b_flag |= BFERR; ! 485: bdone(bp); ! 486: return; ! 487: } ! 488: } ! 489: ! 490: bp->b_actf = NULL; ! 491: ! 492: if (fl.fl_actf == NULL) ! 493: fl.fl_actf = bp; ! 494: else ! 495: fl.fl_actl->b_actf = bp; ! 496: ! 497: fl.fl_actl = bp; ! 498: ! 499: if (fl.fl_state == SIDLE) ! 500: { ! 501: drvl[FL_MAJOR].d_time = 0; ! 502: if (fldequeue()) ! 503: flstart(); ! 504: } ! 505: } ! 506: ! 507: /** ! 508: * ! 509: * int ! 510: * fldequeue() - obtain next disk read/write operation ! 511: * ! 512: * Action: Pull some work from the disk queue. ! 513: * ! 514: * Return: 0 = no work. ! 515: * * = work to do. ! 516: */ ! 517: static int ! 518: fldequeue() ! 519: { ! 520: register BUF * bp = fl.fl_actf; ! 521: register struct fdata *dp; ! 522: ! 523: if (bp == NULL) ! 524: return (0); ! 525: ! 526: dp = &fdata[fkind(bp->b_dev)]; ! 527: fl.fl_secn = (bp->b_bno % dp->fd_nspt) + 1; ! 528: fl.fl_head = bp->b_bno / dp->fd_nspt; ! 529: fl.fl_fcyl = fl.fl_head / dp->fd_nhds; ! 530: fl.fl_head = fl.fl_head % dp->fd_nhds; ! 531: ! 532: fl.fl_nsec = bp->b_count / BSIZE; ! 533: ! 534: if (bp->b_faddr == 0L) ! 535: { ! 536: printf("FL: called with a null address for b_faddr, bno=%d\n" ! 537: ,bp->b_bno); ! 538: fl.fl_actf = bp->b_actf; ! 539: return 0; ! 540: } ! 541: else ! 542: fl.fl_addr = vtop(bp->b_faddr); ! 543: ! 544: return (1); ! 545: } ! 546: ! 547: ! 548: /** ! 549: * ! 550: * void ! 551: * flstart() - start or restart next disk read/write operation. ! 552: * ! 553: * Action: Initiate disk read/write operation. ! 554: **/ ! 555: static void ! 556: flstart() ! 557: { ! 558: fl_rb.length = 0x51; ! 559: fl_rb.logical_id = 3; ! 560: fl_rb.unit = 0; ! 561: fl_rb.reserved = 0L; ! 562: fl_rb.ret_code = 0xffff; ! 563: ! 564: /* Note that the items below are set up the same way for a ! 565: * read or a write. */ ! 566: fl_rb.vars.f8.reserved = 0; ! 567: fl_rb.vars.f8.reserved1 = 0L; ! 568: fl_rb.vars.f8.dptr = fl.fl_addr; ! 569: fl_rb.vars.f8.reserved2 = 0; ! 570: fl_rb.vars.f8.cylinder = fl.fl_fcyl; ! 571: fl_rb.vars.f8.head = fl.fl_head; ! 572: fl_rb.vars.f8.sector = fl.fl_secn; ! 573: fl_rb.vars.f8.sectors_read = fl.fl_nsec; ! 574: ! 575: if (fl.fl_actf->b_req == BWRITE) { ! 576: fl_rb.function = 9; ! 577: fl.fl_state = SWRITE; ! 578: } ! 579: else { ! 580: fl_rb.function = 8; ! 581: fl.fl_state = SREAD; ! 582: } ! 583: ! 584: floppy_function(START_P); ! 585: } ! 586: ! 587: /** ! 588: * ! 589: * void ! 590: * flintr() - Interrupt routine. ! 591: * ! 592: */ ! 593: static void ! 594: flintr() ! 595: { ! 596: d1_func(&fl_rb, INTERRUPT_P); ! 597: defer(floppy_functionb, INTERRUPT_P); ! 598: } ! 599: ! 600: /** ! 601: * ! 602: * int ! 603: * flerror() ! 604: * ! 605: * Action: Check for drive error. ! 606: * If found, increment error count and report it. ! 607: * ! 608: * Return: 0 = No error found. ! 609: * 1 = Error occurred. ! 610: */ ! 611: static int ! 612: flerror() ! 613: { ! 614: register BUF * bp = fl.fl_actf; ! 615: ! 616: if (fl_rb.ret_code <= 2) ! 617: return 0; /* For now, do nothing */ ! 618: else ! 619: { ! 620: #if 0 ! 621: printf("fl%d%c: bno=%U head=%u cyl=%u error=%x", ! 622: fl.fl_drv, ! 623: (bp->b_dev & SDEV) ? 'x' : fl.fl_partn % NPARTN + 'a', ! 624: (bp->b_count/BSIZE) + bp->b_bno ! 625: + fl.fl_caching - fl.fl_nsec, ! 626: fl.fl_head, fl.fl_fcyl, fl_rb.ret_code); ! 627: #endif ! 628: return fl_rb.ret_code; ! 629: } ! 630: } ! 631: ! 632: /** ! 633: * ! 634: * void ! 635: * flrecov() ! 636: * ! 637: * Action: Attempt recovery. ! 638: */ ! 639: static void ! 640: flrecov() ! 641: { ! 642: register BUF *bp = fl.fl_actf; ! 643: ! 644: switch (fl_rb.ret_code) { ! 645: ! 646: case 0x8006: /* Media changed - retry */ ! 647: switch(fl.fl_state) ! 648: { ! 649: case SREAD: ! 650: case SWRITE: ! 651: flreset(); ! 652: fldequeue(); ! 653: flstart(); ! 654: break; ! 655: default: ! 656: break; ! 657: } ! 658: break; ! 659: default: /* Anything else - Give up on block */ ! 660: flstatus(); ! 661: bp->b_flag |= BFERR; ! 662: fldone(); ! 663: } ! 664: } ! 665: ! 666: ! 667: /* ! 668: * Dissassemble the floppy error status for user reference. ! 669: */ ! 670: ! 671: static void ! 672: flstatus() ! 673: { ! 674: printf("fd0: head=%u cyl=%u <", ! 675: fl.fl_head, fl.fl_fcyl ); ! 676: ! 677: switch (fl_rb.ret_code) { ! 678: case 0x800d: ! 679: printf("Not Ready>"); ! 680: break; ! 681: case 0x9120: ! 682: printf("Equipment Check>"); ! 683: break; ! 684: case 0x9102: ! 685: printf("Missing Address Mark>"); ! 686: break; ! 687: case 0x8003: ! 688: printf("Write Protected>"); ! 689: break; ! 690: case 0x9108: ! 691: printf("Overrun>"); ! 692: break; ! 693: case 0x9110: ! 694: printf("Bad Data CRC>"); ! 695: break; ! 696: defualt: ! 697: printf("Error 0x%x>", fl_rb.ret_code); ! 698: } ! 699: ! 700: printf("\n"); ! 701: } ! 702: ! 703: /** ! 704: * ! 705: * void ! 706: * fldone() ! 707: * ! 708: * Action: Release current i/o buffer to the O/S. ! 709: */ ! 710: static void ! 711: fldone() ! 712: { ! 713: register BUF * bp = fl.fl_actf; ! 714: ! 715: drvl[FL_MAJOR].d_time = 0; ! 716: fl.fl_state = SIDLE; ! 717: bdone(bp); ! 718: ! 719: if (bp != NULL) ! 720: fl.fl_actf = bp->b_actf; ! 721: else ! 722: fl.fl_actf = NULL; ! 723: ! 724: if (fldequeue()) ! 725: flstart(); ! 726: else if (intimeout == 0) { ! 727: intimeout = 1; /* Set up to turn off the drive */ ! 728: drvl[FL_MAJOR].d_time = 5; ! 729: } ! 730: } ! 731: ! 732: ! 733: ! 734: void floppy_function(type) ! 735: int type; ! 736: { ! 737: d1_func(&fl_rb, type); ! 738: floppy_functionb(); ! 739: } ! 740: ! 741: static TIM fltim1; ! 742: ! 743: void floppy_functionb() ! 744: { ! 745: while (fl_rb.ret_code == 2) /* Wait for time */ ! 746: { ! 747: /* ! 748: timeout(&fltim1, 1, wakeup, (int)&fltim1); ! 749: sleep((char *)&fltim1, CVTTOUT, IVTTOUT, SVTTOUT); ! 750: */ ! 751: long i; ! 752: for(i=0L; i < fl_rb.vars.f8.wait_time; i+=16) ! 753: ; ! 754: ! 755: d1_func(&fl_rb, INTERRUPT_P); ! 756: } ! 757: ! 758: if (fl_rb.ret_code == 0) /* Finished */ ! 759: { ! 760: if (fl.fl_state != SRESET) ! 761: { ! 762: fl.fl_actf->b_resid = 0; ! 763: fldone(); ! 764: } ! 765: } ! 766: else if (fl_rb.ret_code == 1) /* Wait for int */ ! 767: { ! 768: #if 0 ! 769: if (fl.fl_state == SRESET) /* Wait for int */ ! 770: {long i;for (i=0;i<500000L;i++);} ! 771: /*fl.fl_state = SINT; */ ! 772: #endif ! 773: } ! 774: else ! 775: { ! 776: flrecov(); ! 777: ! 778: /* ! 779: printf("FL: error %x in %s.\n", fl_rb.ret_code, smsg[fl.fl_state]); ! 780: printf("fl: bp->b_bno=%lx, fl.fl_secn=%d, fl.fl_fcyl=%d, fl.fl_h" ! 781: "ead=%d, fl.fl_nsec=%d\n", fl.fl_actf->b_bno, ! 782: fl.fl_secn, fl.fl_fcyl, fl.fl_head, fl.fl_nsec); ! 783: */ ! 784: } ! 785: } ! 786: ! 787: /** ! 788: * ! 789: * void ! 790: * fltimer() - wait for timeout ! 791: * ! 792: * Action: If drvl[FL_MAJOR] is greater than zero, decrement it. ! 793: * If it decrements to zero, call the abios again ! 794: * or turn off the disktimer it timeout = 1; ! 795: */ ! 796: static void ! 797: fltimer() ! 798: { ! 799: register int s; ! 800: ! 801: s = sphi(); ! 802: if (--drvl[FL_MAJOR].d_time > 0) { ! 803: spl(s); ! 804: return; ! 805: } ! 806: if (intimeout) { ! 807: intimeout = 2; ! 808: defer(fl_drive_off,0); ! 809: } ! 810: else ! 811: floppy_function(INTERRUPT_P); ! 812: spl(s); ! 813: } ! 814: ! 815: ! 816: static void ! 817: fl_drive_off() ! 818: { ! 819: fl_rb.logical_id = 3; ! 820: fl_rb.unit = 0; ! 821: fl_rb.function = 0xf; ! 822: fl_rb.reserved = 0L; ! 823: fl_rb.ret_code = 0xffff; ! 824: fl_rb.vars.ff.reserved = 0; ! 825: d1_func(&fl_rb, START_P); ! 826: if (fl_rb.ret_code) ! 827: printf("\nfloppy function 0xf returned = %d\n", ! 828: fl_rb.ret_code); ! 829: intimeout = 0; /* Drive is now turned off */ ! 830: } ! 831:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.