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

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
                    305:        ucnt1 = bp->b_bcount;
                    306:        ucnt2 = 0;
                    307:        adr2 = 0;
                    308: #ifdef DEBUG
                    309:        debug("WTstart: adr1 %lx cnt %x\n", adr1, ucnt1);
                    310: #endif
                    311:        if (ftoseg(adr1) != ftoseg(adr1 + (unsigned) ucnt1 - 1))
                    312:        {
                    313:                adr2 = (adr1 & 0xffff0000L) + 0x10000L;
                    314:                ucnt2 = (adr1 + ucnt1) - adr2;
                    315:                ucnt1 -= ucnt2;
                    316:        }
                    317:        /* at file marks and end of tape, we just return '0 bytes available' */
                    318:        if (wtflags & TPVOL) {
                    319:                bp->b_resid = bp->b_bcount;
                    320:                goto xit;
                    321:        }
                    322:        if ((Hogproc == (struct proc *) 0) && TPHOG(bp->b_dev))
                    323:        {
                    324: #ifdef DEBUG
                    325:                printf("setting Hogproc\n");
                    326: #endif
                    327:                Hogtime = 0;
                    328:                Hogproc = myproc;
                    329:        }
                    330:        if (bp->b_flags & B_READ) {
                    331:                bad = 0;
                    332: 
                    333:                /* For now, we assume that all data will be copied out */
                    334:                /* If read command outstanding, just skip down */
                    335:                if (!(wtflags & TPRO)) {
                    336:                        if (ERROR == wtsense(TP_WRP))   /* clear status */
                    337:                                goto errxit;
                    338: #ifdef DEBUG
                    339:                        debug("WTread: Start read\n");
                    340: #endif
                    341:                        if (!(wtflags & TPREAD) || (wtflags & TPWANY) ||
                    342:                            (rstart() == ERROR))  {
                    343: #ifdef DEBUG
                    344:                                debug("Tpstart: read init error\n"); /* */
                    345: #endif
                    346:                                goto errxit;
                    347:                        }
                    348:                        wtflags |= TPRO|TPRANY;
                    349:                }
                    350: 
                    351:                finished = 0;
                    352:                /* Take a deep breath */
                    353:                if (ucnt1) {
                    354:                        if ((rtape(adr1, ucnt1) == ERROR) &&
                    355:                                        (wtsense(TP_WRP) == ERROR))
                    356:                                goto endio;
                    357:                        /* wait for it */
                    358:                        bad = pollrdy();
                    359:                        finished = bytes;
                    360:                        if (bad)
                    361:                                goto endio;
                    362:                }
                    363:                /* if a second I/O region, start it */
                    364:                if (ucnt2) {
                    365:                        if ((rtape(adr2, ucnt2) == ERROR) &&
                    366:                                        (wtsense(TP_WRP) == ERROR))
                    367:                                ucnt2 = 0;      /* don't poll for me */
                    368:                        }
                    369: 
                    370:                /* if second i/o pending wait for it */
                    371:                if (ucnt2) {
                    372:                        pollrdy();
                    373:                        /* whether pollrdy is ok or not */
                    374:                        finished += bytes;
                    375:                }
                    376:        } else {
                    377:                if (wtflags & TPWP)     /* write protected */
                    378:                        goto errxit;
                    379: 
                    380:                /* If write command outstanding, just skip down */
                    381:                if (!(wtflags & TPWO)) {
                    382:                        if (ERROR == wtsense(0))        /* clear status */
                    383:                        {
                    384: #ifdef DEBUG
                    385:                                debug("TPstart: sense 0\n");
                    386: #endif
                    387:                                goto errxit;
                    388:                        }
                    389:                        if (!(wtflags & TPWRITE) || (wtflags & TPRANY) ||
                    390:                            (wstart() == ERROR))  {
                    391: #ifdef DEBUG
                    392:                                debug("Tpstart: write init error\n"); /* */
                    393: #endif
                    394:                                wtsense(0);
                    395: 
                    396: errxit:                                bp->b_flags |= B_ERROR;
                    397:                                bp->b_resid = bp->b_bcount;
                    398:                                goto xit;
                    399:                        }
                    400:                        wtflags |= TPWO|TPWANY;
                    401:                } 
                    402: 
                    403:                /* and hold your nose */
                    404:                if (ucnt1 && ((wtape(adr1, ucnt1) == ERROR)
                    405:                                && (wtsense(0) == ERROR)))
                    406:                        finished = bytes;
                    407: 
                    408:                else if (ucnt2 &&
                    409:                        (((ucnt1 && pollrdy()) ||
                    410:                                (wtape(adr2, ucnt2) == ERROR)) &&
                    411:                                (wtsense(0) == ERROR)))
                    412:                        finished = ucnt1 + NBPS + bytes;
                    413:                /* All writes and/or copyins were fine! */
                    414:                else
                    415:                        finished = bp->b_bcount;
                    416:                bad = pollrdy();
                    417:        }
                    418: 
                    419:        endio:
                    420:        if(bad == EIO) bad = 0;
                    421:        wterror.wt_err = 0;
                    422:        if (exflag && wtsense((bp->b_flags & B_READ) ? TP_WRP : 0)) {
                    423:                if ((wterror.wt_err & TP_ST0) 
                    424:                        && (wterror.wt_err & (TP_FIL|TP_EOM))) {
                    425: #ifdef DEBUG
                    426:                        debug("WTsta: Hit end of tape\n"); /* */
                    427: #endif
                    428:                        wtflags |= TPVOL;
                    429:                        if (wterror.wt_err & TP_FIL) {
                    430:                                if (wtflags & TPRO)
                    431:                                        /* interrupter is bogus */
                    432:                                        rstart();  /* restart read command */
                    433:                                else
                    434:                                        wtflags &= ~TPWO;
                    435:                                finished += NBPS; 
                    436:                        }
                    437:                /* Reading file marks or writing end of tape return 0 bytes */
                    438:                } else  {
                    439:                        bp->b_flags |= B_ERROR;
                    440:                        wtflags &= ~(TPWO|TPRO);
                    441:                }
                    442:        }
                    443: 
                    444:        if(bad) {
                    445:                bp->b_flags |= B_ERROR;
                    446:                bp->b_error = bad;
                    447:        }
                    448:        bp->b_resid = bp->b_bcount - finished;
                    449: xit:
                    450:        biodone(bp);
                    451:        if (wtimeron)
                    452:                Hogtime = lbolt;
                    453:        else if (Hogproc == myproc)
                    454:                Hogproc = (struct proc *) 0;
                    455: }
                    456: 
                    457: /*
                    458:  * simulate an interrupt periodically while I/O is going
                    459:  * this is necessary in case interrupts get eaten due to
                    460:  * multiple devices on a single IRQ line
                    461:  */
                    462: wtimer()
                    463: {
                    464:        /* If I/O going and not in isr(), simulate interrupt
                    465:         * If no I/O for at least 1 second, stop being a Hog
                    466:         * If I/O done and not a Hog, turn off wtimer()
                    467:         */
                    468:        if (wtio && !isrlock)
                    469:                isr();
                    470: 
                    471:        if ((Hogproc == myproc) && Hogtime && (lbolt-Hogtime > HZ))
                    472:                Hogproc = (struct proc *) 0;
                    473: 
                    474:        if (wtio || (Hogproc == myproc))
                    475:                timeout(wtimer, (caddr_t) 0, HZ);
                    476:        else
                    477:                wtimeron = 0;
                    478: }
                    479: 
                    480: 
                    481: wtrawio(bp)
                    482: struct buf     *bp;
                    483: {
                    484:        wtstrategy(bp);
                    485:        biowait(bp);
                    486:        return(0);
                    487: }
                    488: 
                    489: wt_minphys(bp)
                    490: struct buf     *bp;
                    491: {
                    492:        if (bp->b_bcount > PAGESIZ)
                    493:                bp->b_bcount = PAGESIZ;
                    494: }
                    495: 
                    496: /*
                    497:  * raw read routine
                    498:  */
                    499: wtread(dev, uio)
                    500: struct uio     *uio;
                    501: {
                    502:        if (wtflags & TPSESS) {
                    503:                return(EIO);
                    504:        }
                    505:        physio(wtrawio, &rwtbuf, dev, B_READ, wt_minphys, uio);
                    506:        return(0);
                    507: }
                    508: 
                    509: /*
                    510:  * raw write routine
                    511:  */
                    512: wtwrite(dev, uio)
                    513: struct uio     *uio;
                    514: {
                    515:        if (wtflags & TPSESS) {
                    516:                return(EIO);
                    517:        }
                    518:        physio(wtrawio, &rwtbuf, dev, B_WRITE, wt_minphys, uio);
                    519:        return(0);
                    520: }
                    521: 
                    522: 
                    523: 
                    524: /*
                    525:  * ioctl routine
                    526:  *  for user level QIC commands only
                    527:  */
                    528: wtioctl(dev, cmd, arg, mode)
                    529: int dev, cmd;
                    530: unsigned long arg;
                    531: int mode;
                    532: {
                    533:        if (cmd == WTQICMD)
                    534:        {
                    535:                if ((qicmd((int)arg) == ERROR) || (rdyexc(HZ) == ERROR))
                    536:                {
                    537:                        wtsense(0);
                    538:                        return(EIO);
                    539:                }
                    540:                return(0);
                    541:        }
                    542:        return(EINVAL);
                    543: }
                    544: 
                    545: /*
                    546:  * open routine
                    547:  * called on every device open
                    548:  */
                    549: wtopen(dev, flag)
                    550: int    dev, flag;
                    551: {
                    552:        if (first_wtopen_ever) {
                    553:                wtinit();
                    554:                first_wtopen_ever = 0;
                    555:        }
                    556: #ifdef DEBUG
                    557:        printf("wtopen ...\n");
                    558: #endif
                    559:        if (!pageaddr) {
                    560:                return(ENXIO);
                    561:        }
                    562:        if (wtflags & (TPINUSE)) {
                    563:                return(ENXIO);
                    564:        }
                    565:        if (wtflags & (TPDEAD)) {
                    566:                return(EIO);
                    567:        }
                    568:        /* If a rewind from the last session is going on, wait */
                    569:        while(wtflags & TPREW) {
                    570: #ifdef DEBUG
                    571:                debug("Waiting for rew to finish\n");
                    572: #endif
                    573:                delay(1000000); /* delay one second */
                    574:        }
                    575:        /* Only do reset and select when tape light is off, and tape is rewound.
                    576:         * This allows multiple volumes. */
                    577:        if (wtflags & TPSTART) { 
                    578:                if (t_reset() != SUCCESS) {
                    579:                        return(ENXIO);
                    580:                }
                    581: #ifdef DEBUG
                    582:                debug("reset done. calling wtsense\n");
                    583: #endif
                    584:                if (wtsense(TP_WRP) == ERROR) {
                    585:                        return (EIO);
                    586:                }
                    587: #ifdef DEBUG
                    588:                debug("wtsense done\n");
                    589: #endif
                    590:                wtflags &= ~TPSTART;    
                    591:        }
                    592: 
                    593:        wtflags = TPINUSE;
                    594:        if (flag & FREAD)
                    595:                wtflags |= TPREAD;
                    596:        if (flag & FWRITE)
                    597:                wtflags |= TPWRITE;
                    598:        rwtbuf.b_flags = 0;
                    599:        myproc = curproc;               /* for comparison */
                    600:        switch(TP_DENS(dev)) {
                    601: case 0:
                    602: cmds(0x28);
                    603: break;
                    604: case 1:
                    605: cmds(0x29);
                    606: break;
                    607: case 2:
                    608: cmds(0x27);
                    609: break;
                    610: case 3:
                    611: cmds(0x24);
                    612:        }
                    613:        return(0);
                    614: }
                    615: 
                    616: /*
                    617:  * close routine
                    618:  * called on last device close
                    619:  * If not rewind-on-close, leave read or write command intact.
                    620:  */
                    621: wtclose(dev)
                    622: {
                    623:        int wtdsl2();
                    624: 
                    625: #ifdef DEBUG
                    626:        debug("WTclose:\n");
                    627: #endif
                    628:        if (Hogproc == myproc)
                    629:                Hogproc = (struct proc *) 0;
                    630:        if (!exflag && (wtflags & TPWANY) && !(wtflags & (TPSESS|TPDEAD))) {
                    631:                if (!(wtflags & TPWO))
                    632:                        wstart();
                    633: #ifdef DEBUG
                    634:                debug("WT: Writing file mark\n");
                    635: #endif
                    636:                wmark();        /* write file mark */
                    637: #ifdef DEBUG
                    638:                debug("WT: Wrote file mark, going to wait\n");
                    639: #endif
                    640:                if (rdyexc(HZ/10) == ERROR) {
                    641:                        wtsense(0);
                    642:                        }
                    643:                }
                    644:        if (TP_REWCLOSE(dev) || (wtflags & (TPSESS|TPDEAD))) {
                    645:        /* rewind tape to beginning of tape, deselect tape, and make a note */
                    646:        /* don't wait until rewind, though */
                    647:                /* Ending read or write causes rewind to happen, if no error,
                    648:                 * and READY and EXCEPTION stay up until it finishes */
                    649:                if (wtflags & (TPRO|TPWO))
                    650:                {
                    651: #ifdef DEBUG
                    652:                        debug("End read or write\n");
                    653: #endif
                    654:                        rdyexc(HZ/10);
                    655:                        ioend();
                    656:                        wtflags &= ~(TPRO|TPWO);
                    657:                }
                    658:                else    wtwind();
                    659:                wtflags |= TPSTART | TPREW;
                    660:                timeout(wtdsl2, 0, HZ);
                    661:        }
                    662:        else if (!(wtflags & (TPVOL|TPWANY)))
                    663:        {
                    664:                /* space forward to after next file mark no writing done */
                    665:                /* This allows skipping data without reading it.*/
                    666: #ifdef DEBUG
                    667:                debug("Reading past file mark\n");
                    668: #endif
                    669:                if (!(wtflags & TPRO))
                    670:                        rstart();
                    671:                rmark();
                    672:                if (rdyexc(HZ/10))
                    673:                {
                    674:                        wtsense(TP_WRP);
                    675:                }
                    676:        }
                    677:        wtflags &= TPREW|TPDEAD|TPSTART|TPRO|TPWO;
                    678:        return(0);
                    679: }
                    680: 
                    681: /* return ERROR if user I/O request should receive an I/O error code */
                    682: 
                    683: wtsense(ignor)
                    684: {
                    685:        wtflags &= ~(TPRO|TPWO);
                    686: #ifdef DEBUGx
                    687:        debug("WTsense: start ");
                    688: #endif
                    689:        if (rdstatus(&wterror) == ERROR)
                    690:        {
                    691: #ifdef DEBUG
                    692:                debug("WTsense: Can't read status\n");
                    693: #endif
                    694:                return(ERROR);
                    695:        }
                    696: #ifdef DEBUG
                    697:        if (wterror.wt_err & (TP_ST0|TP_ST1))
                    698:        {
                    699:                debug("Tperror: status %x error %d underruns %d\n",
                    700:                        wterror.wt_err, wterror.wt_ercnt, wterror.wt_urcnt);
                    701:        }
                    702:        else
                    703:                debug("done. no error\n");
                    704: #endif
                    705:        wterror.wt_err &= ~ignor;       /* ignore certain errors */
                    706:        reperr(wterror.wt_err);
                    707:        if (((wterror.wt_err & TP_ST0) && (wterror.wt_err & TP_ERR0)) ||
                    708:                    ((wterror.wt_err & TP_ST1) && (wterror.wt_err & TP_ERR1)))
                    709:                        return  ERROR;
                    710: 
                    711:        return SUCCESS;
                    712: }
                    713: 
                    714: /* lifted from tdriver.c from Wangtek */
                    715: reperr(srb0)
                    716: int srb0;
                    717: {
                    718:        int s0 = srb0 & (TP_ERR0|TP_ERR1);      /* find out which exception to report */
                    719:  
                    720:        if (s0) {
                    721:                if (s0 & TP_USL) 
                    722:                        sterr("Drive not online");
                    723:                else if (s0 & TP_CNI) 
                    724:                        sterr("No cartridge");
                    725:                else if ((s0 & TP_WRP) && !(wtflags & TPWP))
                    726:                {
                    727:                        sterr("Tape is write protected");
                    728:                        wtflags |= TPWP;
                    729:                }
                    730:                /*
                    731:                if (s0 & TP_FIL)
                    732:                        sterr("Filemark detected");
                    733:                */
                    734:                else if (s0 & TP_BNL)
                    735:                        sterr("Block in error not located");
                    736:                else if (s0 & TP_UDA)
                    737:                        sterr("Unrecoverable data error");
                    738:                /*
                    739:                else if (s0 & TP_EOM)
                    740:                        sterr("End of tape");
                    741:                */
                    742:                else if (s0 & TP_NDT)
                    743:                        sterr("No data detected");
                    744:                /*
                    745:                if (s0 & TP_POR)
                    746:                        sterr("Reset occured");
                    747:                */
                    748:                else if (s0 & TP_BOM)
                    749:                        sterr("Beginning of tape");
                    750:                else if (s0 & TP_ILL)
                    751:                        sterr("Illegal command");
                    752:        }
                    753: }
                    754:        
                    755: sterr(errstr)
                    756: char   *errstr;
                    757: {
                    758:        printf("Streamer: %s\n", errstr);
                    759: }
                    760: 
                    761: /* Wait until rewind finishes, and deselect drive */
                    762: wtdsl2() {
                    763:        int     stat;
                    764: 
                    765:        stat = inb(wtport) & (READY|EXCEP);
                    766: #ifdef DEBUG
                    767:        debug("Timeout: Waiting for rewind to finish: stat %x\n", stat);
                    768: #endif
                    769:        switch (stat) {
                    770:                /* They're active low, ya'know */
                    771:                case READY|EXCEP:
                    772:                        timeout(wtdsl2, (caddr_t) 0, HZ);
                    773:                        return;
                    774:                case EXCEP: 
                    775:                        wtflags &= ~TPREW;
                    776:                        return;
                    777:                case READY:
                    778:                case    0:
                    779:                        wtflags &= ~TPREW;
                    780:                        sterr("Rewind failed");
                    781:                        wtsense(TP_WRP);
                    782:                        return;
                    783:                        }
                    784:        }
                    785: 
                    786: wtwind() {
                    787: #ifdef DEBUG
                    788:        debug("WT: About to rewind\n");
                    789: #endif
                    790:        rwind();        /* actually start rewind */
                    791: }
                    792: 
                    793: wtintr(unit) {
                    794:        if (wtflags & (TPWO|TPRO))
                    795:        {
                    796:                isrlock = 1;
                    797:                if (wtio) isr();
                    798:                isrlock = 0;
                    799:        }
                    800: }
                    801: 
                    802: wtinit() {
                    803:        if (wtchan < 1 || wtchan > 3)
                    804:        {
                    805:                sterr("Bad DMA channel, cannot init driver");
                    806:                return;
                    807:        }
                    808:        wtlinit();      /* init assembly language variables */
                    809:        pageset();
                    810: }
                    811: 
                    812: rdyexc(ticks)
                    813: {
                    814:        int s;
                    815: #ifdef DEBUG
                    816:        int os = 0xffff;                /* force printout first time */
                    817: #endif
                    818:        for (;;) {                      /* loop until ready or exception */
                    819:                s=(inb(wtport) & 0xff); /* read the status register */
                    820: #ifdef DEBUG
                    821:                if (os != s) {
                    822:                        debug("Status reg = %x\n", s); /* */
                    823:                        os = s;
                    824:                        }
                    825: #endif
                    826:                if (!(s & EXCEP))       /* check if exception have occured */
                    827:                        break;
                    828:                if (!(s & READY))       /* check if controller is ready */
                    829:                        break;
                    830:                s = splbio();
                    831:                delay((ticks/HZ)*1000000); /* */
                    832:                splx(s);
                    833:        }
                    834: #ifdef DEBUG
                    835:        debug("Status reg = %x on return\n", s); /* */
                    836: #endif
                    837:        return((s & EXCEP)?SUCCESS:ERROR);  /* return exception if it occured */
                    838: }
                    839: 
                    840: pollrdy()
                    841: {
                    842:        int      sps;
                    843: #ifdef DEBUG
                    844:        debug("Pollrdy\n");
                    845: #endif
                    846:        sps = splbio();
                    847:        while (wtio) {
                    848:                int error;
                    849: 
                    850:                if (error = tsleep((caddr_t)&wci, WTPRI | PCATCH,
                    851:                        "wtpoll", 0)) {
                    852:                        splx(sps);
                    853:                        return(error);
                    854:                }
                    855:        }
                    856:        splx(sps);
                    857: #ifdef DEBUG
                    858:        debug("Finish poll, wci %d exflag %d\n", wci, exflag);
                    859: #endif
                    860:        return (EIO);
                    861: }
                    862: 
                    863: wtdma()                /* start up i/o operation, called from dma() in wtlib1.s */
                    864: {
                    865:        wtio = 1;
                    866:        if (!wtimeron)
                    867:        {
                    868:                wtimeron = 1;
                    869:                timeout(wtimer, (caddr_t) 0, HZ/2);
                    870:        }
                    871: }
                    872: 
                    873: wtwake()       /* end i/o operation, called from isr() in wtlib1.s */
                    874: {
                    875:        wtio = 0;
                    876:        wakeup(&wci);
                    877: }
                    878: 
                    879: pageset()
                    880: {
                    881:        unsigned long pp;
                    882: 
                    883:        pp = (unsigned long) pagebuf;
                    884:        pageaddr = kvtop(pp);
                    885: #ifdef DEBUG
                    886:        debug("pageset: addr %lx\n", pageaddr);
                    887: #endif
                    888: }
                    889: 
                    890: 
                    891: 
                    892: #define near
                    893: 
                    894: static near
                    895: sendcmd()
                    896: {
                    897:        /* desired command in global mbits */
                    898: 
                    899:        outb(CTLPORT, mbits | REQUEST);         /* set request */
                    900:        while (inb(STATPORT) & READY);          /* wait for ready */
                    901:        outb(CTLPORT, mbits & ~REQUEST);        /* reset request */
                    902:        while ((inb(STATPORT) & READY) == 0);   /* wait for not ready */
                    903: }
                    904: 
                    905: static near            /* execute command */
                    906: cmds(cmd)
                    907: {
                    908:        register s;
                    909: 
                    910:        do s = inb(STATPORT);
                    911:        while ((s & STAT) == STAT);     /* wait for ready */
                    912: 
                    913:        if ((s & EXCEP) == 0)           /* if exception */
                    914:                return ERROR;           /* error */
                    915:        
                    916:        outb(CMDPORT, cmd);             /* output the command   */
                    917: 
                    918:        outb(CTLPORT, mbits=ONLINE);    /* set & send ONLINE    */
                    919:        sendcmd();
                    920: 
                    921:        return SUCCESS;
                    922: }
                    923: 
                    924: qicmd(cmd)
                    925: {
                    926:        return cmds(cmd);
                    927: }
                    928: 
                    929: rstart()
                    930: {
                    931:        return cmds(RDDATA);
                    932: }
                    933: 
                    934: rmark()
                    935: {
                    936:        return cmds(READFM);
                    937: }
                    938: 
                    939: wstart()
                    940: {
                    941:        return cmds(WRTDATA);
                    942: }
                    943: 
                    944: ioend()
                    945: {
                    946:        register s;
                    947:        register rval = SUCCESS;
                    948: 
                    949:        do s = inb(STATPORT);
                    950:        while ((s & STAT) == STAT);     /* wait for ready */
                    951: 
                    952:        if ((s & EXCEP) == 0)           /* if exception */
                    953:                rval = ERROR;           /* error */
                    954:        
                    955:        mbits &= ~ONLINE;
                    956:        outb(CTLPORT, mbits);           /* reset ONLINE */
                    957:        outb(MASKREG, wtchan+4);        /* turn off dma */
                    958:        outb(CLEARFF, 0);               /* reset direction flag */
                    959: 
                    960:        return rval;
                    961: }
                    962: 
                    963: wmark()
                    964: {
                    965:        register s;
                    966: 
                    967:        if (cmds(WRITEFM) == ERROR)
                    968:                return ERROR;
                    969: 
                    970:        do s = inb(STATPORT);
                    971:        while ((s & STAT) == STAT);     /* wait for ready */
                    972: 
                    973:        if ((s & EXCEP) == 0)           /* if exception */
                    974:                return ERROR;           /* error */
                    975: 
                    976:        return SUCCESS;
                    977: }
                    978: 
                    979: rwind()
                    980: {
                    981:        register s;
                    982: 
                    983:        mbits = CMDOFF;
                    984: 
                    985:        do s = inb(STATPORT);
                    986:        while ((s & STAT) == STAT);     /* wait for ready */
                    987: 
                    988:        outb(CMDPORT, REWIND);
                    989:        sendcmd();
                    990: 
                    991:        return SUCCESS;
                    992: }
                    993: 
                    994: rdstatus(stp)
                    995: char *stp;             /* pointer to 6 byte buffer */
                    996: {
                    997:        register s;
                    998:        int n;
                    999: 
                   1000:        do s = inb(STATPORT);
                   1001:        while ((s & STAT) == STAT);     /* wait for ready or exception */
                   1002: 
                   1003:        outb(CMDPORT, RDSTAT);
                   1004:        sendcmd();                      /* send read status command */
                   1005: 
                   1006:        for (n=0; n<6; n++)
                   1007:        {
                   1008: #ifdef DEBUGx
                   1009:                debug("rdstatus: waiting, byte %d\n", n);
                   1010: #endif
                   1011:                do s = inb(STATPORT);
                   1012:                while ((s & STAT) == STAT);     /* wait for ready */
                   1013: #ifdef DEBUGx
                   1014:                debug("rdstatus: done\n");
                   1015: #endif
                   1016:                if ((s & EXCEP) == 0)           /* if exception */
                   1017:                        return ERROR;           /* error */
                   1018: 
                   1019:                *stp++ = inb(DATAPORT);         /* read status byte */
                   1020: 
                   1021:                outb(CTLPORT, mbits | REQUEST); /* set request */
                   1022: #ifdef DEBUGx
                   1023:                debug("rdstatus: waiting after request, byte %d\n", n);
                   1024: #endif
                   1025:                while ((inb(STATPORT)&READY) == 0);     /* wait for not ready */
                   1026:                for (s=100; s>0; s--);          /* wait an additional time */
                   1027: 
                   1028:                outb(CTLPORT, mbits & ~REQUEST);/* unset request */
                   1029: #ifdef DEBUGx
                   1030:                debug("rdstatus: done\n");
                   1031: #endif
                   1032:        }
                   1033:        return SUCCESS;
                   1034: }
                   1035: 
                   1036: t_reset()
                   1037: {
                   1038:        register i;
                   1039:        mbits |= RESET;
                   1040:        outb(CTLPORT, mbits);           /* send reset */
                   1041:        delay(20);
                   1042:        mbits &= ~RESET;
                   1043:        outb(CTLPORT, mbits);           /* turn off reset */
                   1044:        if ((inb(STATPORT) & RESETMASK) == RESETVAL)
                   1045:                return SUCCESS;
                   1046:        return ERROR;
                   1047: }
                   1048: 
                   1049: static
                   1050: dma()
                   1051: {
                   1052:        int x=splbio();
                   1053:        wtdma();
                   1054:        outb(CLEARFF, 0);
                   1055:        outb(MODEREG, mode);    /* set dma mode */
                   1056:        outb(dmareg, bufptr & 0xFF);
                   1057:        outb(dmareg, (bufptr>>8) & 0xFF);
                   1058:        outb(pagereg, (bufptr>>16) & 0xFF);                         
                   1059:        outb(dmareg+1, (BLKSIZE-1) & 0xFF);
                   1060:        outb(dmareg+1, (BLKSIZE-1) >> 8);
                   1061:        outb(wtport, eqdma+ONLINE);
                   1062:        outb(MASKREG, wtchan);  /* enable command to 8237, start dma */
                   1063:        splx(x);
                   1064: }
                   1065: 
                   1066: static near
                   1067: wtstart(buf, cnt)
                   1068: long buf;
                   1069: int cnt;
                   1070: {
                   1071:        register s;
                   1072: 
                   1073:        bufptr = buf;           /* init statics */
                   1074:        numbytes = cnt;
                   1075:        wci = 0;                /* init flags */
                   1076:        exflag = 0;
                   1077:        bytes = 0;              /* init counter */
                   1078: 
                   1079:        do s = inb(STATPORT) & STAT;
                   1080:        while (s == STAT);      /* wait for ready or error */
                   1081: 
                   1082:        if (s & EXCEP)          /* no error */
                   1083:        {
                   1084:                dma();
                   1085:                return SUCCESS;
                   1086:        }
                   1087:        return ERROR;           /* error */
                   1088: }
                   1089: 
                   1090: rtape(buf, cnt)
                   1091: long buf;                      /* physical address */
                   1092: int cnt;                       /* number of bytes */
                   1093: {
                   1094:        mode = dma_read;
                   1095:        return wtstart(buf,cnt);
                   1096: }
                   1097: 
                   1098: wtape(buf, cnt)
                   1099: long buf;                      /* physical address */
                   1100: int cnt;                       /* number of bytes */
                   1101: {
                   1102:        mode = dma_write;
                   1103:        return wtstart(buf,cnt);
                   1104: }
                   1105: 
                   1106: isr()
                   1107: {
                   1108:        int stat = inb(wtport);
                   1109:        if (!(stat & EXCEP))    /* exception during I/O */
                   1110:        {
                   1111:                if (bytes + BLKSIZE >= numbytes) wci = 1;
                   1112:                exflag = 1;
                   1113:                goto isrwake;
                   1114:        }
                   1115:        if ((stat & READY) || !(inb(STATUSREG) & dma_done))
                   1116:                return;
                   1117:        exflag = 0;
                   1118:        outb(wtport, ONLINE);
                   1119:        bytes += BLKSIZE;
                   1120:        if (bytes >= numbytes)  /* normal completion of I/O */
                   1121:        {
                   1122:                wci = 1;
                   1123: isrwake:
                   1124:                outb(MASKREG, 4+wtchan);        /* turn off dma */
                   1125:                wtwake();                       /* wake up user level */
                   1126:        }
                   1127:        else
                   1128:        {                       /* continue I/O */
                   1129:                bufptr += BLKSIZE;
                   1130:                dma();
                   1131:        }
                   1132: }
                   1133: 
                   1134: wtlinit()
                   1135: {
                   1136:        switch (wtchan) {
                   1137:        case 1:
                   1138:                return;
                   1139:        case 2:
                   1140:                pagereg = 0x81;
                   1141:                dma_done = 4;
                   1142:                break;
                   1143:        case 3:
                   1144:                eqdma = 0x10;
                   1145:                pagereg = 0x82;
                   1146:                dma_done = 8;
                   1147:                break;
                   1148:        }
                   1149:        dma_write = wtchan+0x48;
                   1150:        dma_read = wtchan+0x44;
                   1151:        dmareg = wtchan+wtchan;
                   1152: }
                   1153: 
                   1154: /*
                   1155:  * delay i microseconds
                   1156:  */
                   1157: delay(i)
                   1158: register int i;
                   1159: {
                   1160:        while (i-- > 0)
                   1161:                DELAY(1000);
                   1162: }
                   1163: 
                   1164: wtsize()
                   1165: {
                   1166: }
                   1167: 
                   1168: wtdump()
                   1169: {
                   1170: }
                   1171: 
                   1172: #include "i386/isa/isa_device.h"
                   1173: #include "i386/isa/icu.h"
                   1174: 
                   1175: int    wtprobe(), wtattach();
                   1176: struct isa_driver wtdriver = {
                   1177:        wtprobe, wtattach, "wt",
                   1178: };
                   1179: 
                   1180: wtprobe(dvp)
                   1181:        struct isa_device *dvp;
                   1182: {
                   1183:        int val,i,s;
                   1184: 
                   1185: #ifdef lint
                   1186:        wtintr(0);
                   1187: #endif
                   1188: 
                   1189:        wtport = dvp->id_iobase;
                   1190:        if(t_reset() != SUCCESS) return(0);
                   1191:        return(1);
                   1192: }
                   1193: 
                   1194: wtattach() { }
                   1195: 
                   1196: #endif NWT

unix.superglobalmegacorp.com

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