Annotation of Gnu-Mach/i386/i386at/fd.c, revision 1.1.1.1

1.1       root        1: /* 
                      2:  * Mach Operating System
                      3:  * Copyright (c) 1993,1991,1990,1989 Carnegie Mellon University
                      4:  * All Rights Reserved.
                      5:  * 
                      6:  * Permission to use, copy, modify and distribute this software and its
                      7:  * documentation is hereby granted, provided that both the copyright
                      8:  * notice and this permission notice appear in all copies of the
                      9:  * software, derivative works or modified versions, and any portions
                     10:  * thereof, and that both notices appear in supporting documentation.
                     11:  * 
                     12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     15:  * 
                     16:  * Carnegie Mellon requests users of this software to return to
                     17:  * 
                     18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
                     22:  * 
                     23:  * any improvements or extensions that they make and grant Carnegie Mellon
                     24:  * the rights to redistribute these changes.
                     25:  */
                     26: /*
                     27:   Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
                     28: 
                     29:                All Rights Reserved
                     30: 
                     31: Permission to use, copy, modify, and distribute this software and
                     32: its documentation for any purpose and without fee is hereby
                     33: granted, provided that the above copyright notice appears in all
                     34: copies and that both the copyright notice and this permission notice
                     35: appear in supporting documentation, and that the name of Intel
                     36: not be used in advertising or publicity pertaining to distribution
                     37: of the software without specific, written prior permission.
                     38: 
                     39: INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
                     40: INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
                     41: IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
                     42: CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
                     43: LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
                     44: NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
                     45: WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     46: */
                     47: 
                     48: /*     Copyright (c) 1987, 1988 TOSHIBA Corp.          */
                     49: /*             All Rights Reserved                     */
                     50: 
                     51: #if 0
                     52: 
                     53: #include <fd.h>
                     54: 
                     55: #ifdef MACH_KERNEL
                     56: #include <sys/types.h>
                     57: #include <sys/ioctl.h>
                     58: #include <device/buf.h>
                     59: #include <device/errno.h>
                     60: #else  MACH_KERNEL
                     61: #include <sys/buf.h>
                     62: #include <sys/errno.h>
                     63: #include <sys/user.h>
                     64: #include <sys/ioctl.h>
                     65: #endif MACH_KERNEL
                     66: #include <i386/pio.h>
                     67: #include <i386/machspl.h>
                     68: #include <chips/busses.h>
                     69: #include <i386at/fdreg.h>
                     70: #include <i386at/disk.h>
                     71: #include <vm/vm_kern.h>
                     72: 
                     73: #ifdef DEBUG
                     74: #define D(x) x
                     75: #define DD(x) x
                     76: #else  /* DEBUG */
                     77: #define D(x)
                     78: #define DD(x)
                     79: #endif /* DEBUG */
                     80: 
                     81: /*
                     82:  * Floppy Device-Table Definitions (drtabs)
                     83:  *
                     84:  *      Cyls,Sec,spc,part,Mtype,RWFpl,FGpl
                     85:  */
                     86: struct fddrtab m765f[] = {                     /* format table */
                     87:        80, 18, 1440,  9, 0x88, 0x2a, 0x50,     /* [0] 3.50" 720  Kb  */
                     88:        80, 36, 2880, 18, 0x08, 0x1b, 0x6c,     /* [1] 3.50" 1.44 Meg */
                     89:        40, 18,  720,  9, 0xa8, 0x2a, 0x50,     /* [2] 5.25" 360  Kb  */
                     90:        80, 30, 2400, 15, 0x08, 0x1b, 0x54      /* [3] 5.25" 1.20 Meg */
                     91: };
                     92: 
                     93: /*
                     94:  * The following are static initialization variables
                     95:  * which are based on the configuration.
                     96:  */
                     97: struct ctrl_info ctrl_info[MAXUNIT>>1] = {             /* device data table */
                     98:        {  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } ,
                     99:        {  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
                    100: };
                    101: 
                    102: struct unit_info unit_info[MAXUNIT];           /* unit buffer headers  */
                    103: 
                    104: char *fderr = "FD Error on unit";
                    105: char *fdmsg[] = {
                    106:        "?",
                    107:        "Missing data address mark",
                    108:        "Write protected",
                    109:        "Sector not found",
                    110:        "Data Overrun",                         /* Over run error */
                    111:        "Uncorrectable data read error",        /* CRC Error */
                    112:        "FDC Error",
                    113:        "Illegal format type",
                    114:        "Drive not ready",
                    115:        "diskette not present - please insert",
                    116:        "Illegal interrupt type"
                    117: };
                    118: 
                    119: struct buf     fdrbuf[MAXUNIT];        /* data transfer buffer structures */
                    120: 
                    121: int    fdminphys();
                    122: int    fdintr(), fdprobe(), fdslave();
                    123: void   fdattach();
                    124: int    FdDmaEISA = 0;
                    125: int    FdDmaThreshold = 16 * 1024 * 1024;
                    126: vm_offset_t    FdDmaPage = (vm_offset_t) 0;
                    127: vm_offset_t    fd_std[NFD] = { 0 };
                    128: struct bus_device *fd_dinfo[NFD*2];
                    129: struct bus_ctlr *fd_minfo[NFD];
                    130: struct bus_driver      fddriver = 
                    131:        {fdprobe, fdslave, fdattach, 0, fd_std, "fd", fd_dinfo, "fdc", fd_minfo, 0};
                    132: 
                    133: int    m765verify[MAXUNIT] = {1,1,1,1};        /* write after read flag */
                    134:                                                /* 0 != verify mode     */ 
                    135:                                                /* 0 == not verify mode */
                    136: #ifdef MACH_KERNEL
                    137: extern struct buf *geteblk();
                    138: #endif MACH_KERNEL
                    139: 
                    140: #define trfrate(uip, type)   outb(VFOREG(uip->addr),(((type)&RATEMASK)>>6))
                    141: #define rbskrate(uip, type)  trfrate(uip,(type)&RAPID?RPSEEK:NMSEEK)
                    142: #define getparm(type)   ((type<0||type>3)?(struct fddrtab *)ERROR:&m765f[type])
                    143: #define relative(s1,s2) ((s1)>(s2)?(s1)-(s2):(s2)-(s1))
                    144: 
                    145: fdprobe(port, ctlr)
                    146: struct bus_ctlr *ctlr;
                    147: {
                    148:        int                     spot = STSREG((int) ctlr->address);
                    149:        struct ctrl_info        *cip = &ctrl_info[ctlr->unit];
                    150:        int                     i, in;
                    151: 
                    152:        outb(spot, DATAOK);
                    153:        for (i = 1000; i--;) {
                    154:                in = inb(spot);
                    155:                if ((in&DATAOK) == DATAOK && !(in&0x0f)) {
                    156:                        take_ctlr_irq(ctlr);
                    157:                        cip->b_cmd.c_rbmtr = 0;         /* recalibrate/moter flag */
                    158:                        cip->b_cmd.c_intr = CMDRST;     /* interrupt flag */
                    159:                        cip->b_unitf = 0;
                    160:                        cip->b_uip = 0;
                    161:                        cip->b_rwerr = cip->b_seekerr = cip->b_rberr = 0;
                    162:                        cip->usebuf = 0;
                    163:                        if (FdDmaPage) {
                    164:                                cip->b_pbuf = FdDmaPage + PAGE_SIZE * ctlr->unit;
                    165:                                if (kmem_alloc_pageable(kernel_map,
                    166:                                               (vm_offset_t *)&cip->b_vbuf,
                    167:                                               PAGE_SIZE) != KERN_SUCCESS) {
                    168:                                        printf("%s%d: can not kmem_alloc_pageable.\n",
                    169:                                                ctlr->name, ctlr->unit);
                    170:                                        return 0;
                    171:                                }
                    172:                                (void)pmap_map(cip->b_vbuf,
                    173:                                               (vm_offset_t)cip->b_pbuf, 
                    174:                                               (vm_offset_t)cip->b_pbuf+PAGE_SIZE,
                    175:                                               VM_PROT_READ | VM_PROT_WRITE);
                    176:                        }
                    177:                        printf("%s%d: port = %x, spl = %d, pic = %d.\n", ctlr->name,
                    178:                                ctlr->unit, ctlr->address, ctlr->sysdep, ctlr->sysdep1);
                    179:                        return(1);
                    180:                }
                    181:        }
                    182:        return(0);
                    183: }
                    184: 
                    185: fdslave(dev, xxxx)
                    186: struct bus_device              *dev;
                    187: {
                    188:        return(1);      /* gross hack */
                    189: }
                    190: 
                    191: void fdattach(dev)
                    192: struct bus_device *dev;
                    193: {
                    194:        struct unit_info        *uip = &unit_info[dev->unit];
                    195:        struct ctrl_info        *cip = &ctrl_info[dev->ctlr];
                    196: 
                    197:        uip->dev = dev;
                    198:        dev->address = dev->mi->address;
                    199:        uip->addr = dev->address;
                    200:        uip->b_cmd = &cip->b_cmd;
                    201:        uip->b_seekaddr = 0;
                    202:        uip->av_forw = 0;
                    203:        uip->wakeme = 0;
                    204:        if (cip->b_unitf) {
                    205:                uip->b_unitf=cip->b_unitf->b_unitf;
                    206:                cip->b_unitf->b_unitf=uip;
                    207:        } else {
                    208:                uip->b_unitf=uip;
                    209:                cip->b_unitf=uip;
                    210:        }
                    211:        uip->d_drtab.dr_type &= ~OKTYPE; 
                    212: 
                    213:        printf(", port = %x, spl = %d, pic = %d.",
                    214:                dev->address, dev->sysdep, dev->sysdep1);
                    215: 
                    216:        rstout(uip);
                    217:        specify(uip);
                    218: }
                    219: /*****************************************************************************
                    220:  *
                    221:  * TITLE:      fdopen
                    222:  *
                    223:  * ABSTRACT:   Open a unit. 
                    224:  *
                    225:  ****************************************************************************/
                    226: fdopen(dev, flag, otyp)
                    227: dev_t  dev;
                    228: int    flag;                   /* not used */
                    229: int    otyp;                   /* not used */
                    230: {
                    231:        struct fddrtab          *driv;
                    232:        struct buf              *wbp;
                    233:        spl_t                   x = SPL();
                    234:        int                     error = 0;
                    235:        int                     unit = UNIT(dev);
                    236:        struct unit_info        *uip = &unit_info[unit];
                    237:        int                     slave = uip->dev->slave;
                    238:        struct ctrl_info        *cip = &ctrl_info[uip->dev->ctlr];
                    239:        struct  fdcmd           *cmdp = uip->b_cmd;
                    240:        if (unit < MAXUNIT){
                    241:          /* Since all functions that use this are called from open, we only
                    242:             set this once, right here. */
                    243:                rstout(uip);
                    244:                cip->b_wup = uip;
                    245:                openchk(cmdp);
                    246:                cmdp->c_devflag |= FDMCHK;
                    247:                chkbusy(cmdp);
                    248:                cmdp->c_stsflag |= MTRFLAG;
                    249:                mtr_on(uip);
                    250:                if(inb(VFOREG(uip->addr))&OPENBIT || 
                    251:                   !(uip->d_drtab.dr_type&OKTYPE)){
                    252:                        uip->d_drtab.dr_type &= ~OKTYPE;
                    253:                        if(!rbrate(RAPID, uip))
                    254:                                fdseek(RAPID, uip, 2);
                    255:                        if(inb(VFOREG(uip->addr))&OPENBIT)
                    256:                                error = ENXIO;
                    257:                }
                    258:                cmdp->c_stsflag &= ~MTRFLAG;
                    259:                mtr_on(uip);
                    260:                openfre(cmdp);
                    261:                if(!error && !(uip->d_drtab.dr_type & OKTYPE)) {
                    262:                        if (MEDIATYPE(dev)>3)
                    263:                                goto endopen;
                    264:                        driv = &m765f[MEDIATYPE(dev)];
                    265:                        wbp = geteblk(BLKSIZE);
                    266:                        m765sweep(uip, driv);
                    267:                        cmdp->c_rbmtr &= ~(1<<(RBSHIFT+(slave)));
                    268:                        ++cip->b_rwerr;
                    269:                        wbp->b_dev = dev; wbp->b_error = 0; wbp->b_resid = 0;
                    270:                        wbp->b_flags = (B_READ|B_VERIFY); wbp->b_bcount = 512;
                    271:                        wbp->b_pfcent = 2*driv->dr_spc + driv->dr_nsec - 1;
                    272:                        setqueue(wbp, uip);
                    273:                        biowait(wbp);
                    274:                        brelse(wbp);
                    275:                        error = 0;
                    276:                        uip->d_drtab.dr_type |= OKTYPE;
                    277:                }
                    278:        } else
                    279:                error = ENXIO;
                    280:       endopen:
                    281:        splx(x);
                    282:        return(error);
                    283: }
                    284: /*****************************************************************************
                    285:  *
                    286:  * TITLE:      fdclose
                    287:  *
                    288:  * ABSTRACT:   Close a unit.
                    289:  *
                    290:  *     Called on last close. mark the unit closed and not-ready.
                    291:  *
                    292:  *     Unix doesn't actually "open" an inode for rootdev, swapdev or pipedev.
                    293:  *     If UNIT(swapdev) != UNIT(rootdev), then must add code in init() to 
                    294:  *     "open" swapdev.  These  devices should never be closed.
                    295:  *
                    296:  *****************************************************************************/
                    297: fdclose(dev, flag, otyp, offset)
                    298: dev_t  dev;            /* major, minor numbers */
                    299: int    flag;           /* not used */
                    300: int    otyp;           /* not used */
                    301: off_t  offset;         /* not used */
                    302: {
                    303:        extern                  dev_t   rootdev, swapdev;
                    304:        struct unit_info        *uip = &unit_info[UNIT(dev)];
                    305:        spl_t s;
                    306: 
                    307: #ifdef MACH_KERNEL
                    308: #else  MACH_KERNEL
                    309:        if ((dev == rootdev) || (dev == swapdev))  /* never close these */
                    310:                return(0);
                    311: #endif MACH_KERNEL
                    312: 
                    313:        /* Clear the bit.
                    314:         * If last close of drive insure drtab queue is empty before returning.
                    315:         */
                    316:        s = SPL();
                    317:        while(uip->av_forw != 0) {
                    318:                uip->wakeme = 1;
                    319:                sleep(uip, PRIBIO);
                    320:        }
                    321:        splx(s);
                    322: #ifdef MACH_KERNEL
                    323:        return(0);
                    324: #else  MACH_KERNEL
                    325:        close(0);
                    326: #endif MACH_KERNEL
                    327: }
                    328: /*****************************************************************************
                    329:  *
                    330:  * TITLE:      fdstrategy
                    331:  *
                    332:  * ABSTRACT:   Queue an I/O Request, and start it if not busy already.
                    333:  *
                    334:  *     Reject request if unit is not-ready.
                    335:  *
                    336:  *     Note:   check for not-ready done here ==> could get requests
                    337:  *             queued prior to unit going not-ready.
                    338:  *             not-ready status to those requests that are attempted
                    339:  *             before a new volume is inserted.  Once a new volume is
                    340:  *             inserted, would get good I/O's to wrong volume.
                    341:  *
                    342:  * CALLS:      iodone(),setqueue()
                    343:  *
                    344:  * CALLING ROUTINES:   fdread (indirectly, thru physio)
                    345:  *                     fdwrite (indirectly, thru physio)
                    346:  *
                    347:  ****************************************************************************/
                    348: fdstrategy(bp)
                    349: struct buf *bp;        /* buffer header */
                    350: {
                    351:        unsigned                bytes_left;
                    352:        daddr_t                 secno;
                    353:        struct unit_info        *uip = &unit_info[UNIT(bp->b_dev)];
                    354:        struct fddrtab          *dr = &uip->d_drtab;
                    355:        struct fddrtab          *sdr;
                    356: 
                    357:        bp->b_error = 0;
                    358:        /* set b_resid to b_bcount because we haven't done anything yet */
                    359:        bp->b_resid = bp->b_bcount;
                    360:        if (!(dr->dr_type & OKTYPE) || 
                    361:            ((sdr = getparm(MEDIATYPE(bp->b_dev)))==(struct fddrtab *)ERROR) ||
                    362:            /* wrong parameters */
                    363:            (sdr->dr_ncyl != dr->dr_ncyl) || (sdr->dr_nsec != dr->dr_nsec) ||
                    364:            ((sdr->dr_type|OKTYPE) != dr->dr_type) ||
                    365:            (sdr->dr_rwgpl != dr->dr_rwgpl) ||
                    366:            (sdr->dr_fgpl != dr->dr_fgpl)) {
                    367:                bp->b_flags |= B_ERROR;
                    368:                bp->b_error = EIO;
                    369:                biodone(bp);
                    370:                return(0);
                    371:        }
                    372:        /*
                    373:         * Figure "secno" from b_blkno. Adjust sector # for partition.
                    374:         *
                    375:         * If reading just past the end of the device, it's
                    376:         * End of File.  If not reading, or if read starts further in
                    377:         * than the first sector after the partition, it's an error.
                    378:         *
                    379:         * secno is logical blockno / # of logical blocks per sector */
                    380:        secno = (bp->b_blkno * NBPSCTR) >> 9;
                    381:        if (secno >= dr->p_nsec) {
                    382:                if (!((bp->b_flags & B_READ) && (secno == dr->p_nsec))){
                    383:                        /* off the deep end */
                    384:                        bp->b_flags |= B_ERROR;
                    385:                        bp->b_error = ENXIO;
                    386:                }
                    387:                biodone(bp);
                    388:                return(0);
                    389:        }
                    390: /* At this point, it is no longer possible to directly return from strategy.
                    391:    We now set b_resid to the number of bytes we cannot transfer because
                    392:    they lie beyond the end of the request's partition.  This value is 0
                    393:    if the entire request is within the partition. */
                    394:        bytes_left = (dr->p_nsec - secno) << 9;
                    395:        bp->b_resid = ((bp->b_bcount<=bytes_left)?0:(bp->b_bcount-bytes_left));
                    396:        bp->b_pfcent = secno;
                    397:        setqueue(bp, uip);
                    398:        return(0);
                    399: }
                    400: 
                    401: /***************************************************************************
                    402:  *
                    403:  *     set queue to buffer
                    404:  *
                    405:  ***************************************************************************/
                    406: setqueue(bp, uip)
                    407: struct buf *bp;
                    408: struct unit_info *uip;
                    409: {
                    410:        spl_t                   x = SPL();
                    411:        struct ctrl_info        *cip = &ctrl_info[uip->dev->ctlr];
                    412:        struct  fdcmd           *cmdp = uip->b_cmd;
                    413: 
                    414:        openchk(cmdp);          /* openning check */
                    415:        cmdp->c_devflag |= STRCHK;
                    416:        fd_disksort(uip, bp);   /* queue the request */
                    417:        /*
                    418:         * If no requests are in progress, start this one up.  Else
                    419:         * leave it on the queue, and fdintr will call m765io later.
                    420:         */
                    421:        if(!cip->b_uip)
                    422:                m765io(uip);
                    423:        splx(x);
                    424: }
                    425: /***************************************************************************
                    426:  *
                    427:  *     check io_busy routine
                    428:  *
                    429:  ***************************************************************************/
                    430: chkbusy(cmdp)
                    431: struct fdcmd   *cmdp;
                    432: {
                    433:        while(cmdp->c_devflag & STRCHK){
                    434:                cmdp->c_devflag |= STRWAIT;
                    435:                sleep(&cmdp->c_devflag,PZERO);
                    436:        } 
                    437: }
                    438: /***************************************************************************
                    439:  *
                    440:  *     check fdopen() routine
                    441:  *
                    442:  ***************************************************************************/
                    443: openchk(cmdp)
                    444: struct fdcmd   *cmdp;
                    445: {
                    446:        while(cmdp->c_devflag & FDMCHK ){
                    447:                cmdp->c_devflag |= FDWAIT;
                    448:                sleep(&cmdp->c_devflag,PZERO);
                    449:        } 
                    450: }
                    451: /***************************************************************************
                    452:  *
                    453:  *     free fdopen() routine
                    454:  *
                    455:  ***************************************************************************/
                    456: openfre(cmdp)
                    457: struct fdcmd   *cmdp;
                    458: {
                    459:        cmdp->c_devflag &= ~FDMCHK;
                    460:        if(cmdp->c_devflag & FDWAIT){
                    461:                cmdp->c_devflag &= ~FDWAIT;
                    462:                wakeup(&cmdp->c_devflag);
                    463:        }
                    464: }
                    465: /*****************************************************************************
                    466:  *
                    467:  * TITLE:      m765io
                    468:  *
                    469:  * ABSTRACT:   Start handling an I/O request.
                    470:  *
                    471:  ****************************************************************************/
                    472: m765io(uip)
                    473: struct unit_info *uip;
                    474: {
                    475:        extern int(m765iosub)();
                    476:        register struct buf *bp;
                    477:        struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr];
                    478: 
                    479:        bp = uip->av_forw; /*move bp to ctrl_info[ctrl].b_buf*/
                    480:        cip->b_buf = bp;
                    481:        cip->b_uip = uip;
                    482:        cip->b_xferaddr  = bp->b_un.b_addr;
                    483:        cip->b_xfercount = bp->b_bcount - bp->b_resid;
                    484:        cip->b_sector    = bp->b_pfcent;
                    485:        uip->b_cmd->c_stsflag |= MTRFLAG;
                    486:        if(!mtr_start(uip))
                    487:                timeout(m765iosub, uip, HZ);
                    488:        else
                    489:                m765iosub(uip);
                    490: }
                    491: /****************************************************************************
                    492:  *
                    493:  *     m765io subroutine
                    494:  *
                    495:  ****************************************************************************/
                    496: m765iosub(uip)
                    497: struct unit_info *uip;
                    498: {
                    499:        struct fddrtab          *dr = &uip->d_drtab;
                    500:        int                     startsec;
                    501:        int                     slave = uip->dev->slave;
                    502:        struct ctrl_info        *cip = &ctrl_info[uip->dev->ctlr];
                    503:        struct  fdcmd           *cmdp = uip->b_cmd;
                    504: 
                    505:        rwcmdset(uip);
                    506:        if(cip->b_buf->b_flags&B_FORMAT)
                    507:                goto skipchk;
                    508:        startsec = (cmdp->c_rwdata[3] * dr->dr_nsec) + cmdp->c_rwdata[4];
                    509:        if(startsec+(cip->b_xfercount>>9)-1 > dr->dr_spc)
                    510:                cip->b_xferdma = (dr->dr_spc-startsec+1) << 9;
                    511:        else
                    512: skipchk:       cip->b_xferdma = cip->b_xfercount;
                    513:        if(!(cmdp->c_rbmtr & (1<<(RBSHIFT+slave))))
                    514:                        cip->b_status = rbirate(uip);
                    515:        else if(uip->b_seekaddr != cmdp->c_saddr)
                    516:                cip->b_status = fdiseek(uip,cmdp->c_saddr);
                    517:        else
                    518:                cip->b_status = outicmd(uip);
                    519:        if(cip->b_status)
                    520:                intrerr0(uip);
                    521:        return;
                    522: }
                    523: /***************************************************************************
                    524:  *
                    525:  *     read / write / format / verify command set to command table
                    526:  *
                    527:  ***************************************************************************/
                    528: rwcmdset(uip)
                    529: struct unit_info *uip;
                    530: {
                    531:        short                   resid;
                    532:        int                     slave = uip->dev->slave;
                    533:        struct ctrl_info        *cip = &ctrl_info[uip->dev->ctlr];
                    534:        struct fdcmd            *cmdp = uip->b_cmd;
                    535: 
                    536:        switch(cip->b_buf->b_flags&(B_FORMAT|B_VERIFY|B_READ|B_WRITE)){
                    537:        case B_VERIFY|B_WRITE:  /* VERIFY after WRITE */
                    538:                cmdp->c_rwdata[0] = RDMV;
                    539:                break;
                    540:        case B_FORMAT:
                    541:                cmdp->c_dcount = FMTCNT; 
                    542:                cmdp->c_rwdata[0] = FMTM;
                    543:                cmdp->c_saddr = cip->b_sector / uip->d_drtab.dr_spc;
                    544:                resid = cip->b_sector % uip->d_drtab.dr_spc;
                    545:                cmdp->c_rwdata[1] = slave|((resid/uip->d_drtab.dr_nsec)<<2);
                    546:                cmdp->c_rwdata[2] = 
                    547:                        ((struct fmttbl *)cip->b_buf->b_un.b_addr)->s_type;
                    548:                cmdp->c_rwdata[3] = uip->d_drtab.dr_nsec;
                    549:                cmdp->c_rwdata[4] = uip->d_drtab.dr_fgpl;
                    550:                cmdp->c_rwdata[5] = FMTDATA;
                    551:                break;
                    552:        case B_WRITE:
                    553:        case B_READ:
                    554:        case B_READ|B_VERIFY:
                    555:                cmdp->c_dcount = RWCNT;
                    556:                if(cip->b_buf->b_flags&B_READ)
                    557:                        if(cip->b_buf->b_flags&B_VERIFY)
                    558:                                cmdp->c_rwdata[0] = RDMV;
                    559:                        else
                    560:                                cmdp->c_rwdata[0] = RDM;
                    561:                else
                    562:                        cmdp->c_rwdata[0] = WTM;        /* format or write */
                    563:                resid = cip->b_sector % uip->d_drtab.dr_spc;
                    564:                cmdp->c_rwdata[3] = resid / uip->d_drtab.dr_nsec;
                    565:                cmdp->c_rwdata[1] = slave|(cmdp->c_rwdata[3]<<2);
                    566:                cmdp->c_rwdata[2] = cmdp->c_saddr = 
                    567:                        cip->b_sector / uip->d_drtab.dr_spc;
                    568:                cmdp->c_rwdata[4] = (resid % uip->d_drtab.dr_nsec) + 1;
                    569:                cmdp->c_rwdata[5] = 2;
                    570:                cmdp->c_rwdata[6] = uip->d_drtab.dr_nsec;
                    571:                cmdp->c_rwdata[7] = uip->d_drtab.dr_rwgpl;
                    572:                cmdp->c_rwdata[8] = DTL;
                    573:                D(printf("SET %x %x C%x H%x S%x %x %x %x %x ",
                    574:                        cmdp->c_rwdata[0], cmdp->c_rwdata[1],
                    575:                        cmdp->c_rwdata[2], cmdp->c_rwdata[3],
                    576:                        cmdp->c_rwdata[4], cmdp->c_rwdata[5],
                    577:                        cmdp->c_rwdata[6], cmdp->c_rwdata[7],
                    578:                        cmdp->c_rwdata[8]));
                    579:                break;
                    580:        }
                    581: }
                    582: /*****************************************************************************
                    583:  *
                    584:  * TITLE:      fdread
                    585:  *
                    586:  * ABSTRACT:   "Raw" read.  Use physio().
                    587:  *
                    588:  * CALLS:      m765breakup (indirectly, thru physio)
                    589:  *
                    590:  ****************************************************************************/
                    591: fdread(dev, uio)
                    592: register dev_t dev;
                    593: struct uio *uio;
                    594: { 
                    595: #ifdef MACH_KERNEL
                    596:        /* no need for page-size restriction */
                    597:        return (block_io(fdstrategy, minphys, uio));
                    598: #else  MACH_KERNEL
                    599:        return(physio(fdstrategy,&fdrbuf[UNIT(dev)],dev,B_READ,fdminphys,uio));
                    600: #endif MACH_KERNEL
                    601: }
                    602: /*****************************************************************************
                    603:  *
                    604:  * TITLE:      fdwrite
                    605:  *
                    606:  * ABSTRACT:   "Raw" write.  Use physio().
                    607:  *
                    608:  * CALLS:      m765breakup (indirectly, thru physio)
                    609:  *
                    610:  ****************************************************************************/
                    611: fdwrite(dev, uio)
                    612: register dev_t dev;
                    613: struct uio *uio;
                    614: {
                    615: #ifdef MACH_KERNEL
                    616:        /* no need for page-size restriction */
                    617:        return (block_io(fdstrategy, minphys, uio));
                    618: #else  MACH_KERNEL
                    619:        return(physio(fdstrategy,&fdrbuf[UNIT(dev)],dev,B_WRITE,fdminphys,uio));
                    620: #endif MACH_KERNEL
                    621: }
                    622: /*****************************************************************************
                    623:  *
                    624:  * TITLE:      fdminphys
                    625:  *
                    626:  * ABSTRACT:   Trim buffer length if buffer-size is bigger than page size
                    627:  *
                    628:  * CALLS:      physio
                    629:  *
                    630:  ****************************************************************************/
                    631: fdminphys(bp)
                    632: struct buf     *bp;
                    633: {
                    634:        if (bp->b_bcount > PAGESIZ)
                    635:                bp->b_bcount = PAGESIZ;
                    636: }
                    637: #ifdef MACH_KERNEL
                    638: /* IOC_OUT only and not IOC_INOUT */
                    639: io_return_t fdgetstat(dev, flavor, data, count)
                    640:        dev_t           dev;
                    641:        int             flavor;
                    642:        int *           data;           /* pointer to OUT array */
                    643:        unsigned int    *count;         /* OUT */
                    644: {
                    645:        switch (flavor) {
                    646: 
                    647:        /* Mandatory flavors */
                    648: 
                    649:        case DEV_GET_SIZE: {
                    650:                int ret;
                    651:                struct disk_parms       p;
                    652: 
                    653:                ret = fd_getparms(dev, &p);
                    654:                if (ret) return ret;
                    655:                data[DEV_GET_SIZE_DEVICE_SIZE] = p.dp_pnumsec * NBPSCTR;
                    656:                data[DEV_GET_SIZE_RECORD_SIZE] = NBPSCTR;
                    657:                *count = DEV_GET_SIZE_COUNT;
                    658:                break;
                    659:        }
                    660: 
                    661:        /* Extra flavors */
                    662: 
                    663:        case V_GETPARMS:
                    664:                if (*count < sizeof (struct disk_parms)/sizeof (int))
                    665:                        return (D_INVALID_OPERATION);
                    666:                *count = sizeof (struct disk_parms)/sizeof(int);
                    667:                return (fd_getparms(dev, data));
                    668:         default:
                    669:                return (D_INVALID_OPERATION);
                    670:        }
                    671: }
                    672: /* IOC_VOID or IOC_IN or IOC_INOUT */
                    673: /*ARGSUSED*/
                    674: io_return_t fdsetstat(dev, flavor, data, count)
                    675:        dev_t           dev;
                    676:        int             flavor;
                    677:        int *           data;
                    678:        unsigned int    count;
                    679: {
                    680:        int                     unit = UNIT(dev);
                    681:        switch (flavor) {
                    682:        case V_SETPARMS:    /* Caller wants reset_parameters */
                    683:                return(fd_setparms(unit,*(int *)data));
                    684:        case V_FORMAT:
                    685:                return(fd_format(dev,data));
                    686:        case V_VERIFY:  /* cmdarg : 0 == no verify, 0 != verify */
                    687:                m765verify[unit] = *(int *)data;
                    688:                return(D_SUCCESS);
                    689:        default:
                    690:                return(D_INVALID_OPERATION);
                    691:        }
                    692: }
                    693: 
                    694: /*
                    695:  *      Get block size
                    696:  */
                    697: int
                    698: fddevinfo(dev, flavor, info)
                    699: dev_t   dev;
                    700: int    flavor;
                    701: char   *info;
                    702: {
                    703:        register struct fddrtab *dr;
                    704:         register struct fdpart *p;
                    705:        register int result = D_SUCCESS;
                    706: 
                    707:        switch (flavor) {
                    708:        case D_INFO_BLOCK_SIZE:
                    709:                dr = &unit_info[UNIT(dev)].d_drtab;
                    710: 
                    711:                if(dr->dr_type & OKTYPE)
                    712:                        *((int *) info) =  512;
                    713:                else
                    714:                        result = D_INVALID_OPERATION;
                    715: 
                    716:                break;
                    717:        default:
                    718:                result = D_INVALID_OPERATION;
                    719:        }
                    720: 
                    721:         return(result);
                    722: }
                    723: #else  MACH_KERNEL
                    724: /*****************************************************************************
                    725:  *
                    726:  * TITLE:      fdioctl
                    727:  *
                    728:  * ABSTRACT:   m765 driver special functions.
                    729:  *
                    730:  * CALLING ROUTINES:   kernel
                    731:  *
                    732:  ****************************************************************************/
                    733: int 
                    734: fdioctl(dev, cmd, cmdarg, flag)
                    735: dev_t  dev;            /* major, minor numbers */
                    736: int    cmd;            /* command code */
                    737: int    *cmdarg;        /* user structure with parameters */
                    738: int    flag;           /* not used */
                    739: {
                    740:        register unsigned       unit = UNIT(dev);
                    741:        switch (cmd) {
                    742:        case V_SETPARMS:    /* Caller wants reset_parameters */
                    743:                return(fd_setparms(unit,*cmdarg));
                    744:        case V_GETPARMS:    /* Caller wants device parameters */
                    745:                return(fd_getparms(dev,cmdarg));
                    746:        case V_FORMAT:
                    747:                return(fd_format(dev,cmdarg));
                    748:        case V_VERIFY:  /* cmdarg : 0 == no verify, 0 != verify */
                    749:                m765verify[unit] = *cmdarg;
                    750:                return(0);
                    751:        }
                    752:        return(EINVAL);
                    753: }
                    754: #endif MACH_KERNEL
                    755: /****************************************************************************
                    756:  *
                    757:  *     set fd parameters 
                    758:  *
                    759:  ****************************************************************************/
                    760: int
                    761: fd_setparms(unit, cmdarg)
                    762: register unsigned int unit;
                    763: long cmdarg;
                    764: {
                    765:        struct fddrtab   *fdparm;
                    766:        spl_t            x;
                    767:        struct unit_info *uip = &unit_info[unit];
                    768:        struct  fdcmd    *cmdp = uip->b_cmd;
                    769: 
                    770:        cmdp->c_rbmtr &= ~(1<<(RBSHIFT+uip->dev->slave));
                    771:        if ((fdparm = getparm(MEDIATYPE(cmdarg))) == (struct fddrtab *)ERROR)
                    772:                return(EINVAL);
                    773:        x = SPL();
                    774:        openchk(cmdp);
                    775:        cmdp->c_devflag |= FDMCHK;
                    776:        chkbusy(cmdp);
                    777:        m765sweep(uip, fdparm);
                    778:        uip->d_drtab.dr_type |= OKTYPE;
                    779:        openfre(cmdp);
                    780:        splx(x);
                    781:        return(0);
                    782: }
                    783: /****************************************************************************
                    784:  *
                    785:  *     get fd parameters 
                    786:  *
                    787:  ****************************************************************************/
                    788: int
                    789: fd_getparms(dev,cmdarg)
                    790: dev_t  dev;            /* major, minor numbers */
                    791: int    *cmdarg;
                    792: {
                    793:        struct disk_parms       *diskp = (struct disk_parms *)cmdarg;
                    794:        register struct fddrtab *dr = &unit_info[UNIT(dev)].d_drtab;
                    795: 
                    796:        if(dr->dr_type & OKTYPE){
                    797:                diskp->dp_type = DPT_FLOPPY;
                    798:                diskp->dp_heads = 2;
                    799:                diskp->dp_sectors = dr->dr_nsec;
                    800:                diskp->dp_pstartsec = 0;
                    801:                diskp->dp_cyls = dr->dr_ncyl;
                    802:                diskp->dp_pnumsec = dr->p_nsec;
                    803:                return(0);
                    804:        }
                    805:        return(ENXIO);
                    806: }
                    807: /****************************************************************************
                    808:  *
                    809:  *     format command
                    810:  *
                    811:  ****************************************************************************/
                    812: fd_format(dev,cmdarg)
                    813: dev_t  dev;            /* major, minor numbers */
                    814: int    *cmdarg;
                    815: 
                    816: {
                    817:        register struct buf     *bp;
                    818:        register daddr_t        track;
                    819:        union  io_arg           *varg;
                    820:        u_short                 num_trks;
                    821:        register struct fddrtab *dr = &unit_info[UNIT(dev)].d_drtab;
                    822: 
                    823:        if(!(dr->dr_type & OKTYPE))
                    824:                return(EINVAL); 
                    825:        varg = (union io_arg *)cmdarg;
                    826:        num_trks = varg->ia_fmt.num_trks;
                    827:        track = (daddr_t)(varg->ia_fmt.start_trk*dr->dr_nsec);
                    828:        if((track + (num_trks*dr->dr_nsec))>dr->p_nsec)
                    829:                return(EINVAL);
                    830:        bp = geteblk(BLKSIZE);          /* get struct buf area */
                    831:        while (num_trks>0) {
                    832:                bp->b_flags &= ~B_DONE;
                    833:                bp->b_dev = dev;
                    834:                bp->b_error = 0; bp->b_resid = 0;
                    835:                bp->b_flags = B_FORMAT; 
                    836:                bp->b_bcount = dr->dr_nsec * FMTID;
                    837:                bp->b_blkno = (daddr_t)((track << 9) / NBPSCTR);
                    838:                if(makeidtbl(bp->b_un.b_addr,dr,
                    839:                             varg->ia_fmt.start_trk++,varg->ia_fmt.intlv))
                    840:                        return(EINVAL);
                    841:                fdstrategy(bp);
                    842:                biowait(bp);
                    843:                if(bp->b_error)
                    844:                        if((bp->b_error == (char)EBBHARD) || 
                    845:                           (bp->b_error == (char)EBBSOFT))
                    846:                                return(EIO);
                    847:                        else
                    848:                                return(bp->b_error);
                    849:                num_trks--;
                    850:                track += dr->dr_nsec;
                    851:        }
                    852:        brelse(bp);
                    853:        return(0);
                    854: }
                    855: /****************************************************************************
                    856:  *
                    857:  *     make id table for format
                    858:  *
                    859:  ****************************************************************************/
                    860: makeidtbl(tblpt,dr,track,intlv)
                    861: struct fmttbl *tblpt;
                    862: struct fddrtab *dr;
                    863: unsigned short track;
                    864: unsigned short intlv;
                    865: {
                    866:        register int    i,j,secno;
                    867: 
                    868:        if(intlv >= dr->dr_nsec)
                    869:                return(1);
                    870:        for(i=0; i<dr->dr_nsec; i++)
                    871:                tblpt[i].sector = 0;
                    872:        for(i=0,j=0,secno=1; i<dr->dr_nsec; i++){
                    873:                tblpt[j].cyl = track >> 1;
                    874:                tblpt[j].head = track & 1;
                    875:                tblpt[j].sector = secno++;
                    876:                tblpt[j].s_type = 2;
                    877:                if((j+=intlv) < dr->dr_nsec)
                    878:                        continue;
                    879:                for(j-=dr->dr_nsec; j < dr->dr_nsec ; j++)
                    880:                        if(!tblpt[j].sector)
                    881:                                break;
                    882:        }
                    883:        return(0);
                    884: }
                    885: /*****************************************************************************
                    886:  *
                    887:  * TITLE:      fdintr
                    888:  *
                    889:  * ABSTRACT:   Handle interrupt.
                    890:  *
                    891:  *     Interrupt procedure for m765 driver.  Gets status of last
                    892:  *     operation and performs service function according to the
                    893:  *     type of interrupt.  If it was an operation complete interrupt,
                    894:  *     switches on the current driver state and either declares the
                    895:  *     operation done, or starts the next operation
                    896:  *
                    897:  ****************************************************************************/
                    898: fdintr(ctrl)
                    899: int    ctrl;
                    900: {
                    901:        extern                  int(m765intrsub)();
                    902:        struct unit_info        *uip = ctrl_info[ctrl].b_uip;
                    903:        struct unit_info        *wup = ctrl_info[ctrl].b_wup;
                    904:        struct fdcmd            *cmdp = &ctrl_info[ctrl].b_cmd;
                    905:        if(cmdp->c_stsflag & INTROUT)
                    906:                untimeout(fdintr, ctrl);
                    907:        cmdp->c_stsflag &= ~INTROUT;    
                    908:        switch(cmdp->c_intr){
                    909:        case RWFLAG:
                    910:                rwintr(uip);
                    911:                break;  
                    912:        case SKFLAG:
                    913:        case SKEFLAG|SKFLAG:
                    914:        case RBFLAG:
                    915:                timeout(m765intrsub, uip, SEEKWAIT);
                    916:                break;
                    917:        case WUPFLAG:
                    918:                cmdp->c_intr &= ~WUPFLAG;
                    919:                wakeup(wup);
                    920:        }
                    921:        return(0);
                    922: }
                    923: /*****************************************************************************
                    924:  *
                    925:  *     interrup subroutine (seek recalibrate)
                    926:  *
                    927:  *****************************************************************************/
                    928: m765intrsub(uip)
                    929: struct unit_info *uip;
                    930: {
                    931:        struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr];
                    932: 
                    933:        if((cip->b_status = sis(uip))!=  ST0OK)
                    934:                switch(uip->b_cmd->c_intr){
                    935:                case SKFLAG:
                    936:                        seekintr(uip);
                    937:                        break;
                    938:                case SKEFLAG|SKFLAG:
                    939:                        seekintre(uip);
                    940:                        break;
                    941:                case RBFLAG:
                    942:                        rbintr(uip);
                    943:                }
                    944: }
                    945: /*****************************************************************************
                    946:  *
                    947:  *     read / write / format / verify interrupt routine
                    948:  *
                    949:  *****************************************************************************/
                    950: rwintr(uip)
                    951: struct unit_info *uip;
                    952: {
                    953:        int                     rsult[7];
                    954:        register int            rtn, count;
                    955:        struct ctrl_info        *cip = &ctrl_info[uip->dev->ctlr];
                    956:        struct fdcmd            *cmdp = uip->b_cmd;
                    957: 
                    958:        cmdp->c_intr &= ~RWFLAG;
                    959:        if((cip->b_buf->b_flags&(B_READ|B_VERIFY))!=(B_READ|B_VERIFY))
                    960:                if(inb(VFOREG(uip->addr))&OPENBIT){
                    961:                        if(cip->b_buf->b_flags&B_FORMAT){
                    962:                                cip->b_status = TIMEOUT;
                    963:                                intrerr0(uip);
                    964:                        } else {
                    965:                                if((inb(STSREG(uip->addr))&ST0OK)!=ST0OK)
                    966:                                        printf("%s %d : %s\n",
                    967:                                                fderr,
                    968:                                                uip-unit_info,
                    969:                                                fdmsg[DOORERR]);
                    970:                                rstout(uip);
                    971:                                specify(uip);
                    972:                                cmdp->c_rbmtr &= RBRST;
                    973:                                cmdp->c_intr |= SKEFLAG;
                    974:                                if(cmdp->c_saddr > 2)
                    975:                                        fdiseek(uip, cmdp->c_saddr-2);
                    976:                                else
                    977:                                        fdiseek(uip, cmdp->c_saddr+2);
                    978:                        }
                    979:                        return;
                    980:                }
                    981:        for( count = 0 ; count < 7 ; count++ ){
                    982:                if(rtn = fdc_sts(FD_ISTS, uip)) /* status check */
                    983:                        goto rwend;
                    984:                rsult[count] = inb(DATAREG(uip->addr));
                    985:        }
                    986:        rtn = 0;
                    987:        if(rsult[0]&0xc0){
                    988:                rtn = cmdp->c_rwdata[0]<<8;
                    989:                if(rsult[0]&0x80){ rtn |= FDCERR;   goto rwend; }
                    990:                if(rsult[1]&0x80){ rtn |= NOREC;    goto rwend; }
                    991:                if(rsult[1]&0x20){ rtn |= CRCERR;   goto rwend; }
                    992:                if(rsult[1]&0x10){ rtn |= OVERRUN;  goto rwend; }
                    993:                if(rsult[1]&0x04){ rtn |= NOREC;    goto rwend; }
                    994:                if(rsult[1]&0x02){ rtn |= WTPRT;    goto rwend; }
                    995:                if(rsult[1]&0x01){ rtn |= ADDRERR;  goto rwend; }
                    996:                rtn |= FDCERR;
                    997: rwend:         outb(0x0a, 0x06);
                    998:        }
                    999:        if(cip->b_status = rtn) {
                   1000:                D(printf("\n->rwierr %x ", rtn));
                   1001:                rwierr(uip);
                   1002:        } else { /* write command */
                   1003:                if(((cip->b_buf->b_flags&(B_FORMAT|B_READ|B_WRITE))==B_WRITE) 
                   1004:                   && !(cip->b_buf->b_flags & B_VERIFY)) {
                   1005:                        D(printf("->w/v "));
                   1006:                        cip->b_buf->b_flags |= B_VERIFY;
                   1007:                        rwcmdset(uip);
                   1008:                        if(cip->b_status = outicmd(uip))
                   1009:                                intrerr0(uip);
                   1010:                        return;
                   1011:                }
                   1012:                /* clear retry count */
                   1013:                if (cip->usebuf) {
                   1014:                        bcopy(cip->b_vbuf, cip->b_xferaddr, cip->b_xferdma);
                   1015:                        DD(printf("R(%x, %x, %x)\n",
                   1016:                                cip->b_vbuf, cip->b_xferaddr, cip->b_xferdma));
                   1017:                }
                   1018:                cip->b_buf->b_flags &= ~B_VERIFY;
                   1019:                cip->b_rwerr = cip->b_seekerr = cip->b_rberr = 0;
                   1020:                cip->b_xfercount -= cip->b_xferdma;
                   1021:                cip->b_xferaddr += cip->b_xferdma;
                   1022:                cip->b_sector = cip->b_sector+(cip->b_xferdma>>9);
                   1023:                D(printf("->done%s\n", cip->b_xfercount?"":"." ));
                   1024:                /* next address (cyl,head,sec) */
                   1025:                if((int)cip->b_xfercount>0)
                   1026:                        m765iosub(uip);
                   1027:                else
                   1028:                        quechk(uip);
                   1029:        }
                   1030: }
                   1031: /*****************************************************************************
                   1032:  *
                   1033:  *     read / write / format / verify error routine
                   1034:  *
                   1035:  *****************************************************************************/
                   1036: rwierr(uip)
                   1037: struct unit_info *uip;
                   1038: {
                   1039:        short                   status;
                   1040:        struct ctrl_info        *cip = &ctrl_info[uip->dev->ctlr];
                   1041:        struct  fdcmd           *cmdp = uip->b_cmd;
                   1042: 
                   1043:        D(printf("%x-%x-%x ", cip->b_rwerr&SRMASK, cip->b_rwerr&MRMASK, cip->b_rwerr&LRMASK));
                   1044:        if((cip->b_buf->b_flags&(B_READ|B_VERIFY))==(B_READ|B_VERIFY)){
                   1045:                if((cip->b_rwerr&SRMASK)<MEDIARD)
                   1046:                        goto rwrtry;
                   1047:                if((cip->b_rwerr&MRMASK)<MEDIASEEK)
                   1048:                        goto rwseek;
                   1049:                goto rwexit;
                   1050:        } else
                   1051:                if(cip->b_buf->b_flags&B_VERIFY){
                   1052:                        cip->b_buf->b_flags &= ~B_VERIFY;
                   1053:                        rwcmdset(uip);
                   1054:                }
                   1055: rwrtry:        status = cip->b_status;
                   1056:        if((++cip->b_rwerr&SRMASK)<SRETRY)
                   1057:                cip->b_status = outicmd(uip);
                   1058:        else {
                   1059: rwseek:                cip->b_rwerr = (cip->b_rwerr&RMRMASK)+MINC;
                   1060:                if((cip->b_rwerr&MRMASK)<MRETRY){
                   1061:                        cmdp->c_intr |= SKEFLAG;
                   1062:                        if(cmdp->c_saddr > 2)
                   1063:                                cip->b_status=fdiseek(uip,cmdp->c_saddr-2);
                   1064:                        else
                   1065:                                cip->b_status=fdiseek(uip,cmdp->c_saddr+2);
                   1066:                } else {
                   1067:                        cip->b_rwerr = (cip->b_rwerr&LRMASK)+LINC;
                   1068:                        if((cip->b_rwerr&LRMASK)<LRETRY)
                   1069:                                        cip->b_status=rbirate(uip);
                   1070:                }
                   1071:        }
                   1072:        if(cip->b_status){
                   1073:                D(printf("ERR->intrerr0 "));
                   1074:                cip->b_status = status;
                   1075: rwexit:                intrerr0(uip);
                   1076:        }
                   1077: }
                   1078: /*****************************************************************************
                   1079:  *
                   1080:  *     recalibrate interrupt routine
                   1081:  *
                   1082:  *****************************************************************************/
                   1083: rbintr(uip)
                   1084: struct unit_info *uip;
                   1085: {
                   1086:        struct ctrl_info        *cip = &ctrl_info[uip->dev->ctlr];
                   1087:        struct fdcmd            *cmdp = uip->b_cmd;
                   1088: 
                   1089:        cmdp->c_intr &= ~RBFLAG;
                   1090:        if(cip->b_status) {
                   1091:                if(++cip->b_rberr<SRETRY)
                   1092:                        cip->b_status = rbirate(uip);
                   1093:        } else {
                   1094:                cmdp->c_rbmtr |= 1<<(RBSHIFT+uip->dev->slave);
                   1095:                uip->b_seekaddr = 0;
                   1096:                cip->b_rberr = 0;
                   1097:                cip->b_status=fdiseek(uip, cmdp->c_saddr);
                   1098:        }
                   1099:        if(cip->b_status)
                   1100:                intrerr0(uip);
                   1101: }
                   1102: /******************************************************************************
                   1103:  *
                   1104:  *     seek interrupt routine
                   1105:  *
                   1106:  *****************************************************************************/
                   1107: seekintr(uip)
                   1108: struct unit_info *uip;
                   1109: {
                   1110:        struct ctrl_info        *cip = &ctrl_info[uip->dev->ctlr];
                   1111:        struct fdcmd            *cmdp = uip->b_cmd;
                   1112: 
                   1113:        cmdp->c_intr &= ~SKFLAG;
                   1114:        if(cip->b_status)
                   1115:                seekierr(uip, cmdp->c_saddr);
                   1116:        else {
                   1117:                uip->b_seekaddr = cmdp->c_saddr;
                   1118:                cip->b_status = outicmd(uip);
                   1119:        }
                   1120:        if(cip->b_status)
                   1121:                intrerr0(uip);
                   1122:        else
                   1123:                cip->b_seekerr = 0;
                   1124: }
                   1125: /*****************************************************************************
                   1126:  *
                   1127:  *     seek error retry interrupt routine
                   1128:  *
                   1129:  *****************************************************************************/
                   1130: seekintre(uip)
                   1131: struct unit_info *uip;
                   1132: {
                   1133:        register char           seekpoint;
                   1134:        struct ctrl_info        *cip = &ctrl_info[uip->dev->ctlr];
                   1135:        struct fdcmd            *cmdp = uip->b_cmd;
                   1136: 
                   1137:        cmdp->c_intr &= ~(SKEFLAG|SKFLAG);
                   1138:        if(cmdp->c_saddr > 2)
                   1139:                seekpoint = cmdp->c_saddr-2;
                   1140:        else
                   1141:                seekpoint = cmdp->c_saddr+2;
                   1142:        if(cip->b_status)
                   1143:                seekierr(uip, seekpoint);
                   1144:        else {
                   1145:                uip->b_seekaddr = seekpoint;
                   1146:                cip->b_status = fdiseek(uip, cmdp->c_saddr);
                   1147:        }
                   1148:        if(cip->b_status)
                   1149:                intrerr0(uip);
                   1150:        else
                   1151:                cip->b_seekerr = 0;
                   1152: }
                   1153: /*****************************************************************************
                   1154:  *
                   1155:  *     seek error routine
                   1156:  *
                   1157:  *****************************************************************************/
                   1158: seekierr(uip, seekpoint)
                   1159: struct unit_info *uip;
                   1160: register char          seekpoint;
                   1161: {
                   1162:        struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr];
                   1163: 
                   1164:        if((++cip->b_seekerr&SRMASK)<SRETRY)
                   1165:                cip->b_status=fdiseek(uip, seekpoint);
                   1166:        else {
                   1167:                cip->b_seekerr = (cip->b_seekerr&MRMASK) + MINC;
                   1168:                if((cip->b_seekerr&MRMASK)<MRETRY)
                   1169:                        cip->b_status=rbirate(uip);
                   1170:        }
                   1171:        if(cip->b_status)
                   1172:                intrerr0(uip);
                   1173: }
                   1174: /*****************************************************************************
                   1175:  *
                   1176:  * TITLE:      m765sweep
                   1177:  *
                   1178:  * ABSTRACT:   Perform an initialization sweep.  
                   1179:  *
                   1180:  **************************************************************************/
                   1181: m765sweep(uip, cdr)
                   1182: struct unit_info *uip;
                   1183: register struct fddrtab  *cdr; /* device initialization data */
                   1184: {
                   1185:        register struct fddrtab *dr = &uip->d_drtab;
                   1186: 
                   1187:        dr->dr_ncyl = cdr->dr_ncyl;
                   1188:        dr->dr_nsec = cdr->dr_nsec;
                   1189:        dr->dr_spc  = cdr->dr_spc;
                   1190:        dr->p_nsec  = cdr->p_nsec;
                   1191:        dr->dr_type = cdr->dr_type;
                   1192:        dr->dr_rwgpl= cdr->dr_rwgpl;
                   1193:        dr->dr_fgpl = cdr->dr_fgpl;
                   1194: }
                   1195: /*****************************************************************************
                   1196:  *
                   1197:  *  TITLE:  m765disksort
                   1198:  *
                   1199:  *****************************************************************************/
                   1200: fd_disksort(uip, bp)
                   1201: struct unit_info *uip;         /*  Pointer to head of active queue     */
                   1202: register struct buf *bp;       /*  Pointer to buffer to be inserted    */
                   1203: {
                   1204:        register struct buf *bp2; /*  Pointer to next buffer in queue   */
                   1205:        register struct buf *bp1; /*  Pointer where to insert buffer    */
                   1206: 
                   1207:        if (!(bp1 = uip->av_forw)) {
                   1208:                /* No other buffers to compare against */
                   1209:                uip->av_forw = bp;
                   1210:                bp->av_forw = 0;
                   1211:                return;
                   1212:        }
                   1213:        bp2 = bp1->av_forw;
                   1214:        while(bp2 && (relative(bp1->b_pfcent,bp->b_pfcent) >=
                   1215:                      relative(bp1->b_pfcent,bp2->b_pfcent))) {
                   1216:                bp1 = bp2;
                   1217:                bp2 = bp1->av_forw;
                   1218:        }
                   1219:        bp1->av_forw = bp;
                   1220:        bp->av_forw = bp2;
                   1221: }
                   1222: /*****************************************************************************
                   1223:  *
                   1224:  *     Set Interrupt error and FDC reset
                   1225:  *
                   1226:  *****************************************************************************/
                   1227: intrerr0(uip)
                   1228: struct unit_info *uip;
                   1229: {
                   1230:        struct buf              *bp; /* Pointer to next buffer in queue */
                   1231:        int                     resid;
                   1232:        struct ctrl_info        *cip = &ctrl_info[uip->dev->ctlr];
                   1233:        struct  fdcmd           *cmdp = uip->b_cmd;
                   1234:        register struct fddrtab *dr = &uip->d_drtab;
                   1235: 
                   1236:        if((cip->b_buf->b_flags&(B_READ|B_VERIFY))!=(B_READ|B_VERIFY)){
                   1237:                resid = cip->b_xfercount = cip->b_xferdma-1-inb(DMACNT)*0x101;
                   1238:                resid = (cip->b_sector + (resid>>9)) % dr->dr_spc;
                   1239:                printf("%s %d : %s\n",
                   1240:                        fderr,
                   1241:                        uip->dev->slave,
                   1242:                        fdmsg[cip->b_status&BYTEMASK]);
                   1243:                printf("cylinder = %d  ",cmdp->c_saddr);
                   1244:                printf("head = %d  sector = %d  byte/sec = %d\n",
                   1245:                resid / dr->dr_nsec , (resid % dr->dr_nsec)+1 , 512);
                   1246:        }
                   1247:        cip->b_rwerr = cip->b_seekerr = cip->b_rberr = 0;
                   1248:        cmdp->c_intr = CMDRST;
                   1249:        if(((cip->b_buf->b_flags&(B_READ|B_VERIFY))!=(B_READ|B_VERIFY)) &&
                   1250:           uip->dev->slave)
                   1251:                dr->dr_type &= ~OKTYPE; 
                   1252:        bp = cip->b_buf;
                   1253:        bp->b_flags |= B_ERROR;
                   1254:        switch(cip->b_status&BYTEMASK){
                   1255:        case ADDRERR:
                   1256:        case OVERRUN:
                   1257:        case FDCERR:
                   1258:        case TIMEOUT:
                   1259:                bp->b_error = EIO;
                   1260:                break;
                   1261:        case WTPRT:
                   1262: #ifdef MACH_KERNEL
                   1263:                bp->b_error = ENXIO;
                   1264: #else
                   1265:                bp->b_error = ENODEV;
                   1266: #endif
                   1267:                break;
                   1268:        case NOREC:
                   1269:                bp->b_error = EBBHARD;
                   1270:                break;
                   1271:        case CRCERR:
                   1272:                bp->b_error = EBBSOFT;
                   1273:        }
                   1274:        rstout(uip);
                   1275:        specify(uip);
                   1276:        cmdp->c_rbmtr &= RBRST;
                   1277:        quechk(uip);
                   1278: }
                   1279: /*****************************************************************************
                   1280:  *
                   1281:  *     Next queue check routine
                   1282:  *
                   1283:  *****************************************************************************/
                   1284: quechk(uip)
                   1285: struct unit_info *uip;
                   1286: {
                   1287:        register struct buf     *bp = uip->av_forw;
                   1288:        struct ctrl_info        *cip = &ctrl_info[uip->dev->ctlr];
                   1289:        struct unit_info        *loop;
                   1290:        struct fdcmd            *cmdp = uip->b_cmd;
                   1291:        /* clear retry count */
                   1292:        cip->b_rwerr = cip->b_seekerr = cip->b_rberr = 0;
                   1293:        bp->b_resid = bp->b_resid + cip->b_xfercount;
                   1294:        uip->av_forw=bp->av_forw;
                   1295:        if (!uip->av_forw && uip->wakeme) {
                   1296:                uip->wakeme = 0;
                   1297:                wakeup(uip);
                   1298:        }
                   1299:        biodone(bp);
                   1300:        loop = uip;
                   1301:        do {
                   1302:                loop=loop->b_unitf;
                   1303:                if (loop->av_forw) {
                   1304:                        m765io(loop);
                   1305:                        return;
                   1306:                }
                   1307:        } while (loop!=uip);
                   1308:        cip->b_uip = 0;
                   1309:        cmdp->c_stsflag &= ~MTRFLAG;
                   1310:        mtr_on(uip);
                   1311:        cmdp->c_devflag &= ~STRCHK;
                   1312:        if(cmdp->c_devflag & STRWAIT){
                   1313:                cmdp->c_devflag &= ~STRWAIT;
                   1314:                wakeup(&cmdp->c_devflag);
                   1315:        }
                   1316: }
                   1317: fdprint(dev,str)
                   1318: dev_t  dev;
                   1319: char   *str;
                   1320: {
                   1321:        printf("floppy disk driver: %s on bad dev %d, partition %d\n",
                   1322:                        str, UNIT(dev), 0);
                   1323: }
                   1324: fdsize()
                   1325: {
                   1326:        printf("fdsize()        -- not implemented\n");
                   1327: }
                   1328: fddump()
                   1329: {
                   1330:        printf("fddump()        -- not implemented\n");
                   1331: }
                   1332: /*****************************************************************************
                   1333:  *
                   1334:  *     fdc reset routine
                   1335:  *
                   1336:  *****************************************************************************/
                   1337: rstout(uip)
                   1338: struct unit_info *uip;
                   1339: {
                   1340:        register int    outd;
                   1341: 
                   1342:        outd = ((uip->b_cmd->c_rbmtr&MTRMASK)<<MTR_ON)|uip->dev->slave;
                   1343:        outb(CTRLREG(uip->addr), outd);
                   1344:        outd |= FDC_RST;
                   1345:        outb(CTRLREG(uip->addr), outd);
                   1346:        outd |= DMAREQ;
                   1347:        outb(CTRLREG(uip->addr), outd);
                   1348: }
                   1349: /*****************************************************************************
                   1350:  *
                   1351:  *     specify command routine
                   1352:  *
                   1353:  *****************************************************************************/
                   1354: specify(uip)
                   1355: struct unit_info *uip;
                   1356: {
                   1357:        /* status check */
                   1358:        if(fdc_sts(FD_OSTS, uip))
                   1359:                return;
                   1360:        /* Specify command */
                   1361:        outb(DATAREG(uip->addr), SPCCMD);
                   1362:        /* status check */
                   1363:        if(fdc_sts(FD_OSTS, uip))
                   1364:                return;
                   1365:        /* Step rate,Head unload time */
                   1366:        outb(DATAREG(uip->addr), SRTHUT);
                   1367:        /* status check */
                   1368:        if(fdc_sts(FD_OSTS, uip))
                   1369:                return;
                   1370:        /* Head load time,Non DMA Mode*/
                   1371:        outb(DATAREG(uip->addr), HLTND);
                   1372:        return;
                   1373: }
                   1374: /****************************************************************************
                   1375:  *
                   1376:  *     recalibrate command routine
                   1377:  *
                   1378:  ****************************************************************************/
                   1379: rbrate(mtype,uip)
                   1380: char    mtype;
                   1381: struct unit_info *uip;
                   1382: {
                   1383:        register int    rtn = 1, rty_flg=2;
                   1384:        spl_t           x;
                   1385:        struct  fdcmd   *cmdp = uip->b_cmd;
                   1386: 
                   1387:        rbskrate(uip, mtype);                   /* set transfer rate */
                   1388:        while((rty_flg--)&&rtn){
                   1389:                if(rtn = fdc_sts(FD_OSTS, uip)) /* status check */
                   1390:                        break;
                   1391:                /*recalibrate command*/
                   1392:                outb(DATAREG(uip->addr), RBCMD);
                   1393:                if(rtn = fdc_sts(FD_OSTS, uip)) /* status check */
                   1394:                        break;
                   1395:                /* Device to wake up specified in open */
                   1396:                cmdp->c_intr |= WUPFLAG;
                   1397:                x = SPL();
                   1398:                outb(DATAREG(uip->addr), uip->dev->slave);
                   1399:                rtn = ERROR;
                   1400:                while(rtn) {
                   1401:                        uip->wakeme = 1;
                   1402:                        sleep(uip, PZERO);
                   1403:                        if((rtn = sis(uip)) == ST0OK)
                   1404:                          /* Device to wake up specified in open */
                   1405:                                cmdp->c_intr |= WUPFLAG;
                   1406:                        else
                   1407:                                break;
                   1408:                }
                   1409:                splx(x);
                   1410:        }
                   1411:        return(rtn);
                   1412: }
                   1413: /*****************************************************************************
                   1414:  *
                   1415:  *     seek command routine
                   1416:  *
                   1417:  ****************************************************************************/
                   1418: fdseek(mtype, uip, cylno)
                   1419: register char  mtype;
                   1420: struct unit_info *uip;
                   1421: register int   cylno;
                   1422: {
                   1423:        spl_t           x;
                   1424:        int             rtn;
                   1425:        struct  fdcmd   *cmdp = uip->b_cmd;
                   1426: 
                   1427:        rbskrate(uip, mtype);
                   1428:        if(rtn = fdc_sts(FD_OSTS, uip))                 /* status check */
                   1429:                return(rtn);
                   1430:        outb(DATAREG(uip->addr), SEEKCMD);              /* seek command */
                   1431:        if(rtn = fdc_sts(FD_OSTS, uip))                 /* status check */
                   1432:                return(rtn);
                   1433:        outb(DATAREG(uip->addr), uip->dev->slave);      /* drive number */
                   1434:        if(rtn = fdc_sts(FD_OSTS, uip))                 /* status check */
                   1435:                return(rtn);
                   1436:        x = SPL();
                   1437:        /* Device to wake up specified in open */
                   1438:        cmdp->c_intr |= WUPFLAG;
                   1439:        outb(DATAREG(uip->addr), cylno);                /* seek count */
                   1440:        rtn = ERROR;
                   1441:        while(rtn){     
                   1442:                uip->wakeme = 1;
                   1443:                sleep(uip, PZERO);
                   1444:                if((rtn = sis(uip)) == ST0OK)
                   1445:                  /* Device to wake up specified in open */
                   1446:                        cmdp->c_intr |= WUPFLAG;
                   1447:                else
                   1448:                        break;
                   1449:        }
                   1450:        splx(x);
                   1451:        return(rtn);
                   1452: }
                   1453: /*****************************************************************************
                   1454:  *
                   1455:  *     seek commnd routine(use interrupt)
                   1456:  *
                   1457:  *****************************************************************************/
                   1458: fdiseek(uip, cylno) 
                   1459: struct unit_info *uip;
                   1460: int    cylno;
                   1461: {
                   1462:        register int    rtn;
                   1463: 
                   1464:        D(printf("SK %x ", cylno));
                   1465:        rbskrate(uip, uip->d_drtab.dr_type);/* set transfer rate */
                   1466:        if(rtn = fdc_sts(FD_OSTS, uip))         /* status check */
                   1467:                goto fdiend;
                   1468:        outb(DATAREG(uip->addr), SEEKCMD);      /* seek command */
                   1469:        if(rtn = fdc_sts(FD_OSTS, uip))         /* status check */
                   1470:                goto fdiend;
                   1471:        outb(DATAREG(uip->addr), uip->dev->slave);      /* drive number */
                   1472:        if(rtn = fdc_sts(FD_OSTS, uip))         /* status check */
                   1473:                goto fdiend;
                   1474:        uip->b_seekaddr = cylno;
                   1475:        if(uip->d_drtab.dr_type&DOUBLE)
                   1476:                cylno = cylno * 2;
                   1477:        uip->b_cmd->c_intr |= SKFLAG;
                   1478:        outb(DATAREG(uip->addr), cylno);        /* seek count */
                   1479: fdiend:        
                   1480:        if(rtn)
                   1481:                rtn |= SEEKCMD<<8;
                   1482:        return(rtn);
                   1483: }
                   1484: /*****************************************************************************
                   1485:  *
                   1486:  *     recalibrate command routine(use interrupt)
                   1487:  *
                   1488:  *****************************************************************************/
                   1489: rbirate(uip)
                   1490: struct unit_info *uip;
                   1491: {
                   1492:        register int    rtn;
                   1493: 
                   1494:        rbskrate(uip, uip->d_drtab.dr_type);/* set transfer rate */
                   1495:        if(!(rtn = fdc_sts(FD_OSTS, uip))) {            /* status check */
                   1496:                /* recalibrate command */
                   1497:                outb(DATAREG(uip->addr), RBCMD);
                   1498:                if(!(rtn = fdc_sts(FD_OSTS, uip))) {    /* status check */
                   1499:                        uip->b_cmd->c_intr |= RBFLAG;
                   1500:                        outb(DATAREG(uip->addr), uip->dev->slave);
                   1501:                }
                   1502:        }
                   1503:        return(rtn ? rtn|RBCMD<<8 : 0);
                   1504: }
                   1505: /*****************************************************************************
                   1506:  *
                   1507:  *     read / write / format / verify command out routine(use interrupt)
                   1508:  *
                   1509:  *****************************************************************************/
                   1510: outicmd(uip)
                   1511: struct unit_info *uip;
                   1512: {
                   1513:        int                     rtn;
                   1514:        register int            *data,cnt0,dmalen;
                   1515:        register long           address;
                   1516:        struct ctrl_info        *cip = &ctrl_info[uip->dev->ctlr];
                   1517:        struct fdcmd            *cmdp = uip->b_cmd;
                   1518:        spl_t                    x = splhi();
                   1519: 
                   1520:        outb(DMACMD1,DMADATA0); /* DMA #1 command register      */
                   1521:        outb(DMAMSK1,DMADATA1); /* DMA #1 all mask register     */
                   1522:        /* Perhaps outb(0x0a,0x02); might work better on line above? */
                   1523:        switch(cmdp->c_rwdata[0]){
                   1524:        case RDM:
                   1525:                D(printf("RDM"));
                   1526:                outb(DMABPFF,DMARD);
                   1527:                outb(DMAMODE,DMARD);
                   1528:                break;
                   1529:        case WTM:
                   1530:        case FMTM:
                   1531:                D(printf("W"));
                   1532:                outb(DMABPFF,DMAWT);
                   1533:                outb(DMAMODE,DMAWT);
                   1534:                break;
                   1535:        case RDMV:
                   1536:                D(printf("RDMV"));
                   1537:                outb(DMABPFF,DMAVRF);
                   1538:                outb(DMAMODE,DMAVRF);
                   1539:        }
                   1540:        /* get work buffer physical address */
                   1541:        address = kvtophys(cip->b_xferaddr);
                   1542:        dmalen = i386_trunc_page(address) + I386_PGBYTES - address;
                   1543:        if ( (cip->b_rwerr&MRMASK) >= 0x10)
                   1544:                dmalen = 0x200;
                   1545:        if (dmalen<=cip->b_xferdma) 
                   1546:                cip->b_xferdma = dmalen;
                   1547:        else
                   1548:                dmalen = cip->b_xferdma;
                   1549:        if (address >= FdDmaThreshold) {
                   1550:                DD(printf(">(%x[%x], %x[%x] L%x\n",
                   1551:                        address, cip->b_pbuf,
                   1552:                        cip->b_xferaddr, cip->b_vbuf, dmalen));
                   1553:                if (!FdDmaEISA) {
                   1554:                        cip->usebuf = 1;
                   1555:                        address = (long)cip->b_pbuf;
                   1556:                        if (cmdp->c_rwdata[0] == WTM || cmdp->c_rwdata[0] == FMTM) {
                   1557:                                bcopy(cip->b_xferaddr, cip->b_vbuf, dmalen);
                   1558:                                DD(printf("W(%x, %x, %x)\n",
                   1559:                                        cip->b_xferaddr, cip->b_vbuf, dmalen));
                   1560:                        }
                   1561:                } else
                   1562:                        cip->usebuf = 0;
                   1563:        } else
                   1564:                cip->usebuf = 0;
                   1565:        D(printf(" %x L%x ", address, dmalen));
                   1566:        /* set buffer address */
                   1567:        outb(DMAADDR,(int)address&BYTEMASK);
                   1568:        outb(DMAADDR,(((int)address>>8)&BYTEMASK));
                   1569:        outb(DMAPAGE,(((int)address>>16)&BYTEMASK));
                   1570:        if (FdDmaEISA)
                   1571:                outb(FdDmaEISA+DMAPAGE-0x80,(((int)address>>24)&BYTEMASK));
                   1572:        /* set transfer count */
                   1573:        outb(DMACNT,(--dmalen)&BYTEMASK);
                   1574:        outb(DMACNT,((dmalen>>8)&BYTEMASK));
                   1575:        outb(DMAMSK,CHANNEL2);
                   1576:        splx(x);
                   1577:        trfrate(uip, uip->d_drtab.dr_type);     /* set transfer rate */
                   1578:        data = &cmdp->c_rwdata[0];
                   1579:        for(cnt0 = 0; cnt0<cmdp->c_dcount; cnt0++,data++){
                   1580:                if(rtn = fdc_sts(FD_OSTS, uip)) /*status check*/
                   1581:                        break;
                   1582:                outb(DATAREG(uip->addr), *data);
                   1583:        }
                   1584:        if(!rtn){
                   1585:                cmdp->c_intr |= RWFLAG;
                   1586:                cmdp->c_stsflag |= INTROUT;
                   1587:                cnt0 = ((cip->b_buf->b_flags&(B_READ|B_VERIFY)) ==
                   1588:                        (B_READ|B_VERIFY))?TOUT:ITOUT;
                   1589: #ifdef MACH_KERNEL
                   1590:                timeout(fdintr,uip->dev->ctlr,cnt0);
                   1591: #else  MACH_KERNEL
                   1592:                cmdp->c_timeid = timeout(fdintr,uip->dev->ctlr,cnt0);
                   1593: #endif MACH_KERNEL
                   1594:        }
                   1595:        return(rtn);
                   1596: }
                   1597: /*****************************************************************************
                   1598:  *
                   1599:  *     sense interrupt status routine
                   1600:  *
                   1601:  *****************************************************************************/
                   1602: sis(uip)
                   1603: struct unit_info *uip;
                   1604: {
                   1605:        register int    rtn, st0;
                   1606: 
                   1607:        if(rtn = fdc_sts(FD_OSTS, uip)) /* status check */
                   1608:                return(rtn);
                   1609:        outb(DATAREG(uip->addr), SISCMD);
                   1610:        if(rtn = fdc_sts(FD_ISTS, uip)) /* status check */
                   1611:                return(rtn);
                   1612:        st0 = inb(DATAREG(uip->addr)) & ST0OK;  /* get st0 */
                   1613:        if(rtn = fdc_sts(FD_ISTS, uip)) /* status check */
                   1614:                return(rtn);
                   1615:        inb(DATAREG(uip->addr));        /* get pcn */
                   1616:        if (st0&(ST0AT|ST0IC))
                   1617:                st0 = FDCERR;
                   1618:        return(st0);
                   1619: }
                   1620: 
                   1621: /*****************************************************************************
                   1622:  *
                   1623:  *     fdc status get routine
                   1624:  *
                   1625:  *****************************************************************************/
                   1626: fdc_sts(mode, uip)
                   1627: register int   mode;
                   1628: struct unit_info *uip;
                   1629: {
                   1630:        register int    ind;
                   1631:        int             cnt0 = STSCHKCNT;
                   1632: 
                   1633:        while(cnt0--)
                   1634:                if(((ind=inb(STSREG(uip->addr))) & DATAOK) && 
                   1635:                   ((ind & DTOCPU) == mode))
                   1636:                        return(0);
                   1637:        return(TIMEOUT);
                   1638: }
                   1639: /*****************************************************************************
                   1640:  *
                   1641:  *     motor on routine
                   1642:  *
                   1643:  *****************************************************************************/
                   1644: mtr_on(uip)
                   1645: struct unit_info *uip;
                   1646: {
                   1647:        extern          int(mtr_off)();
                   1648:        extern          int(wakeup)();
                   1649:        struct  fdcmd   *cmdp = uip->b_cmd;
                   1650: 
                   1651:        if(!(mtr_start(uip))){
                   1652:                timeout(wakeup,&cmdp->c_stsflag,HZ);
                   1653:                sleep(&cmdp->c_stsflag,PZERO);
                   1654:        }
                   1655:        cmdp->c_stsflag |= MTROFF;
                   1656: #ifdef MACH_KERNEL
                   1657:        timeout(mtr_off,uip,MTRSTOP);
                   1658: #else  MACH_KERNEL
                   1659:        cmdp->c_mtrid = timeout(mtr_off,uip,MTRSTOP);
                   1660: #endif MACH_KERNEL
                   1661: }
                   1662: /*****************************************************************************
                   1663:  *
                   1664:  *     motor start routine
                   1665:  *
                   1666:  *****************************************************************************/
                   1667: mtr_start(uip)
                   1668: struct unit_info *uip;
                   1669: {
                   1670:        int             status;
                   1671:        int             (mtr_off)();
                   1672:        struct  fdcmd   *cmdp = uip->b_cmd;
                   1673:        int             slave = uip->dev->slave;
                   1674:        if(cmdp->c_stsflag & MTROFF){
                   1675:                untimeout(mtr_off, uip);
                   1676:                cmdp->c_stsflag &= ~MTROFF;
                   1677:        }
                   1678:        status = cmdp->c_rbmtr&(1<<slave);
                   1679:        cmdp->c_rbmtr |= (1<<slave);
                   1680:        outb(CTRLREG(uip->addr), ((cmdp->c_rbmtr&MTRMASK)<<MTR_ON)|
                   1681:                                     FDC_RST|slave|DMAREQ);
                   1682:        return(status);
                   1683: }
                   1684: /*****************************************************************************
                   1685:  *
                   1686:  *     motor off routine
                   1687:  *
                   1688:  *****************************************************************************/
                   1689: mtr_off(uip)
                   1690: struct unit_info *uip;
                   1691: {
                   1692:        struct  fdcmd   *cmdp = uip->b_cmd;
                   1693: 
                   1694:        cmdp->c_stsflag &= ~MTROFF;
                   1695:        if(!(cmdp->c_stsflag&MTRFLAG)){
                   1696:                cmdp->c_rbmtr &= MTRRST;
                   1697:                outb(CTRLREG(uip->addr), FDC_RST | DMAREQ);
                   1698:        }
                   1699: }
                   1700: 
                   1701: #endif

unix.superglobalmegacorp.com

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