Annotation of coherent/d/286_KERNEL/USRSRC/io/st.c, revision 1.1

1.1     ! root        1: /* (-lgl
        !             2:  *     COHERENT Driver Kit Version 1.1.0
        !             3:  *     Copyright (c) 1982, 1990 by Mark Williams Company.
        !             4:  *     All rights reserved. May not be copied without permission.
        !             5:  -lgl) */
        !             6: /*
        !             7:  * This is a driver for the
        !             8:  * Archive SC-400 Series Tape Controller.
        !             9:  */
        !            10: #include       <sys/coherent.h>
        !            11: #include       <sys/buf.h>
        !            12: #include       <sys/con.h>
        !            13: #include       <sys/const.h>
        !            14: #include       <sys/devices.h>
        !            15: #include       <sys/inode.h>
        !            16: #include       <sys/mtioctl.h>
        !            17: #include       <sys/sched.h>
        !            18: #include       <sys/seg.h>
        !            19: #include       <sys/stat.h>
        !            20: #include       <sys/uproc.h>
        !            21: #include       <errno.h>
        !            22: 
        !            23: /*
        !            24:  * Fixed parameters.
        !            25:  */
        !            26: #define        NCMDS   8                       /* Max # chained commands */
        !            27: 
        !            28: /*
        !            29:  * Configurable parameters
        !            30:  */
        !            31: int    STIRQ   = 3;                    /* IRQ Level 3 */
        !            32: int    STPORT  = 0x200;                /* I/O Port    */
        !            33: int    STDMA   = 1;                    /* DMA Channel */
        !            34: 
        !            35: #define        BIT(n)          (1 << (n))
        !            36: 
        !            37: /*
        !            38:  * Forward referenced functions.
        !            39:  */
        !            40: void   stcache();
        !            41: void   stflush();
        !            42: void   stinvoke();
        !            43: void   ststart();
        !            44: void   stintr();
        !            45: void   strecov();
        !            46: void   stnext();
        !            47: void   stdiag();
        !            48: void   stspin();
        !            49: 
        !            50: /*
        !            51:  * Driver configuration.
        !            52:  */
        !            53: int    stload();
        !            54: int    stuload();
        !            55: int    stopen();
        !            56: int    stclose();
        !            57: int    stread();
        !            58: int    stwrite();
        !            59: int    stioctl();
        !            60: void   stwatch();
        !            61: int    nulldev();
        !            62: int    nonedev();
        !            63: 
        !            64: CON    stcon   = {
        !            65:        DFCHR,                          /* Flags        */
        !            66:        ST_MAJOR,                               /* Major index  */
        !            67:        stopen,                         /* Open         */
        !            68:        stclose,                        /* Close        */
        !            69:        nonedev,                        /* Block        */
        !            70:        stread,                         /* Read         */
        !            71:        stwrite,                        /* Write        */
        !            72:        stioctl,                        /* Ioctl        */
        !            73:        nulldev,                        /* Powerfail    */
        !            74:        stwatch,                        /* Timeout      */
        !            75:        stload,                         /* Load         */
        !            76:        stuload                         /* Unload       */
        !            77: };
        !            78: 
        !            79: /*
        !            80:  * I/O Port Addresses
        !            81:  */
        !            82: #define        DATA_REG        (STPORT+0)      /* Data register */
        !            83: #define        CTRL_REG        (STPORT+1)      /* Control/Status register */
        !            84: #define        DMAGO_REG       (STPORT+2)      /* DMA Go register */
        !            85: #define        DMARST_REG      (STPORT+3)      /* DMA reset register */
        !            86: 
        !            87: /*
        !            88:  * Control Register
        !            89:  */
        !            90: #define        CR_RSTSAC       BIT(7)          /* 1 -> reset control micro     */
        !            91: #define        CR_REQ          BIT(6)          /* 1 -> request to LSI chip     */
        !            92: #define        CR_IEN          BIT(5)          /* 1 -> enables interrupts      */
        !            93: #define        CR_DNIEN        BIT(4)          /* 1 -> enable DONE interrupts  */
        !            94: 
        !            95: /*
        !            96:  * Status Register
        !            97:  */
        !            98: #define        SR_IRQF         BIT(7)          /* 1 -> Interrupt Request Flag  */
        !            99: #define        SR_NRDY         BIT(6)          /* 0 -> Ready                   */
        !           100: #define        SR_NEXC         BIT(5)          /* 0 -> Exception               */
        !           101: #define        SR_DONE         BIT(4)          /* 1 -> DMA Done                */
        !           102: #define        SR_TO_PC        BIT(3)          /* 1 -> Direction is to PC      */
        !           103: 
        !           104: /*
        !           105:  * Controller Commands.
        !           106:  */
        !           107: #define        CC_SELECT       0x01            /* Select Drive 0               */
        !           108: #define        CC_LOCK         0x11            /* Select Drive 0 and Lock      */
        !           109: #define        CC_BOT          0x21            /* Rewind to beginning of tape  */
        !           110: #define        CC_ERASE        0x22            /* Completely erase cartridge   */
        !           111: #define        CC_TENSION      0x24            /* Wind tape to BOT, EOT, BOT   */
        !           112: #define        CC_AUTO         0x25            /* Select auto-initialization   */
        !           113: #define        CC_QIC11        0x26            /* Select QIC-11 media format   */
        !           114: #define        CC_QIC24        0x27            /* Select QIC-24 media format   */
        !           115: #define        CC_WRITE        0x40            /* Write to tape                */
        !           116: #define        CC_WFM          0x60            /* Write file mark              */
        !           117: #define        CC_READ         0x80            /* Read from tape               */
        !           118: #define        CC_RFM          0xA0            /* Skip past next file mark     */
        !           119: #define        CC_SENSE        0xC0            /* Read controller status       */
        !           120: 
        !           121: /*
        !           122:  * Sense Status Bytes 0 and 1.
        !           123:  */
        !           124: #define        SS0_FIL         BIT(0)          /* File Mark Detected           */
        !           125: #define        SS0_BNL         BIT(1)          /* Bad Block Not located        */
        !           126: #define        SS0_UDA         BIT(2)          /* Unrecoverable data error     */
        !           127: #define        SS0_EOM         BIT(3)          /* End of media                 */
        !           128: #define        SS0_WRP         BIT(4)          /* Write Protected Cartridge    */
        !           129: #define        SS0_USL         BIT(5)          /* Unselected Drive             */
        !           130: #define        SS0_CNI         BIT(6)          /* Cartridge Not In Place       */
        !           131: #define        SS0_ERR         (SS0_BNL+SS0_UDA+SS0_USL+SS0_CNI)
        !           132: 
        !           133: #define        SS1_POR         BIT(0)          /* Power on Reset Occurred      */
        !           134: #define        SS1_BOM         BIT(3)          /* Beginning of media           */
        !           135: #define        SS1_MBD         BIT(4)          /* Marginal Block Detected      */
        !           136: #define        SS1_NDT         BIT(5)          /* No Data Detected             */
        !           137: #define        SS1_ILL         BIT(6)          /* Illegal Command              */
        !           138: #define        SS1_ERR         (SS1_NDT+SS1_ILL)
        !           139: 
        !           140: /*
        !           141:  * Device States.
        !           142:  */
        !           143: #define        SDEAD   0               /* controller not found    */
        !           144: #define        SIDLE   1               /* controller idle         */
        !           145: #define        SCMD    2               /* initiating command      */
        !           146: #define        SRUN    3               /* performing command      */
        !           147: #define        SRDWR   4               /* starting read/write     */
        !           148: #define        SBLOCK  5               /* performing read/write   */
        !           149: #define        SBLEND  6               /* concluding block i/o    */
        !           150: #define        SSENSE  7               /* reading status bytes    */
        !           151: #define        SSDONE  8               /* concluding status sense */
        !           152: 
        !           153: /*
        !           154:  * Driver State Information.
        !           155:  */
        !           156: struct st_s {
        !           157:        int     st_state;
        !           158:        int     st_mode;                /* IPR or IPW                   */
        !           159:        int     st_iocmd;               /* CC_READ or CC_WRITE          */
        !           160:        int     st_cmd;                 /* last command executed        */
        !           161:        int     st_cmds[NCMDS];         /* list of chained commands     */
        !           162:        int     st_ncmds;               /* num of chained commands      */
        !           163:        int     st_iswr;
        !           164:        int     st_wasio;
        !           165:        int     st_iseof;
        !           166:        int     st_error;
        !           167:        paddr_t st_paddr;
        !           168:        fsize_t st_resid;
        !           169:        fsize_t st_size;
        !           170:        saddr_t st_sel;
        !           171:        SEG *   st_seg;
        !           172:        char    st_status[6];
        !           173:        int     st_nstat;
        !           174:        int     st_rdys;                /* number of ready watchdogs    */
        !           175:        int     st_nlost;               /* number of lost interrupts    */
        !           176: } st;
        !           177: 
        !           178: /**
        !           179:  *
        !           180:  * void
        !           181:  * stload()            -- initialize tape device
        !           182:  *
        !           183:  *     Action: Reset tape controller and drive.
        !           184:  *             Seize tape interrupt vector.
        !           185:  *
        !           186:  *     Note:   If the tape controller is present and operational,
        !           187:  *             a interrupt will occur and set st.st_state to SIDLE.
        !           188:  */
        !           189: static
        !           190: stload()
        !           191: {
        !           192:        /*
        !           193:         * Paranoia - Turn off DMA.
        !           194:         * Should already be turned off.
        !           195:         */
        !           196:        dmaoff( STDMA );
        !           197: 
        !           198:        /*
        !           199:         * Reset tape controller and drive
        !           200:         */
        !           201:        outb( CTRL_REG, CR_RSTSAC );
        !           202: 
        !           203:        /*
        !           204:         * Wait at least 25 microseconds
        !           205:         */
        !           206:        stspin( 25 );
        !           207: 
        !           208:        /*
        !           209:         * Terminate reset condition
        !           210:         */
        !           211:        outb( CTRL_REG, CR_IEN );
        !           212: 
        !           213:        /*
        !           214:         * Seize tape interrupt vector.
        !           215:         */
        !           216:        setivec( STIRQ, &stintr );
        !           217: }
        !           218: 
        !           219: /**
        !           220:  *
        !           221:  * stuload( dev )              -- Unload tape device.
        !           222:  * dev_t dev;
        !           223:  */
        !           224: stuload( dev )
        !           225: dev_t dev;
        !           226: {
        !           227:        /*
        !           228:         * Turn off DMA.
        !           229:         */
        !           230:        dmaoff( STDMA );
        !           231: 
        !           232:        /*
        !           233:         * Release tape interrupt vector.
        !           234:         */
        !           235:        clrivec( STIRQ );
        !           236: 
        !           237:        /*
        !           238:         * Disable tape interrupts.
        !           239:         */
        !           240:        outb( CTRL_REG, 0 );
        !           241: }
        !           242: 
        !           243: /**
        !           244:  *
        !           245:  * stopen( dev, mode )         -- open tape device
        !           246:  * dev_t dev;
        !           247:  * int mode;
        !           248:  *
        !           249:  *     Input:  dev  = tape device to be opened.
        !           250:  *             mode = desired access mode.
        !           251:  *
        !           252:  *     Action: Refuse access if tape drive does not exist or is in use.
        !           253:  *             Refuse simultaneous read and write access.
        !           254:  *             Refuse access if cartridge is not inserted in tape drive.
        !           255:  *             Refuse write access to a write protected cartridge.
        !           256:  *             Allocate tape cache.
        !           257:  *             Initialize device state.
        !           258:  *             Lock tape cartridge.
        !           259:  */
        !           260: static
        !           261: stopen( dev, mode )
        !           262: register dev_t dev;
        !           263: register int   mode;
        !           264: {
        !           265:        int s;
        !           266: 
        !           267:        /*
        !           268:         * Refuse access if no tape drive.
        !           269:         */
        !           270:        if ( st.st_state == SDEAD ) {
        !           271:                u.u_error = ENXIO;
        !           272:                return;
        !           273:        }
        !           274: 
        !           275:        /*
        !           276:         * Refuse access if tape drive is already open.
        !           277:         */
        !           278:        if ( st.st_mode != 0 ) {
        !           279:                u.u_error = EDBUSY;
        !           280:                return;
        !           281:        }
        !           282: 
        !           283:        /*
        !           284:         * Access must be read-only or write-only.
        !           285:         */
        !           286:        if ( (mode != IPR) && (mode != IPW) ) {
        !           287:                u.u_error = EINVAL;
        !           288:                return;
        !           289:        }
        !           290: 
        !           291:        /*
        !           292:         * Wait for tape drive to become idle.
        !           293:         */
        !           294:        if ( stwait() < 0 ) {
        !           295:                u.u_error = EINTR;
        !           296:                return;
        !           297:        }
        !           298: 
        !           299:        /*
        !           300:         * Initialize tape interface.
        !           301:         */
        !           302:        s = sphi();
        !           303:        outb( DMARST_REG, 0 );
        !           304:        outb( CTRL_REG, CR_IEN );
        !           305:        spl( s );
        !           306: 
        !           307:        /*
        !           308:         * Obtain tape status.
        !           309:         */
        !           310:        stinvoke( CC_SENSE );
        !           311: 
        !           312:        /*
        !           313:         * Wait for tape status.
        !           314:         */
        !           315:        if ( stwait() < 0 ) {
        !           316:                u.u_error = EINTR;
        !           317:                return;
        !           318:        }
        !           319: 
        !           320:        /*
        !           321:         * Refuse access if no cartridge.
        !           322:         */
        !           323:        if ( st.st_status[0] & (SS0_CNI|SS0_USL) ) {
        !           324:                u.u_error = EDATTN;
        !           325:                return;
        !           326:        }
        !           327: 
        !           328:        /*
        !           329:         * Refuse write access to a write protected cartridge.
        !           330:         */
        !           331:        if ( (mode == IPW) && (st.st_status[0] & SS0_WRP) ) {
        !           332:                u.u_error = EROFS;
        !           333:                return;
        !           334:        }
        !           335: 
        !           336:        /*
        !           337:         * Calculate desired cache size in Kbytes.
        !           338:         */
        !           339:        st.st_size = minor(dev) & ~0x80;
        !           340:        if ( st.st_size == 0 )
        !           341:                st.st_size = 256;
        !           342: 
        !           343:        /*
        !           344:         * Allocate cache
        !           345:         */
        !           346:        for ( st.st_size *= 1024; st.st_size != 0; st.st_size -= 1024 )
        !           347:                if ( st.st_seg = salloc( st.st_size, SFSYST|SFNSWP|SFNCLR ) )
        !           348:                        break;
        !           349: 
        !           350:        /*
        !           351:         * Refuse access if couldn't allocate cache.
        !           352:         */
        !           353:        if ( st.st_seg == 0 ) {
        !           354:                u.u_error = ENOMEM;
        !           355:                return;
        !           356:        };
        !           357: 
        !           358:        /*
        !           359:         * Initialize device state.
        !           360:         */
        !           361:        st.st_sel   = FP_SEL(st.st_seg->s_faddr);
        !           362:        st.st_iswr  = (mode == IPW);
        !           363:        st.st_paddr = st.st_seg->s_paddr;
        !           364:        st.st_resid = (mode == IPW) ? st.st_size : 0 ;
        !           365:        st.st_iocmd = (mode == IPW) ? CC_WRITE : CC_READ ;
        !           366:        st.st_mode  = mode;
        !           367:        st.st_iseof = 0;
        !           368:        st.st_wasio = 0;
        !           369:        st.st_error = 0;
        !           370:        st.st_rdys  = 0;
        !           371:        st.st_nlost = 0;
        !           372: 
        !           373:        /*
        !           374:         * Lock cartridge if at beginning of media.
        !           375:         */
        !           376:        if ( st.st_status[1] & SS1_BOM )
        !           377:                stinvoke( CC_LOCK );
        !           378: }
        !           379: 
        !           380: /**
        !           381:  *
        !           382:  * stclose( dev, mode )                -- close tape device
        !           383:  * dev_t dev;
        !           384:  * int mode;
        !           385:  *
        !           386:  *     Input:  dev  = tape device to be closed.
        !           387:  *             mode = access mode.
        !           388:  *
        !           389:  *     Action: If access mode was for writing, flush the tape cache.
        !           390:  *             If data was written to tape, write a file mark.
        !           391:  *             If data was read from tape on the non rewinding device,
        !           392:  *             read until end of file or an error is encountered.
        !           393:  *             Rewind the tape if the rewinding device is open.
        !           394:  *             Unlock the tape cartridge.
        !           395:  *             Clear tape state and release tape cache memory.
        !           396:  */
        !           397: static
        !           398: stclose( dev, mode )
        !           399: register dev_t dev;
        !           400: {
        !           401:        /*
        !           402:         * Check if tape was opened for writing.
        !           403:         */
        !           404:        if ( st.st_iswr ) {
        !           405: 
        !           406:                /*
        !           407:                 * Flush the tape cache.
        !           408:                 */
        !           409:                stflush();
        !           410: 
        !           411:                /*
        !           412:                 * Write a file mark if data was written to tape.
        !           413:                 */
        !           414:                if ( st.st_wasio )
        !           415:                        stinvoke( CC_WFM );
        !           416:        }
        !           417: 
        !           418:        /*
        !           419:         * Check if non-rewinding device was opened for reading.
        !           420:         */
        !           421:        else if ( st.st_wasio && (dev & 0x80 ) ) {
        !           422: 
        !           423:                /*
        !           424:                 * Read file mark if not just past one.
        !           425:                 */
        !           426:                if ( (st.st_status[0] & SS0_FIL) == 0 )
        !           427:                        stinvoke( CC_RFM );
        !           428:        }
        !           429: 
        !           430:        /*
        !           431:         * Rewinding device.
        !           432:         */
        !           433:        if ( (dev & 0x80) == 0 ) {
        !           434: 
        !           435:                /*
        !           436:                 * Wait for controller to idle.
        !           437:                 */
        !           438:                while ( stwait() < 0 )
        !           439:                        ;
        !           440: 
        !           441:                /*
        !           442:                 * Initiate rewind.
        !           443:                 */
        !           444:                stinvoke( CC_BOT   );
        !           445: 
        !           446:                /*
        !           447:                 * Unlock the drive [turn off the light].
        !           448:                 */
        !           449:                stinvoke( CC_SELECT );
        !           450:        }
        !           451: 
        !           452:        /*
        !           453:         * Clear tape state, releasing tape cache.
        !           454:         */
        !           455:        sfree( st.st_seg );
        !           456:        st.st_seg  = 0;
        !           457:        st.st_mode = 0;
        !           458: }
        !           459: 
        !           460: /**
        !           461:  *
        !           462:  * stread( dev, iop )  -- tape device read
        !           463:  * dev_t dev;
        !           464:  * IO * iop;
        !           465:  *
        !           466:  *     Input:  dev = tape device to be read from.
        !           467:  *             iop = pointer to IO structure.
        !           468:  *
        !           469:  *     Action: Transfer data from tape cache to user memory,
        !           470:  *             filling the cache as required by initiating reads from tape.
        !           471:  */
        !           472: 
        !           473: static
        !           474: stread( dev, iop )
        !           475: dev_t  dev;
        !           476: register IO * iop;
        !           477: {
        !           478:        register int n;
        !           479:        register int ioc;
        !           480: 
        !           481:        ioc = iop->io_ioc;
        !           482:        
        !           483:        while ( iop->io_ioc > 0 ) {
        !           484: 
        !           485:                /*
        !           486:                 * Check for empty cache.
        !           487:                 */
        !           488:                while ( st.st_resid == 0 ) {
        !           489: 
        !           490:                        /*
        !           491:                         * Special handling if end of file was encountered.
        !           492:                         */
        !           493:                        if ( st.st_iseof ) {
        !           494: 
        !           495:                                /*
        !           496:                                 * Clear EOF if no data was transferred yet.
        !           497:                                 */
        !           498:                                if ( ioc == iop->io_ioc )
        !           499:                                        st.st_iseof = 0;
        !           500: 
        !           501:                                return;
        !           502:                        }
        !           503: 
        !           504:                        /*
        !           505:                         * Abort on I/O error.
        !           506:                         */
        !           507:                        if ( u.u_error = st.st_error ) {
        !           508:                                stdiag();
        !           509:                                return;
        !           510:                        }
        !           511: 
        !           512:                        /*
        !           513:                         * Fill the cache from tape.
        !           514:                         */
        !           515:                        stcache();
        !           516:                }
        !           517: 
        !           518:                /*
        !           519:                 * Determine max data transferable in one chunk.
        !           520:                 */
        !           521:                n = iop->io_ioc;
        !           522:                if ( n > st.st_resid )
        !           523:                        n = st.st_resid;
        !           524: 
        !           525:                /*
        !           526:                 * Transfer some data from cache to user memory.
        !           527:                 */
        !           528:                if ( pucopy( st.st_paddr, iop->io_base, n ) != n )
        !           529:                        return;
        !           530: 
        !           531:                /*
        !           532:                 * Update addresses and counts.
        !           533:                 */
        !           534:                iop->io_base += n;
        !           535:                iop->io_ioc  -= n;
        !           536:                st.st_resid  -= n;
        !           537:                st.st_paddr  += n;
        !           538:        }
        !           539: }
        !           540: 
        !           541: /**
        !           542:  *
        !           543:  * stwrite( dev, iop ) -- write to tape device
        !           544:  * dev_t dev;
        !           545:  * IO * iop;
        !           546:  *
        !           547:  *     Input:  dev = tape device to be written to.
        !           548:  *             iop = pointer to IO structure.
        !           549:  *
        !           550:  *     Action: Transfer data from user memory to tape cache,
        !           551:  *             flushing the cache as required by initiating writes to tape.
        !           552:  */
        !           553: 
        !           554: static
        !           555: stwrite( dev, iop )
        !           556: dev_t  dev;
        !           557: register IO *iop;
        !           558: {
        !           559:        register int n;
        !           560: 
        !           561:        while ( iop->io_ioc > 0 ) {
        !           562: 
        !           563:                /*
        !           564:                 * Determine max data transferable in one chunk.
        !           565:                 */
        !           566:                n = iop->io_ioc;
        !           567:                if ( n > st.st_resid )
        !           568:                        n = st.st_resid;
        !           569: 
        !           570:                /*
        !           571:                 * Transfer some data from user memory to cache.
        !           572:                 */
        !           573:                if ( upcopy( iop->io_base, st.st_paddr, n ) != n )
        !           574:                        break;
        !           575: 
        !           576:                /*
        !           577:                 * Update addresses and counts.
        !           578:                 */
        !           579:                iop->io_base += n;
        !           580:                iop->io_ioc  -= n;
        !           581:                st.st_paddr  += n;
        !           582:                st.st_resid  -= n;
        !           583: 
        !           584:                /*
        !           585:                 * Flush the cache to tape if full.
        !           586:                 */
        !           587:                if ( st.st_resid == 0 )
        !           588:                        stflush();
        !           589: 
        !           590:                /*
        !           591:                 * Abort on I/O error.
        !           592:                 */
        !           593:                if ( u.u_error = st.st_error ) {
        !           594:                        stdiag();
        !           595:                        return;
        !           596:                }
        !           597:        }
        !           598: }
        !           599: 
        !           600: /**
        !           601:  *
        !           602:  * stioctl( dev, cmd, arg )    -- service tape I/O control requests
        !           603:  * int dev;
        !           604:  * int cmd;
        !           605:  * int arg;
        !           606:  *
        !           607:  *     Input:  dev = tape device to be serviced
        !           608:  *             cmd = ioctl command
        !           609:  *             arg = argument to ioctl command
        !           610:  *
        !           611:  *     Action: Service tape I/O control request.
        !           612:  */
        !           613: 
        !           614: static
        !           615: stioctl( dev, cmd, arg )
        !           616: {
        !           617:        if ( st.st_iswr )
        !           618:                stflush();
        !           619: 
        !           620:        st.st_error = EINVAL;
        !           621: 
        !           622:        switch ( cmd ) {
        !           623: 
        !           624:        case MTERASE:
        !           625:                stinvoke( CC_ERASE );
        !           626:                break;
        !           627: 
        !           628:        case MTTENSE:
        !           629:                stinvoke( CC_TENSION );
        !           630:                break;
        !           631: 
        !           632:        case MTREWIND:
        !           633:                if ( st.st_iswr && st.st_wasio ) {
        !           634:                        stinvoke( CC_WFM );
        !           635:                        st.st_wasio = 0;
        !           636:                }
        !           637:                stinvoke( CC_BOT );
        !           638:                break;
        !           639: 
        !           640:        case MTWEOF:
        !           641:                if ( st.st_iswr ) {
        !           642:                        stinvoke( CC_WFM );
        !           643:                        st.st_wasio = 0;
        !           644:                }
        !           645:                break;
        !           646: 
        !           647:        case MTFSKIP:
        !           648:                if ( ! st.st_iswr ) {
        !           649:                        if ( ! st.st_iseof )
        !           650:                                stinvoke( CC_RFM );
        !           651:                        st.st_iseof = 0;
        !           652:                        st.st_resid = 0;
        !           653:                }
        !           654:                break;
        !           655:        }
        !           656: 
        !           657:        /*
        !           658:         * Record tape error code.
        !           659:         */
        !           660:        u.u_error = st.st_error;
        !           661: }
        !           662: 
        !           663: /**
        !           664:  *
        !           665:  * void
        !           666:  * stcache()   -- read from tape into cache
        !           667:  *
        !           668:  *     Action: Read as much data as possible into the tape cache.
        !           669:  *             Set st.st_paddr to the cache address.
        !           670:  *             Set st.st_resid to the number of data bytes in the cache.
        !           671:  */
        !           672: static void
        !           673: stcache()
        !           674: {
        !           675:        /*
        !           676:         * Try to fill cache from tape.
        !           677:         */
        !           678:        st.st_paddr = st.st_seg->s_paddr;
        !           679:        st.st_resid = st.st_size;
        !           680:        ststart();
        !           681: 
        !           682:        /*
        !           683:         * Update cache information.
        !           684:         */
        !           685:        st.st_paddr = st.st_seg->s_paddr;
        !           686:        st.st_resid = st.st_size - st.st_resid;
        !           687: 
        !           688:        /*
        !           689:         * Clear the cache on I/O error.
        !           690:         */
        !           691:        if ( st.st_error )
        !           692:                st.st_resid = 0;
        !           693: }
        !           694: 
        !           695: /**
        !           696:  *
        !           697:  * void
        !           698:  * stflush()   -- flush cache to tape
        !           699:  *
        !           700:  *     Action: Ensure tape cache is block aligned.
        !           701:  *             Write cache to the tape.
        !           702:  *             Set st.st_paddr to the cache address.
        !           703:  *             Set st.st_resid to the number of cache bytes available.
        !           704:  */
        !           705: static void
        !           706: stflush()
        !           707: {
        !           708:        static char zc;
        !           709: 
        !           710:        /*
        !           711:         * Check for empty cache.
        !           712:         */
        !           713:        if ( st.st_resid == st.st_size )
        !           714:                return;
        !           715: 
        !           716:        /*
        !           717:         * Block align the cache.
        !           718:         */
        !           719:        while ( st.st_resid % BSIZE ) {
        !           720:                kpcopy( &zc, st.st_paddr, 1 );
        !           721:                st.st_paddr++;
        !           722:                st.st_resid--;
        !           723:        }
        !           724: 
        !           725:        /*
        !           726:         * Flush the cache to tape.
        !           727:         */
        !           728:        st.st_paddr = st.st_seg->s_paddr;
        !           729:        st.st_resid = st.st_size - st.st_resid;
        !           730:        ststart();
        !           731: 
        !           732:        /*
        !           733:         * Update cache information.
        !           734:         */
        !           735:        st.st_paddr = st.st_seg->s_paddr;
        !           736:        st.st_resid = st.st_size;
        !           737: }
        !           738: 
        !           739: /**
        !           740:  *
        !           741:  * void
        !           742:  * stinvoke()  -- start tape control operation
        !           743:  *
        !           744:  *     Action: Initiate tape control operation.
        !           745:  */
        !           746: static void
        !           747: stinvoke( cmd )
        !           748: int cmd;
        !           749: {
        !           750:        register int s;
        !           751: 
        !           752:        /*
        !           753:         * Disable interrupts.
        !           754:         */
        !           755:        s = sphi();
        !           756: 
        !           757:        /*
        !           758:         * Wait for controller to become idle.
        !           759:         */
        !           760:        while ( st.st_state != SIDLE ) {
        !           761: 
        !           762:                /*
        !           763:                 * Create chained command if possible.
        !           764:                 */
        !           765:                if ( st.st_ncmds < NCMDS ) {
        !           766:                        st.st_cmds[ st.st_ncmds++ ] = cmd;
        !           767:                        spl( s );
        !           768:                        return;
        !           769:                }
        !           770: 
        !           771:                sleep( &st, CVTTOUT, IVTTOUT, SVTTOUT );
        !           772:        }
        !           773: 
        !           774:        /*
        !           775:         * Setup for tape operation.
        !           776:         */
        !           777:        drvl[ST_MAJOR].d_time = 1;
        !           778:        st.st_state = SCMD;
        !           779:        st.st_error = 0;
        !           780:        st.st_rdys  = 0;
        !           781:        stspin( 100 );
        !           782: 
        !           783:        /*
        !           784:         * Request tape operation.
        !           785:         * Do NOT wait for results.
        !           786:         */
        !           787:        outb( DATA_REG, st.st_cmd = cmd );
        !           788:        outb( CTRL_REG, CR_IEN+CR_REQ );
        !           789: 
        !           790:        /*
        !           791:         * Enable interrupts.
        !           792:         */
        !           793:        spl( s );
        !           794: }
        !           795: 
        !           796: /**
        !           797:  *
        !           798:  * void
        !           799:  * ststart()   -- start tape read/write operation
        !           800:  *
        !           801:  *     Action: Initiate tape read/write operation.
        !           802:  *             Wait for tape operation to complete.
        !           803:  */
        !           804: static void
        !           805: ststart()
        !           806: {
        !           807:        register int s;
        !           808: 
        !           809:        /*
        !           810:         * Disable interrupts.
        !           811:         */
        !           812:        s = sphi();
        !           813: 
        !           814:        /*
        !           815:         * Wait for controller to become idle.
        !           816:         */
        !           817:        while ( st.st_state != SIDLE )
        !           818:                sleep( &st, CVTTOUT, IVTTOUT, SVTTOUT );
        !           819: 
        !           820:        /*
        !           821:         * Setup for tape read/write.
        !           822:         */
        !           823:        drvl[ST_MAJOR].d_time = 1;
        !           824:        st.st_state = SRDWR;
        !           825:        st.st_error = 0;
        !           826:        st.st_rdys  = 0;
        !           827:        stspin( 100 );
        !           828: 
        !           829:        /*
        !           830:         * Tape read/write was last command executed.
        !           831:         */
        !           832:        if ( st.st_cmd == st.st_iocmd ) {
        !           833:                /*
        !           834:                 * Resume tape i/o operation.
        !           835:                 * Simulate RDY interrupt.
        !           836:                 */
        !           837:                stintr();
        !           838:        }
        !           839:        else {
        !           840:                /*
        !           841:                 * Request tape operation.
        !           842:                 */
        !           843:                outb( DATA_REG, st.st_cmd = st.st_iocmd );
        !           844:                outb( CTRL_REG, CR_IEN+CR_REQ );
        !           845:        }
        !           846: 
        !           847:        /*
        !           848:         * Wait for tape operation to complete.
        !           849:         */
        !           850:        while ( st.st_state != SIDLE )
        !           851:                sleep( &st, CVTTOUT, IVTTOUT, SVTTOUT );
        !           852: 
        !           853:        /*
        !           854:         * Enable interrupts.
        !           855:         */
        !           856:        spl( s );
        !           857: }
        !           858: 
        !           859: /**
        !           860:  *
        !           861:  * void
        !           862:  * stintr()    -- tape interrupt handler
        !           863:  *
        !           864:  *     Action: Service tape interrupts.
        !           865:  *             Perform transitions to new tape states.
        !           866:  *             Wake sleeping processes if appropriate.
        !           867:  */
        !           868: static void
        !           869: stintr()
        !           870: {
        !           871:        register int csr;
        !           872:        register int s;
        !           873: 
        !           874:        s   = sphi();
        !           875:        csr = inb( CTRL_REG );
        !           876: 
        !           877:        /*
        !           878:         * Initiate exception recovery.
        !           879:         */
        !           880:        if ( (csr & SR_NEXC) == 0 ) {
        !           881:                strecov();
        !           882:                spl( s );
        !           883:                return;
        !           884:        }
        !           885: 
        !           886:        /*
        !           887:         * Clear ready watchdog count.
        !           888:         */
        !           889:        st.st_rdys = 0;
        !           890: 
        !           891:        /*
        !           892:         * Process normal operations.
        !           893:         */
        !           894:        switch ( st.st_state ) {
        !           895: 
        !           896:        case SCMD:
        !           897:                /*
        !           898:                 * Command has been acknowledged.
        !           899:                 * Wait for command completion.
        !           900:                 */
        !           901:                outb( CTRL_REG, CR_IEN );
        !           902:                st.st_state = (st.st_cmd == CC_SENSE) ? SSENSE : SRUN;
        !           903:                st.st_nstat = 0;
        !           904:                break;
        !           905: 
        !           906:        case SRUN:
        !           907:                /*
        !           908:                 * Command has completed.
        !           909:                 * Chain a sense status command if no other chained commands.
        !           910:                 */
        !           911:                if ( st.st_ncmds == 0 )
        !           912:                        st.st_cmds[ st.st_ncmds++ ] = CC_SENSE;
        !           913: 
        !           914:                /*
        !           915:                 * Initiate next chained command.
        !           916:                 */
        !           917:                stnext();
        !           918:                break;
        !           919: 
        !           920:        case SRDWR:
        !           921:                /*
        !           922:                 * Read/Write command had been acknowledged.
        !           923:                 * Clear tape request, enable done interrupt.
        !           924:                 */
        !           925:                outb( CTRL_REG, CR_IEN+CR_DNIEN );
        !           926: 
        !           927:                /*
        !           928:                 * Define direct memory access parameters.
        !           929:                 */
        !           930:                dmaon( STDMA, st.st_paddr, BSIZE, st.st_iswr );
        !           931: 
        !           932:                /*
        !           933:                 * If tape read command, wait for interface to switch direction
        !           934:                 */
        !           935:                if ( st.st_iocmd == CC_READ )
        !           936:                        while ( (inb(CTRL_REG) & SR_TO_PC) != SR_TO_PC )
        !           937:                                ;
        !           938: 
        !           939:                /*
        !           940:                 * Enable DMA transfer on tape interface and at DMA controller chip.
        !           941:                 */
        !           942:                st.st_state = SBLOCK;
        !           943:                outb( DMAGO_REG, 0 );
        !           944:                dmago( STDMA );
        !           945:                break;
        !           946: 
        !           947:        case SBLOCK:
        !           948:                /*
        !           949:                 * Perform Block I/O.
        !           950:                 * Ignore RDY interrupt, wait for [DMA] DONE interrupt.
        !           951:                 */
        !           952:                if ( (csr & SR_DONE) == 0 )
        !           953:                        break;
        !           954: 
        !           955:                /*
        !           956:                 * Turn off DMA.
        !           957:                 */
        !           958:                dmaoff( STDMA );
        !           959: 
        !           960:                /*
        !           961:                 * If more data remains to be transferred, reenable DMA.
        !           962:                 * NOTE: do -= BEFORE if() to avoid potential compiler bug.
        !           963:                 */
        !           964:                st.st_resid -= BSIZE;
        !           965:                if ( st.st_resid > 0 ) {
        !           966:                        st.st_paddr += BSIZE;
        !           967:                        dmaon( STDMA, st.st_paddr, BSIZE, st.st_iswr );
        !           968:                        outb( DMAGO_REG, 0 );
        !           969:                        dmago( STDMA );
        !           970:                        break;
        !           971:                }
        !           972: 
        !           973:                /*
        !           974:                 * Disable done interrupt.
        !           975:                 * Wait for I/O completion.
        !           976:                 */
        !           977:                outb( CTRL_REG, CR_IEN );
        !           978:                st.st_state = SBLEND;
        !           979:                break;
        !           980: 
        !           981:        case SBLEND:
        !           982:                /*
        !           983:                 * Completion of Block I/O.
        !           984:                 * Clear the file mark and beginning of media indicators.
        !           985:                 * Record the fact that data has been transferred.
        !           986:                 */
        !           987:                st.st_status[0] &= ~SS0_FIL;
        !           988:                st.st_status[1] &= ~SS1_BOM;
        !           989:                st.st_wasio = 1;
        !           990:                stnext();
        !           991:                break;
        !           992: 
        !           993:        case SSENSE:
        !           994:                /*
        !           995:                 * Sense Status Byte.
        !           996:                 * Wait for availability.
        !           997:                 */
        !           998:                do {
        !           999:                        csr = inb(CTRL_REG) & (SR_NRDY|SR_TO_PC);
        !          1000:                } while ( csr != SR_TO_PC );
        !          1001: 
        !          1002:                /*
        !          1003:                 * Save status byte.
        !          1004:                 */
        !          1005:                st.st_status[st.st_nstat] = inb(DATA_REG);
        !          1006: 
        !          1007:                /*
        !          1008:                 * Acknowledge reception.
        !          1009:                 * CR_REQ must be present for at least 20 microseconds.
        !          1010:                 */
        !          1011:                outb( CTRL_REG, CR_IEN+CR_REQ );
        !          1012:                stspin( 20 );
        !          1013:                outb( CTRL_REG, CR_IEN );
        !          1014: 
        !          1015:                /*
        !          1016:                 * Change state to status completion if all bytes saved.
        !          1017:                 */
        !          1018:                if ( ++(st.st_nstat) == 6 )
        !          1019:                        st.st_state = SSDONE;
        !          1020:                break;
        !          1021: 
        !          1022:        case SSDONE:
        !          1023:                /*
        !          1024:                 * Completion of Sense Status Command.
        !          1025:                 * Check for file mark.
        !          1026:                 */
        !          1027:                if ( st.st_status[0] & SS0_FIL ) {
        !          1028:                        outb( DMARST_REG, 0 );
        !          1029:                        st.st_iseof = 1;
        !          1030:                }
        !          1031: 
        !          1032:                /*
        !          1033:                 * Check for I/O error.
        !          1034:                 */
        !          1035:                else if ( (st.st_status[0] & SS0_ERR) ||
        !          1036:                          (st.st_status[1] & SS1_ERR) ) {
        !          1037:                        st.st_error = EIO;
        !          1038:                }
        !          1039: 
        !          1040:                /*
        !          1041:                 * Check for write protected cartridge.
        !          1042:                 */
        !          1043:                else if ( (st.st_iocmd == CC_WRITE) &&
        !          1044:                          (st.st_status[0] & SS0_WRP) ) {
        !          1045:                        st.st_error = EROFS;
        !          1046:                }
        !          1047: 
        !          1048:                stnext();
        !          1049:                break;
        !          1050:        }
        !          1051: 
        !          1052:        spl( s );
        !          1053: }
        !          1054: 
        !          1055: /**
        !          1056:  *
        !          1057:  * void
        !          1058:  * strecov()   -- initiate recovery from exception conditions
        !          1059:  *
        !          1060:  *     Action: Invoked when the tape controller asserts EXCEPTION.
        !          1061:  *             A sense status command is initiated to clear the exception.
        !          1062:  */
        !          1063: static void
        !          1064: strecov()
        !          1065: {
        !          1066:        /*
        !          1067:         * Ensure tape interface is idle.
        !          1068:         */
        !          1069:        outb( CTRL_REG, CR_IEN );
        !          1070:        stspin( 100 );
        !          1071: 
        !          1072:        /*
        !          1073:         * Turn off DMA on read/write exception.
        !          1074:         */
        !          1075:        if ( st.st_cmd == st.st_iocmd )
        !          1076:                dmaoff( STDMA );
        !          1077: 
        !          1078:        /*
        !          1079:         * Initiate sense status command.
        !          1080:         */
        !          1081:        outb( DATA_REG, st.st_cmd = CC_SENSE );
        !          1082:        outb( CTRL_REG, CR_IEN+CR_REQ );
        !          1083:        drvl[ST_MAJOR].d_time = 1;
        !          1084:        st.st_state = SCMD;
        !          1085:        st.st_error = 0;
        !          1086:        st.st_rdys  = 0;
        !          1087: }
        !          1088: 
        !          1089: /**
        !          1090:  *
        !          1091:  * static void
        !          1092:  * stnext()    -- initiate next chained command.
        !          1093:  */
        !          1094: static void
        !          1095: stnext()
        !          1096: {
        !          1097:        /*
        !          1098:         * Ensure tape interface is idle.
        !          1099:         */
        !          1100:        outb( CTRL_REG, CR_IEN );
        !          1101:        drvl[ST_MAJOR].d_time = 0;
        !          1102:        st.st_state = SIDLE;
        !          1103:        stspin( 100 );
        !          1104: 
        !          1105:        /*
        !          1106:         * Initiate a chained command.
        !          1107:         */
        !          1108:        if ( st.st_ncmds ) {
        !          1109:                outb( DATA_REG, st.st_cmd = st.st_cmds[ --st.st_ncmds ] );
        !          1110:                outb( CTRL_REG, CR_IEN+CR_REQ );
        !          1111:                drvl[ST_MAJOR].d_time = 1;
        !          1112:                st.st_state = SCMD;
        !          1113:                st.st_error = 0;
        !          1114:                st.st_rdys  = 0;
        !          1115:                return;
        !          1116:        }
        !          1117: 
        !          1118:        /*
        !          1119:         * Wake waiting processes.
        !          1120:         */
        !          1121:        wakeup( &st );
        !          1122: }
        !          1123: 
        !          1124: /**
        !          1125:  *
        !          1126:  * void
        !          1127:  * stwatch()   -- periodic [1 sec] watchdog
        !          1128:  *
        !          1129:  *     Action: If an exception condition exists, initate recovery actions.
        !          1130:  *             If ready condition exists for 1-2 seconds, simulate interrupt.
        !          1131:  *
        !          1132:  *     Notes:  If an exception condition occurs after a ready interrupt has
        !          1133:  *             been serviced, but before the ready condition is cleared,
        !          1134:  *             the exception interrupt will not occur, and is simulated here.
        !          1135:  */
        !          1136: static void
        !          1137: stwatch()
        !          1138: {
        !          1139:        register int csr;
        !          1140:        register int s;
        !          1141: 
        !          1142:        /*
        !          1143:         * Disable interrupts, preventing critical race with stintr().
        !          1144:         */
        !          1145:        s   = sphi();
        !          1146:        csr = inb(CTRL_REG);
        !          1147: 
        !          1148:        /*
        !          1149:         * Initiate recovery from exception conditions.
        !          1150:         */
        !          1151:        if ( (csr & SR_NEXC) == 0 )
        !          1152:                strecov();
        !          1153: 
        !          1154:        /*
        !          1155:         * Reset ready watchdog if not ready.
        !          1156:         */
        !          1157:        else if ( csr & SR_NRDY ) 
        !          1158:                st.st_rdys = 0;
        !          1159: 
        !          1160:        /*
        !          1161:         * Simulate lost ready interrupts after 2 seconds.
        !          1162:         */
        !          1163:        else if ( ++st.st_rdys >= 2 )
        !          1164:                stintr();
        !          1165: 
        !          1166:        /*
        !          1167:         * Enable interrupts.
        !          1168:         */
        !          1169:        spl( s );
        !          1170: }
        !          1171: 
        !          1172: /**
        !          1173:  * 
        !          1174:  * void
        !          1175:  * stdiag()    - Report tape status.
        !          1176:  *
        !          1177:  *     Action: Identify and report the highest priority tape error.
        !          1178:  *             There will normally only be one valid error present.
        !          1179:  *             The USL error can invalidate most remaining flags.
        !          1180:  *             The CNI error can invalidate cartridge related flags.
        !          1181:  *
        !          1182:  *     Notes:  Never called from interrupt level, but always from background.
        !          1183:  */
        !          1184: static void
        !          1185: stdiag()
        !          1186: {
        !          1187:        if ( st.st_status[0] & SS0_USL )
        !          1188:                printf( "st: Unselected Drive\n" );
        !          1189: 
        !          1190:        else if ( st.st_status[0] & SS0_CNI )
        !          1191:                printf( "st: Cartridge missing\n" );
        !          1192: 
        !          1193:        else if ( st.st_status[1] & SS1_NDT )
        !          1194:                printf( "st: No data detected\n" );
        !          1195: 
        !          1196:        else if ( st.st_status[0] & SS0_BNL )
        !          1197:                printf( "st: Bad block not located\n" );
        !          1198: 
        !          1199:        else if ( st.st_status[0] & SS0_UDA )
        !          1200:                printf( "st: Unrecoverable data error\n" );
        !          1201: 
        !          1202:        else if ( st.st_status[1] & SS1_ILL )
        !          1203:                printf( "st: Illegal command\n" );
        !          1204: 
        !          1205:        else
        !          1206:                printf( "st: %x\n", (st.st_status[1] << 8) + st.st_status[0] );
        !          1207: }
        !          1208: 
        !          1209: /**
        !          1210:  *
        !          1211:  * int
        !          1212:  * stwait()    -- wait for tape controller to idle.
        !          1213:  *
        !          1214:  *     Return: 0  = tape controller idle.
        !          1215:  *             -1 = signal received.
        !          1216:  */
        !          1217: static int
        !          1218: stwait()
        !          1219: {
        !          1220:        int s;
        !          1221: 
        !          1222:        s = sphi();
        !          1223:        while ( st.st_state != SIDLE ) {
        !          1224: 
        !          1225:                sleep( &st, CVTTOUT, IVTTOUT, SVTTOUT );
        !          1226: 
        !          1227:                if ( SELF->p_ssig ) {
        !          1228:                        spl( s );
        !          1229:                        return -1;
        !          1230:                }
        !          1231:        }
        !          1232:        spl( s );
        !          1233: 
        !          1234:        return 0;
        !          1235: }
        !          1236: 
        !          1237: /**
        !          1238:  *
        !          1239:  * void
        !          1240:  * stspin( usec )      -- delay execution
        !          1241:  * int usec;
        !          1242:  *
        !          1243:  *     Input:  usec = number of micro-seconds to delay.
        !          1244:  *
        !          1245:  *     Action: Wait at least 'usec' micro-seconds.
        !          1246:  *
        !          1247:  *     Notes:  Provides minimum delay required at times by tape controller.
        !          1248:  *             Should function properly up to at least 16 Mhz system clock.
        !          1249:  */
        !          1250: 
        !          1251: static void
        !          1252: stspin( usec )
        !          1253: register int usec;
        !          1254: {
        !          1255:        while ( --usec >= 0 )
        !          1256:                ;
        !          1257: }

unix.superglobalmegacorp.com

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