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