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