|
|
1.1 ! root 1: /* ! 2: * io.386/fdc.c ! 3: * ! 4: * Support 765-style controller for diskette and floppy tape ! 5: * ! 6: * Revised: Wed Jun 9 12:15:08 1993 CDT ! 7: */ ! 8: ! 9: /* ! 10: * ---------------------------------------------------------------------- ! 11: * Includes. ! 12: */ ! 13: #include <sys/coherent.h> ! 14: ! 15: #include <errno.h> ! 16: #include <sys/buf.h> ! 17: #include <sys/con.h> ! 18: #include <sys/devices.h> ! 19: #include <sys/dmac.h> ! 20: #include <sys/fdc765.h> ! 21: #include <sys/stat.h> ! 22: ! 23: /* ! 24: * ---------------------------------------------------------------------- ! 25: * Definitions. ! 26: * Constants. ! 27: * Macros with argument lists. ! 28: * Typedefs. ! 29: * Enums. ! 30: */ ! 31: ! 32: /* Number of ticks to busy-wait the kernel before timeout awaiting RQM. */ ! 33: #define FDC_RQM_WAIT 2 ! 34: ! 35: enum { ! 36: FL_TIMING = 1, ! 37: FT_TIMING = 2 ! 38: }; ! 39: ! 40: enum { ! 41: FL_INTR = 1, ! 42: FT_INTR = 2 ! 43: }; ! 44: ! 45: /* ! 46: * ---------------------------------------------------------------------- ! 47: * Functions. ! 48: * Import Functions. ! 49: * Export Functions. ! 50: * Local Functions. ! 51: */ ! 52: extern int nulldev(); ! 53: extern unsigned int inb(); ! 54: ! 55: void fdcCmdStatus(); ! 56: void fdcDrvSelect(); ! 57: void fdcDrvStatus(); ! 58: int fdcGet(); ! 59: void fdcIntStatus(); ! 60: int fdcPut(); ! 61: void fdcRecal(); ! 62: void fdcReset(); ! 63: void fdcResetSel(); ! 64: void fdcSense(); ! 65: void fdcSpecify(); ! 66: void fdcStatus(); ! 67: ! 68: int setFlIntr(); ! 69: void setFlTimer(); ! 70: int setFtIntr(); ! 71: void setFtTimer(); ! 72: ! 73: static int fdcload(); ! 74: static int fdcunload(); ! 75: static int fdcopen(); ! 76: static int fdcclose(); ! 77: static int fdcblock(); ! 78: static int fdcread(); ! 79: static int fdcwrite(); ! 80: static int fdcioctl(); ! 81: static int fdctimeout(); ! 82: ! 83: static void fdcIntr(); ! 84: static void fdcRate(); ! 85: static int fdcWaitRQM(); ! 86: ! 87: static int setFdcIntr(); ! 88: static void setFdcTiming(); ! 89: ! 90: /* ! 91: * ---------------------------------------------------------------------- ! 92: * Global Data. ! 93: * Import Variables. ! 94: * Export Variables. ! 95: * Local Variables. ! 96: */ ! 97: ! 98: CON fdccon = { ! 99: DFBLK | DFCHR, /* Flags */ ! 100: FL_MAJOR, /* Major index */ ! 101: fdcopen, /* Open */ ! 102: fdcclose, /* Close */ ! 103: fdcblock, /* Block */ ! 104: fdcread, /* Read */ ! 105: fdcwrite, /* Write */ ! 106: fdcioctl, /* Ioctl */ ! 107: nulldev, /* Powerfail */ ! 108: fdctimeout, /* Timeout */ ! 109: fdcload, /* Load */ ! 110: fdcunload /* Unload */ ! 111: }; ! 112: ! 113: /* ! 114: * Two patchable pointers, for enabling diskette and/or tape device control. ! 115: */ ! 116: CON * flCon = NULL; ! 117: CON * ftCon = NULL; ! 118: ! 119: /* Global struct "fdc" passes FDC status to diskette and tape drivers. */ ! 120: struct FDC fdc; ! 121: ! 122: void (*flIntr)(); ! 123: void (*ftIntr)(); ! 124: ! 125: static int fdcIntOwner; ! 126: static int fdcTiming; ! 127: ! 128: /* ! 129: * ---------------------------------------------------------------------- ! 130: * Code. ! 131: */ ! 132: ! 133: /***************************************************************************/ ! 134: /* ! 135: * First part of fdc module. ! 136: * ! 137: * Kernel interface. ! 138: */ ! 139: ! 140: /* ! 141: * The load routine asks the ! 142: * switches how many drives are present ! 143: * in the machine, and sets up the field ! 144: * in the floppy database. It also grabs ! 145: * the level 6 interrupt vector. ! 146: */ ! 147: static int ! 148: fdcload() ! 149: { ! 150: register int s; ! 151: ! 152: if (flCon == NULL && ftCon == NULL) { ! 153: printf("fdc has no target devices\n"); ! 154: return; ! 155: } ! 156: ! 157: /* ! 158: * Ensure DMA channel 2 is turned off. ! 159: * The Computerland ROM does not disable DMA channel after autoboot ! 160: * from hard disk. The Western Digital controller board appears to ! 161: * send a dma burst when the floppy controller chip is reset. ! 162: */ ! 163: dmaoff(DMA_CH2); ! 164: ! 165: if (flCon) ! 166: (*flCon->c_load)(); ! 167: if (ftCon) ! 168: (*ftCon->c_load)(); ! 169: ! 170: /* ! 171: * Initialize the floppy disk controller (if we ! 172: * have any floppy drives). ! 173: */ ! 174: s = sphi(); ! 175: ! 176: setivec(6, fdcIntr); ! 177: fdcReset(); ! 178: ! 179: spl(s); ! 180: } ! 181: ! 182: /* ! 183: * Release resources. ! 184: */ ! 185: static int ! 186: fdcunload() ! 187: { ! 188: if (flCon == NULL && ftCon == NULL) ! 189: return; ! 190: ! 191: if (flCon) ! 192: (*flCon->c_uload)(); ! 193: if (ftCon) ! 194: (*ftCon->c_uload)(); ! 195: ! 196: /* ! 197: * Cancel periodic (1 second) invocation. ! 198: */ ! 199: drvl[FL_MAJOR].d_time = 0; ! 200: fdcTiming = 0; ! 201: ! 202: /* ! 203: * Turn motors off. ! 204: */ ! 205: outb(FDCDOR, DORNMR); /* Leave interrupts disabled. */ ! 206: ! 207: /* ! 208: * Clear interrupt vector. ! 209: */ ! 210: clrivec(6); ! 211: } ! 212: ! 213: static int ! 214: fdcopen(dev, mode) ! 215: dev_t dev; ! 216: int mode; ! 217: { ! 218: if (FDC_DISKETTE(dev)) { ! 219: if (flCon) ! 220: (*flCon->c_open)(dev, mode); ! 221: else { ! 222: SET_U_ERROR(ENXIO, "fdcopen()-no floppy"); ! 223: return; ! 224: } ! 225: } else if (FDC_TAPE(dev)) { ! 226: if (ftCon) ! 227: (*ftCon->c_open)(dev, mode); ! 228: else { ! 229: SET_U_ERROR(ENXIO, "fdcopen()-no tape"); ! 230: return; ! 231: } ! 232: } else { ! 233: SET_U_ERROR(ENXIO, "fdcopen()-no device"); ! 234: return; ! 235: } ! 236: } ! 237: ! 238: static int ! 239: fdcclose(dev, mode) ! 240: dev_t dev; ! 241: int mode; ! 242: { ! 243: if (FDC_DISKETTE(dev)) { ! 244: if (flCon) ! 245: (*flCon->c_close)(dev, mode); ! 246: else { ! 247: SET_U_ERROR(ENXIO, "fdcclose()-no floppy"); ! 248: return; ! 249: } ! 250: } else if (FDC_TAPE(dev)) { ! 251: if (ftCon) ! 252: (*ftCon->c_close)(dev, mode); ! 253: else { ! 254: SET_U_ERROR(ENXIO, "fdcclose()-no tape"); ! 255: return; ! 256: } ! 257: } else { ! 258: SET_U_ERROR(ENXIO, "fdcclose()-no device"); ! 259: return; ! 260: } ! 261: } ! 262: ! 263: static int ! 264: fdcread(dev, iop) ! 265: dev_t dev; ! 266: IO *iop; ! 267: { ! 268: if (FDC_DISKETTE(dev)) { ! 269: if (flCon) ! 270: (*flCon->c_read)(dev, iop); ! 271: else { ! 272: SET_U_ERROR(ENXIO, "fdcread()-no floppy"); ! 273: return; ! 274: } ! 275: } else if (FDC_TAPE(dev)) { ! 276: if (ftCon) ! 277: (*ftCon->c_read)(dev, iop); ! 278: else { ! 279: SET_U_ERROR(ENXIO, "fdcread()-no tape"); ! 280: return; ! 281: } ! 282: } else { ! 283: SET_U_ERROR(ENXIO, "fdcread()-no device"); ! 284: return; ! 285: } ! 286: } ! 287: ! 288: static int ! 289: fdcwrite(dev, iop) ! 290: dev_t dev; ! 291: IO *iop; ! 292: { ! 293: if (FDC_DISKETTE(dev)) { ! 294: if (flCon) ! 295: (*flCon->c_write)(dev, iop); ! 296: else { ! 297: SET_U_ERROR(ENXIO, "fdcwrite()-no floppy"); ! 298: return; ! 299: } ! 300: } else if (FDC_TAPE(dev)) { ! 301: if (ftCon) ! 302: (*ftCon->c_write)(dev, iop); ! 303: else { ! 304: SET_U_ERROR(ENXIO, "fdcwrite()-no tape"); ! 305: return; ! 306: } ! 307: } else { ! 308: SET_U_ERROR(ENXIO, "fdcwrite()-no device"); ! 309: return; ! 310: } ! 311: } ! 312: ! 313: static int ! 314: fdcioctl(dev, com, par) ! 315: dev_t dev; ! 316: int com; ! 317: char *par; ! 318: { ! 319: if (FDC_DISKETTE(dev)) { ! 320: if (flCon) ! 321: (*flCon->c_ioctl)(dev, com, par); ! 322: else { ! 323: SET_U_ERROR(ENXIO, "fdcioctl()-no floppy"); ! 324: return; ! 325: } ! 326: } else if (FDC_TAPE(dev)) { ! 327: if (ftCon) ! 328: (*ftCon->c_ioctl)(dev, com, par); ! 329: else { ! 330: SET_U_ERROR(ENXIO, "fdcioctl()-no tape"); ! 331: return; ! 332: } ! 333: } else { ! 334: SET_U_ERROR(ENXIO, "fdcioctl()-no device"); ! 335: return; ! 336: } ! 337: } ! 338: ! 339: /* Can't set u.u_error inside block routine. */ ! 340: static int ! 341: fdcblock(bp) ! 342: BUF *bp; ! 343: { ! 344: if (FDC_DISKETTE(bp->b_dev)) { ! 345: if (flCon) ! 346: (*flCon->c_block)(bp); ! 347: } else if (FDC_TAPE(bp->b_dev)) ! 348: if (ftCon) ! 349: (*ftCon->c_block)(bp); ! 350: } ! 351: ! 352: /***************************************************************************/ ! 353: /* ! 354: * Second part of fdc module. ! 355: * ! 356: * Hardware interface. ! 357: */ ! 358: ! 359: /* ! 360: * Get status (if any) from last command ! 361: */ ! 362: void ! 363: fdcCmdStatus() ! 364: { ! 365: register int b; ! 366: register int n = 0; /* # of status bytes read */ ! 367: register int i = 0; /* Timeout count */ ! 368: register int s; ! 369: ! 370: s = sphi(); ! 371: ! 372: /* ! 373: * Read all the status bytes the controller will give us. ! 374: */ ! 375: ! 376: for (;;) { ! 377: b = fdcGet(); ! 378: if (b == -1) ! 379: break; ! 380: ! 381: if (n < FDC_NUM_CMD_STAT) ! 382: fdc.fdc_cmdstat[n++] = b; ! 383: } ! 384: ! 385: fdc.fdc_ncmdstat = n; ! 386: spl(s); ! 387: } ! 388: ! 389: /* ! 390: * fdcDrvSelect() ! 391: * ! 392: * Select the drive indicated by "drive" (0..3). ! 393: * If "motorOn" is nonzero, turn the motor on as well. ! 394: */ ! 395: void ! 396: fdcDrvSelect(drive, motorOn) ! 397: int drive, motorOn; ! 398: { ! 399: unsigned char motorBits = 0; ! 400: ! 401: if (drive >= 4) { ! 402: printf("Can't fdcDrvSelect(%d,%d) ", drive, motorOn); ! 403: return; ! 404: } ! 405: ! 406: /* If needed, generate motor on bit for current selected drive. */ ! 407: if (motorOn) ! 408: motorBits = 0x10 << drive; ! 409: ! 410: outb(FDCDOR, DORNMR | DORIEN | drive | motorBits); ! 411: fdcSense(); /* Just in case --- */ ! 412: } ! 413: ! 414: /* ! 415: * Send Sense Drive Status command to FDC. ! 416: */ ! 417: void ! 418: fdcDrvStatus(drive, head) ! 419: int drive, head; ! 420: { ! 421: fdcPut(CMDSDRV); ! 422: fdcPut(drive | (head << 2)); ! 423: } ! 424: ! 425: /* ! 426: * Read NEC data register, doing needed handshake. ! 427: * Return -1 in case of timeout before RQM or no data available. ! 428: */ ! 429: int ! 430: fdcGet() ! 431: { ! 432: int ret = -1; ! 433: ! 434: /* Wait for RQM, then expect DIO true. */ ! 435: if (busyWait(fdcWaitRQM, FDC_RQM_WAIT) && (inb(FDCMSR) & MSRDIO)) ! 436: ret = inb(FDCDAT); ! 437: ! 438: return ret; ! 439: } ! 440: ! 441: /* ! 442: * Get Interrupt status ! 443: */ ! 444: void ! 445: fdcIntStatus() ! 446: { ! 447: register int b; ! 448: register int n = 0; /* # of status bytes read */ ! 449: register int i = 0; /* Timeout count */ ! 450: register int s; ! 451: ! 452: s = sphi(); ! 453: ! 454: /* ! 455: * Issue a sense interrupt command and stash result. ! 456: */ ! 457: fdcPut(CMDSINT); ! 458: ! 459: n = 0; ! 460: for (;;) { ! 461: b = fdcGet(); ! 462: if (b == -1) ! 463: break; ! 464: ! 465: if (n < FDC_NUM_INT_STAT) ! 466: fdc.fdc_intstat[n++] = b; ! 467: } ! 468: fdc.fdc_nintstat = n; ! 469: spl(s); ! 470: } ! 471: ! 472: /* ! 473: * Since the FDC is run in DMA mode, possible interrupt causes are: ! 474: * ! 475: * 1 Result phase of: Read Data, Read Track, Read ID, Read Deleted Data, ! 476: * Write Data, Format Cylinder, Write Deleted Data, Scan. ! 477: * ! 478: * 2 Ready line of diskette drive changes state. ! 479: * ! 480: * 3 End of Seek or Recalibrate. ! 481: * ! 482: * In case 1, the interrupt is cleared by read/write data to FDC. ! 483: * In cases 2 and 3, a Sense Interrupt is needed to clear the interrupt ! 484: * and determine its cause. ! 485: * ! 486: * The following comment is obsolete, but possibly of interest: ! 487: *********************************************** ! 488: * The interrupt routine gets all ! 489: * the status bytes the controller chip ! 490: * will give it, then issues a sense interrupt ! 491: * status command (which is necessary for a seek ! 492: * to complete!) and throws all of the status ! 493: * bytes away. ! 494: *********************************************** ! 495: */ ! 496: static void ! 497: fdcIntr() ! 498: { ! 499: register int s; ! 500: ! 501: s = sphi(); ! 502: ! 503: /* Invalidate previously stored interrupt and command status. */ ! 504: fdc.fdc_nintstat = 0; ! 505: fdc.fdc_ncmdstat = 0; ! 506: ! 507: /* Vector to diskette or tape device interrupt handler. */ ! 508: if ((fdcIntOwner & FL_INTR) && flIntr) ! 509: (*flIntr)(); ! 510: ! 511: if ((fdcIntOwner & FT_INTR) && ftIntr) ! 512: (*ftIntr)(); ! 513: spl(s); ! 514: } ! 515: ! 516: /* ! 517: * Send a command byte to the NEC chip, first waiting until the chip ! 518: * says that it is ready. ! 519: * Return 0 if able to send, or -1 if timed out or FDC had wrong I/O ! 520: * direction. ! 521: */ ! 522: int ! 523: fdcPut(cmd) ! 524: int cmd; ! 525: { ! 526: int ret = -1; ! 527: ! 528: /* Wait for RQM, then expect DIO false. */ ! 529: if (busyWait(fdcWaitRQM, FDC_RQM_WAIT)) { ! 530: if ((inb(FDCMSR) & MSRDIO) == 0) { ! 531: outb(FDCDAT, cmd); ! 532: ret = 0; ! 533: } ! 534: } ! 535: ! 536: return ret; ! 537: } ! 538: ! 539: /* ! 540: * Set transfer rate (FDC_RATE_250K/300K/500K/1MEG) ! 541: */ ! 542: void ! 543: fdcRate(rate) ! 544: int rate; ! 545: { ! 546: outb(FDCRATE, rate); ! 547: } ! 548: ! 549: /* ! 550: * Given drive # (0..3), send a Recalibrate command to the FDC. ! 551: * ! 552: * Sense interrupt - fdcIntStatus() - *must* be done when the ! 553: * ensuing IRQ happens. ! 554: */ ! 555: void ! 556: fdcRecal(drive) ! 557: int drive; ! 558: { ! 559: fdcPut(CMDRCAL); ! 560: fdcPut(drive); ! 561: } ! 562: ! 563: /* ! 564: * Given drive # (0..3), head (0..1), and cylinder (0..255), ! 565: * send a seek command to the FDC. ! 566: * ! 567: * Sense interrupt - fdcIntStatus() - *must* be done when the ! 568: * ensuing IRQ happens. ! 569: */ ! 570: void ! 571: fdcSeek(drive, head, cyl) ! 572: int drive, head, cyl; ! 573: { ! 574: fdcPut(CMDSEEK); ! 575: fdcPut(drive | (head << 2)); ! 576: fdcPut(cyl); ! 577: } ! 578: ! 579: /* ! 580: * fdcSense() issues Sense Drive Status and Sense Interrupt Status, ! 581: * saving information from the FDC into global struct "fdc". ! 582: * ! 583: * It is called in response to FDC interrupts. ! 584: */ ! 585: void ! 586: fdcSense() ! 587: { ! 588: fdcCmdStatus(); /* Get command status. */ ! 589: fdcIntStatus(); /* Get int status, just in case. */ ! 590: } ! 591: ! 592: /* ! 593: * Send Specify command and data bytes to FDC. ! 594: * Always specify DMA mode (ND bit = 0). ! 595: */ ! 596: void ! 597: fdcSpecify(srt, hut, hlt) ! 598: int srt, hut, hlt; ! 599: { ! 600: fdcPut(CMDSPEC); ! 601: fdcPut((srt << 4) | hut); ! 602: fdcPut(hlt << 1); ! 603: } ! 604: ! 605: /* ! 606: * Dissassemble the floppy error status for user reference. ! 607: */ ! 608: void ! 609: fdcStatus() ! 610: { ! 611: printf("fd%d: head=%u", ! 612: fdc.fdc_cmdstat[0] & 3, (fdc.fdc_cmdstat[0] & 4) >> 1); ! 613: ! 614: /* ! 615: * Report on ST0 bits. ! 616: */ ! 617: if (fdc.fdc_ncmdstat >= 1) { ! 618: if (fdc.fdc_cmdstat[0] & ST0_NR) ! 619: printf(" <Not Ready>"); ! 620: ! 621: if (fdc.fdc_cmdstat[0] & ST0_EC) ! 622: printf(" <Equipment Check>"); ! 623: } ! 624: ! 625: /* ! 626: * Report on ST1 bits. ! 627: */ ! 628: if (fdc.fdc_ncmdstat >= 2) { ! 629: if (fdc.fdc_cmdstat[1] & ST1_MA) ! 630: printf(" <Missing Address Mark>"); ! 631: ! 632: if (fdc.fdc_cmdstat[1] & ST1_NW) ! 633: printf(" <Write Protected>"); ! 634: ! 635: if (fdc.fdc_cmdstat[1] & ST1_ND) ! 636: printf(" <No Data>"); ! 637: ! 638: if (fdc.fdc_cmdstat[1] & ST1_OR) ! 639: printf(" <Overrun>"); ! 640: ! 641: if (fdc.fdc_cmdstat[1] & ST1_DE) ! 642: printf(" <Data Error>"); ! 643: ! 644: if (fdc.fdc_cmdstat[1] & ST1_EN) ! 645: printf(" <End of Cyl>"); ! 646: } ! 647: ! 648: /* ! 649: * Report on ST2 bits. ! 650: */ ! 651: if (fdc.fdc_ncmdstat >= 3) { ! 652: if (fdc.fdc_cmdstat[2] & ST2_MD) ! 653: printf(" <Missing Data Address Mark>"); ! 654: ! 655: if (fdc.fdc_cmdstat[2] & ST2_BC) ! 656: printf(" <Bad Cylinder>"); ! 657: ! 658: if (fdc.fdc_cmdstat[2] & ST2_WC) ! 659: printf(" <Wrong Cylinder>"); ! 660: ! 661: if (fdc.fdc_cmdstat[2] & ST2_DD) ! 662: printf(" <Bad Data CRC>"); ! 663: ! 664: if (fdc.fdc_cmdstat[2] & ST2_CM) ! 665: printf(" <Data Deleted>"); ! 666: } ! 667: ! 668: printf("\n"); ! 669: } ! 670: ! 671: /* ! 672: * Wait for FDC Main Status Register to assert Request for Master. ! 673: * This function is designed to be called by busyWait(). ! 674: * It returns nonzero if RQM is asserted, 0 if not. ! 675: */ ! 676: static int ! 677: fdcWaitRQM() ! 678: { ! 679: return (inb(FDCMSR) & MSRRQM); ! 680: } ! 681: ! 682: /* ! 683: * If sw is nonzero, start the timer for diskette; ! 684: * else, stop the timer. ! 685: */ ! 686: void ! 687: setFlTimer(sw) ! 688: int sw; ! 689: { ! 690: setFdcTiming(sw, FL_TIMING); ! 691: } ! 692: ! 693: /* ! 694: * If sw is nonzero, start the timer for floppy tape; ! 695: * else, stop the timer. ! 696: */ ! 697: void ! 698: setFtTimer(sw) ! 699: int sw; ! 700: { ! 701: setFdcTiming(sw, FT_TIMING); ! 702: } ! 703: ! 704: static void ! 705: setFdcTiming(sw, mask) ! 706: int sw, mask; ! 707: { ! 708: int s = sphi(); ! 709: ! 710: /* ! 711: * Only do something if current request changes status of ! 712: * timing for the device. ! 713: */ ! 714: if (sw && (fdcTiming & mask) == 0) { ! 715: fdcTiming |= mask; ! 716: drvl[FL_MAJOR].d_time = 1; ! 717: goto setFdcTimingDone; ! 718: } ! 719: if (sw == 0 && (fdcTiming & mask)) { ! 720: fdcTiming &= ~mask; ! 721: if (fdcTiming == 0) ! 722: drvl[FL_MAJOR].d_time = 0; ! 723: goto setFdcTimingDone; ! 724: } ! 725: ! 726: setFdcTimingDone: ! 727: spl(s); ! 728: return; ! 729: } ! 730: ! 731: static int ! 732: fdctimeout() ! 733: { ! 734: if ((fdcTiming & FL_TIMING) && flCon) ! 735: (*flCon->c_timer)(); ! 736: if ((fdcTiming & FT_TIMING) && ftCon) ! 737: (*ftCon->c_timer)(); ! 738: } ! 739: ! 740: /* ! 741: * Reset the fdc. ! 742: * Sets drive select bits to 00, motor on bits to 0000. ! 743: */ ! 744: void ! 745: fdcReset() ! 746: { ! 747: outb(FDCDOR, 0); ! 748: ! 749: /* "Not Reset FDC" must remain low for at least 3.5 usec */ ! 750: busyWait2(NULL, 4); ! 751: outb(FDCDOR, DORNMR | DORIEN); ! 752: } ! 753: ! 754: /* ! 755: * Reset the fdc. ! 756: * Maintain drive select and motor enable (as specified) during the reset. ! 757: */ ! 758: void ! 759: fdcResetSel(drive, motorOn) ! 760: int drive, motorOn; ! 761: { ! 762: unsigned char motorBits = 0; ! 763: unsigned char outByte; ! 764: ! 765: /* If needed, generate motor on bit for current selected drive. */ ! 766: if (motorOn) ! 767: motorBits = 0x10 << drive; ! 768: ! 769: /* ! 770: * Send drive select, motor on if needed, interrupt enable. ! 771: * The "not reset" bit is zero, which is the point of this routine. ! 772: */ ! 773: outByte = motorBits | drive | DORIEN; ! 774: outb(FDCDOR, outByte); ! 775: ! 776: /* "Not Reset FDC" must remain low for at least 3.5 usec */ ! 777: busyWait2(NULL, 4); ! 778: ! 779: outByte |= DORNMR; ! 780: outb(FDCDOR, outByte); ! 781: } ! 782: ! 783: /* ! 784: * If sw is nonzero, try to seize the fdc interrupt for the diskette; ! 785: * else, try to release it. ! 786: * ! 787: * Return 1 on success, 0 on failure. ! 788: */ ! 789: int ! 790: setFlIntr(sw) ! 791: int sw; ! 792: { ! 793: return setFdcIntr(sw, FL_INTR); ! 794: } ! 795: ! 796: /* ! 797: * If sw is nonzero, try to seize the fdc interrupt for floppy tape; ! 798: * else, try to release it. ! 799: * ! 800: * Return 1 on success, 0 on failure. ! 801: */ ! 802: int ! 803: setFtIntr(sw) ! 804: int sw; ! 805: { ! 806: return setFdcIntr(sw, FT_INTR); ! 807: } ! 808: ! 809: static int ! 810: setFdcIntr(sw, mask) ! 811: int sw, mask; ! 812: { ! 813: int ret; ! 814: ! 815: /* ! 816: * if attaching ! 817: * if fdc interrupt is free ! 818: * attach as requested ! 819: * else ! 820: * return failure ! 821: * else ! 822: * if fdc requesting device now owns fdc interrupt ! 823: * detach as requested ! 824: * else ! 825: * return failure ! 826: */ ! 827: if (sw) ! 828: if (fdcIntOwner == 0) { ! 829: fdcIntOwner = mask; ! 830: ret = 1; ! 831: } else ! 832: ret = 0; ! 833: else ! 834: if (fdcIntOwner == mask) { ! 835: fdcIntOwner = 0; ! 836: ret = 1; ! 837: } else ! 838: ret = 0; ! 839: } ! 840: ! 841: /* * * * * End of fdc.c * * * * */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.