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

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

unix.superglobalmegacorp.com

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