Annotation of Net2/arch/i386/isa/wt.c, revision 1.1.1.3

1.1       root        1: /*-
                      2:  * Copyright (c) 1991 The Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. All advertising materials mentioning features or use of this software
                     14:  *    must display the following acknowledgement:
                     15:  *     This product includes software developed by the University of
                     16:  *     California, Berkeley and its contributors.
                     17:  * 4. Neither the name of the University nor the names of its contributors
                     18:  *    may be used to endorse or promote products derived from this software
                     19:  *    without specific prior written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     31:  * SUCH DAMAGE.
                     32:  *
                     33:  *     @(#)wt.c        7.1 (Berkeley) 5/9/91
                     34:  */
                     35: 
                     36: /*
                     37:  *
                     38:  * Copyright (c) 1989 Carnegie-Mellon University.
                     39:  * All rights reserved.
                     40:  *
                     41:  * Authors: Robert Baron
                     42:  * 
                     43:  * Permission to use, copy, modify and distribute this software and
                     44:  * its documentation is hereby granted, provided that both the copyright
                     45:  * notice and this permission notice appear in all copies of the
                     46:  * software, derivative works or modified versions, and any portions
                     47:  * thereof, and that both notices appear in supporting documentation.
                     48:  * 
                     49:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 
                     50:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 
                     51:  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     52:  * 
                     53:  * Carnegie Mellon requests users of this software to return to
                     54:  *
                     55:  *  Software Distribution Coordinator  or  [email protected]
                     56:  *  School of Computer Science
                     57:  *  Carnegie Mellon University
                     58:  *  Pittsburgh PA 15213-3890
                     59:  *
                     60:  * any improvements or extensions that they make and grant Carnegie the
                     61:  * rights to redistribute these changes.
                     62:  */
                     63: 
                     64: #include "wt.h"
                     65: #if NWT > 0
                     66: /* 
                     67:  * HISTORY
                     68:  * $Log:       wt.c,v $
                     69:  * Revision 2.2.1.3  90/01/08  13:29:38  rvb
                     70:  *     Add Intel copyright.
                     71:  *     [90/01/08            rvb]
                     72:  * 
                     73:  * Revision 2.2.1.2  89/12/21  18:00:09  rvb
                     74:  *     Change WTPRI to make the streamer tape read/write
                     75:  *     interruptible.          [lin]
                     76:  * 
                     77:  * Revision 2.2.1.1  89/11/10  09:49:49  rvb
                     78:  *     ORC likes their streamer port at 0x288.
                     79:  *     [89/11/08            rvb]
                     80:  * 
                     81:  * Revision 2.2  89/09/25  12:33:02  rvb
                     82:  *     Driver was provided by Intel 9/18/89.
                     83:  *     [89/09/23            rvb]
                     84:  * 
                     85:  */
                     86: 
                     87: /*
                     88:  *
                     89:  *  Copyright 1988, 1989 by Intel Corporation
                     90:  *
                     91:  *     Support Bell Tech QIC-02 and WANGTEK QIC-36 or QIC-02
                     92:  */
                     93: 
                     94: /*#include <sys/errno.h>
                     95: #include <sys/signal.h>
                     96: #include <sys/types.h>*/
                     97: #include "sys/param.h"
                     98: #include "sys/buf.h"
                     99: #include "sys/file.h"
                    100: #include "sys/proc.h"
                    101: #include "sys/user.h"
                    102: #include "i386/isa/wtreg.h"
                    103: 
                    104: #ifdef ORC
                    105: unsigned wtport = 0x288;       /* base I/O port of controller  */
                    106: #else  ORC
                    107: unsigned wtport = 0x300;       /* base I/O port of controller  */
                    108: #endif ORC
                    109:                                /* standard = 0x300             */
                    110:                                /* alternate = 0x338            */
                    111: 
                    112: unsigned wtchan = 1;           /* DMA channel number           */
                    113:                                /* stardard = 1                 */
                    114:                                /* hardware permits 1, 2 or 3.  */
                    115:                                /* (Avoid DMA 2: used by disks) */
                    116: 
                    117: int    first_wtopen_ever = 1;
                    118: 
                    119: 
                    120: #define        ERROR           1       /* return from tape routines */
                    121: #define        SUCCESS         0       /* return from tape routines */
                    122: 
                    123: int    wci = 0;
                    124: int    exflag = 0;
                    125: int    bytes = 0;
                    126: 
                    127: static unsigned char eqdma = 0x8;
                    128: static unsigned char pagereg = 0x83;
                    129: static unsigned char dmareg = 2;
                    130: static unsigned char dma_write = 0x49;
                    131: static unsigned char dma_read = 0x45;
                    132: static unsigned char dma_done = 2;
                    133: static unsigned char mode = 0;
                    134: static unsigned char mbits;    /* map bits into each other */
                    135: static long bufptr;
                    136: static unsigned numbytes;
                    137: /*
                    138: _wci           dw      0       ; interrupt chain finished normally
                    139: _exflag                dw      0       ; exception variable
                    140: _bytes         dw      0       ; current bytes
                    141: 
                    142: eqdma          db      8h      ; enable dma command: ch1,ch2=8h, ch3=10h
                    143: pagereg                db      83h     ; ch1=83h, ch2=81h, ch3=82h
                    144: dmareg         db      2       ; ch1=2, ch2=4, ch3=6
                    145: dma_write      db      49h     ; write dma command: 48h+_wtchan
                    146: dma_read       db      45h     ; read dma command: 44h+_wtchan
                    147: dma_done       db      2       ; dma done flag: 1<<_wtchan
                    148: mode           db      0       ; dma operation mode
                    149: lbufptr                dw      0       ; buffer pointer to data buffers, low word
                    150: hbufptr                dw      0       ; buffer pointer to data buffers, high word
                    151: numbytes       dw      0       ; number of bytes to read or write (new)
                    152: */
                    153: 
                    154: #define PAGESIZ                4096
                    155: #define HZ             60
                    156: 
                    157: /* tape controller ports */
                    158: #define STATPORT       wtport
                    159: #define CTLPORT                STATPORT
                    160: #define CMDPORT                (wtport+1)
                    161: #define DATAPORT       CMDPORT
                    162: 
                    163: /* defines for reading out status from wangtek tape controller */
                    164: #define READY          0x01    /* ready bit define        */
                    165: #define EXCEP          0x02    /* exception bit define    */
                    166: #define STAT           (READY|EXCEP)
                    167: #define        RESETMASK       0x7
                    168: #define        RESETVAL        (RESETMASK & ~EXCEP)
                    169: 
                    170: /* tape controller control bits (CTLPORT) */
                    171: #define        ONLINE  0x01
                    172: #define        RESET   0x02
                    173: #define        REQUEST 0x04            /* request command */
                    174: #define        CMDOFF  0xC0
                    175: 
                    176: /* QIC-02 commands (CMDPORT) */
                    177: #define        RDDATA  0x80            /* read data */
                    178: #define        READFM  0xA0            /* read file mark */
                    179: #define        WRTDATA 0x40            /* write data */
                    180: #define        WRITEFM 0x60            /* write file mark */
                    181: #define        RDSTAT  0xC0            /* read status command */
                    182: #define        REWIND  0x21            /* rewind command (position+bot) */
                    183: 
                    184: /* 8237 DMA controller regs */
                    185: #define        STATUSREG       0x8
                    186: #define MASKREG                0xA
                    187: #define MODEREG                0xB
                    188: #define CLEARFF                0xC
                    189: 
                    190: /* streamer tape block size */
                    191: #define BLKSIZE        512
                    192: 
                    193: /* Tape characteristics */
                    194: #define        NBPS            512     /* 512-byte blocks */
                    195: #define        ERROR           1       /* return from tape routines */
                    196: #define        SUCCESS         0       /* return from tape routines */
                    197: 
                    198: /* Minor devs */
                    199: #define        TP_REWCLOSE(d)  ((minor(d)&04) == 0) /* Rewind tape on close if read/write */
                    200: #define        TP_DENS(dev)    ((minor(dev) >> 3) & 03) /* set density */
                    201: #define TPHOG(d)       0       /* use Hogproc during tape I/O  */
                    202: 
                    203: /* defines for wtflags */
                    204: #define        TPINUSE 0x0001          /* tape is already open */
                    205: #define        TPREAD  0x0002          /* tape is only open for reading */
                    206: #define        TPWRITE 0x0004          /* tape is only open for writing */
                    207: #define        TPSTART 0x0008          /* tape must be rewound and reset */
                    208: #define        TPDEAD  0x0010          /* tape drive does not work or driver error */
                    209: #define        TPSESS  0x0020          /* no more reads or writes allowed in session */
                    210:                                /* for example, when tape has to be changed */
                    211: #define        TPSTOP  0x0040          /* Stop command outstanding */
                    212: #define        TPREW   0x0080          /* Rewind command outstanding, see wtdsl2() */
                    213: #define        TPVOL   0x0100          /* Read file mark, or hit end of tape */
                    214: #define        TPWO    0x0200          /* write command outstanding */
                    215: #define        TPRO    0x0400          /* read command outstanding */
                    216: #define TPWANY 0x0800          /* write command requested */
                    217: #define TPRANY 0x1000          /* read command requested */
                    218: #define        TPWP    0x2000          /* write protect error seen */
                    219: 
                    220: unsigned int   wtflags = TPSTART;      /* state of tape drive */
                    221: 
                    222: struct buf     rwtbuf;         /* header for raw i/o */
                    223: struct  proc   *myproc;        /* process which opened tape driver */
                    224: 
                    225: char wtimeron;                 /* wtimer() active flag */
                    226: char wtio;                     /* dma (i/o) active flag */
                    227: char isrlock;                  /* isr() flag */
                    228: 
                    229: struct proc * Hogproc; /* no Hogproc on Microport */
                    230: #define        ftoseg(x)       ((unsigned) (x >> 16))
                    231: 
                    232: struct wtstatus {
                    233:        ushort  wt_err;         /* code for error encountered */
                    234:        ushort  wt_ercnt;       /* number of error blocks */
                    235:        ushort  wt_urcnt;       /* number of underruns */
                    236: }      wterror;
                    237: 
                    238: /* defines for wtstatus.wt_err */
                    239: #define        TP_POR          0x100   /* Power on/reset occurred */
                    240: #define        TP_RES1         0x200   /* Reserved for end of media */
                    241: #define        TP_RES2         0x400   /* Reserved for bus parity */
                    242: #define        TP_BOM          0x800   /* Beginning of media */
                    243: #define        TP_MBD          0x1000  /* Marginal block detected */
                    244: #define        TP_NDT          0x2000  /* No data detected */
                    245: #define        TP_ILL          0x4000  /* Illegal command */
                    246: #define        TP_ST1          0x8000  /* Status byte 1 bits */
                    247: #define        TP_FIL          0x01    /* File mark detected */
                    248: #define        TP_BNL          0x02    /* Bad block not located */
                    249: #define        TP_UDA          0x04    /* Unrecoverable data error */
                    250: #define        TP_EOM          0x08    /* End of media */
                    251: #define        TP_WRP          0x10    /* Write protected cartridge */
                    252: #define        TP_USL          0x20    /* Unselected drive */
                    253: #define        TP_CNI          0x40    /* Cartridge not in place */
                    254: #define        TP_ST0          0x80    /* Status byte 0 bits */
                    255: 
                    256: /* Grounds for reporting I/O error to user */
                    257: #define        TP_ERR0         (TP_BNL|TP_UDA|TP_WRP|TP_CNI|TP_FIL|TP_EOM|TP_USL)
                    258: #define        TP_ERR1         (TP_MBD|TP_NDT|TP_ILL)
                    259: /* TP_ILL should never happen! */
                    260: /*
                    261: #define        TP_ERR0         0x7f
                    262: #define        TP_ERR1         0x7700
                    263: */
                    264: 
                    265: /* defines for reading out status from wangtek tape controller */
                    266: #define READY          0x01    /* ready bit define        */
                    267: #define EXCEP          0x02    /* exception bit define    */
                    268: 
                    269: /* sleep priority */
                    270: #define WTPRI  (PZERO+10)
                    271: 
                    272: char   pagebuf[NBPS];          /* buffer of size NBPS */
                    273: unsigned long  pageaddr;       /* physical addr of pagebuf */
                    274:                                /* pageaddr is used with DMA controller */
                    275: time_t Hogtime;                        /* lbolt when Hog timer started */
                    276: extern time_t  lbolt;
                    277: 
                    278: #define        debug   printf
                    279: 
                    280: /*
                    281:  * Strategy routine.
                    282:  *
                    283:  * Arguments:
                    284:  *  Pointer to buffer structure
                    285:  * Function:
                    286:  *  Start transfer.
                    287:  *
                    288:  * It would be nice to have this multiple-threaded.
                    289:  * There is a version of dump from Berkeley that works with multiple processes
                    290:  * trading off with disk & tape I/O.
                    291:  */
                    292: 
                    293: int
                    294: wtstrategy(bp)
                    295: register struct buf *bp;
                    296: {
                    297:        unsigned ucnt1, ucnt2, finished;
                    298:        unsigned long adr1, adr2;
                    299:        int     bad;
                    300: 
                    301:        adr1 = kvtop(bp->b_un.b_addr);
                    302: #ifdef DEBUG
                    303:        debug("bpaddr %x\n", adr1);
                    304: #endif
1.1.1.3 ! root      305:        ucnt1 = bp->b_bcount % NBPG;
1.1       root      306:        ucnt2 = 0;
                    307:        adr2 = 0;
                    308: #ifdef DEBUG
                    309:        debug("WTstart: adr1 %lx cnt %x\n", adr1, ucnt1);
                    310: #endif
1.1.1.3 ! root      311:        /* 64K boundary? (XXX) */
1.1       root      312:        if (ftoseg(adr1) != ftoseg(adr1 + (unsigned) ucnt1 - 1))
                    313:        {
                    314:                adr2 = (adr1 & 0xffff0000L) + 0x10000L;
                    315:                ucnt2 = (adr1 + ucnt1) - adr2;
                    316:                ucnt1 -= ucnt2;
                    317:        }
1.1.1.3 ! root      318:        /* page boundary? */
        !           319:        if (trunc_page(adr1) != trunc_page(adr1 + (unsigned) ucnt1 - 1))
        !           320:        { unsigned u;
        !           321:                u = NBPG - ((unsigned)bp->b_un.b_addr & (NBPG-1));
        !           322:                adr2 = kvtop(bp->b_un.b_addr + u);
        !           323:                ucnt2 = ucnt1 - u;
        !           324:                ucnt1 = u;
        !           325:        }
1.1       root      326:        /* at file marks and end of tape, we just return '0 bytes available' */
                    327:        if (wtflags & TPVOL) {
                    328:                bp->b_resid = bp->b_bcount;
                    329:                goto xit;
                    330:        }
                    331:        if ((Hogproc == (struct proc *) 0) && TPHOG(bp->b_dev))
                    332:        {
                    333: #ifdef DEBUG
                    334:                printf("setting Hogproc\n");
                    335: #endif
                    336:                Hogtime = 0;
                    337:                Hogproc = myproc;
                    338:        }
                    339:        if (bp->b_flags & B_READ) {
                    340:                bad = 0;
                    341: 
                    342:                /* For now, we assume that all data will be copied out */
                    343:                /* If read command outstanding, just skip down */
                    344:                if (!(wtflags & TPRO)) {
                    345:                        if (ERROR == wtsense(TP_WRP))   /* clear status */
                    346:                                goto errxit;
                    347: #ifdef DEBUG
                    348:                        debug("WTread: Start read\n");
                    349: #endif
                    350:                        if (!(wtflags & TPREAD) || (wtflags & TPWANY) ||
                    351:                            (rstart() == ERROR))  {
                    352: #ifdef DEBUG
                    353:                                debug("Tpstart: read init error\n"); /* */
                    354: #endif
                    355:                                goto errxit;
                    356:                        }
                    357:                        wtflags |= TPRO|TPRANY;
                    358:                }
                    359: 
                    360:                finished = 0;
                    361:                /* Take a deep breath */
                    362:                if (ucnt1) {
                    363:                        if ((rtape(adr1, ucnt1) == ERROR) &&
                    364:                                        (wtsense(TP_WRP) == ERROR))
                    365:                                goto endio;
                    366:                        /* wait for it */
                    367:                        bad = pollrdy();
                    368:                        finished = bytes;
                    369:                        if (bad)
                    370:                                goto endio;
                    371:                }
                    372:                /* if a second I/O region, start it */
                    373:                if (ucnt2) {
                    374:                        if ((rtape(adr2, ucnt2) == ERROR) &&
                    375:                                        (wtsense(TP_WRP) == ERROR))
                    376:                                ucnt2 = 0;      /* don't poll for me */
                    377:                        }
                    378: 
                    379:                /* if second i/o pending wait for it */
                    380:                if (ucnt2) {
                    381:                        pollrdy();
                    382:                        /* whether pollrdy is ok or not */
                    383:                        finished += bytes;
                    384:                }
                    385:        } else {
                    386:                if (wtflags & TPWP)     /* write protected */
                    387:                        goto errxit;
                    388: 
                    389:                /* If write command outstanding, just skip down */
                    390:                if (!(wtflags & TPWO)) {
                    391:                        if (ERROR == wtsense(0))        /* clear status */
                    392:                        {
                    393: #ifdef DEBUG
                    394:                                debug("TPstart: sense 0\n");
                    395: #endif
                    396:                                goto errxit;
                    397:                        }
                    398:                        if (!(wtflags & TPWRITE) || (wtflags & TPRANY) ||
                    399:                            (wstart() == ERROR))  {
                    400: #ifdef DEBUG
                    401:                                debug("Tpstart: write init error\n"); /* */
                    402: #endif
                    403:                                wtsense(0);
                    404: 
                    405: errxit:                                bp->b_flags |= B_ERROR;
                    406:                                bp->b_resid = bp->b_bcount;
                    407:                                goto xit;
                    408:                        }
                    409:                        wtflags |= TPWO|TPWANY;
                    410:                } 
                    411: 
                    412:                /* and hold your nose */
                    413:                if (ucnt1 && ((wtape(adr1, ucnt1) == ERROR)
                    414:                                && (wtsense(0) == ERROR)))
                    415:                        finished = bytes;
                    416: 
                    417:                else if (ucnt2 &&
                    418:                        (((ucnt1 && pollrdy()) ||
                    419:                                (wtape(adr2, ucnt2) == ERROR)) &&
                    420:                                (wtsense(0) == ERROR)))
                    421:                        finished = ucnt1 + NBPS + bytes;
                    422:                /* All writes and/or copyins were fine! */
                    423:                else
                    424:                        finished = bp->b_bcount;
                    425:                bad = pollrdy();
                    426:        }
                    427: 
                    428:        endio:
                    429:        if(bad == EIO) bad = 0;
                    430:        wterror.wt_err = 0;
                    431:        if (exflag && wtsense((bp->b_flags & B_READ) ? TP_WRP : 0)) {
                    432:                if ((wterror.wt_err & TP_ST0) 
                    433:                        && (wterror.wt_err & (TP_FIL|TP_EOM))) {
                    434: #ifdef DEBUG
                    435:                        debug("WTsta: Hit end of tape\n"); /* */
                    436: #endif
                    437:                        wtflags |= TPVOL;
                    438:                        if (wterror.wt_err & TP_FIL) {
                    439:                                if (wtflags & TPRO)
                    440:                                        /* interrupter is bogus */
                    441:                                        rstart();  /* restart read command */
                    442:                                else
                    443:                                        wtflags &= ~TPWO;
                    444:                                finished += NBPS; 
                    445:                        }
                    446:                /* Reading file marks or writing end of tape return 0 bytes */
                    447:                } else  {
                    448:                        bp->b_flags |= B_ERROR;
                    449:                        wtflags &= ~(TPWO|TPRO);
                    450:                }
                    451:        }
                    452: 
                    453:        if(bad) {
                    454:                bp->b_flags |= B_ERROR;
                    455:                bp->b_error = bad;
                    456:        }
                    457:        bp->b_resid = bp->b_bcount - finished;
                    458: xit:
                    459:        biodone(bp);
                    460:        if (wtimeron)
                    461:                Hogtime = lbolt;
                    462:        else if (Hogproc == myproc)
                    463:                Hogproc = (struct proc *) 0;
                    464: }
                    465: 
                    466: /*
                    467:  * simulate an interrupt periodically while I/O is going
                    468:  * this is necessary in case interrupts get eaten due to
                    469:  * multiple devices on a single IRQ line
                    470:  */
                    471: wtimer()
                    472: {
                    473:        /* If I/O going and not in isr(), simulate interrupt
                    474:         * If no I/O for at least 1 second, stop being a Hog
                    475:         * If I/O done and not a Hog, turn off wtimer()
                    476:         */
                    477:        if (wtio && !isrlock)
                    478:                isr();
                    479: 
                    480:        if ((Hogproc == myproc) && Hogtime && (lbolt-Hogtime > HZ))
                    481:                Hogproc = (struct proc *) 0;
                    482: 
                    483:        if (wtio || (Hogproc == myproc))
                    484:                timeout(wtimer, (caddr_t) 0, HZ);
                    485:        else
                    486:                wtimeron = 0;
                    487: }
                    488: 
                    489: 
                    490: wtrawio(bp)
                    491: struct buf     *bp;
                    492: {
                    493:        wtstrategy(bp);
                    494:        biowait(bp);
                    495:        return(0);
                    496: }
                    497: 
                    498: /*
                    499:  * ioctl routine
                    500:  *  for user level QIC commands only
                    501:  */
                    502: wtioctl(dev, cmd, arg, mode)
                    503: int dev, cmd;
                    504: unsigned long arg;
                    505: int mode;
                    506: {
                    507:        if (cmd == WTQICMD)
                    508:        {
                    509:                if ((qicmd((int)arg) == ERROR) || (rdyexc(HZ) == ERROR))
                    510:                {
                    511:                        wtsense(0);
                    512:                        return(EIO);
                    513:                }
                    514:                return(0);
                    515:        }
                    516:        return(EINVAL);
                    517: }
                    518: 
                    519: /*
                    520:  * open routine
                    521:  * called on every device open
                    522:  */
                    523: wtopen(dev, flag)
                    524: int    dev, flag;
                    525: {
                    526:        if (first_wtopen_ever) {
                    527:                wtinit();
                    528:                first_wtopen_ever = 0;
                    529:        }
                    530: #ifdef DEBUG
                    531:        printf("wtopen ...\n");
                    532: #endif
                    533:        if (!pageaddr) {
                    534:                return(ENXIO);
                    535:        }
                    536:        if (wtflags & (TPINUSE)) {
                    537:                return(ENXIO);
                    538:        }
                    539:        if (wtflags & (TPDEAD)) {
                    540:                return(EIO);
                    541:        }
                    542:        /* If a rewind from the last session is going on, wait */
                    543:        while(wtflags & TPREW) {
                    544: #ifdef DEBUG
                    545:                debug("Waiting for rew to finish\n");
                    546: #endif
1.1.1.3 ! root      547:                DELAY(1000000); /* delay one second */
1.1       root      548:        }
                    549:        /* Only do reset and select when tape light is off, and tape is rewound.
                    550:         * This allows multiple volumes. */
                    551:        if (wtflags & TPSTART) { 
                    552:                if (t_reset() != SUCCESS) {
                    553:                        return(ENXIO);
                    554:                }
                    555: #ifdef DEBUG
                    556:                debug("reset done. calling wtsense\n");
                    557: #endif
                    558:                if (wtsense(TP_WRP) == ERROR) {
                    559:                        return (EIO);
                    560:                }
                    561: #ifdef DEBUG
                    562:                debug("wtsense done\n");
                    563: #endif
                    564:                wtflags &= ~TPSTART;    
                    565:        }
                    566: 
                    567:        wtflags = TPINUSE;
                    568:        if (flag & FREAD)
                    569:                wtflags |= TPREAD;
                    570:        if (flag & FWRITE)
                    571:                wtflags |= TPWRITE;
                    572:        rwtbuf.b_flags = 0;
                    573:        myproc = curproc;               /* for comparison */
1.1.1.3 ! root      574: #ifdef not
1.1       root      575:        switch(TP_DENS(dev)) {
                    576: case 0:
                    577: cmds(0x28);
                    578: break;
                    579: case 1:
                    580: cmds(0x29);
                    581: break;
                    582: case 2:
                    583: cmds(0x27);
                    584: break;
                    585: case 3:
                    586: cmds(0x24);
                    587:        }
1.1.1.3 ! root      588: #endif
1.1       root      589:        return(0);
                    590: }
                    591: 
                    592: /*
                    593:  * close routine
                    594:  * called on last device close
                    595:  * If not rewind-on-close, leave read or write command intact.
                    596:  */
                    597: wtclose(dev)
                    598: {
                    599:        int wtdsl2();
                    600: 
                    601: #ifdef DEBUG
                    602:        debug("WTclose:\n");
                    603: #endif
                    604:        if (Hogproc == myproc)
                    605:                Hogproc = (struct proc *) 0;
                    606:        if (!exflag && (wtflags & TPWANY) && !(wtflags & (TPSESS|TPDEAD))) {
                    607:                if (!(wtflags & TPWO))
                    608:                        wstart();
                    609: #ifdef DEBUG
                    610:                debug("WT: Writing file mark\n");
                    611: #endif
                    612:                wmark();        /* write file mark */
                    613: #ifdef DEBUG
                    614:                debug("WT: Wrote file mark, going to wait\n");
                    615: #endif
                    616:                if (rdyexc(HZ/10) == ERROR) {
                    617:                        wtsense(0);
                    618:                        }
                    619:                }
                    620:        if (TP_REWCLOSE(dev) || (wtflags & (TPSESS|TPDEAD))) {
                    621:        /* rewind tape to beginning of tape, deselect tape, and make a note */
                    622:        /* don't wait until rewind, though */
                    623:                /* Ending read or write causes rewind to happen, if no error,
                    624:                 * and READY and EXCEPTION stay up until it finishes */
                    625:                if (wtflags & (TPRO|TPWO))
                    626:                {
                    627: #ifdef DEBUG
                    628:                        debug("End read or write\n");
                    629: #endif
                    630:                        rdyexc(HZ/10);
                    631:                        ioend();
                    632:                        wtflags &= ~(TPRO|TPWO);
                    633:                }
                    634:                else    wtwind();
                    635:                wtflags |= TPSTART | TPREW;
                    636:                timeout(wtdsl2, 0, HZ);
                    637:        }
                    638:        else if (!(wtflags & (TPVOL|TPWANY)))
                    639:        {
                    640:                /* space forward to after next file mark no writing done */
                    641:                /* This allows skipping data without reading it.*/
                    642: #ifdef DEBUG
                    643:                debug("Reading past file mark\n");
                    644: #endif
                    645:                if (!(wtflags & TPRO))
                    646:                        rstart();
                    647:                rmark();
                    648:                if (rdyexc(HZ/10))
                    649:                {
                    650:                        wtsense(TP_WRP);
                    651:                }
                    652:        }
                    653:        wtflags &= TPREW|TPDEAD|TPSTART|TPRO|TPWO;
                    654:        return(0);
                    655: }
                    656: 
                    657: /* return ERROR if user I/O request should receive an I/O error code */
                    658: 
                    659: wtsense(ignor)
                    660: {
                    661:        wtflags &= ~(TPRO|TPWO);
                    662: #ifdef DEBUGx
                    663:        debug("WTsense: start ");
                    664: #endif
                    665:        if (rdstatus(&wterror) == ERROR)
                    666:        {
                    667: #ifdef DEBUG
                    668:                debug("WTsense: Can't read status\n");
                    669: #endif
                    670:                return(ERROR);
                    671:        }
                    672: #ifdef DEBUG
                    673:        if (wterror.wt_err & (TP_ST0|TP_ST1))
                    674:        {
                    675:                debug("Tperror: status %x error %d underruns %d\n",
                    676:                        wterror.wt_err, wterror.wt_ercnt, wterror.wt_urcnt);
                    677:        }
                    678:        else
                    679:                debug("done. no error\n");
                    680: #endif
                    681:        wterror.wt_err &= ~ignor;       /* ignore certain errors */
                    682:        reperr(wterror.wt_err);
                    683:        if (((wterror.wt_err & TP_ST0) && (wterror.wt_err & TP_ERR0)) ||
                    684:                    ((wterror.wt_err & TP_ST1) && (wterror.wt_err & TP_ERR1)))
                    685:                        return  ERROR;
                    686: 
                    687:        return SUCCESS;
                    688: }
                    689: 
                    690: /* lifted from tdriver.c from Wangtek */
                    691: reperr(srb0)
                    692: int srb0;
                    693: {
                    694:        int s0 = srb0 & (TP_ERR0|TP_ERR1);      /* find out which exception to report */
                    695:  
                    696:        if (s0) {
                    697:                if (s0 & TP_USL) 
                    698:                        sterr("Drive not online");
                    699:                else if (s0 & TP_CNI) 
                    700:                        sterr("No cartridge");
                    701:                else if ((s0 & TP_WRP) && !(wtflags & TPWP))
                    702:                {
                    703:                        sterr("Tape is write protected");
                    704:                        wtflags |= TPWP;
                    705:                }
                    706:                /*
                    707:                if (s0 & TP_FIL)
                    708:                        sterr("Filemark detected");
                    709:                */
                    710:                else if (s0 & TP_BNL)
                    711:                        sterr("Block in error not located");
                    712:                else if (s0 & TP_UDA)
                    713:                        sterr("Unrecoverable data error");
                    714:                /*
                    715:                else if (s0 & TP_EOM)
                    716:                        sterr("End of tape");
                    717:                */
                    718:                else if (s0 & TP_NDT)
                    719:                        sterr("No data detected");
                    720:                /*
                    721:                if (s0 & TP_POR)
                    722:                        sterr("Reset occured");
                    723:                */
                    724:                else if (s0 & TP_BOM)
                    725:                        sterr("Beginning of tape");
                    726:                else if (s0 & TP_ILL)
                    727:                        sterr("Illegal command");
                    728:        }
                    729: }
                    730:        
                    731: sterr(errstr)
                    732: char   *errstr;
                    733: {
                    734:        printf("Streamer: %s\n", errstr);
                    735: }
                    736: 
                    737: /* Wait until rewind finishes, and deselect drive */
                    738: wtdsl2() {
                    739:        int     stat;
                    740: 
                    741:        stat = inb(wtport) & (READY|EXCEP);
                    742: #ifdef DEBUG
                    743:        debug("Timeout: Waiting for rewind to finish: stat %x\n", stat);
                    744: #endif
                    745:        switch (stat) {
                    746:                /* They're active low, ya'know */
                    747:                case READY|EXCEP:
                    748:                        timeout(wtdsl2, (caddr_t) 0, HZ);
                    749:                        return;
                    750:                case EXCEP: 
                    751:                        wtflags &= ~TPREW;
                    752:                        return;
                    753:                case READY:
                    754:                case    0:
                    755:                        wtflags &= ~TPREW;
                    756:                        sterr("Rewind failed");
                    757:                        wtsense(TP_WRP);
                    758:                        return;
                    759:                        }
                    760:        }
                    761: 
                    762: wtwind() {
                    763: #ifdef DEBUG
                    764:        debug("WT: About to rewind\n");
                    765: #endif
                    766:        rwind();        /* actually start rewind */
                    767: }
                    768: 
                    769: wtintr(unit) {
                    770:        if (wtflags & (TPWO|TPRO))
                    771:        {
                    772:                isrlock = 1;
                    773:                if (wtio) isr();
                    774:                isrlock = 0;
                    775:        }
                    776: }
                    777: 
                    778: wtinit() {
                    779:        if (wtchan < 1 || wtchan > 3)
                    780:        {
                    781:                sterr("Bad DMA channel, cannot init driver");
                    782:                return;
                    783:        }
                    784:        wtlinit();      /* init assembly language variables */
                    785:        pageset();
                    786: }
                    787: 
                    788: rdyexc(ticks)
                    789: {
                    790:        int s;
                    791: #ifdef DEBUG
                    792:        int os = 0xffff;                /* force printout first time */
                    793: #endif
                    794:        for (;;) {                      /* loop until ready or exception */
                    795:                s=(inb(wtport) & 0xff); /* read the status register */
                    796: #ifdef DEBUG
                    797:                if (os != s) {
                    798:                        debug("Status reg = %x\n", s); /* */
                    799:                        os = s;
                    800:                        }
                    801: #endif
                    802:                if (!(s & EXCEP))       /* check if exception have occured */
                    803:                        break;
                    804:                if (!(s & READY))       /* check if controller is ready */
                    805:                        break;
                    806:                s = splbio();
1.1.1.3 ! root      807:                DELAY((ticks/HZ)*1000000); /* */
1.1       root      808:                splx(s);
                    809:        }
                    810: #ifdef DEBUG
                    811:        debug("Status reg = %x on return\n", s); /* */
                    812: #endif
                    813:        return((s & EXCEP)?SUCCESS:ERROR);  /* return exception if it occured */
                    814: }
                    815: 
                    816: pollrdy()
                    817: {
                    818:        int      sps;
                    819: #ifdef DEBUG
                    820:        debug("Pollrdy\n");
                    821: #endif
                    822:        sps = splbio();
                    823:        while (wtio) {
                    824:                int error;
                    825: 
                    826:                if (error = tsleep((caddr_t)&wci, WTPRI | PCATCH,
                    827:                        "wtpoll", 0)) {
                    828:                        splx(sps);
                    829:                        return(error);
                    830:                }
                    831:        }
                    832:        splx(sps);
                    833: #ifdef DEBUG
                    834:        debug("Finish poll, wci %d exflag %d\n", wci, exflag);
                    835: #endif
                    836:        return (EIO);
                    837: }
                    838: 
                    839: wtdma()                /* start up i/o operation, called from dma() in wtlib1.s */
                    840: {
                    841:        wtio = 1;
                    842:        if (!wtimeron)
                    843:        {
                    844:                wtimeron = 1;
                    845:                timeout(wtimer, (caddr_t) 0, HZ/2);
                    846:        }
                    847: }
                    848: 
                    849: wtwake()       /* end i/o operation, called from isr() in wtlib1.s */
                    850: {
                    851:        wtio = 0;
                    852:        wakeup(&wci);
                    853: }
                    854: 
                    855: pageset()
                    856: {
                    857:        unsigned long pp;
                    858: 
                    859:        pp = (unsigned long) pagebuf;
                    860:        pageaddr = kvtop(pp);
                    861: #ifdef DEBUG
                    862:        debug("pageset: addr %lx\n", pageaddr);
                    863: #endif
                    864: }
                    865: 
                    866: 
                    867: 
                    868: #define near
                    869: 
                    870: static near
                    871: sendcmd()
                    872: {
                    873:        /* desired command in global mbits */
                    874: 
                    875:        outb(CTLPORT, mbits | REQUEST);         /* set request */
                    876:        while (inb(STATPORT) & READY);          /* wait for ready */
                    877:        outb(CTLPORT, mbits & ~REQUEST);        /* reset request */
                    878:        while ((inb(STATPORT) & READY) == 0);   /* wait for not ready */
                    879: }
                    880: 
                    881: static near            /* execute command */
                    882: cmds(cmd)
                    883: {
                    884:        register s;
                    885: 
                    886:        do s = inb(STATPORT);
                    887:        while ((s & STAT) == STAT);     /* wait for ready */
                    888: 
                    889:        if ((s & EXCEP) == 0)           /* if exception */
                    890:                return ERROR;           /* error */
                    891:        
                    892:        outb(CMDPORT, cmd);             /* output the command   */
                    893: 
                    894:        outb(CTLPORT, mbits=ONLINE);    /* set & send ONLINE    */
                    895:        sendcmd();
                    896: 
                    897:        return SUCCESS;
                    898: }
                    899: 
                    900: qicmd(cmd)
                    901: {
                    902:        return cmds(cmd);
                    903: }
                    904: 
                    905: rstart()
                    906: {
                    907:        return cmds(RDDATA);
                    908: }
                    909: 
                    910: rmark()
                    911: {
                    912:        return cmds(READFM);
                    913: }
                    914: 
                    915: wstart()
                    916: {
                    917:        return cmds(WRTDATA);
                    918: }
                    919: 
                    920: ioend()
                    921: {
                    922:        register s;
                    923:        register rval = SUCCESS;
                    924: 
                    925:        do s = inb(STATPORT);
                    926:        while ((s & STAT) == STAT);     /* wait for ready */
                    927: 
                    928:        if ((s & EXCEP) == 0)           /* if exception */
                    929:                rval = ERROR;           /* error */
                    930:        
                    931:        mbits &= ~ONLINE;
                    932:        outb(CTLPORT, mbits);           /* reset ONLINE */
                    933:        outb(MASKREG, wtchan+4);        /* turn off dma */
                    934:        outb(CLEARFF, 0);               /* reset direction flag */
                    935: 
                    936:        return rval;
                    937: }
                    938: 
                    939: wmark()
                    940: {
                    941:        register s;
                    942: 
                    943:        if (cmds(WRITEFM) == ERROR)
                    944:                return ERROR;
                    945: 
                    946:        do s = inb(STATPORT);
                    947:        while ((s & STAT) == STAT);     /* wait for ready */
                    948: 
                    949:        if ((s & EXCEP) == 0)           /* if exception */
                    950:                return ERROR;           /* error */
                    951: 
                    952:        return SUCCESS;
                    953: }
                    954: 
                    955: rwind()
                    956: {
                    957:        register s;
                    958: 
                    959:        mbits = CMDOFF;
                    960: 
                    961:        do s = inb(STATPORT);
                    962:        while ((s & STAT) == STAT);     /* wait for ready */
                    963: 
                    964:        outb(CMDPORT, REWIND);
                    965:        sendcmd();
                    966: 
                    967:        return SUCCESS;
                    968: }
                    969: 
                    970: rdstatus(stp)
                    971: char *stp;             /* pointer to 6 byte buffer */
                    972: {
                    973:        register s;
                    974:        int n;
                    975: 
                    976:        do s = inb(STATPORT);
                    977:        while ((s & STAT) == STAT);     /* wait for ready or exception */
                    978: 
                    979:        outb(CMDPORT, RDSTAT);
                    980:        sendcmd();                      /* send read status command */
                    981: 
                    982:        for (n=0; n<6; n++)
                    983:        {
                    984: #ifdef DEBUGx
                    985:                debug("rdstatus: waiting, byte %d\n", n);
                    986: #endif
                    987:                do s = inb(STATPORT);
                    988:                while ((s & STAT) == STAT);     /* wait for ready */
                    989: #ifdef DEBUGx
                    990:                debug("rdstatus: done\n");
                    991: #endif
                    992:                if ((s & EXCEP) == 0)           /* if exception */
                    993:                        return ERROR;           /* error */
                    994: 
                    995:                *stp++ = inb(DATAPORT);         /* read status byte */
                    996: 
                    997:                outb(CTLPORT, mbits | REQUEST); /* set request */
                    998: #ifdef DEBUGx
                    999:                debug("rdstatus: waiting after request, byte %d\n", n);
                   1000: #endif
                   1001:                while ((inb(STATPORT)&READY) == 0);     /* wait for not ready */
                   1002:                for (s=100; s>0; s--);          /* wait an additional time */
                   1003: 
                   1004:                outb(CTLPORT, mbits & ~REQUEST);/* unset request */
                   1005: #ifdef DEBUGx
                   1006:                debug("rdstatus: done\n");
                   1007: #endif
                   1008:        }
                   1009:        return SUCCESS;
                   1010: }
                   1011: 
                   1012: t_reset()
                   1013: {
                   1014:        register i;
                   1015:        mbits |= RESET;
                   1016:        outb(CTLPORT, mbits);           /* send reset */
1.1.1.3 ! root     1017:        DELAY(20);
1.1       root     1018:        mbits &= ~RESET;
                   1019:        outb(CTLPORT, mbits);           /* turn off reset */
                   1020:        if ((inb(STATPORT) & RESETMASK) == RESETVAL)
                   1021:                return SUCCESS;
                   1022:        return ERROR;
                   1023: }
                   1024: 
                   1025: static
                   1026: dma()
                   1027: {
                   1028:        int x=splbio();
                   1029:        wtdma();
                   1030:        outb(CLEARFF, 0);
                   1031:        outb(MODEREG, mode);    /* set dma mode */
                   1032:        outb(dmareg, bufptr & 0xFF);
                   1033:        outb(dmareg, (bufptr>>8) & 0xFF);
                   1034:        outb(pagereg, (bufptr>>16) & 0xFF);                         
                   1035:        outb(dmareg+1, (BLKSIZE-1) & 0xFF);
                   1036:        outb(dmareg+1, (BLKSIZE-1) >> 8);
                   1037:        outb(wtport, eqdma+ONLINE);
                   1038:        outb(MASKREG, wtchan);  /* enable command to 8237, start dma */
                   1039:        splx(x);
                   1040: }
                   1041: 
                   1042: static near
                   1043: wtstart(buf, cnt)
                   1044: long buf;
                   1045: int cnt;
                   1046: {
                   1047:        register s;
                   1048: 
                   1049:        bufptr = buf;           /* init statics */
                   1050:        numbytes = cnt;
                   1051:        wci = 0;                /* init flags */
                   1052:        exflag = 0;
                   1053:        bytes = 0;              /* init counter */
                   1054: 
                   1055:        do s = inb(STATPORT) & STAT;
                   1056:        while (s == STAT);      /* wait for ready or error */
                   1057: 
                   1058:        if (s & EXCEP)          /* no error */
                   1059:        {
                   1060:                dma();
                   1061:                return SUCCESS;
                   1062:        }
                   1063:        return ERROR;           /* error */
                   1064: }
                   1065: 
                   1066: rtape(buf, cnt)
                   1067: long buf;                      /* physical address */
                   1068: int cnt;                       /* number of bytes */
                   1069: {
                   1070:        mode = dma_read;
                   1071:        return wtstart(buf,cnt);
                   1072: }
                   1073: 
                   1074: wtape(buf, cnt)
                   1075: long buf;                      /* physical address */
                   1076: int cnt;                       /* number of bytes */
                   1077: {
                   1078:        mode = dma_write;
                   1079:        return wtstart(buf,cnt);
                   1080: }
                   1081: 
                   1082: isr()
                   1083: {
                   1084:        int stat = inb(wtport);
                   1085:        if (!(stat & EXCEP))    /* exception during I/O */
                   1086:        {
                   1087:                if (bytes + BLKSIZE >= numbytes) wci = 1;
                   1088:                exflag = 1;
                   1089:                goto isrwake;
                   1090:        }
                   1091:        if ((stat & READY) || !(inb(STATUSREG) & dma_done))
                   1092:                return;
                   1093:        exflag = 0;
                   1094:        outb(wtport, ONLINE);
                   1095:        bytes += BLKSIZE;
                   1096:        if (bytes >= numbytes)  /* normal completion of I/O */
                   1097:        {
                   1098:                wci = 1;
                   1099: isrwake:
                   1100:                outb(MASKREG, 4+wtchan);        /* turn off dma */
                   1101:                wtwake();                       /* wake up user level */
                   1102:        }
                   1103:        else
                   1104:        {                       /* continue I/O */
                   1105:                bufptr += BLKSIZE;
                   1106:                dma();
                   1107:        }
                   1108: }
                   1109: 
                   1110: wtlinit()
                   1111: {
                   1112:        switch (wtchan) {
                   1113:        case 1:
                   1114:                return;
                   1115:        case 2:
                   1116:                pagereg = 0x81;
                   1117:                dma_done = 4;
                   1118:                break;
                   1119:        case 3:
                   1120:                eqdma = 0x10;
                   1121:                pagereg = 0x82;
                   1122:                dma_done = 8;
                   1123:                break;
                   1124:        }
                   1125:        dma_write = wtchan+0x48;
                   1126:        dma_read = wtchan+0x44;
                   1127:        dmareg = wtchan+wtchan;
                   1128: }
                   1129: 
                   1130: wtsize()
                   1131: {
                   1132: }
                   1133: 
                   1134: wtdump()
                   1135: {
                   1136: }
                   1137: 
                   1138: #include "i386/isa/isa_device.h"
                   1139: #include "i386/isa/icu.h"
                   1140: 
                   1141: int    wtprobe(), wtattach();
                   1142: struct isa_driver wtdriver = {
                   1143:        wtprobe, wtattach, "wt",
                   1144: };
                   1145: 
                   1146: wtprobe(dvp)
                   1147:        struct isa_device *dvp;
                   1148: {
                   1149:        int val,i,s;
                   1150: 
                   1151: #ifdef lint
                   1152:        wtintr(0);
                   1153: #endif
                   1154: 
                   1155:        wtport = dvp->id_iobase;
                   1156:        if(t_reset() != SUCCESS) return(0);
                   1157:        return(1);
                   1158: }
                   1159: 
                   1160: wtattach() { }
                   1161: 
                   1162: #endif NWT

unix.superglobalmegacorp.com

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