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