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

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

unix.superglobalmegacorp.com

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