|
|
1.1 root 1: /*
2: * Copyright (c) 1988 Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * Computer Consoles Inc.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: *
36: *
37: * @(#)cy.c 7.8 (Berkeley) 5/8/91
38: */
39:
40: #include "yc.h"
41: #if NCY > 0
42: /*
43: * Cipher Tapemaster driver.
44: */
45: #define CYDEBUG
46: #ifdef CYDEBUG
47: int cydebug = 0;
48: #define dlog(params) if (cydebug) log params
49: #else
50: #define dlog(params) /* */
51: #endif
52:
53: #include "sys/param.h"
54: #include "sys/systm.h"
55: #include "sys/vm.h"
56: #include "sys/buf.h"
57: #include "sys/file.h"
58: #include "sys/signal.h"
59: #include "sys/ioctl.h"
60: #include "sys/mtio.h"
61: #include "sys/errno.h"
62: #include "sys/cmap.h"
63: #include "sys/time.h"
64: #include "sys/kernel.h"
65: #include "sys/syslog.h"
66: #include "sys/tprintf.h"
67:
68: #include "../include/cpu.h"
69: #include "../include/mtpr.h"
70: #include "../include/pte.h"
71:
72: #include "../vba/vbavar.h"
73: #define CYERROR
74: #include "../vba/cyreg.h"
75:
76: /*
77: * There is a ccybuf per tape controller.
78: * It is used as the token to pass to the internal routines
79: * to execute tape ioctls, and also acts as a lock on the slaves
80: * on the controller, since there is only one per controller.
81: * In particular, when the tape is rewinding on close we release
82: * the user process but any further attempts to use the tape drive
83: * before the rewind completes will hang waiting for ccybuf.
84: */
85: struct buf ccybuf[NCY];
86:
87: int cyprobe(), cyslave(), cyattach();
88: struct buf ycutab[NYC];
89: short yctocy[NYC];
90: struct vba_ctlr *cyminfo[NCY];
91: struct vba_device *ycdinfo[NYC];
92: long cystd[] = { 0 };
93: struct vba_driver cydriver =
94: { cyprobe, cyslave, cyattach, 0, cystd, "yc", ycdinfo, "cy", cyminfo };
95:
96: /* bits in minor device */
97: #define YCUNIT(dev) (minor(dev)&03)
98: #define CYUNIT(dev) (yctocy[YCUNIT(dev)])
99: #define T_NOREWIND 0x04
100: #define T_1600BPI 0x00 /* pseudo */
101: #define T_3200BPI 0x08 /* unused */
102:
103: #define INF 1000000L /* close to infinity */
104:
105: /*
106: * Software state and shared command areas per controller.
107: *
108: * The i/o intermediate buffer must be allocated in startup()
109: * so its address will fit in 20-bits (YECH!!!!!!!!!!!!!!).
110: */
111: struct cy_softc {
112: int cy_bs; /* controller's buffer size */
113: struct cyscp *cy_scp; /* system configuration block address */
114: struct cyccb cy_ccb; /* channel control block */
115: struct cyscb cy_scb; /* system configuration block */
116: struct cytpb cy_tpb; /* tape parameter block */
117: struct cytpb cy_nop; /* nop parameter block for cyintr */
118: struct vb_buf cy_rbuf; /* vba resources */
119: } cy_softc[NCY];
120:
121: /*
122: * Software state per tape transport.
123: */
124: struct yc_softc {
125: char yc_openf; /* lock against multiple opens */
126: char yc_lastiow; /* last operation was a write */
127: short yc_tact; /* timeout is active */
128: long yc_timo; /* time until timeout expires */
129: u_short yc_control; /* copy of last tpcb.tpcontrol */
130: u_short yc_status; /* copy of last tpcb.tpstatus */
131: u_short yc_resid; /* copy of last bc */
132: u_short yc_dens; /* prototype control word with density info */
133: tpr_t yc_tpr; /* handle for tprintf */
134: daddr_t yc_blkno; /* block number, for block device tape */
135: daddr_t yc_nxrec; /* position of end of tape, if known */
136: int yc_blksize; /* current tape blocksize estimate */
137: int yc_blks; /* number of I/O operations since open */
138: int yc_softerrs; /* number of soft I/O errors since open */
139: } yc_softc[NYC];
140:
141: /*
142: * States for vm->um_tab.b_active, the per controller state flag.
143: * This is used to sequence control in the driver.
144: */
145: #define SSEEK 1 /* seeking */
146: #define SIO 2 /* doing seq i/o */
147: #define SCOM 3 /* sending control command */
148: #define SREW 4 /* sending a rewind */
149: #define SERASE 5 /* erase inter-record gap */
150: #define SERASED 6 /* erased inter-record gap */
151:
152: /* there's no way to figure these out dynamically? -- yech */
153: struct cyscp *cyscp[] =
154: { (struct cyscp *)0xc0000c06, (struct cyscp *)0xc0000c16 };
155: #define NCYSCP (sizeof (cyscp) / sizeof (cyscp[0]))
156:
157: cyprobe(reg, vm)
158: caddr_t reg;
159: struct vba_ctlr *vm;
160: {
161: register br, cvec; /* must be r12, r11 */
162: register struct cy_softc *cy;
163: int ctlr = vm->um_ctlr;
164:
165: #ifdef lint
166: br = 0; cvec = br; br = cvec;
167: cyintr(0);
168: #endif
169: if (badcyaddr(reg+1))
170: return (0);
171: if (ctlr > NCYSCP || cyscp[ctlr] == 0) /* XXX */
172: return (0);
173: cy = &cy_softc[ctlr];
174: cy->cy_scp = cyscp[ctlr]; /* XXX */
175: /*
176: * Tapemaster controller must have interrupt handler
177: * disable interrupt, so we'll just kludge things
178: * (stupid multibus non-vectored interrupt crud).
179: */
180: if (cyinit(ctlr, reg)) {
181: uncache(&cy->cy_tpb.tpcount);
182: cy->cy_bs = htoms(cy->cy_tpb.tpcount);
183: /*
184: * Setup nop parameter block for clearing interrupts.
185: */
186: cy->cy_nop.tpcmd = CY_NOP;
187: cy->cy_nop.tpcontrol = 0;
188: /*
189: * Allocate page tables.
190: */
191: if (cybuf == 0) {
192: printf("no cy buffer!!!\n");
193: return (0);
194: }
195: cy->cy_rbuf.vb_rawbuf = cybuf + ctlr * CYMAXIO;
196: if (vbainit(&cy->cy_rbuf, CYMAXIO, VB_20BIT) == 0) {
197: printf("cy%d: vbainit failed\n", ctlr);
198: return (0);
199: }
200:
201: br = 0x13, cvec = 0x80; /* XXX */
202: return (sizeof (struct cyccb));
203: } else
204: return (0);
205: }
206:
207: /*
208: * Check to see if a drive is attached to a controller.
209: * Since we can only tell that a drive is there if a tape is loaded and
210: * the drive is placed online, we always indicate the slave is present.
211: */
212: cyslave(vi, addr)
213: struct vba_device *vi;
214: caddr_t addr;
215: {
216:
217: #ifdef lint
218: vi = vi; addr = addr;
219: #endif
220: return (1);
221: }
222:
223: cyattach(vi)
224: struct vba_device *vi;
225: {
226: register struct cy_softc *cy;
227: int ctlr = vi->ui_mi->um_ctlr;
228:
229: yctocy[vi->ui_unit] = ctlr;
230: cy = &cy_softc[ctlr];
231: if (vi->ui_slave == 0 && cy->cy_bs)
232: printf("; %dkb buffer", cy->cy_bs/1024);
233: }
234:
235: /*
236: * Initialize the controller after a controller reset or
237: * during autoconfigure. All of the system control blocks
238: * are initialized and the controller is asked to configure
239: * itself for later use.
240: */
241: cyinit(ctlr, addr)
242: int ctlr;
243: register caddr_t addr;
244: {
245: register struct cy_softc *cy = &cy_softc[ctlr];
246: register int *pte;
247:
248: /*
249: * Initialize the system configuration pointer.
250: */
251: /* make kernel writable */
252: pte = (int *)&Sysmap[btop((int)cy->cy_scp &~ KERNBASE)];
253: *pte &= ~PG_PROT; *pte |= PG_KW;
254: mtpr(TBIS, cy->cy_scp);
255: /* load the correct values in the scp */
256: cy->cy_scp->csp_buswidth = CSP_16BITS;
257: cyldmba(cy->cy_scp->csp_scb, (caddr_t)&cy->cy_scb);
258: /* put it back to read-only */
259: *pte &= ~PG_PROT; *pte |= PG_KR;
260: mtpr(TBIS, cy->cy_scp);
261:
262: /*
263: * Init system configuration block.
264: */
265: cy->cy_scb.csb_fixed = CSB_FIXED;
266: /* set pointer to the channel control block */
267: cyldmba(cy->cy_scb.csb_ccb, (caddr_t)&cy->cy_ccb);
268:
269: /*
270: * Initialize the chanel control block.
271: */
272: cy->cy_ccb.cbcw = CBCW_CLRINT;
273: cy->cy_ccb.cbgate = GATE_OPEN;
274: /* set pointer to the tape parameter block */
275: cyldmba(cy->cy_ccb.cbtpb, (caddr_t)&cy->cy_tpb);
276:
277: /*
278: * Issue a nop cmd and get the internal buffer size for buffered i/o.
279: */
280: cy->cy_tpb.tpcmd = CY_NOP;
281: cy->cy_tpb.tpcontrol = CYCW_16BITS;
282: cy->cy_ccb.cbgate = GATE_CLOSED;
283: CY_GO(addr);
284: if (cywait(&cy->cy_ccb) || (cy->cy_tpb.tpstatus&CYS_ERR)) {
285: uncache(&cy->cy_tpb.tpstatus);
286: printf("cy%d: timeout or err during init, status=%b\n", ctlr,
287: cy->cy_tpb.tpstatus, CYS_BITS);
288: return (0);
289: }
290: cy->cy_tpb.tpcmd = CY_CONFIG;
291: cy->cy_tpb.tpcontrol = CYCW_16BITS;
292: cy->cy_ccb.cbgate = GATE_CLOSED;
293: CY_GO(addr);
294: if (cywait(&cy->cy_ccb) || (cy->cy_tpb.tpstatus&CYS_ERR)) {
295: uncache(&cy->cy_tpb.tpstatus);
296: printf("cy%d: configuration failure, status=%b\n", ctlr,
297: cy->cy_tpb.tpstatus, CYS_BITS);
298: return (0);
299: }
300: return (1);
301: }
302:
303: int cytimer();
304: /*
305: * Open the device. Tapes are unique open
306: * devices, so we refuse if it is already open.
307: * We also check that a tape is available, and
308: * don't block waiting here; if you want to wait
309: * for a tape you should timeout in user code.
310: */
311: cyopen(dev, flag)
312: dev_t dev;
313: register int flag;
314: {
315: register int ycunit;
316: register struct vba_device *vi;
317: register struct yc_softc *yc;
318:
319: ycunit = YCUNIT(dev);
320: if (ycunit >= NYC || (vi = ycdinfo[ycunit]) == 0 || vi->ui_alive == 0)
321: return (ENXIO);
322: if ((yc = &yc_softc[ycunit])->yc_openf)
323: return (EBUSY);
324: yc->yc_openf = 1;
325: #define PACKUNIT(vi) \
326: (((vi->ui_slave&1)<<11)|((vi->ui_slave&2)<<9)|((vi->ui_slave&4)>>2))
327: /* no way to select density */
328: yc->yc_dens = PACKUNIT(vi)|CYCW_IE|CYCW_16BITS;
329: if (yc->yc_tact == 0) {
330: yc->yc_timo = INF;
331: yc->yc_tact = 1;
332: timeout(cytimer, (caddr_t)dev, 5*hz);
333: }
334: cycommand(dev, CY_SENSE, 1);
335: if ((yc->yc_status&CYS_OL) == 0) { /* not on-line */
336: uprintf("cy%d: not online\n", ycunit);
337: yc->yc_openf = 0;
338: return (EIO);
339: }
340: if ((flag&FWRITE) && (yc->yc_status&CYS_WP)) {
341: uprintf("cy%d: no write ring\n", ycunit);
342: yc->yc_openf = 0;
343: return (EIO);
344: }
345: yc->yc_blkno = (daddr_t)0;
346: yc->yc_nxrec = INF;
347: yc->yc_lastiow = 0;
348: yc->yc_blksize = CYMAXIO; /* guess > 0 */
349: yc->yc_blks = 0;
350: yc->yc_softerrs = 0;
351: yc->yc_tpr = tprintf_open();
352: return (0);
353: }
354:
355: /*
356: * Close tape device.
357: *
358: * If tape was open for writing or last operation was a write,
359: * then write two EOF's and backspace over the last one.
360: * Unless this is a non-rewinding special file, rewind the tape.
361: * Make the tape available to others.
362: */
363: cyclose(dev, flag)
364: dev_t dev;
365: int flag;
366: {
367: struct yc_softc *yc = &yc_softc[YCUNIT(dev)];
368:
369: if (flag == FWRITE || (flag&FWRITE) && yc->yc_lastiow) {
370: cycommand(dev, CY_WEOF, 1); /* can't use count with WEOF */
371: cycommand(dev, CY_WEOF, 1);
372: cycommand(dev, CY_SREV, 1);
373: }
374: if ((minor(dev)&T_NOREWIND) == 0)
375: /*
376: * 0 count means don't hang waiting for rewind complete
377: * rather ccybuf stays busy until the operation completes
378: * preventing further opens from completing by preventing
379: * a CY_SENSE from completing.
380: */
381: cycommand(dev, CY_REW, 0);
382: if (yc->yc_blks > 10 && yc->yc_softerrs > yc->yc_blks / 10)
383: log(LOG_INFO, "yc%d: %d soft errors in %d blocks\n",
384: YCUNIT(dev), yc->yc_softerrs, yc->yc_blks);
385: dlog((LOG_INFO, "%d soft errors in %d blocks\n",
386: yc->yc_softerrs, yc->yc_blks));
387: tprintf_close(yc->yc_tpr);
388: yc->yc_openf = 0;
389: return (0);
390: }
391:
392: /*
393: * Execute a command on the tape drive a specified number of times.
394: */
395: cycommand(dev, com, count)
396: dev_t dev;
397: int com, count;
398: {
399: register struct buf *bp;
400: int s;
401:
402: bp = &ccybuf[CYUNIT(dev)];
403: s = spl3();
404: dlog((LOG_INFO, "cycommand(%o, %x, %d), b_flags %x\n",
405: dev, com, count, bp->b_flags));
406: while (bp->b_flags&B_BUSY) {
407: /*
408: * This special check is because B_BUSY never
409: * gets cleared in the non-waiting rewind case.
410: */
411: if (bp->b_repcnt == 0 && (bp->b_flags&B_DONE))
412: break;
413: bp->b_flags |= B_WANTED;
414: sleep((caddr_t)bp, PRIBIO);
415: }
416: bp->b_flags = B_BUSY|B_READ;
417: splx(s);
418: bp->b_dev = dev;
419: bp->b_repcnt = count;
420: bp->b_command = com;
421: bp->b_blkno = 0;
422: cystrategy(bp);
423: /*
424: * In case of rewind from close; don't wait.
425: * This is the only case where count can be 0.
426: */
427: if (count == 0)
428: return;
429: biowait(bp);
430: if (bp->b_flags&B_WANTED)
431: wakeup((caddr_t)bp);
432: bp->b_flags &= B_ERROR;
433: }
434:
435: cystrategy(bp)
436: register struct buf *bp;
437: {
438: int ycunit = YCUNIT(bp->b_dev);
439: register struct vba_ctlr *vm;
440: register struct buf *dp;
441: int s;
442:
443: /*
444: * Put transfer at end of unit queue.
445: */
446: dlog((LOG_INFO, "cystrategy(%o, %x)\n", bp->b_dev, bp->b_command));
447: dp = &ycutab[ycunit];
448: bp->av_forw = NULL;
449: vm = ycdinfo[ycunit]->ui_mi;
450: /* BEGIN GROT */
451: if (bp->b_flags & B_RAW) {
452: if (bp->b_bcount >= CYMAXIO) {
453: uprintf("cy%d: i/o size too large\n", vm->um_ctlr);
454: bp->b_error = EINVAL;
455: bp->b_resid = bp->b_bcount;
456: bp->b_flags |= B_ERROR;
457: biodone(bp);
458: return;
459: }
460: }
461: /* END GROT */
462: s = spl3();
463: if (dp->b_actf == NULL) {
464: dp->b_actf = bp;
465: /*
466: * Transport not already active...
467: * put at end of controller queue.
468: */
469: dp->b_forw = NULL;
470: if (vm->um_tab.b_actf == NULL)
471: vm->um_tab.b_actf = dp;
472: else
473: vm->um_tab.b_actl->b_forw = dp;
474: } else
475: dp->b_actl->av_forw = bp;
476: dp->b_actl = bp;
477: /*
478: * If the controller is not busy, get it going.
479: */
480: if (vm->um_tab.b_active == 0)
481: cystart(vm);
482: splx(s);
483: }
484:
485: /*
486: * Start activity on a cy controller.
487: */
488: cystart(vm)
489: register struct vba_ctlr *vm;
490: {
491: register struct buf *bp, *dp;
492: register struct yc_softc *yc;
493: register struct cy_softc *cy;
494: int ycunit;
495: daddr_t blkno;
496:
497: dlog((LOG_INFO, "cystart()\n"));
498: /*
499: * Look for an idle transport on the controller.
500: */
501: loop:
502: if ((dp = vm->um_tab.b_actf) == NULL)
503: return;
504: if ((bp = dp->b_actf) == NULL) {
505: vm->um_tab.b_actf = dp->b_forw;
506: goto loop;
507: }
508: ycunit = YCUNIT(bp->b_dev);
509: yc = &yc_softc[ycunit];
510: cy = &cy_softc[CYUNIT(bp->b_dev)];
511: /*
512: * Default is that last command was NOT a write command;
513: * if we do a write command we will notice this in cyintr().
514: */
515: yc->yc_lastiow = 0;
516: if (yc->yc_openf < 0 ||
517: (bp->b_command != CY_SENSE && (cy->cy_tpb.tpstatus&CYS_OL) == 0)) {
518: /*
519: * Have had a hard error on a non-raw tape
520: * or the tape unit is now unavailable (e.g.
521: * taken off line).
522: */
523: dlog((LOG_INFO, "openf %d command %x status %b\n",
524: yc->yc_openf, bp->b_command, cy->cy_tpb.tpstatus, CYS_BITS));
525: bp->b_flags |= B_ERROR;
526: goto next;
527: }
528: if (bp == &ccybuf[CYUNIT(bp->b_dev)]) {
529: /*
530: * Execute control operation with the specified count.
531: *
532: * Set next state; give 5 minutes to complete
533: * rewind or file mark search, or 10 seconds per
534: * iteration (minimum 60 seconds and max 5 minutes)
535: * to complete other ops.
536: */
537: if (bp->b_command == CY_REW) {
538: vm->um_tab.b_active = SREW;
539: yc->yc_timo = 5*60;
540: } else if (bp->b_command == CY_FSF ||
541: bp->b_command == CY_BSF) {
542: vm->um_tab.b_active = SCOM;
543: yc->yc_timo = 5*60;
544: } else {
545: vm->um_tab.b_active = SCOM;
546: yc->yc_timo = imin(imax(10*(int)bp->b_repcnt,60),5*60);
547: }
548: cy->cy_tpb.tprec = htoms(bp->b_repcnt);
549: dlog((LOG_INFO, "bpcmd "));
550: goto dobpcmd;
551: }
552: /*
553: * For raw I/O, save the current block
554: * number in case we have to retry.
555: */
556: if (bp->b_flags & B_RAW) {
557: if (vm->um_tab.b_errcnt == 0) {
558: yc->yc_blkno = bp->b_blkno;
559: yc->yc_nxrec = yc->yc_blkno + 1;
560: }
561: } else {
562: /*
563: * Handle boundary cases for operation
564: * on non-raw tapes.
565: */
566: if (bp->b_blkno > yc->yc_nxrec) {
567: /*
568: * Can't read past known end-of-file.
569: */
570: bp->b_flags |= B_ERROR;
571: bp->b_error = ENXIO;
572: goto next;
573: }
574: if (bp->b_blkno == yc->yc_nxrec && bp->b_flags&B_READ) {
575: /*
576: * Reading at end of file returns 0 bytes.
577: */
578: bp->b_resid = bp->b_bcount;
579: clrbuf(bp);
580: goto next;
581: }
582: if ((bp->b_flags&B_READ) == 0)
583: /*
584: * Writing sets EOF.
585: */
586: yc->yc_nxrec = bp->b_blkno + 1;
587: }
588: if ((blkno = yc->yc_blkno) == bp->b_blkno) {
589: caddr_t addr;
590: int cmd;
591:
592: /*
593: * Choose the appropriate i/o command based on the
594: * transfer size, the estimated block size,
595: * and the controller's internal buffer size.
596: * If the request length is longer than the tape
597: * block length, a buffered read will fail,
598: * thus, we request at most the size that we expect.
599: * We then check for larger records when the read completes.
600: * If we're retrying a read on a raw device because
601: * the original try was a buffer request which failed
602: * due to a record length error, then we force the use
603: * of the raw controller read (YECH!!!!).
604: */
605: if (bp->b_flags&B_READ) {
606: if (yc->yc_blksize <= cy->cy_bs &&
607: vm->um_tab.b_errcnt == 0)
608: cmd = CY_BRCOM;
609: else
610: cmd = CY_RCOM;
611: } else {
612: /*
613: * On write error retries erase the
614: * inter-record gap before rewriting.
615: */
616: if (vm->um_tab.b_errcnt &&
617: vm->um_tab.b_active != SERASED) {
618: vm->um_tab.b_active = SERASE;
619: bp->b_command = CY_ERASE;
620: yc->yc_timo = 60;
621: goto dobpcmd;
622: }
623: cmd = (bp->b_bcount > cy->cy_bs) ? CY_WCOM : CY_BWCOM;
624: }
625: vm->um_tab.b_active = SIO;
626: addr = (caddr_t)vbasetup(bp, &cy->cy_rbuf, 1);
627: cy->cy_tpb.tpcmd = cmd;
628: cy->cy_tpb.tpcontrol = yc->yc_dens;
629: if (cmd == CY_RCOM || cmd == CY_WCOM)
630: cy->cy_tpb.tpcontrol |= CYCW_LOCK;
631: cy->cy_tpb.tpstatus = 0;
632: cy->cy_tpb.tpcount = 0;
633: cyldmba(cy->cy_tpb.tpdata, (caddr_t)addr);
634: cy->cy_tpb.tprec = 0;
635: if (cmd == CY_BRCOM)
636: cy->cy_tpb.tpsize = htoms(imin(yc->yc_blksize,
637: (int)bp->b_bcount));
638: else
639: cy->cy_tpb.tpsize = htoms(bp->b_bcount);
640: cyldmba(cy->cy_tpb.tplink, (caddr_t)0);
641: do
642: uncache(&cy->cy_ccb.cbgate);
643: while (cy->cy_ccb.cbgate == GATE_CLOSED);
644: cyldmba(cy->cy_ccb.cbtpb, (caddr_t)&cy->cy_tpb);
645: cy->cy_ccb.cbcw = CBCW_IE;
646: cy->cy_ccb.cbgate = GATE_CLOSED;
647: dlog((LOG_INFO, "CY_GO(%x) cmd %x control %x size %d\n",
648: vm->um_addr, cy->cy_tpb.tpcmd, cy->cy_tpb.tpcontrol,
649: htoms(cy->cy_tpb.tpsize)));
650: CY_GO(vm->um_addr);
651: return;
652: }
653: /*
654: * Tape positioned incorrectly; set to seek forwards
655: * or backwards to the correct spot. This happens
656: * for raw tapes only on error retries.
657: */
658: vm->um_tab.b_active = SSEEK;
659: if (blkno < bp->b_blkno) {
660: bp->b_command = CY_SFORW;
661: cy->cy_tpb.tprec = htoms(bp->b_blkno - blkno);
662: } else {
663: bp->b_command = CY_SREV;
664: cy->cy_tpb.tprec = htoms(blkno - bp->b_blkno);
665: }
666: yc->yc_timo = imin(imax((int)(10 * htoms(cy->cy_tpb.tprec)), 60), 5*60);
667: dobpcmd:
668: /*
669: * Do the command in bp. Reverse direction commands
670: * are indicated by having CYCW_REV or'd into their
671: * value. For these we must set the appropriate bit
672: * in the control field.
673: */
674: if (bp->b_command&CYCW_REV) {
675: cy->cy_tpb.tpcmd = bp->b_command &~ CYCW_REV;
676: cy->cy_tpb.tpcontrol = yc->yc_dens | CYCW_REV;
677: dlog((LOG_INFO, "cmd %x control %x\n", cy->cy_tpb.tpcmd, cy->cy_tpb.tpcontrol));
678: } else {
679: cy->cy_tpb.tpcmd = bp->b_command;
680: cy->cy_tpb.tpcontrol = yc->yc_dens;
681: dlog((LOG_INFO, "cmd %x control %x\n", cy->cy_tpb.tpcmd, cy->cy_tpb.tpcontrol));
682: }
683: cy->cy_tpb.tpstatus = 0;
684: cy->cy_tpb.tpcount = 0;
685: cyldmba(cy->cy_tpb.tplink, (caddr_t)0);
686: do
687: uncache(&cy->cy_ccb.cbgate);
688: while (cy->cy_ccb.cbgate == GATE_CLOSED);
689: cyldmba(cy->cy_ccb.cbtpb, (caddr_t)&cy->cy_tpb);
690: cy->cy_ccb.cbcw = CBCW_IE;
691: cy->cy_ccb.cbgate = GATE_CLOSED;
692: dlog((LOG_INFO, "CY_GO(%x) cmd %x control %x rec %d\n",
693: vm->um_addr, cy->cy_tpb.tpcmd, cy->cy_tpb.tpcontrol,
694: htoms(cy->cy_tpb.tprec)));
695: CY_GO(vm->um_addr);
696: return;
697: next:
698: /*
699: * Done with this operation due to error or the
700: * fact that it doesn't do anything.
701: * Dequeue the transfer and continue
702: * processing this slave.
703: */
704: vm->um_tab.b_errcnt = 0;
705: dp->b_actf = bp->av_forw;
706: biodone(bp);
707: goto loop;
708: }
709:
710: /*
711: * Cy interrupt routine.
712: */
713: cyintr(cyunit)
714: int cyunit;
715: {
716: struct buf *dp;
717: register struct buf *bp;
718: register struct vba_ctlr *vm = cyminfo[cyunit];
719: register struct cy_softc *cy;
720: register struct yc_softc *yc;
721: int err;
722: register state;
723:
724: dlog((LOG_INFO, "cyintr(%d)\n", cyunit));
725: /*
726: * First, turn off the interrupt from the controller
727: * (device uses Multibus non-vectored interrupts...yech).
728: */
729: cy = &cy_softc[vm->um_ctlr];
730: cy->cy_ccb.cbcw = CBCW_CLRINT;
731: cyldmba(cy->cy_ccb.cbtpb, (caddr_t)&cy->cy_nop);
732: cy->cy_ccb.cbgate = GATE_CLOSED;
733: CY_GO(vm->um_addr);
734: if ((dp = vm->um_tab.b_actf) == NULL) {
735: dlog((LOG_ERR, "cy%d: stray interrupt", vm->um_ctlr));
736: return;
737: }
738: bp = dp->b_actf;
739: cy = &cy_softc[cyunit];
740: cyuncachetpb(cy);
741: yc = &yc_softc[YCUNIT(bp->b_dev)];
742: /*
743: * If last command was a rewind and tape is
744: * still moving, wait for the operation to complete.
745: */
746: if (vm->um_tab.b_active == SREW) {
747: vm->um_tab.b_active = SCOM;
748: if ((cy->cy_tpb.tpstatus&CYS_RDY) == 0) {
749: yc->yc_timo = 5*60; /* 5 minutes */
750: return;
751: }
752: }
753: /*
754: * An operation completed...record status.
755: */
756: yc->yc_timo = INF;
757: yc->yc_control = cy->cy_tpb.tpcontrol;
758: yc->yc_status = cy->cy_tpb.tpstatus;
759: yc->yc_resid = bp->b_bcount - htoms(cy->cy_tpb.tpcount);
760: dlog((LOG_INFO, "cmd %x control %b status %b resid %d\n",
761: cy->cy_tpb.tpcmd, yc->yc_control, CYCW_BITS,
762: yc->yc_status, CYS_BITS, yc->yc_resid));
763: if ((bp->b_flags&B_READ) == 0)
764: yc->yc_lastiow = 1;
765: state = vm->um_tab.b_active;
766: vm->um_tab.b_active = 0;
767: /*
768: * Check for errors.
769: */
770: if (cy->cy_tpb.tpstatus&CYS_ERR) {
771: err = cy->cy_tpb.tpstatus&CYS_ERR;
772: dlog((LOG_INFO, "error %d\n", err));
773: /*
774: * If we hit the end of tape file, update our position.
775: */
776: if (err == CYER_FM) {
777: yc->yc_status |= CYS_FM;
778: state = SCOM; /* force completion */
779: cyseteof(bp); /* set blkno and nxrec */
780: goto opdone;
781: }
782: /*
783: * Fix up errors which occur due to backspacing over
784: * the beginning of the tape.
785: */
786: if (err == CYER_BOT && cy->cy_tpb.tpcontrol&CYCW_REV) {
787: yc->yc_status |= CYS_BOT;
788: goto ignoreerr;
789: }
790: /*
791: * If we were reading raw tape and the only error was that the
792: * record was too long, then we don't consider this an error.
793: */
794: if ((bp->b_flags & (B_READ|B_RAW)) == (B_READ|B_RAW) &&
795: err == CYER_STROBE) {
796: /*
797: * Retry reads with the command changed to
798: * a raw read if necessary. Setting b_errcnt
799: * here causes cystart (above) to force a CY_RCOM.
800: */
801: if (cy->cy_tpb.tpcmd == CY_BRCOM &&
802: vm->um_tab.b_errcnt++ == 0) {
803: yc->yc_blkno++;
804: goto opcont;
805: } else
806: goto ignoreerr;
807: }
808: /*
809: * If error is not hard, and this was an i/o operation
810: * retry up to 8 times.
811: */
812: if (state == SIO && (CYMASK(err) &
813: ((bp->b_flags&B_READ) ? CYER_RSOFT : CYER_WSOFT))) {
814: if (++vm->um_tab.b_errcnt < 7) {
815: yc->yc_blkno++;
816: goto opcont;
817: }
818: } else
819: /*
820: * Hard or non-i/o errors on non-raw tape
821: * cause it to close.
822: */
823: if ((bp->b_flags&B_RAW) == 0 &&
824: yc->yc_openf > 0)
825: yc->yc_openf = -1;
826: /*
827: * Couldn't recover from error.
828: */
829: tprintf(yc->yc_tpr,
830: "yc%d: hard error bn%d status=%b, %s\n", YCUNIT(bp->b_dev),
831: bp->b_blkno, yc->yc_status, CYS_BITS,
832: (err < NCYERROR) ? cyerror[err] : "");
833: bp->b_flags |= B_ERROR;
834: goto opdone;
835: } else if (cy->cy_tpb.tpcmd == CY_BRCOM) {
836: int reclen = htoms(cy->cy_tpb.tprec);
837:
838: /*
839: * If we did a buffered read, check whether the read
840: * was long enough. If we asked the controller for less
841: * than the user asked for because the previous record
842: * was shorter, update our notion of record size
843: * and retry. If the record is longer than the buffer,
844: * bump the errcnt so the retry will use direct read.
845: */
846: if (reclen > yc->yc_blksize && bp->b_bcount > yc->yc_blksize) {
847: yc->yc_blksize = reclen;
848: if (reclen > cy->cy_bs)
849: vm->um_tab.b_errcnt++;
850: yc->yc_blkno++;
851: goto opcont;
852: }
853: }
854: /*
855: * Advance tape control FSM.
856: */
857: ignoreerr:
858: /*
859: * If we hit a tape mark update our position.
860: */
861: if (yc->yc_status&CYS_FM && bp->b_flags&B_READ) {
862: cyseteof(bp);
863: goto opdone;
864: }
865: switch (state) {
866:
867: case SIO:
868: /*
869: * Read/write increments tape block number.
870: */
871: yc->yc_blkno++;
872: yc->yc_blks++;
873: if (vm->um_tab.b_errcnt || yc->yc_status & CYS_CR)
874: yc->yc_softerrs++;
875: yc->yc_blksize = htoms(cy->cy_tpb.tpcount);
876: dlog((LOG_ERR, "blocksize %d", yc->yc_blksize));
877: goto opdone;
878:
879: case SCOM:
880: /*
881: * For forward/backward space record update current position.
882: */
883: if (bp == &ccybuf[CYUNIT(bp->b_dev)])
884: switch ((int)bp->b_command) {
885:
886: case CY_SFORW:
887: yc->yc_blkno -= bp->b_repcnt;
888: break;
889:
890: case CY_SREV:
891: yc->yc_blkno += bp->b_repcnt;
892: break;
893: }
894: goto opdone;
895:
896: case SSEEK:
897: yc->yc_blkno = bp->b_blkno;
898: goto opcont;
899:
900: case SERASE:
901: /*
902: * Completed erase of the inter-record gap due to a
903: * write error; now retry the write operation.
904: */
905: vm->um_tab.b_active = SERASED;
906: goto opcont;
907: }
908:
909: opdone:
910: /*
911: * Reset error count and remove from device queue.
912: */
913: vm->um_tab.b_errcnt = 0;
914: dp->b_actf = bp->av_forw;
915: /*
916: * Save resid and release resources.
917: */
918: bp->b_resid = bp->b_bcount - htoms(cy->cy_tpb.tpcount);
919: if (bp != &ccybuf[cyunit])
920: vbadone(bp, &cy->cy_rbuf);
921: biodone(bp);
922: /*
923: * Circulate slave to end of controller
924: * queue to give other slaves a chance.
925: */
926: vm->um_tab.b_actf = dp->b_forw;
927: if (dp->b_actf) {
928: dp->b_forw = NULL;
929: if (vm->um_tab.b_actf == NULL)
930: vm->um_tab.b_actf = dp;
931: else
932: vm->um_tab.b_actl->b_forw = dp;
933: }
934: if (vm->um_tab.b_actf == 0)
935: return;
936: opcont:
937: cystart(vm);
938: }
939:
940: cytimer(dev)
941: int dev;
942: {
943: register struct yc_softc *yc = &yc_softc[YCUNIT(dev)];
944: int s;
945:
946: if (yc->yc_openf == 0 && yc->yc_timo == INF) {
947: yc->yc_tact = 0;
948: return;
949: }
950: if (yc->yc_timo != INF && (yc->yc_timo -= 5) < 0) {
951: printf("yc%d: lost interrupt\n", YCUNIT(dev));
952: yc->yc_timo = INF;
953: s = spl3();
954: cyintr(CYUNIT(dev));
955: splx(s);
956: }
957: timeout(cytimer, (caddr_t)dev, 5*hz);
958: }
959:
960: cyseteof(bp)
961: register struct buf *bp;
962: {
963: register int cyunit = CYUNIT(bp->b_dev);
964: register struct cy_softc *cy = &cy_softc[cyunit];
965: register struct yc_softc *yc = &yc_softc[YCUNIT(bp->b_dev)];
966:
967: if (bp == &ccybuf[cyunit]) {
968: if (yc->yc_blkno > bp->b_blkno) {
969: /* reversing */
970: yc->yc_nxrec = bp->b_blkno - htoms(cy->cy_tpb.tpcount);
971: yc->yc_blkno = yc->yc_nxrec;
972: } else {
973: yc->yc_blkno = bp->b_blkno + htoms(cy->cy_tpb.tpcount);
974: yc->yc_nxrec = yc->yc_blkno - 1;
975: }
976: return;
977: }
978: /* eof on read */
979: yc->yc_nxrec = bp->b_blkno;
980: }
981:
982: /*ARGSUSED*/
983: cyioctl(dev, cmd, data, flag)
984: caddr_t data;
985: dev_t dev;
986: {
987: int ycunit = YCUNIT(dev);
988: register struct yc_softc *yc = &yc_softc[ycunit];
989: register struct buf *bp = &ccybuf[CYUNIT(dev)];
990: register callcount;
991: int fcount, op;
992: struct mtop *mtop;
993: struct mtget *mtget;
994: /* we depend of the values and order of the MT codes here */
995: static cyops[] =
996: {CY_WEOF,CY_FSF,CY_BSF,CY_SFORW,CY_SREV,CY_REW,CY_OFFL,CY_SENSE};
997:
998: switch (cmd) {
999:
1000: case MTIOCTOP: /* tape operation */
1001: mtop = (struct mtop *)data;
1002: switch (op = mtop->mt_op) {
1003:
1004: case MTWEOF:
1005: callcount = mtop->mt_count;
1006: fcount = 1;
1007: break;
1008:
1009: case MTFSR: case MTBSR:
1010: callcount = 1;
1011: fcount = mtop->mt_count;
1012: break;
1013:
1014: case MTFSF: case MTBSF:
1015: callcount = mtop->mt_count;
1016: fcount = 1;
1017: break;
1018:
1019: case MTREW: case MTOFFL: case MTNOP:
1020: callcount = 1;
1021: fcount = 1;
1022: break;
1023:
1024: default:
1025: return (ENXIO);
1026: }
1027: if (callcount <= 0 || fcount <= 0)
1028: return (EINVAL);
1029: while (--callcount >= 0) {
1030: #ifdef notdef
1031: /*
1032: * Gagh, this controller is the pits...
1033: */
1034: if (op == MTFSF || op == MTBSF) {
1035: do
1036: cycommand(dev, cyops[op], 1);
1037: while ((bp->b_flags&B_ERROR) == 0 &&
1038: (yc->yc_status&(CYS_EOT|CYS_BOT|CYS_FM)) == 0);
1039: } else
1040: #endif
1041: cycommand(dev, cyops[op], fcount);
1042: dlog((LOG_INFO,
1043: "cyioctl: status %x, b_flags %x, resid %d\n",
1044: yc->yc_status, bp->b_flags, bp->b_resid));
1045: if ((bp->b_flags&B_ERROR) ||
1046: (yc->yc_status&(CYS_BOT|CYS_EOT)))
1047: break;
1048: }
1049: bp->b_resid = callcount + 1;
1050: /*
1051: * Pick up the device's error number and pass it
1052: * to the user; if there is an error but the number
1053: * is 0 set a generalized code.
1054: */
1055: if ((bp->b_flags & B_ERROR) == 0)
1056: return (0);
1057: if (bp->b_error)
1058: return (bp->b_error);
1059: return (EIO);
1060:
1061: case MTIOCGET:
1062: cycommand(dev, CY_SENSE, 1);
1063: mtget = (struct mtget *)data;
1064: mtget->mt_dsreg = yc->yc_status;
1065: mtget->mt_erreg = yc->yc_control;
1066: mtget->mt_resid = yc->yc_resid;
1067: mtget->mt_type = MT_ISCY;
1068: break;
1069:
1070: default:
1071: return (ENXIO);
1072: }
1073: return (0);
1074: }
1075:
1076: /*
1077: * Poll until the controller is ready.
1078: */
1079: cywait(cp)
1080: register struct cyccb *cp;
1081: {
1082: register int i = 5000;
1083:
1084: uncache(&cp->cbgate);
1085: while (i-- > 0 && cp->cbgate == GATE_CLOSED) {
1086: DELAY(1000);
1087: uncache(&cp->cbgate);
1088: }
1089: return (i <= 0);
1090: }
1091:
1092: /*
1093: * Load a 20 bit pointer into a Tapemaster pointer.
1094: */
1095: cyldmba(reg, value)
1096: register u_char *reg;
1097: caddr_t value;
1098: {
1099: register int v = (int)value;
1100:
1101: *reg++ = v;
1102: *reg++ = v >> 8;
1103: *reg++ = 0;
1104: *reg = (v&0xf0000) >> 12;
1105: }
1106:
1107: /*
1108: * Unconditionally reset all controllers to their initial state.
1109: */
1110: cyreset(vba)
1111: int vba;
1112: {
1113: register caddr_t addr;
1114: register int ctlr;
1115:
1116: for (ctlr = 0; ctlr < NCY; ctlr++)
1117: if (cyminfo[ctlr] && cyminfo[ctlr]->um_vbanum == vba) {
1118: addr = cyminfo[ctlr]->um_addr;
1119: CY_RESET(addr);
1120: if (!cyinit(ctlr, addr)) {
1121: printf("cy%d: reset failed\n", ctlr);
1122: cyminfo[ctlr] = NULL;
1123: }
1124: }
1125: }
1126:
1127: cyuncachetpb(cy)
1128: struct cy_softc *cy;
1129: {
1130: register long *lp = (long *)&cy->cy_tpb;
1131: register int i;
1132:
1133: for (i = 0; i < howmany(sizeof (struct cytpb), sizeof (long)); i++)
1134: uncache(lp++);
1135: }
1136:
1137: /*
1138: * Dump routine.
1139: */
1140: #define DUMPREC (32*1024)
1141: cydump(dev)
1142: dev_t dev;
1143: {
1144: register struct cy_softc *cy;
1145: register int bs, num, start;
1146: register caddr_t addr;
1147: int unit = CYUNIT(dev), error;
1148:
1149: if (unit >= NCY || cyminfo[unit] == 0 ||
1150: (cy = &cy_softc[unit])->cy_bs == 0 || YCUNIT(dev) >= NYC)
1151: return (ENXIO);
1152: if (cywait(&cy->cy_ccb))
1153: return (EFAULT);
1154: #define phys(a) ((caddr_t)((int)(a)&~0xc0000000))
1155: addr = phys(cyminfo[unit]->um_addr);
1156: num = maxfree, start = NBPG*2;
1157: while (num > 0) {
1158: bs = num > btoc(DUMPREC) ? btoc(DUMPREC) : num;
1159: error = cydwrite(cy, start, bs, addr);
1160: if (error)
1161: return (error);
1162: start += bs, num -= bs;
1163: }
1164: cyweof(cy, addr);
1165: cyweof(cy, addr);
1166: uncache(&cy->cy_tpb);
1167: if (cy->cy_tpb.tpstatus&CYS_ERR)
1168: return (EIO);
1169: cyrewind(cy, addr);
1170: return (0);
1171: }
1172:
1173: cydwrite(cy, pf, npf, addr)
1174: register struct cy_softc *cy;
1175: int pf, npf;
1176: caddr_t addr;
1177: {
1178:
1179: cy->cy_tpb.tpcmd = CY_WCOM;
1180: cy->cy_tpb.tpcontrol = CYCW_LOCK|CYCW_25IPS|CYCW_16BITS;
1181: cy->cy_tpb.tpstatus = 0;
1182: cy->cy_tpb.tpsize = htoms(npf*NBPG);
1183: cyldmba(cy->cy_tpb.tplink, (caddr_t)0);
1184: cyldmba(cy->cy_tpb.tpdata, (caddr_t)(pf*NBPG));
1185: cyldmba(cy->cy_ccb.cbtpb, (caddr_t)&cy->cy_tpb);
1186: cy->cy_ccb.cbgate = GATE_CLOSED;
1187: CY_GO(addr);
1188: if (cywait(&cy->cy_ccb))
1189: return (EFAULT);
1190: uncache(&cy->cy_tpb);
1191: if (cy->cy_tpb.tpstatus&CYS_ERR)
1192: return (EIO);
1193: return (0);
1194: }
1195:
1196: cyweof(cy, addr)
1197: register struct cy_softc *cy;
1198: caddr_t addr;
1199: {
1200:
1201: cy->cy_tpb.tpcmd = CY_WEOF;
1202: cy->cy_tpb.tpcount = htoms(1);
1203: cy->cy_ccb.cbgate = GATE_CLOSED;
1204: CY_GO(addr);
1205: (void) cywait(&cy->cy_ccb);
1206: }
1207:
1208: cyrewind(cy, addr)
1209: register struct cy_softc *cy;
1210: caddr_t addr;
1211: {
1212:
1213: cy->cy_tpb.tpcmd = CY_REW;
1214: cy->cy_tpb.tpcount = htoms(1);
1215: cy->cy_ccb.cbgate = GATE_CLOSED;
1216: CY_GO(addr);
1217: (void) cywait(&cy->cy_ccb);
1218: }
1219: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.