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

unix.superglobalmegacorp.com

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