|
|
1.1 root 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: * @(#)uu.c 7.1 (Berkeley) 6/5/86
7: */
8:
9: #include "uu.h"
10: #if NUU > 0
11: /*
12: * TU58 DECtape II/DL11 device driver
13: *
14: * The TU58 is treated as a block device (only). Error detection and
15: * recovery is not very extensive, but sufficient to handle the most
16: * common errors. It is assumed that the TU58 will follow the RSP
17: * protocol exactly, very few protocol errors are checked for.
18: *
19: * To reduce interrupt latency, `options UUDMA' should be specified
20: * in the config file to make sure the `pseudo-DMA' code in locore.s
21: * will be compiled into the system. Otherwise overrun errors will
22: * occur frequently (these errors are not reported).
23: *
24: * TODO:
25: *
26: * - Add ioctl code to wind/rewind cassette
27: *
28: */
29:
30: #include "../machine/pte.h"
31:
32: #include "param.h"
33: #include "systm.h"
34: #include "buf.h"
35: #include "conf.h"
36: #include "time.h"
37: #include "kernel.h"
38: #include "errno.h"
39: #include "file.h"
40:
41: #include "../vax/cpu.h"
42: #include "../vax/nexus.h"
43: #include "../vax/rsp.h"
44:
45: #include "ubavar.h"
46: #include "ubareg.h"
47: #include "uureg.h"
48:
49: #define NTUBLK 512 /* number of blocks on a TU58 cassette */
50: #define WRV 01 /* bit in minor dev => write w. read verify */
51: #define NDPC 02 /* drives per controller */
52: #define NUX NDPC * NUU /* number of drives */
53: #define NUUQ 02 /* # of block which can be queued up */
54: #define UMASK 01 /* unit number mask */
55: #define UUIPL 0x14 /* ipl level to use */
56:
57: struct packet uucmd[NUU]; /* a command sent to the TU58 */
58: struct packet uudata[NUU]; /* a command or data returned from TU58 */
59: struct buf uitab[NUU]; /* buffer queue headers */
60:
61: /*
62: * Driver soft carrier structure
63: */
64: struct uu_softc {
65: u_char *tu_rbptr; /* pointer to buffer for read */
66: int tu_rcnt; /* how much to read */
67: u_char *tu_wbptr; /* pointer to buffer for write */
68: int tu_wcnt; /* how much to write */
69: int tu_state; /* current state of tansfer operation */
70: int tu_flag; /* read in progress flag */
71: char *tu_addr; /* real buffer data address */
72: int tu_count; /* real requested count */
73: int tu_serrs; /* count of soft errors */
74: int tu_cerrs; /* count of checksum errors */
75: int tu_herrs; /* count of hard errors */
76: char tu_dopen[2]; /* drive is open */
77: } uu_softc[NUU];
78:
79: #if defined(VAX750) || defined(VAX730)
80: extern char *tustates[];
81: #else
82: char *tustates[TUS_NSTATES] = {
83: "INIT1", "INIT2", "IDLE", "SENDH", "SENDD", "SENDC", "SENDR",
84: "SENDW", "GETH", "GETD", "GETC", "GET", "WAIT", "RCVERR", "CHKERR"
85: };
86: #endif
87:
88: #define UNIT(dev) (minor(dev)>>1)
89:
90: u_char uunull[2] = { 0, 0 }; /* nulls to send for initialization */
91: u_char uuinit[2] = { TUF_INITF, TUF_INITF }; /* inits to send */
92:
93: struct uba_device *uudinfo[NUU];
94:
95: int uuprobe(), uuattach(), uurintr(), uuxintr(), uuwatch();
96: u_short uustd[] = { 0176500, 0 };
97: struct uba_driver uudriver =
98: { uuprobe, 0, uuattach, 0, uustd, "uu", uudinfo };
99:
100: int uuwstart;
101: int uuwake();
102: static char uu_pcnt[NUX]; /* pee/vee counters, one per drive */
103:
104: /*ARGSUSED*/
105: uuprobe(reg)
106: caddr_t reg;
107: {
108: register int br, cvec; /* value result */
109: struct uudevice *uuaddr = (struct uudevice *)reg;
110:
111: #ifdef lint
112: br = 0; cvec = br; br = cvec;
113: uurintr(0); uuxintr(0);
114: #endif
115: uuaddr->tcs = UUCS_INTR;
116: DELAY(1000);
117: uuaddr->tcs = 0;
118: cvec -= 4; /* since we are using the xmitter intrpt */
119: return(sizeof (*uuaddr));
120: }
121:
122: uuattach(ui)
123: register struct uba_device *ui;
124: {
125: }
126:
127: /*ARGSUSED1*/
128: uuopen(dev, flag)
129: dev_t dev;
130: int flag;
131: {
132: register struct uba_device *ui;
133: register struct uu_softc *uuc;
134: register struct uudevice *uuaddr;
135: int ctlr, unit = UNIT(dev), s;
136:
137: ctlr = unit / NDPC;
138: if (unit >= NUX || (ui = uudinfo[ctlr]) == 0 || ui->ui_alive == 0)
139: return (ENXIO);
140: uuc = &uu_softc[ctlr];
141: if (uuc->tu_dopen[unit&UMASK])
142: return (EBUSY);
143: if (uuwstart++ == 0)
144: timeout(uuwatch, (caddr_t)0, hz);
145:
146: uuc->tu_dopen[unit&UMASK]++;
147: uuaddr = (struct uudevice *)ui->ui_addr;
148: s = splx(UUIPL);
149: /*
150: * If the other device on this controller
151: * is already active, no need to initialize
152: */
153: if (uuc->tu_dopen[0] && uuc->tu_dopen[1])
154: goto ok;
155:
156: /*
157: * If the unit already initialized,
158: * just enable interrupts and return.
159: */
160: if (uuc->tu_state == TUS_IDLE) {
161: uuaddr->rcs = UUCS_INTR;
162: goto ok;
163: }
164:
165: /*
166: * Must initialize, reset the cassette
167: * and wait for things to settle down.
168: */
169: uureset(ctlr);
170: sleep((caddr_t)uuc, PZERO+1);
171: uitab[ctlr].b_active = NULL;
172: if (uuc->tu_state != TUS_IDLE) {
173: uuc->tu_state = TUS_INIT1;
174: uuc->tu_dopen[unit&UMASK] = 0;
175: uuc->tu_rcnt = uuc->tu_wcnt = 0;
176: uuaddr->rcs = 0;
177: uuaddr->tcs = 0;
178: splx(s);
179: return (EIO);
180: }
181: ok:
182: splx(s);
183: return (0);
184: }
185:
186: /*
187: * Wait for all outstanding IO on this drive
188: * complete, before closing. If both drives on
189: * this controller are idle, mark the controller
190: * `inactive'.
191: */
192:
193: uuclose(dev, flag)
194: dev_t dev;
195: int flag;
196: {
197: int s, unit = UNIT(dev);
198: register struct uu_softc *uuc = &uu_softc[unit/NDPC];
199: struct buf *bp, *last = NULL;
200: struct uudevice *uuaddr = (struct uudevice *)uudinfo[unit/NDPC]->ui_addr;
201:
202: s = splx(UUIPL);
203: while (uu_pcnt[unit])
204: sleep(&uu_pcnt[unit], PRIBIO);
205: /*
206: * No more writes are pending, scan the
207: * buffer queue for oustanding reads from
208: * this unit.
209: */
210: for (bp = uitab[unit/NDPC].b_actf; bp; bp = bp->b_actf) {
211: if (bp->b_dev == dev)
212: last = bp;
213: }
214: if (last) {
215: last->b_flags |= B_CALL;
216: last->b_iodone = uuwake;
217: sleep((caddr_t)last, PRIBIO);
218: }
219: uuc->tu_dopen[unit&UMASK] = 0;
220: if (!uuc->tu_dopen[0] && !uuc->tu_dopen[1]) {
221: uuc->tu_flag = 0;
222: uuaddr->rcs = 0;
223: }
224: splx(s);
225: }
226:
227: uuwake(bp)
228: struct buf *bp;
229: {
230: wakeup(bp);
231: }
232:
233: uureset(ctlr)
234: int ctlr;
235: {
236: register struct uu_softc *uuc = &uu_softc[ctlr];
237: register struct packet *cmd = &uucmd[ctlr];
238: struct uba_device *ui = uudinfo[ctlr];
239: register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr;
240:
241: uitab[ctlr].b_active++;
242: uuc->tu_state = TUS_INIT1;
243: uuc->tu_wbptr = uunull;
244: uuc->tu_wcnt = sizeof (uunull);
245: uuc->tu_rcnt = 0;
246: cmd->pk_flag = TUF_CMD;
247: cmd->pk_mcount = sizeof (*cmd) - 4;
248: cmd->pk_mod = 0;
249: cmd->pk_seq = 0;
250: cmd->pk_sw = 0;
251: uuaddr->rcs = 0;
252: uuaddr->tcs = UUCS_INTR | UUCS_BREAK;
253: uuxintr(ctlr); /* start output */
254: }
255:
256: /*
257: * Strategy routine for block I/O
258: */
259: uustrategy(bp)
260: register struct buf *bp;
261: {
262: register struct buf *uutab;
263: struct uba_device *ui;
264: int s, unit = UNIT(bp->b_dev);
265:
266: if ((unit > NUX) || (bp->b_blkno >= NTUBLK))
267: goto bad;
268: ui = uudinfo[unit/NDPC];
269: if (ui == 0 || ui->ui_alive == 0)
270: goto bad;
271: uutab = &uitab[unit/NDPC]; /* one request queue per controller */
272: s = splx(UUIPL);
273: if ((bp->b_flags&B_READ) == 0)
274: tu_pee(&uu_pcnt[unit]);
275: bp->b_actf = NULL;
276: if (uutab->b_actf == NULL)
277: uutab->b_actf = bp;
278: else
279: uutab->b_actl->b_actf = bp;
280: uutab->b_actl = bp;
281: if (uutab->b_active == 0)
282: uustart(ui);
283: splx(s);
284: return;
285:
286: bad:
287: bp->b_flags |= B_ERROR;
288: bp->b_error = ENXIO;
289: iodone(bp);
290: return;
291: }
292:
293: /*
294: * Start the transfer
295: */
296: uustart(ui)
297: register struct uba_device *ui;
298: {
299: register struct buf *bp;
300: register struct uu_softc *uuc;
301: struct packet *cmd;
302: int ctlr = ui->ui_unit, s;
303:
304: if ((bp = uitab[ctlr].b_actf) == NULL)
305: return;
306: s = splx(UUIPL);
307: uuc = &uu_softc[ctlr];
308: if (uuc->tu_state != TUS_IDLE) {
309: uureset(ctlr);
310: splx(s);
311: return;
312: }
313: cmd = &uucmd[ctlr];
314: uitab[ctlr].b_active++;
315: uitab[ctlr].b_errcnt = 0;
316: uuc->tu_addr = bp->b_un.b_addr;
317: uuc->tu_count = cmd->pk_count = bp->b_bcount;
318: cmd->pk_block = bp->b_blkno;
319: if (bp->b_flags&B_READ) {
320: cmd->pk_op = TUOP_READ;
321: cmd->pk_mod = 0;
322: uuc->tu_state = TUS_SENDR;
323: } else {
324: cmd->pk_op = TUOP_WRITE;
325: cmd->pk_mod = minor(bp->b_dev)&WRV ? TUMD_WRV : 0;
326: uuc->tu_state = TUS_SENDW;
327: }
328: cmd->pk_unit = UNIT(bp->b_dev)&UMASK;
329: cmd->pk_sw = 0;
330: cmd->pk_chksum =
331: tuchk(*((short *)cmd), (u_short *)&cmd->pk_op, (int)cmd->pk_mcount);
332: uuc->tu_wbptr = (u_char *)cmd;
333: uuc->tu_wcnt = sizeof (*cmd);
334: uuxintr(ctlr);
335: splx(s);
336: }
337:
338: /*
339: * TU58 receiver interrupt, handles whatever condition the
340: * pseudo DMA routine in locore is unable to handle,
341: * or, if UUDMA is undefined, handle all receiver interrupt
342: * processing.
343: */
344: uurintr(ctlr)
345: int ctlr;
346: {
347: struct uba_device *ui = uudinfo[ctlr];
348: register struct uu_softc *uuc = &uu_softc[ctlr];
349: register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr;
350: register struct buf *uutab = &uitab[ctlr];
351: struct packet *data, *cmd;
352: struct buf *bp;
353: int c, unit;
354:
355: c = uuaddr->rdb;
356: data = &uudata[ctlr];
357: cmd = &uucmd[ctlr];
358: #if !defined(UUDMA)
359: if (c & UURDB_ERROR)
360: uuc->tu_state = TUS_RCVERR;
361: else {
362: if (uuc->tu_rcnt) {
363: *uuc->tu_rbptr++ = c;
364: if (--uuc->tu_rcnt)
365: return;
366: }
367: }
368: #endif
369:
370: /*
371: * Switch on the tu_state of the transfer.
372: */
373: switch(uuc->tu_state) {
374:
375: /*
376: * A data error occured in uudma
377: * (either overrun or break)
378: */
379: case TUS_RCVERR:
380: if ((c & UURDB_ORUN) == 0)
381: printf("uu%d: break received, transfer restarted\n",
382: data->pk_unit);
383: #ifdef UUDEBUG
384: else
385: printf("uu%d: data overrun, recovered\n",
386: data->pk_unit);
387: #endif
388: uuc->tu_serrs++;
389: uu_restart(ctlr, ui);
390: break;
391:
392: /*
393: * If we get an unexpected "continue",
394: * start all over again...
395: */
396: case TUS_INIT2:
397: uuc->tu_state = c == TUF_CONT ? TUS_IDLE : TUS_INIT1;
398: uuc->tu_flag = 0;
399: wakeup((caddr_t)uuc);
400: uustart(ui);
401: break;
402:
403: /*
404: * Only transition from this state
405: * is on a "continue", so if we don't
406: * get it, reset the world.
407: */
408: case TUS_WAIT: /* waiting for continue */
409: switch(c) {
410: case TUF_CONT: /* got the expected continue */
411: uuc->tu_flag = 0;
412: data->pk_flag = TUF_DATA;
413: data->pk_mcount = MIN(128, uuc->tu_count);
414: data->pk_chksum =
415: tuchk(*((short *)data), (caddr_t)uuc->tu_addr,
416: (int)data->pk_mcount);
417: uuc->tu_state = TUS_SENDH;
418: uuc->tu_wbptr = (u_char *)data;
419: uuc->tu_wcnt = 2;
420: uuxintr(ctlr);
421: break;
422:
423: case TUF_CMD: /* sending us an END packet...error */
424: uuc->tu_state = TUS_GET;
425: uuc->tu_rbptr = (u_char *)data;
426: uuc->tu_rcnt = sizeof (*data) - 1;
427: uuc->tu_flag = 1;
428: uuaddr->tcs = 0;
429: *uuc->tu_rbptr++ = c & UUDB_DMASK;
430: break;
431:
432: case TUF_INITF:
433: uureset(ctlr);
434: break;
435:
436: default: /* something random...bad news */
437: uuc->tu_state = TUS_INIT1;
438: break;
439: }
440: break;
441:
442: case TUS_SENDW:
443: if (c != TUF_CONT && c != TUF_INITF)
444: goto bad;
445: uu_restart(ctlr, ui);
446: break;
447:
448: /*
449: * Got header, now get data; amount to
450: * fetch is included in packet.
451: * (data packets are handled entirely
452: * in uudma)
453: */
454: case TUS_GETH:
455: #ifndef UUDMA
456: if (data->pk_flag == TUF_DATA)
457: uuc->tu_rbptr = (u_char *)uuc->tu_addr;
458: #endif
459: uuc->tu_rcnt = data->pk_mcount;
460: uuc->tu_state = TUS_GETD;
461: break;
462:
463: /*
464: * Got the data, now fetch the checksum.
465: */
466: case TUS_GETD:
467: uuc->tu_rbptr = (u_char *)&data->pk_chksum;
468: uuc->tu_rcnt = sizeof (data->pk_chksum);
469: uuc->tu_state = TUS_GETC;
470: break;
471:
472: case TUS_GETC:
473: /* got entire packet */
474: if (data->pk_chksum !=
475: tuchk(*((short *)data), (u_short *)
476: (data->pk_flag == TUF_DATA ?
477: (u_short *) uuc->tu_addr : (u_short *)&data->pk_op),
478: (int)data->pk_mcount))
479: case TUS_CHKERR:
480: uuc->tu_cerrs++;
481: case TUS_GET:
482: if (data->pk_flag == TUF_DATA) {
483: /* data packet, advance to next */
484: uuc->tu_addr += data->pk_mcount;
485: uuc->tu_count -= data->pk_mcount;
486: uuc->tu_state = TUS_GETH;
487: uuc->tu_rbptr = (u_char *)data; /* next packet */
488: uuc->tu_rcnt = 2;
489: } else if (data->pk_flag==TUF_CMD && data->pk_op==TUOP_END) {
490: /* end packet, idle and reenable transmitter */
491: uuc->tu_state = TUS_IDLE;
492: uuc->tu_flag = 0;
493: uuaddr->tcs = UUCS_INTR;
494: if ((bp = uutab->b_actf) == NULL) {
495: printf("uu%d: no bp, active %d\n",
496: data->pk_unit, uitab[ctlr].b_active);
497: uustart(ui);
498: return;
499: }
500: unit = UNIT(bp->b_dev);
501: if (data->pk_mod > 1) { /* hard error */
502: printf("uu%d: hard error bn%d,", unit,
503: bp->b_blkno);
504: printf(" pk_mod 0%o\n", data->pk_mod&0xff);
505: bp->b_flags |= B_ERROR;
506: uuc->tu_herrs++;
507: } else if (data->pk_mod) /* soft error */
508: uuc->tu_serrs++;
509: uutab->b_active = NULL;
510: uutab->b_actf = bp->b_actf;
511: bp->b_resid = uuc->tu_count;
512: if ((bp->b_flags&B_READ) == 0)
513: tu_vee(&uu_pcnt[unit]);
514: iodone(bp);
515: uustart(ui);
516: } else {
517: /*
518: * Neither data nor end: data was lost
519: * somehow, flush and restart the transfer.
520: */
521: uuaddr->rcs = 0;
522: uu_restart(ctlr, ui);
523: uuc->tu_serrs++;
524: }
525: break;
526:
527: case TUS_IDLE:
528: case TUS_INIT1:
529: break;
530:
531: default:
532: bad:
533: if (c == TUF_INITF) {
534: printf("uu%d protocol error, state=", data->pk_unit);
535: printstate(uuc->tu_state);
536: printf(", op=%x, cnt=%d, block=%d\n",
537: cmd->pk_op, cmd->pk_count, cmd->pk_block);
538: uutab->b_active = NULL;
539: if (bp = uutab->b_actf) {
540: bp->b_flags |= B_ERROR;
541: uutab->b_actf = bp->b_actf;
542: if ((bp->b_flags&B_READ) == 0)
543: tu_vee(&uu_pcnt[unit]);
544: iodone(bp);
545: }
546: uuc->tu_state = TUS_INIT1;
547: } else {
548: printf("uu%d receive state error, state=",
549: data->pk_unit);
550: printstate(uuc->tu_state);
551: printf(", byte=%x\n", c & 0xff);
552: #ifdef notdef
553: uuc->tu_state = TUS_INIT1;
554: #endif
555: wakeup((caddr_t)uuc);
556: }
557: }
558: }
559:
560:
561: /*
562: * TU58 transmitter interrupt
563: */
564: uuxintr(ctlr)
565: int ctlr;
566: {
567: register struct uu_softc *uuc = &uu_softc[ctlr];
568: register struct uudevice *uuaddr;
569: register struct packet *data;
570: struct uba_device *ui = uudinfo[ctlr];
571: int c;
572:
573: data = &uudata[ctlr];
574: uuaddr = (struct uudevice *) ui->ui_addr;
575: top:
576: if (uuc->tu_wcnt > 0) {
577: /* still stuff to send, send one byte */
578: while ((uuaddr->tcs & UUCS_READY) == 0)
579: ;
580: uuaddr->tdb = *uuc->tu_wbptr++;
581: uuc->tu_wcnt--;
582: return;
583: }
584:
585: /*
586: * Last message byte was sent out.
587: * Switch on tu_state of transfer.
588: */
589: switch(uuc->tu_state) {
590:
591: /*
592: * Two nulls have been sent, remove break, and send inits
593: */
594: case TUS_INIT1:
595: uuc->tu_flag = 0;
596: uuaddr->tcs = UUCS_INTR;
597: uuc->tu_state = TUS_INIT2;
598: uuc->tu_wbptr = uuinit;
599: uuc->tu_wcnt = sizeof (uuinit);
600: goto top;
601:
602: /*
603: * Inits have been sent, wait for a continue msg.
604: */
605: case TUS_INIT2:
606: c = uuaddr->rdb; /* prevent overrun error */
607: uuaddr->rcs = UUCS_INTR;
608: uuc->tu_flag = 1;
609: break;
610:
611: /*
612: * Read cmd packet sent, get ready for data
613: */
614: case TUS_SENDR:
615: uuc->tu_state = TUS_GETH;
616: uuc->tu_rbptr = (u_char *)data;
617: uuc->tu_rcnt = 2;
618: uuc->tu_flag = 1;
619: uuaddr->tcs = 0;
620: uuaddr->rcs = UUCS_INTR;
621: break;
622:
623: /*
624: * Write cmd packet sent, wait for continue
625: */
626: case TUS_SENDW:
627: uuc->tu_state = TUS_WAIT;
628: uuc->tu_flag = 1;
629: if ((uuaddr->rcs&UUCS_INTR) == 0) {
630: printf("NO IE\n");
631: uuaddr->rcs = UUCS_INTR;
632: }
633: break;
634:
635: /*
636: * Header sent, send data.
637: */
638: case TUS_SENDH:
639: uuc->tu_state = TUS_SENDD;
640: uuc->tu_wbptr = (u_char *)uuc->tu_addr;
641: uuc->tu_wcnt = data->pk_mcount;
642: goto top;
643:
644: /*
645: * Data sent, follow with checksum.
646: */
647: case TUS_SENDD:
648: uuc->tu_state = TUS_SENDC;
649: uuc->tu_wbptr = (u_char *)&data->pk_chksum;
650: uuc->tu_wcnt = 2;
651: goto top;
652:
653: /*
654: * Checksum sent, wait for continue.
655: */
656: case TUS_SENDC:
657: /*
658: * Update buffer address and count.
659: */
660: uuc->tu_addr += data->pk_mcount;
661: uuc->tu_count -= data->pk_mcount;
662: if (uuc->tu_count > 0) {
663: uuc->tu_state = TUS_WAIT;
664: uuc->tu_flag = 1;
665: break;
666: }
667:
668: /*
669: * End of transmission, get ready for end packet.
670: */
671: uuc->tu_state = TUS_GET;
672: uuc->tu_rbptr = (u_char *)data;
673: uuc->tu_rcnt = sizeof (*data);
674: uuc->tu_flag = 1;
675: uuaddr->tcs = 0;
676: break;
677:
678: /*
679: * Random interrupt
680: */
681: case TUS_IDLE: /* stray interrupt? */
682:
683: default:
684: break;
685: }
686: }
687:
688: uuwatch()
689: {
690: register struct uu_softc *uuc;
691: register struct uudevice *uuaddr;
692: struct uba_device *ui;
693: struct buf *bp, *uutab;
694: int s, ctlr, active = 0;
695:
696: for (ctlr=0; ctlr<NUU; ctlr++) {
697: int i;
698:
699: uuc = &uu_softc[ctlr];
700:
701: if (uuc->tu_dopen[0] || uuc->tu_dopen[1])
702: active++;
703: if (uuc->tu_flag == 0)
704: /*
705: * If no read is in progress
706: * just skip
707: */
708: continue;
709:
710: ui = uudinfo[ctlr];
711: uuaddr = (struct uudevice *)ui->ui_addr;
712: uutab = &uitab[ctlr];
713: if (uuc->tu_flag++ < 40)
714: continue;
715: printf("uu%d: read stalled\n", uudata[ctlr].pk_unit);
716: #ifdef UUDEBUG
717: printf("%X %X %X %X %X %X %X\n", uuc->tu_rbptr, uuc->tu_rcnt,
718: uuc->tu_wbptr, uuc->tu_wcnt, uuc->tu_state, uuc->tu_addr,
719: uuc->tu_count);
720: #endif
721: s = splx(UUIPL);
722: uuc->tu_flag = 0;
723: i = uuaddr->rdb; /* dummy */
724: uuaddr->rcs = UUCS_INTR; /* in case we were flushing */
725: uuaddr->tcs = UUCS_INTR;
726: uuc->tu_state = TUS_IDLE;
727: if (!uutab->b_active) {
728: wakeup((caddr_t)uuc);
729: goto retry;
730: }
731: if (++uutab->b_errcnt <= 1) {
732: uustart(ui);
733: goto retry;
734: }
735: if (bp = uutab->b_actf) {
736: bp->b_flags |= B_ERROR;
737: if ((bp->b_flags&B_READ) == 0)
738: tu_vee(&uu_pcnt[UNIT(bp->b_dev)]);
739: iodone(bp);
740: }
741: retry:
742: (void) splx(s);
743: }
744: if (active)
745: timeout(uuwatch, (caddr_t)0, hz);
746: else
747: uuwstart = 0;
748: return;
749: }
750:
751: #if !defined(VAX750) && !defined(VAX730)
752: /*
753: * Compute checksum TU58 fashion
754: */
755: #ifdef lint
756: tuchk(word, cp, n)
757: register word;
758: register unsigned short *cp;
759: int n;
760: {
761: register int c = n >> 1;
762: register long temp;
763:
764: do {
765: temp = *cp++; /* temp, only because vax cc won't *r++ */
766: word += temp;
767: } while (--c > 0);
768: if (n & 1)
769: word += *(unsigned char *)cp;
770: while (word & 0xffff0000)
771: word = (word & 0xffff) + ((word >> 16) & 0xffff);
772: return (word);
773: }
774: #else
775: tuchk(word0, wp, n)
776: register int word0; /* r11 */
777: register char *wp; /* r10 */
778: register int n; /* r9 */
779: {
780: asm("loop:");
781: asm(" addw2 (r10)+,r11"); /* add a word to sum */
782: asm(" adwc $0,r11"); /* add in carry, end-around */
783: asm(" acbl $2,$-2,r9,loop"); /* done yet? */
784: asm(" blbc r9,ok"); /* odd byte count? */
785: asm(" movzbw (r10),r10"); /* yes, get last byte */
786: asm(" addw2 r10,r11"); /* add it in */
787: asm(" adwc $0,r11"); /* and the carry */
788: asm("ok:");
789: asm(" movl r11,r0"); /* return sum */
790: }
791: #endif
792:
793: /*
794: * Make sure this incredibly slow device
795: * doesn't eat up all the buffers in the
796: * system by putting the requesting process
797: * (remember: this device is 'single-user')
798: * to sleep if the write-behind queue grows
799: * larger than NUUQ.
800: */
801: tu_pee(cp)
802: char *cp;
803: {
804: register int s;
805:
806: s = splx(UUIPL);
807: if (++(*cp) > NUUQ)
808: sleep(cp, PRIBIO);
809: splx(s);
810: }
811:
812: tu_vee(cp)
813: char *cp;
814: {
815: register int s;
816:
817: s = splx(UUIPL);
818: if (--(*cp) <= NUUQ)
819: wakeup(cp);
820: splx(s);
821: }
822: #endif
823:
824: uuioctl(dev, cmd, data, flag)
825: dev_t dev;
826: caddr_t data;
827: {
828: /*
829: * add code to wind/rewind cassette here
830: */
831: return (ENXIO);
832: }
833:
834: uu_restart(ctlr, ui)
835: int ctlr;
836: struct uba_device *ui;
837: {
838: uureset(ctlr);
839: timeout(uustart, (caddr_t)ui, hz * 3);
840: }
841:
842: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.