Annotation of coherent/b/STREAMS/io.386/fdc.c, revision 1.1.1.1

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 * * * *                  */

unix.superglobalmegacorp.com

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