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

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: /*
                    490:  * ioctl routine
                    491:  *  for user level QIC commands only
                    492:  */
                    493: wtioctl(dev, cmd, arg, mode)
                    494: int dev, cmd;
                    495: unsigned long arg;
                    496: int mode;
                    497: {
                    498:        if (cmd == WTQICMD)
                    499:        {
                    500:                if ((qicmd((int)arg) == ERROR) || (rdyexc(HZ) == ERROR))
                    501:                {
                    502:                        wtsense(0);
                    503:                        return(EIO);
                    504:                }
                    505:                return(0);
                    506:        }
                    507:        return(EINVAL);
                    508: }
                    509: 
                    510: /*
                    511:  * open routine
                    512:  * called on every device open
                    513:  */
                    514: wtopen(dev, flag)
                    515: int    dev, flag;
                    516: {
                    517:        if (first_wtopen_ever) {
                    518:                wtinit();
                    519:                first_wtopen_ever = 0;
                    520:        }
                    521: #ifdef DEBUG
                    522:        printf("wtopen ...\n");
                    523: #endif
                    524:        if (!pageaddr) {
                    525:                return(ENXIO);
                    526:        }
                    527:        if (wtflags & (TPINUSE)) {
                    528:                return(ENXIO);
                    529:        }
                    530:        if (wtflags & (TPDEAD)) {
                    531:                return(EIO);
                    532:        }
                    533:        /* If a rewind from the last session is going on, wait */
                    534:        while(wtflags & TPREW) {
                    535: #ifdef DEBUG
                    536:                debug("Waiting for rew to finish\n");
                    537: #endif
                    538:                delay(1000000); /* delay one second */
                    539:        }
                    540:        /* Only do reset and select when tape light is off, and tape is rewound.
                    541:         * This allows multiple volumes. */
                    542:        if (wtflags & TPSTART) { 
                    543:                if (t_reset() != SUCCESS) {
                    544:                        return(ENXIO);
                    545:                }
                    546: #ifdef DEBUG
                    547:                debug("reset done. calling wtsense\n");
                    548: #endif
                    549:                if (wtsense(TP_WRP) == ERROR) {
                    550:                        return (EIO);
                    551:                }
                    552: #ifdef DEBUG
                    553:                debug("wtsense done\n");
                    554: #endif
                    555:                wtflags &= ~TPSTART;    
                    556:        }
                    557: 
                    558:        wtflags = TPINUSE;
                    559:        if (flag & FREAD)
                    560:                wtflags |= TPREAD;
                    561:        if (flag & FWRITE)
                    562:                wtflags |= TPWRITE;
                    563:        rwtbuf.b_flags = 0;
                    564:        myproc = curproc;               /* for comparison */
                    565:        switch(TP_DENS(dev)) {
                    566: case 0:
                    567: cmds(0x28);
                    568: break;
                    569: case 1:
                    570: cmds(0x29);
                    571: break;
                    572: case 2:
                    573: cmds(0x27);
                    574: break;
                    575: case 3:
                    576: cmds(0x24);
                    577:        }
                    578:        return(0);
                    579: }
                    580: 
                    581: /*
                    582:  * close routine
                    583:  * called on last device close
                    584:  * If not rewind-on-close, leave read or write command intact.
                    585:  */
                    586: wtclose(dev)
                    587: {
                    588:        int wtdsl2();
                    589: 
                    590: #ifdef DEBUG
                    591:        debug("WTclose:\n");
                    592: #endif
                    593:        if (Hogproc == myproc)
                    594:                Hogproc = (struct proc *) 0;
                    595:        if (!exflag && (wtflags & TPWANY) && !(wtflags & (TPSESS|TPDEAD))) {
                    596:                if (!(wtflags & TPWO))
                    597:                        wstart();
                    598: #ifdef DEBUG
                    599:                debug("WT: Writing file mark\n");
                    600: #endif
                    601:                wmark();        /* write file mark */
                    602: #ifdef DEBUG
                    603:                debug("WT: Wrote file mark, going to wait\n");
                    604: #endif
                    605:                if (rdyexc(HZ/10) == ERROR) {
                    606:                        wtsense(0);
                    607:                        }
                    608:                }
                    609:        if (TP_REWCLOSE(dev) || (wtflags & (TPSESS|TPDEAD))) {
                    610:        /* rewind tape to beginning of tape, deselect tape, and make a note */
                    611:        /* don't wait until rewind, though */
                    612:                /* Ending read or write causes rewind to happen, if no error,
                    613:                 * and READY and EXCEPTION stay up until it finishes */
                    614:                if (wtflags & (TPRO|TPWO))
                    615:                {
                    616: #ifdef DEBUG
                    617:                        debug("End read or write\n");
                    618: #endif
                    619:                        rdyexc(HZ/10);
                    620:                        ioend();
                    621:                        wtflags &= ~(TPRO|TPWO);
                    622:                }
                    623:                else    wtwind();
                    624:                wtflags |= TPSTART | TPREW;
                    625:                timeout(wtdsl2, 0, HZ);
                    626:        }
                    627:        else if (!(wtflags & (TPVOL|TPWANY)))
                    628:        {
                    629:                /* space forward to after next file mark no writing done */
                    630:                /* This allows skipping data without reading it.*/
                    631: #ifdef DEBUG
                    632:                debug("Reading past file mark\n");
                    633: #endif
                    634:                if (!(wtflags & TPRO))
                    635:                        rstart();
                    636:                rmark();
                    637:                if (rdyexc(HZ/10))
                    638:                {
                    639:                        wtsense(TP_WRP);
                    640:                }
                    641:        }
                    642:        wtflags &= TPREW|TPDEAD|TPSTART|TPRO|TPWO;
                    643:        return(0);
                    644: }
                    645: 
                    646: /* return ERROR if user I/O request should receive an I/O error code */
                    647: 
                    648: wtsense(ignor)
                    649: {
                    650:        wtflags &= ~(TPRO|TPWO);
                    651: #ifdef DEBUGx
                    652:        debug("WTsense: start ");
                    653: #endif
                    654:        if (rdstatus(&wterror) == ERROR)
                    655:        {
                    656: #ifdef DEBUG
                    657:                debug("WTsense: Can't read status\n");
                    658: #endif
                    659:                return(ERROR);
                    660:        }
                    661: #ifdef DEBUG
                    662:        if (wterror.wt_err & (TP_ST0|TP_ST1))
                    663:        {
                    664:                debug("Tperror: status %x error %d underruns %d\n",
                    665:                        wterror.wt_err, wterror.wt_ercnt, wterror.wt_urcnt);
                    666:        }
                    667:        else
                    668:                debug("done. no error\n");
                    669: #endif
                    670:        wterror.wt_err &= ~ignor;       /* ignore certain errors */
                    671:        reperr(wterror.wt_err);
                    672:        if (((wterror.wt_err & TP_ST0) && (wterror.wt_err & TP_ERR0)) ||
                    673:                    ((wterror.wt_err & TP_ST1) && (wterror.wt_err & TP_ERR1)))
                    674:                        return  ERROR;
                    675: 
                    676:        return SUCCESS;
                    677: }
                    678: 
                    679: /* lifted from tdriver.c from Wangtek */
                    680: reperr(srb0)
                    681: int srb0;
                    682: {
                    683:        int s0 = srb0 & (TP_ERR0|TP_ERR1);      /* find out which exception to report */
                    684:  
                    685:        if (s0) {
                    686:                if (s0 & TP_USL) 
                    687:                        sterr("Drive not online");
                    688:                else if (s0 & TP_CNI) 
                    689:                        sterr("No cartridge");
                    690:                else if ((s0 & TP_WRP) && !(wtflags & TPWP))
                    691:                {
                    692:                        sterr("Tape is write protected");
                    693:                        wtflags |= TPWP;
                    694:                }
                    695:                /*
                    696:                if (s0 & TP_FIL)
                    697:                        sterr("Filemark detected");
                    698:                */
                    699:                else if (s0 & TP_BNL)
                    700:                        sterr("Block in error not located");
                    701:                else if (s0 & TP_UDA)
                    702:                        sterr("Unrecoverable data error");
                    703:                /*
                    704:                else if (s0 & TP_EOM)
                    705:                        sterr("End of tape");
                    706:                */
                    707:                else if (s0 & TP_NDT)
                    708:                        sterr("No data detected");
                    709:                /*
                    710:                if (s0 & TP_POR)
                    711:                        sterr("Reset occured");
                    712:                */
                    713:                else if (s0 & TP_BOM)
                    714:                        sterr("Beginning of tape");
                    715:                else if (s0 & TP_ILL)
                    716:                        sterr("Illegal command");
                    717:        }
                    718: }
                    719:        
                    720: sterr(errstr)
                    721: char   *errstr;
                    722: {
                    723:        printf("Streamer: %s\n", errstr);
                    724: }
                    725: 
                    726: /* Wait until rewind finishes, and deselect drive */
                    727: wtdsl2() {
                    728:        int     stat;
                    729: 
                    730:        stat = inb(wtport) & (READY|EXCEP);
                    731: #ifdef DEBUG
                    732:        debug("Timeout: Waiting for rewind to finish: stat %x\n", stat);
                    733: #endif
                    734:        switch (stat) {
                    735:                /* They're active low, ya'know */
                    736:                case READY|EXCEP:
                    737:                        timeout(wtdsl2, (caddr_t) 0, HZ);
                    738:                        return;
                    739:                case EXCEP: 
                    740:                        wtflags &= ~TPREW;
                    741:                        return;
                    742:                case READY:
                    743:                case    0:
                    744:                        wtflags &= ~TPREW;
                    745:                        sterr("Rewind failed");
                    746:                        wtsense(TP_WRP);
                    747:                        return;
                    748:                        }
                    749:        }
                    750: 
                    751: wtwind() {
                    752: #ifdef DEBUG
                    753:        debug("WT: About to rewind\n");
                    754: #endif
                    755:        rwind();        /* actually start rewind */
                    756: }
                    757: 
                    758: wtintr(unit) {
                    759:        if (wtflags & (TPWO|TPRO))
                    760:        {
                    761:                isrlock = 1;
                    762:                if (wtio) isr();
                    763:                isrlock = 0;
                    764:        }
                    765: }
                    766: 
                    767: wtinit() {
                    768:        if (wtchan < 1 || wtchan > 3)
                    769:        {
                    770:                sterr("Bad DMA channel, cannot init driver");
                    771:                return;
                    772:        }
                    773:        wtlinit();      /* init assembly language variables */
                    774:        pageset();
                    775: }
                    776: 
                    777: rdyexc(ticks)
                    778: {
                    779:        int s;
                    780: #ifdef DEBUG
                    781:        int os = 0xffff;                /* force printout first time */
                    782: #endif
                    783:        for (;;) {                      /* loop until ready or exception */
                    784:                s=(inb(wtport) & 0xff); /* read the status register */
                    785: #ifdef DEBUG
                    786:                if (os != s) {
                    787:                        debug("Status reg = %x\n", s); /* */
                    788:                        os = s;
                    789:                        }
                    790: #endif
                    791:                if (!(s & EXCEP))       /* check if exception have occured */
                    792:                        break;
                    793:                if (!(s & READY))       /* check if controller is ready */
                    794:                        break;
                    795:                s = splbio();
                    796:                delay((ticks/HZ)*1000000); /* */
                    797:                splx(s);
                    798:        }
                    799: #ifdef DEBUG
                    800:        debug("Status reg = %x on return\n", s); /* */
                    801: #endif
                    802:        return((s & EXCEP)?SUCCESS:ERROR);  /* return exception if it occured */
                    803: }
                    804: 
                    805: pollrdy()
                    806: {
                    807:        int      sps;
                    808: #ifdef DEBUG
                    809:        debug("Pollrdy\n");
                    810: #endif
                    811:        sps = splbio();
                    812:        while (wtio) {
                    813:                int error;
                    814: 
                    815:                if (error = tsleep((caddr_t)&wci, WTPRI | PCATCH,
                    816:                        "wtpoll", 0)) {
                    817:                        splx(sps);
                    818:                        return(error);
                    819:                }
                    820:        }
                    821:        splx(sps);
                    822: #ifdef DEBUG
                    823:        debug("Finish poll, wci %d exflag %d\n", wci, exflag);
                    824: #endif
                    825:        return (EIO);
                    826: }
                    827: 
                    828: wtdma()                /* start up i/o operation, called from dma() in wtlib1.s */
                    829: {
                    830:        wtio = 1;
                    831:        if (!wtimeron)
                    832:        {
                    833:                wtimeron = 1;
                    834:                timeout(wtimer, (caddr_t) 0, HZ/2);
                    835:        }
                    836: }
                    837: 
                    838: wtwake()       /* end i/o operation, called from isr() in wtlib1.s */
                    839: {
                    840:        wtio = 0;
                    841:        wakeup(&wci);
                    842: }
                    843: 
                    844: pageset()
                    845: {
                    846:        unsigned long pp;
                    847: 
                    848:        pp = (unsigned long) pagebuf;
                    849:        pageaddr = kvtop(pp);
                    850: #ifdef DEBUG
                    851:        debug("pageset: addr %lx\n", pageaddr);
                    852: #endif
                    853: }
                    854: 
                    855: 
                    856: 
                    857: #define near
                    858: 
                    859: static near
                    860: sendcmd()
                    861: {
                    862:        /* desired command in global mbits */
                    863: 
                    864:        outb(CTLPORT, mbits | REQUEST);         /* set request */
                    865:        while (inb(STATPORT) & READY);          /* wait for ready */
                    866:        outb(CTLPORT, mbits & ~REQUEST);        /* reset request */
                    867:        while ((inb(STATPORT) & READY) == 0);   /* wait for not ready */
                    868: }
                    869: 
                    870: static near            /* execute command */
                    871: cmds(cmd)
                    872: {
                    873:        register s;
                    874: 
                    875:        do s = inb(STATPORT);
                    876:        while ((s & STAT) == STAT);     /* wait for ready */
                    877: 
                    878:        if ((s & EXCEP) == 0)           /* if exception */
                    879:                return ERROR;           /* error */
                    880:        
                    881:        outb(CMDPORT, cmd);             /* output the command   */
                    882: 
                    883:        outb(CTLPORT, mbits=ONLINE);    /* set & send ONLINE    */
                    884:        sendcmd();
                    885: 
                    886:        return SUCCESS;
                    887: }
                    888: 
                    889: qicmd(cmd)
                    890: {
                    891:        return cmds(cmd);
                    892: }
                    893: 
                    894: rstart()
                    895: {
                    896:        return cmds(RDDATA);
                    897: }
                    898: 
                    899: rmark()
                    900: {
                    901:        return cmds(READFM);
                    902: }
                    903: 
                    904: wstart()
                    905: {
                    906:        return cmds(WRTDATA);
                    907: }
                    908: 
                    909: ioend()
                    910: {
                    911:        register s;
                    912:        register rval = SUCCESS;
                    913: 
                    914:        do s = inb(STATPORT);
                    915:        while ((s & STAT) == STAT);     /* wait for ready */
                    916: 
                    917:        if ((s & EXCEP) == 0)           /* if exception */
                    918:                rval = ERROR;           /* error */
                    919:        
                    920:        mbits &= ~ONLINE;
                    921:        outb(CTLPORT, mbits);           /* reset ONLINE */
                    922:        outb(MASKREG, wtchan+4);        /* turn off dma */
                    923:        outb(CLEARFF, 0);               /* reset direction flag */
                    924: 
                    925:        return rval;
                    926: }
                    927: 
                    928: wmark()
                    929: {
                    930:        register s;
                    931: 
                    932:        if (cmds(WRITEFM) == ERROR)
                    933:                return ERROR;
                    934: 
                    935:        do s = inb(STATPORT);
                    936:        while ((s & STAT) == STAT);     /* wait for ready */
                    937: 
                    938:        if ((s & EXCEP) == 0)           /* if exception */
                    939:                return ERROR;           /* error */
                    940: 
                    941:        return SUCCESS;
                    942: }
                    943: 
                    944: rwind()
                    945: {
                    946:        register s;
                    947: 
                    948:        mbits = CMDOFF;
                    949: 
                    950:        do s = inb(STATPORT);
                    951:        while ((s & STAT) == STAT);     /* wait for ready */
                    952: 
                    953:        outb(CMDPORT, REWIND);
                    954:        sendcmd();
                    955: 
                    956:        return SUCCESS;
                    957: }
                    958: 
                    959: rdstatus(stp)
                    960: char *stp;             /* pointer to 6 byte buffer */
                    961: {
                    962:        register s;
                    963:        int n;
                    964: 
                    965:        do s = inb(STATPORT);
                    966:        while ((s & STAT) == STAT);     /* wait for ready or exception */
                    967: 
                    968:        outb(CMDPORT, RDSTAT);
                    969:        sendcmd();                      /* send read status command */
                    970: 
                    971:        for (n=0; n<6; n++)
                    972:        {
                    973: #ifdef DEBUGx
                    974:                debug("rdstatus: waiting, byte %d\n", n);
                    975: #endif
                    976:                do s = inb(STATPORT);
                    977:                while ((s & STAT) == STAT);     /* wait for ready */
                    978: #ifdef DEBUGx
                    979:                debug("rdstatus: done\n");
                    980: #endif
                    981:                if ((s & EXCEP) == 0)           /* if exception */
                    982:                        return ERROR;           /* error */
                    983: 
                    984:                *stp++ = inb(DATAPORT);         /* read status byte */
                    985: 
                    986:                outb(CTLPORT, mbits | REQUEST); /* set request */
                    987: #ifdef DEBUGx
                    988:                debug("rdstatus: waiting after request, byte %d\n", n);
                    989: #endif
                    990:                while ((inb(STATPORT)&READY) == 0);     /* wait for not ready */
                    991:                for (s=100; s>0; s--);          /* wait an additional time */
                    992: 
                    993:                outb(CTLPORT, mbits & ~REQUEST);/* unset request */
                    994: #ifdef DEBUGx
                    995:                debug("rdstatus: done\n");
                    996: #endif
                    997:        }
                    998:        return SUCCESS;
                    999: }
                   1000: 
                   1001: t_reset()
                   1002: {
                   1003:        register i;
                   1004:        mbits |= RESET;
                   1005:        outb(CTLPORT, mbits);           /* send reset */
                   1006:        delay(20);
                   1007:        mbits &= ~RESET;
                   1008:        outb(CTLPORT, mbits);           /* turn off reset */
                   1009:        if ((inb(STATPORT) & RESETMASK) == RESETVAL)
                   1010:                return SUCCESS;
                   1011:        return ERROR;
                   1012: }
                   1013: 
                   1014: static
                   1015: dma()
                   1016: {
                   1017:        int x=splbio();
                   1018:        wtdma();
                   1019:        outb(CLEARFF, 0);
                   1020:        outb(MODEREG, mode);    /* set dma mode */
                   1021:        outb(dmareg, bufptr & 0xFF);
                   1022:        outb(dmareg, (bufptr>>8) & 0xFF);
                   1023:        outb(pagereg, (bufptr>>16) & 0xFF);                         
                   1024:        outb(dmareg+1, (BLKSIZE-1) & 0xFF);
                   1025:        outb(dmareg+1, (BLKSIZE-1) >> 8);
                   1026:        outb(wtport, eqdma+ONLINE);
                   1027:        outb(MASKREG, wtchan);  /* enable command to 8237, start dma */
                   1028:        splx(x);
                   1029: }
                   1030: 
                   1031: static near
                   1032: wtstart(buf, cnt)
                   1033: long buf;
                   1034: int cnt;
                   1035: {
                   1036:        register s;
                   1037: 
                   1038:        bufptr = buf;           /* init statics */
                   1039:        numbytes = cnt;
                   1040:        wci = 0;                /* init flags */
                   1041:        exflag = 0;
                   1042:        bytes = 0;              /* init counter */
                   1043: 
                   1044:        do s = inb(STATPORT) & STAT;
                   1045:        while (s == STAT);      /* wait for ready or error */
                   1046: 
                   1047:        if (s & EXCEP)          /* no error */
                   1048:        {
                   1049:                dma();
                   1050:                return SUCCESS;
                   1051:        }
                   1052:        return ERROR;           /* error */
                   1053: }
                   1054: 
                   1055: rtape(buf, cnt)
                   1056: long buf;                      /* physical address */
                   1057: int cnt;                       /* number of bytes */
                   1058: {
                   1059:        mode = dma_read;
                   1060:        return wtstart(buf,cnt);
                   1061: }
                   1062: 
                   1063: wtape(buf, cnt)
                   1064: long buf;                      /* physical address */
                   1065: int cnt;                       /* number of bytes */
                   1066: {
                   1067:        mode = dma_write;
                   1068:        return wtstart(buf,cnt);
                   1069: }
                   1070: 
                   1071: isr()
                   1072: {
                   1073:        int stat = inb(wtport);
                   1074:        if (!(stat & EXCEP))    /* exception during I/O */
                   1075:        {
                   1076:                if (bytes + BLKSIZE >= numbytes) wci = 1;
                   1077:                exflag = 1;
                   1078:                goto isrwake;
                   1079:        }
                   1080:        if ((stat & READY) || !(inb(STATUSREG) & dma_done))
                   1081:                return;
                   1082:        exflag = 0;
                   1083:        outb(wtport, ONLINE);
                   1084:        bytes += BLKSIZE;
                   1085:        if (bytes >= numbytes)  /* normal completion of I/O */
                   1086:        {
                   1087:                wci = 1;
                   1088: isrwake:
                   1089:                outb(MASKREG, 4+wtchan);        /* turn off dma */
                   1090:                wtwake();                       /* wake up user level */
                   1091:        }
                   1092:        else
                   1093:        {                       /* continue I/O */
                   1094:                bufptr += BLKSIZE;
                   1095:                dma();
                   1096:        }
                   1097: }
                   1098: 
                   1099: wtlinit()
                   1100: {
                   1101:        switch (wtchan) {
                   1102:        case 1:
                   1103:                return;
                   1104:        case 2:
                   1105:                pagereg = 0x81;
                   1106:                dma_done = 4;
                   1107:                break;
                   1108:        case 3:
                   1109:                eqdma = 0x10;
                   1110:                pagereg = 0x82;
                   1111:                dma_done = 8;
                   1112:                break;
                   1113:        }
                   1114:        dma_write = wtchan+0x48;
                   1115:        dma_read = wtchan+0x44;
                   1116:        dmareg = wtchan+wtchan;
                   1117: }
                   1118: 
                   1119: /*
                   1120:  * delay i microseconds
                   1121:  */
                   1122: delay(i)
                   1123: register int i;
                   1124: {
                   1125:        while (i-- > 0)
                   1126:                DELAY(1000);
                   1127: }
                   1128: 
                   1129: wtsize()
                   1130: {
                   1131: }
                   1132: 
                   1133: wtdump()
                   1134: {
                   1135: }
                   1136: 
                   1137: #include "i386/isa/isa_device.h"
                   1138: #include "i386/isa/icu.h"
                   1139: 
                   1140: int    wtprobe(), wtattach();
                   1141: struct isa_driver wtdriver = {
                   1142:        wtprobe, wtattach, "wt",
                   1143: };
                   1144: 
                   1145: wtprobe(dvp)
                   1146:        struct isa_device *dvp;
                   1147: {
                   1148:        int val,i,s;
                   1149: 
                   1150: #ifdef lint
                   1151:        wtintr(0);
                   1152: #endif
                   1153: 
                   1154:        wtport = dvp->id_iobase;
                   1155:        if(t_reset() != SUCCESS) return(0);
                   1156:        return(1);
                   1157: }
                   1158: 
                   1159: wtattach() { }
                   1160: 
                   1161: #endif NWT

unix.superglobalmegacorp.com

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