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