xref: /original-bsd/sys/vax/vax/tu.c (revision 18f6d767)
1 /*	tu.c	6.4	84/08/28	*/
2 
3 #if defined(VAX750) || defined(VAX730)
4 /*
5  * TU58 DECtape II device driver
6  *
7  * TU58 console cassette driver (for VAX-11/750 or VAX-11/730).
8  * The TU58 is treated as a block device (only).  Error detection and
9  * recovery is not extensive, but sufficient for most situations. It is
10  * assumed that the TU58 will follow the RSP (or MRSP) protocol exactly,
11  * very few protocol errors are checked for.  It is also assumed that
12  * the 730 uses Modified RSP (MRSP), while the 750 may use either RSP
13  * or MRSP depending on whether defined(MRSP) is true or not.
14  * In the case of a 750 without MRSP, the only way for the CPU to
15  * keep up with the tu58 is to lock out virtually everything else.
16  *
17  * NOTE: Reading large amounts of data from the tu58 is likely
18  *	 to crash your system if you are running multiuser.
19  *	 	******FOR SINGLE USER USE ONLY*****
20  */
21 #include "param.h"
22 #include "systm.h"
23 #include "buf.h"
24 #include "conf.h"
25 #include "dir.h"
26 #include "user.h"
27 #include "kernel.h"
28 
29 #include "cpu.h"
30 #include "mtpr.h"
31 #include "rsp.h"
32 
33 #define	printd	if(tudebug) printf
34 #ifdef	printd
35 int	tudebug;	/* printd */
36 #endif	printd
37 
38 #define	NTU	((cpu == VAX_750) ? 1 : 2)
39 #define DNUM    01		/* mask for drive number (should match NTU) */
40 #define	NTUBLK	512		/* number of blocks on a TU58 cassette */
41 #define WRV     02              /* bit in minor dev => write w. read verify */
42 #define NTUQ    2               /* # of blocks which can be queued up */
43 #define	TUIPL	((cpu == VAX_750) ? 0x17 : 0x14)
44 
45 #ifndef MRSP
46 #define MRSP (cpu != VAX_750)
47 #endif
48 
49 /*
50  * State information
51  */
52 struct tu {
53 	u_char	*tu_rbptr;	/* pointer to buffer for read */
54 	int	tu_rcnt;	/* how much to read */
55 	u_char	*tu_wbptr;	/* pointer to buffer for write */
56 	int	tu_wcnt;	/* how much to write */
57 	int	tu_state;	/* current state of tansfer operation */
58 	int	tu_flag;	/* read in progress flag */
59 	char	*tu_addr;	/* real buffer data address */
60 	int	tu_count;	/* real requested count */
61 	int	tu_serrs;	/* count of soft errors */
62 	int	tu_cerrs;	/* count of checksum errors */
63 	int	tu_herrs;	/* count of hard errors */
64 	char    tu_dopen[2];	/* drive is open */
65 } tu;
66 
67 
68 /*
69  * Device register bits
70  */
71 #define	READY	0200		/* transmitter ready */
72 #define	DONE	0200		/* receiver done */
73 #define	IE	0100		/* interrupt enable */
74 #define	BREAK	1		/* send break */
75 
76 struct packet tucmd;		/* a command sent to the TU58 */
77 struct packet tudata;		/* a command or data returned from TU58 */
78 
79 char *tustates[TUS_NSTATES] = {
80 	"INIT1", "INIT2", "IDLE", "SENDH", "SENDD", "SENDC", "SENDR",
81 	"SENDW", "GETH", "GETD", "GETC", "GET", "WAIT", "RCVERR", "CHKERR"
82 };
83 
84 u_char	tunull[2] = { 0, 0 };	/* nulls to send for initialization */
85 u_char	tuinit[2] = { TUF_INITF, TUF_INITF };	/* inits to send */
86 static char tu_pcnt[2];            		/* pee/vee counters */
87 int	tutimer = 0;
88 int	tuwake();
89 struct buf tutab;				/* I/O queue header */
90 
91 /*
92  * Open the TU58
93  */
94 /*ARGSUSED*/
95 tuopen(dev, flag)
96 {
97 	extern int tuwatch();
98 	register s;
99 
100 #ifdef lint
101 	turintr(); tuwintr();
102 #endif
103 	if ((minor(dev)&DNUM) >= NTU)
104 		return (ENXIO);
105 	if (tu.tu_dopen[minor(dev)&DNUM])
106 		return (EBUSY);
107 	if (tutimer++ == 0)
108 		timeout(tuwatch, (caddr_t)0, hz);
109 
110 	s = splx(TUIPL);
111 	tu.tu_dopen[minor(dev)&DNUM]++;
112 	/*
113 	 * If the cassette's already initialized,
114 	 * just enable interrupts and return.
115 	 */
116 	if (tu.tu_state == TUS_IDLE) {
117 		mtpr(CSRS, IE);
118 		goto ok;
119 	}
120 
121 	/*
122 	 * Must initialize, reset the cassette
123 	 * and wait for things to settle down.
124 	 */
125 	tureset();
126 	sleep((caddr_t)&tu, PZERO+1);
127 	tutab.b_active = NULL;
128 	if (tu.tu_state != TUS_IDLE) {
129 		tu.tu_state = TUS_INIT1;
130 		tu.tu_dopen[minor(dev)&DNUM] = 0;
131 		tu.tu_rcnt = tu.tu_wcnt = 0;
132 		mtpr(CSTS, 0);
133 		mtpr(CSRS, 0);
134 		splx(s);
135 		return (EIO);
136 	}
137 ok:
138 	splx(s);
139 	return (0);
140 }
141 
142 /*
143  * Close the TU58, but make sure all
144  * outstanding i/o is complete first..
145  */
146 tuclose(dev, flag)
147 	dev_t dev;
148 	int flag;
149 {
150 	int s, unit = minor(dev);
151 	struct buf *bp, *last = NULL;
152 
153 	s = splx(TUIPL);
154 	while (tu_pcnt[unit])
155 		sleep(&tu_pcnt[unit], PRIBIO);
156 	/*
157 	 * No more writes are pending, scan the
158 	 * buffer queue for oustanding reads from
159 	 * this unit.
160 	 */
161 	for (bp = tutab.b_actf; bp; bp = bp->b_actf) {
162 		if (bp->b_dev == dev)
163 			last = bp;
164 	}
165 	if (last) {
166 		last->b_flags |= B_CALL;
167 		last->b_iodone = tuwake;
168 		sleep((caddr_t)last, PRIBIO);
169 	}
170 	tu.tu_dopen[unit&DNUM] = 0;
171 	if (!tu.tu_dopen[0] && !tu.tu_dopen[1]) {
172 		tutimer = 0;
173 		mtpr(CSRS, 0);
174 		tu.tu_flag = 0;
175 	}
176 	splx(s);
177 }
178 
179 tuwake(bp)
180 	struct buf *bp;
181 {
182 	wakeup(bp);
183 }
184 
185 /*
186  * Reset the TU58
187  */
188 tureset()
189 {
190 
191 	mtpr(CSRS, 0);
192 	tu.tu_state = TUS_INIT1;
193 	tu.tu_wbptr = tunull;
194 	tu.tu_wcnt = sizeof (tunull);
195 	tucmd.pk_flag = TUF_CMD;
196 	tucmd.pk_mcount = sizeof (tucmd) - 4;
197 	tucmd.pk_mod = 0;
198 	tucmd.pk_seq = 0;
199 	tucmd.pk_sw = MRSP ? TUSW_MRSP : 0;
200 	tutab.b_active++;
201 	mtpr(CSTS, IE | BREAK);
202 	tuxintr();			/* start output */
203 }
204 
205 /*
206  * Strategy routine for block I/O
207  */
208 tustrategy(bp)
209 	register struct buf *bp;
210 {
211 	register int s;
212 
213 	if (bp->b_blkno >= NTUBLK) {
214 		bp->b_flags |= B_ERROR;
215 		iodone(bp);
216 		return;
217 	}
218 	if ((bp->b_flags&B_READ) == 0)
219 		tu_pee(&tu_pcnt[minor(bp->b_dev)&DNUM]);
220 	bp->av_forw = NULL;
221 	s = splx(TUIPL);
222 	if (tutab.b_actf == NULL)
223 		tutab.b_actf = bp;
224 	else
225 		tutab.b_actl->av_forw = bp;
226 	tutab.b_actl = bp;
227 	if (tutab.b_active == NULL)
228 		tustart();
229 	splx(s);
230 }
231 
232 /*
233  * Start the transfer
234  */
235 tustart()
236 {
237 	register struct buf *bp;
238 	int s;
239 
240 	if ((bp = tutab.b_actf) == NULL)
241 		return;
242 	s = splx(TUIPL);
243 	if (tu.tu_state != TUS_IDLE) {
244 		tureset();
245 		splx(s);
246 		return;
247 	}
248 	tutab.b_active++;
249 	tutab.b_errcnt = 0;
250 	tucmd.pk_op = bp->b_flags&B_READ ? TUOP_READ : TUOP_WRITE;
251 	tucmd.pk_mod = ((bp->b_flags&B_READ) == 0 && (minor(bp->b_dev)&WRV)) ?
252 	    TUMD_WRV : 0;
253 	tucmd.pk_unit = (minor(bp->b_dev)&DNUM);
254 	tucmd.pk_sw = MRSP ? TUSW_MRSP : 0;
255 	tucmd.pk_count = tu.tu_count = bp->b_bcount;
256 	tucmd.pk_block = bp->b_blkno;
257 	tucmd.pk_chksum =
258 	    tuchk(*((short *)&tucmd), (u_short *)&tucmd.pk_op,
259 		(int)tucmd.pk_mcount);
260 	tu.tu_state = bp->b_flags&B_READ ? TUS_SENDR : TUS_SENDW;
261 	tu.tu_addr = bp->b_un.b_addr;
262 	tu.tu_wbptr = (u_char *)&tucmd;
263 	tu.tu_wcnt = sizeof (tucmd);
264 	tuxintr();
265 	splx(s);
266 }
267 
268 /*
269  * TU58 receiver interrupt
270  */
271 turintr()
272 {
273 	register struct buf *bp;
274 	register int c;
275 
276 	c = mfpr(CSRD)&0xff;
277 	if (MRSP) {
278 		while ((mfpr(CSTS)&READY) == 0)
279 			;
280 		mtpr(CSTD, TUF_CONT);			/* ACK */
281 		if (tu.tu_rcnt) {
282 			*tu.tu_rbptr++ = c;
283 			if (--tu.tu_rcnt)
284 				return;
285 		}
286 	}
287 
288 	/*
289 	 * Switch on the state of the transfer.
290 	 */
291 	switch(tu.tu_state) {
292 
293 	/*
294 	 * Probably an overrun error,
295 	 * cannot happen if MRSP is used
296 	 */
297 	case TUS_RCVERR:
298 		mtpr(CSRS, 0);					/* flush */
299 		printf("overrun error, transfer restarted\n");	/* DEBUG */
300 		tu.tu_serrs++;
301 		tu_restart();
302 		break;
303 
304 	/*
305 	 * If we get an unexpected "continue",
306 	 * start all over again...
307 	 */
308 	case TUS_INIT2:
309 		tu.tu_state = c == TUF_CONT ? TUS_IDLE : TUS_INIT1;
310 		tu.tu_flag = 0;
311 		wakeup((caddr_t)&tu);
312 		tustart();
313 		break;
314 
315 	/*
316 	 * Only transition from this state
317 	 * is on a "continue", so if we don't
318 	 * get it, reset the world.
319 	 */
320 	case TUS_WAIT:			/* waiting for continue */
321 		switch(c) {
322 		case TUF_CONT:  /* got the expected continue */
323 			tu.tu_flag = 0;
324 			tudata.pk_flag = TUF_DATA;
325 			tudata.pk_mcount = MIN(128, tu.tu_count);
326 			tudata.pk_chksum =
327 			    tuchk(*((short *)&tudata), (caddr_t)tu.tu_addr,
328 				(int)tudata.pk_mcount);
329 			tu.tu_state = TUS_SENDH;
330 			tu.tu_wbptr = (u_char *)&tudata;
331 			tu.tu_wcnt = 2;
332 			tuxintr();
333 			break;
334 
335 		case TUF_CMD:   /* sending us an END packet...error */
336 			tu.tu_state = TUS_GET;
337 			tu.tu_rbptr = (u_char *) &tudata;
338 			tu.tu_rcnt = sizeof (tudata) - 1;
339 			tu.tu_flag = 1;
340 			mtpr (CSTS, 0);
341 			*tu.tu_rbptr = c;
342 			break;
343 
344 		case TUF_INITF:
345 			tureset();
346 			break;
347 
348 		default:        /* something random...bad news */
349 			tu.tu_state = TUS_INIT1;
350 			break;
351 		}
352 		break;
353 
354 	case TUS_SENDW:
355 		if (c != TUF_CONT && c != TUF_INITF)
356 			goto bad;
357 		tureset();
358 		break;
359 
360 	/*
361 	 * Got header, now get data; amount to
362 	 * fetch is included in packet.
363 	 */
364 	case TUS_GETH:
365 		if (MRSP && (tudata.pk_flag == TUF_DATA))
366 			tu.tu_rbptr = (u_char *)tu.tu_addr;
367 		tu.tu_rcnt = tudata.pk_mcount;
368 		tu.tu_state = TUS_GETD;
369 		break;
370 
371 	/*
372 	 * Got the data, now fetch the checksum.
373 	 */
374 	case TUS_GETD:
375 		tu.tu_rbptr = (u_char *)&tudata.pk_chksum;
376 		tu.tu_rcnt = sizeof (tudata.pk_chksum);
377 		tu.tu_state = TUS_GETC;
378 		break;
379 
380 	case TUS_CHKERR:		/* from tudma only */
381 		tu.tu_cerrs++;
382 		goto tus_get;
383 
384 	case TUS_GET:
385 		if (MRSP)
386 			/*
387 		 	 * The checksum has already been calculated and
388 		 	 * verified in the pseudo DMA routine
389 		 	 */
390 			goto tus_get;
391 
392 	case TUS_GETC:
393 		/* got entire packet */
394 		if (tudata.pk_chksum !=
395 		    tuchk(*((short *)&tudata), (u_short *)
396 		     (tudata.pk_flag == TUF_DATA ?
397 		     (u_short *) tu.tu_addr : (u_short *)&tudata.pk_op),
398 		     (int)tudata.pk_mcount))
399 			tu.tu_cerrs++;
400 tus_get:
401 		if (tudata.pk_flag == TUF_DATA) {
402 			/* data packet, advance to next */
403 			tu.tu_addr += tudata.pk_mcount;
404 			tu.tu_count -= tudata.pk_mcount;
405 			tu.tu_state = TUS_GETH;
406 			tu.tu_rbptr = (u_char *)&tudata; /* next packet */
407 			tu.tu_rcnt = 2;
408 		} else if (tudata.pk_flag==TUF_CMD && tudata.pk_op==TUOP_END) {
409 			/* end packet, idle and reenable transmitter */
410 			tu.tu_state = TUS_IDLE;
411 			tu.tu_flag = 0;
412 			mtpr(CSTS, IE);
413 			printd("ON ");
414 			if ((bp = tutab.b_actf) == NULL) {
415 				printf("tu%d: no bp, active %d\n",
416 					tudata.pk_unit, tutab.b_active);
417 				tustart();
418 				return;
419 			}
420 			if (tudata.pk_mod > 1) {        /* hard error */
421 				bp->b_flags |= B_ERROR;
422 				tu.tu_herrs++;
423 				printf("tu%d: hard error bn%d,",
424 					minor(bp->b_dev)&DNUM, bp->b_blkno);
425 				printf("  pk_mod %o\n", tudata.pk_mod&0377);
426 			} else if (tudata.pk_mod != 0)	/* soft error */
427 				tu.tu_serrs++;
428 			tutab.b_active = NULL;
429 			tutab.b_actf = bp->av_forw;
430 			bp->b_resid = tu.tu_count;
431 			if ((bp->b_flags&B_READ) == 0)
432 				tu_vee(&tu_pcnt[minor(bp->b_dev)&DNUM]);
433 			iodone(bp);
434 			tustart();
435 		} else {
436 			/*
437 			 * Neither data nor end: data was lost
438 			 * somehow, restart the transfer
439 			 */
440 			mtpr(CSRS, 0);		/* flush the rest */
441 			tu_restart();
442 			tu.tu_serrs++;
443 		}
444 		break;
445 
446 	case TUS_IDLE:
447 	case TUS_INIT1:
448 		break;
449 
450 	default:
451 bad:
452 		if (c == TUF_INITF) {
453 			printf("tu%d protocol error, state=",
454 							(int)tudata.pk_unit);
455 			printstate(tu.tu_state);
456 			printf(", op=%x, cnt=%d, block=%d\n",
457 			    tucmd.pk_op, tucmd.pk_count, tucmd.pk_block);
458 			tutab.b_active = NULL;
459 			if (bp = tutab.b_actf) {
460 				bp->b_flags |= B_ERROR;
461 				tutab.b_actf = bp->av_forw;
462 				if ((bp->b_flags&B_READ) == 0)
463 					tu_vee(&tu_pcnt[minor(bp->b_dev)&DNUM]);
464 				iodone(bp);
465 			}
466 			tu.tu_state = TUS_INIT1;
467 		} else {
468 			printf("tu%d: receive state error, state=",
469 						(int)tudata.pk_unit);
470 			printstate(tu.tu_state);
471 			printf(", byte=%x\n", c & 0xff);
472 			if (tutab.b_actf)
473 				tu_restart();
474 			else
475 				wakeup((caddr_t)&tu);
476 		}
477 	}
478 }
479 
480 /*
481  * TU58 transmitter interrupt
482  */
483 tuxintr()
484 {
485 
486 top:
487 	if (tu.tu_wcnt) {
488 		/* still stuff to send, send one byte */
489 		while ((mfpr(CSTS) & READY) == 0)
490 			;
491 		mtpr(CSTD, *tu.tu_wbptr++);
492 		tu.tu_wcnt--;
493 		return;
494 	}
495 
496 	/*
497 	 * Last message byte was sent out.
498 	 * Switch on state of transfer.
499 	 */
500 	if (tudebug) {
501 		printf("tuxintr: state=");
502 		printstate(tu.tu_state);
503 	}
504 	switch(tu.tu_state) {
505 
506 	/*
507 	 * Two nulls have been sent, remove break, and send inits
508 	 */
509 	case TUS_INIT1:
510 		mtpr(CSTS, IE);
511 		printd("ON2 ");
512 		tu.tu_state = TUS_INIT2;
513 		tu.tu_wbptr = tuinit;
514 		tu.tu_wcnt = sizeof (tuinit);
515 		goto top;
516 
517 	/*
518 	 * Inits have been sent, wait for a continue msg.
519 	 */
520 	case TUS_INIT2:
521 		(void) mfpr(CSRD);
522 		mtpr(CSRS, IE);
523 		tu.tu_flag = 1;
524 		break;
525 
526 	/*
527 	 * Read cmd packet sent, get ready for data
528 	 */
529 	case TUS_SENDR:
530 		tu.tu_state = TUS_GETH;
531 		tu.tu_rbptr = (u_char *)&tudata;
532 		tu.tu_rcnt = 2;
533 		tu.tu_flag = 1;
534 		mtpr(CSTS, 0);	/* disable transmitter interrupts */
535 		printd("OFF ");
536 		break;
537 
538 	/*
539 	 * Write cmd packet sent, wait for continue
540 	 */
541 	case TUS_SENDW:
542 		tu.tu_state = TUS_WAIT;
543 		tu.tu_flag = 1;
544 		if ((mfpr(CSRS)&IE) == 0) {
545 			printf("NO IE\n");
546 			mtpr(CSRS, IE);
547 		}
548 		break;
549 
550 	/*
551 	 * Header sent, send data.
552 	 */
553 	case TUS_SENDH:
554 		tu.tu_state = TUS_SENDD;
555 		tu.tu_wbptr = (u_char *)tu.tu_addr;
556 		tu.tu_wcnt = tudata.pk_mcount;
557 		goto top;
558 
559 	/*
560 	 * Data sent, follow with checksum.
561 	 */
562 	case TUS_SENDD:
563 		tu.tu_state = TUS_SENDC;
564 		tu.tu_wbptr = (u_char *)&tudata.pk_chksum;
565 		tu.tu_wcnt = sizeof tudata.pk_chksum;
566 		goto top;
567 
568 	/*
569 	 * Checksum sent, wait for continue.
570 	 */
571 	case TUS_SENDC:
572 		/*
573 		 * Updata buffer address and count.
574 		 */
575 		tu.tu_addr += tudata.pk_mcount;
576 		tu.tu_count -= tudata.pk_mcount;
577 		if (tu.tu_count) {
578 			tu.tu_state = TUS_WAIT;
579 			tu.tu_flag = 1;
580 			break;
581 		}
582 
583 		/*
584 		 * End of transmission, get ready for end packet.
585 		 */
586 		tu.tu_state = TUS_GET;
587 		tu.tu_rbptr = (u_char *)&tudata;
588 		tu.tu_rcnt = sizeof (tudata);
589 		tu.tu_flag = 1;
590 		mtpr(CSTS, 0);
591 		printd("OFF2 ");
592 		break;
593 
594 	/*
595 	 * Random interrupt, probably from MRSP ACK
596 	 */
597 	case TUS_IDLE:
598 
599 	default:
600 		break;
601 
602 	}
603 	if (tudebug) {
604 		printd("  new tu_state=");
605 		printstate(tu.tu_state);
606 	}
607 }
608 
609 /*
610  * Compute checksum TU58 fashion
611  */
612 #ifdef lint
613 tuchk(word, cp, n)
614 	register word;
615 	register unsigned short *cp;
616 	int n;
617 {
618 	register int c = n >> 1;
619 	register long temp;
620 
621 	do {
622 		temp = *cp++;	/* temp, only because vax cc won't *r++ */
623 		word += temp;
624 	} while (--c > 0);
625 	if (n & 1)
626 		word += *(unsigned char *)cp;
627 	while (word & 0xffff0000)
628 		word = (word & 0xffff) + ((word >> 16) & 0xffff);
629 	return (word);
630 }
631 #else
632 tuchk(word0, wp, n)
633 	register int word0;	/* r11 */
634 	register char *wp;	/* r10 */
635 	register int n;		/* r9 */
636 {
637 	asm("loop:");
638 	asm("	addw2	(r10)+,r11");	/* add a word to sum */
639 	asm("	adwc	$0,r11");	/* add in carry, end-around */
640 	asm("	acbl	$2,$-2,r9,loop");	/* done yet? */
641 	asm("	blbc	r9,ok");	/* odd byte count? */
642 	asm("	movzbw	(r10),r10");	/* yes, get last byte */
643 	asm("	addw2	r10,r11");	/* add it in */
644 	asm("	adwc	$0,r11");	/* and the carry */
645 	asm("ok:");
646 	asm("	movl	r11,r0");	/* return sum */
647 }
648 #endif
649 
650 tuwatch()
651 {
652 	register int s;
653 	register struct buf *bp;
654 
655 	if (tutimer == 0)
656 		return;
657 
658 	if (tu.tu_flag == 0) {		/* if no read in progress - skip */
659 		timeout(tuwatch, (caddr_t)0, hz);
660 		return;
661 	}
662 	if (tu.tu_flag++ <= 40) {
663 		timeout(tuwatch, (caddr_t)0, hz);
664 		return;
665 	}
666 	printf("tu%d: read stalled\n", tudata.pk_unit);
667 #ifdef TUDEBUG
668 	printf("%X %X %X %X %X %X %X %X\n", tu.tu_rbptr, tu.tu_rcnt,
669 		tu.tu_wbptr, tu.tu_wcnt, tu.tu_state, tu.tu_flag,
670 		tu.tu_addr, tu.tu_count);
671 #endif
672 	s = splx(TUIPL);
673 	tu.tu_flag = 0;
674 	(void) mfpr(CSRD);
675 	mtpr(CSRS, IE);		/* in case we were flushing */
676 	mtpr(CSTS, IE);
677 	tu.tu_state = TUS_IDLE;
678 	if (!tutab.b_active) {
679 		wakeup((caddr_t)&tu);
680 		goto retry;
681 	}
682 	if (++tutab.b_errcnt <= 1) {
683 		tustart();
684 		goto retry;
685 	}
686 	if (bp = tutab.b_actf) {
687 		bp->b_flags |= B_ERROR;
688 		if ((bp->b_flags&B_READ) == 0)
689 			tu_vee(&tu_pcnt[minor(bp->b_dev)&DNUM]);
690 		iodone(bp);
691 	}
692 retry:
693 	splx(s);
694 	timeout(tuwatch, (caddr_t)0, hz);
695 }
696 
697 tu_pee(cp)
698 	char *cp;
699 {
700 	register int s;
701 
702 	s = splx(TUIPL);
703 	if (++(*cp) > NTUQ)
704 		sleep(cp, PRIBIO);
705 	splx(s);
706 }
707 
708 tu_vee(cp)
709 	char *cp;
710 {
711 	register int s;
712 
713 	s = splx(TUIPL);
714 	if (--(*cp) <= NTUQ)
715 		wakeup(cp);
716 	splx(s);
717 }
718 
719 tu_restart()
720 {
721 	tureset();
722 	timeout(tustart, (caddr_t)0, hz * 3);
723 }
724 
725 #endif
726