|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1990 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution is only permitted until one year after the first shipment
6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
7: * binary forms are permitted provided that: (1) source distributions retain
8: * this entire copyright notice and comment, and (2) distributions including
9: * binaries display the following acknowledgement: This product includes
10: * software developed by the University of California, Berkeley and its
11: * contributors'' in the documentation or other materials provided with the
12: * distribution and in all advertising materials mentioning features or use
13: * of this software. Neither the name of the University nor the names of
14: * its contributors may be used to endorse or promote products derived from
15: * this software without specific prior written permission.
16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19: *
20: * @(#)ct.c 7.1 (Berkeley) 5/8/90
21: */
22:
23: #include "ct.h"
24: #if NCT > 0
25: /*
26: * CS80 cartridge tape driver (9144, 88140, 9145)
27: *
28: * Reminder:
29: * C_CC bit (character count option) when used in the CS/80 command
30: * 'set options' will cause the tape not to stream.
31: *
32: * TODO:
33: * make filesystem compatible
34: * make block mode work according to mtio(4) spec. (if possible)
35: * merge with cs80 disk driver
36: * finish support of 9145
37: */
38:
39: #include "param.h"
40: #include "buf.h"
41: #include "ioctl.h"
42: #include "mtio.h"
43: #include "errno.h"
44: #include "ctreg.h"
45: #include "device.h"
46: #include "user.h"
47: #include "tty.h"
48: #include "proc.h"
49:
50: /* number of eof marks to remember */
51: #define EOFS 128
52:
53: int ctinit(), ctstart(), ctgo(), ctintr();
54: struct driver ctdriver = {
55: ctinit, "ct", ctstart, ctgo, ctintr,
56: };
57:
58: struct ct_softc {
59: struct hp_device *sc_hd;
60: struct ct_iocmd sc_ioc;
61: struct ct_rscmd sc_rsc;
62: struct ct_stat sc_stat;
63: struct ct_ssmcmd sc_ssmc;
64: struct ct_srcmd sc_src;
65: struct ct_soptcmd sc_soptc;
66: struct ct_ulcmd sc_ul;
67: struct ct_wfmcmd sc_wfm;
68: struct ct_clearcmd sc_clear;
69: struct buf *sc_bp;
70: int sc_blkno;
71: int sc_cmd;
72: int sc_resid;
73: char *sc_addr;
74: int sc_flags;
75: short sc_type;
76: short sc_punit;
77: caddr_t sc_ctty;
78: struct devqueue sc_dq;
79: int sc_eofp;
80: int sc_eofs[EOFS];
81: } ct_softc[NCT];
82:
83: /* flags */
84: #define CTF_OPEN 0x01
85: #define CTF_ALIVE 0x02
86: #define CTF_WRT 0x04
87: #define CTF_CMD 0x08
88: #define CTF_IO 0x10
89: #define CTF_BEOF 0x20
90: #define CTF_AEOF 0x40
91: #define CTF_EOT 0x80
92: #define CTF_STATWAIT 0x100
93: #define CTF_CANSTREAM 0x200
94: #define CTF_WRTTN 0x400
95:
96: struct ctinfo {
97: short hwid;
98: short punit;
99: char *desc;
100: } ctinfo[] = {
101: CT7946ID, 1, "7946A",
102: CT7912PID, 1, "7912P",
103: CT7914PID, 1, "7914P",
104: CT9144ID, 0, "9144",
105: CT9145ID, 0, "9145",
106: };
107: int nctinfo = sizeof(ctinfo) / sizeof(ctinfo[0]);
108:
109: struct buf cttab[NCT];
110: struct buf ctbuf[NCT];
111:
112: #define CT_NOREW 4
113: #define CT_STREAM 8
114: #define UNIT(x) (minor(x) & 3)
115: #define ctpunit(x) ((x) & 7)
116:
117: #ifdef DEBUG
118: int ctdebug = 0;
119: #define CDB_FILES 0x01
120: #define CT_BSF 0x02
121: #endif
122:
123: ctinit(hd)
124: register struct hp_device *hd;
125: {
126: register struct ct_softc *sc = &ct_softc[hd->hp_unit];
127:
128: sc->sc_hd = hd;
129: sc->sc_punit = ctpunit(hd->hp_flags);
130: if (ctident(sc, hd) < 0)
131: return(0);
132: ctreset(sc, hd);
133: sc->sc_dq.dq_ctlr = hd->hp_ctlr;
134: sc->sc_dq.dq_unit = hd->hp_unit;
135: sc->sc_dq.dq_slave = hd->hp_slave;
136: sc->sc_dq.dq_driver = &ctdriver;
137: sc->sc_flags |= CTF_ALIVE;
138: return(1);
139: }
140:
141: ctident(sc, hd)
142: register struct ct_softc *sc;
143: register struct hp_device *hd;
144: {
145: struct ct_describe desc;
146: u_char stat, cmd[3];
147: char name[7];
148: int id, i;
149:
150: /*
151: * Read device id and verify that:
152: * 1. It is a CS80 device
153: * 2. It is one of our recognized tape devices
154: * 3. It has the proper physical unit number
155: */
156: id = hpibid(hd->hp_ctlr, hd->hp_slave);
157: if ((id & 0x200) == 0)
158: return(-1);
159: for (i = 0; i < nctinfo; i++)
160: if (id == ctinfo[i].hwid)
161: break;
162: if (i == nctinfo || sc->sc_punit != ctinfo[i].punit)
163: return(-1);
164: id = i;
165:
166: /*
167: * Collect device description.
168: * Right now we only need this to differentiate 7945 from 7946.
169: * Note that we always issue the describe command to unit 0.
170: */
171: cmd[0] = C_SUNIT(0);
172: cmd[1] = C_SVOL(0);
173: cmd[2] = C_DESC;
174: hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, cmd, sizeof(cmd));
175: hpibrecv(hd->hp_ctlr, hd->hp_slave, C_EXEC, &desc, 37);
176: hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
177: bzero(name, sizeof(name));
178: if (!stat) {
179: register int n = desc.d_name;
180: for (i = 5; i >= 0; i--) {
181: name[i] = (n & 0xf) + '0';
182: n >>= 4;
183: }
184: }
185: switch (ctinfo[id].hwid) {
186: case CT7946ID:
187: if (bcmp(name, "079450", 6) == 0)
188: return(-1); /* not really a 7946 */
189: /* fall into... */
190: case CT9144ID:
191: case CT9145ID:
192: sc->sc_type = CT9144;
193: sc->sc_flags |= CTF_CANSTREAM;
194: break;
195:
196: case CT7912PID:
197: case CT7914PID:
198: sc->sc_type = CT88140;
199: break;
200: }
201: printf("ct%d: %s %stape\n", hd->hp_unit, ctinfo[id].desc,
202: (sc->sc_flags & CTF_CANSTREAM) ? "streaming " : " ");
203: return(id);
204: }
205:
206: ctreset(sc, hd)
207: register struct ct_softc *sc;
208: register struct hp_device *hd;
209: {
210: u_char stat;
211:
212: sc->sc_clear.unit = C_SUNIT(sc->sc_punit);
213: sc->sc_clear.cmd = C_CLEAR;
214: hpibsend(hd->hp_ctlr, hd->hp_slave, C_TCMD, &sc->sc_clear,
215: sizeof(sc->sc_clear));
216: hpibswait(hd->hp_ctlr, hd->hp_slave);
217: hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
218: sc->sc_src.unit = C_SUNIT(CTCTLR);
219: sc->sc_src.nop = C_NOP;
220: sc->sc_src.cmd = C_SREL;
221: sc->sc_src.param = C_REL;
222: hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &sc->sc_src,
223: sizeof(sc->sc_src));
224: hpibswait(hd->hp_ctlr, hd->hp_slave);
225: hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
226: sc->sc_ssmc.unit = C_SUNIT(sc->sc_punit);
227: sc->sc_ssmc.cmd = C_SSM;
228: sc->sc_ssmc.refm = REF_MASK;
229: sc->sc_ssmc.fefm = FEF_MASK;
230: sc->sc_ssmc.aefm = AEF_MASK;
231: sc->sc_ssmc.iefm = IEF_MASK;
232: hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &sc->sc_ssmc,
233: sizeof(sc->sc_ssmc));
234: hpibswait(hd->hp_ctlr, hd->hp_slave);
235: hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
236: sc->sc_soptc.unit = C_SUNIT(sc->sc_punit);
237: sc->sc_soptc.nop = C_NOP;
238: sc->sc_soptc.cmd = C_SOPT;
239: sc->sc_soptc.opt = C_SPAR;
240: hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &sc->sc_soptc,
241: sizeof(sc->sc_soptc));
242: hpibswait(hd->hp_ctlr, hd->hp_slave);
243: hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
244: }
245:
246: /*ARGSUSED*/
247: ctopen(dev, flag)
248: dev_t dev;
249: {
250: register struct ct_softc *sc = &ct_softc[UNIT(dev)];
251: u_char stat;
252: int cc;
253:
254: if (UNIT(dev) >= NCT || (sc->sc_flags & CTF_ALIVE) == 0)
255: return(ENXIO);
256: if (sc->sc_flags & CTF_OPEN)
257: return(EBUSY);
258: sc->sc_soptc.unit = C_SUNIT(sc->sc_punit);
259: sc->sc_soptc.nop = C_NOP;
260: sc->sc_soptc.cmd = C_SOPT;
261: if ((dev & CT_STREAM) && (sc->sc_flags & CTF_CANSTREAM))
262: sc->sc_soptc.opt = C_SPAR | C_IMRPT;
263: else
264: sc->sc_soptc.opt = C_SPAR;
265: /*
266: * Check the return of hpibsend() and hpibswait().
267: * Drive could be loading/unloading a tape. If not checked,
268: * driver hangs.
269: */
270: cc = hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
271: C_CMD, &sc->sc_soptc, sizeof(sc->sc_soptc));
272: if (cc != sizeof(sc->sc_soptc))
273: return(EBUSY);
274: hpibswait(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave);
275: cc = hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_QSTAT,
276: &stat, sizeof(stat));
277: if (cc != sizeof(stat))
278: return(EBUSY);
279: sc->sc_ctty = (caddr_t)(u.u_procp->p_flag&SCTTY ?
280: u.u_procp->p_session->s_ttyvp : 0);
281: sc->sc_flags |= CTF_OPEN;
282: return(0);
283: }
284:
285: /*ARGSUSED*/
286: ctclose(dev, flag)
287: dev_t dev;
288: {
289: register struct ct_softc *sc = &ct_softc[UNIT(dev)];
290:
291: if ((sc->sc_flags & (CTF_WRT|CTF_WRTTN)) == (CTF_WRT|CTF_WRTTN) &&
292: (sc->sc_flags & CTF_EOT) == 0 ) { /* XXX return error if EOT ?? */
293: ctcommand(dev, MTWEOF, 2);
294: ctcommand(dev, MTBSR, 1);
295: if (sc->sc_eofp == EOFS - 1)
296: sc->sc_eofs[EOFS - 1]--;
297: else
298: sc->sc_eofp--;
299: #ifdef DEBUG
300: if(ctdebug & CT_BSF)
301: printf("ct%d: ctclose backup eofs prt %d blk %d\n",
302: UNIT(dev), sc->sc_eofp, sc->sc_eofs[sc->sc_eofp]);
303: #endif
304: }
305: if ((minor(dev) & CT_NOREW) == 0)
306: ctcommand(dev, MTREW, 1);
307: sc->sc_flags &= ~(CTF_OPEN | CTF_WRT | CTF_WRTTN);
308: sc->sc_ctty = NULL;
309: #ifdef DEBUG
310: if (ctdebug & CDB_FILES)
311: printf("ctclose: flags %x\n", sc->sc_flags);
312: #endif
313: return(0); /* XXX */
314: }
315:
316: ctcommand(dev, cmd, cnt)
317: dev_t dev;
318: register int cnt;
319: {
320: register struct ct_softc *sc = &ct_softc[UNIT(dev)];
321: register struct buf *bp = &ctbuf[UNIT(dev)];
322: register struct buf *nbp = 0;
323:
324: if (cmd == MTBSF && sc->sc_eofp == EOFS - 1) {
325: cnt = sc->sc_eofs[EOFS - 1] - cnt;
326: ctcommand(dev, MTREW, 1);
327: ctcommand(dev, MTFSF, cnt);
328: cnt = 2;
329: cmd = MTBSR;
330: }
331:
332: if (cmd == MTBSF && sc->sc_eofp - cnt < 0) {
333: cnt = 1;
334: cmd = MTREW;
335: }
336:
337: sc->sc_flags |= CTF_CMD;
338: sc->sc_bp = bp;
339: sc->sc_cmd = cmd;
340: bp->b_dev = dev;
341: if (cmd == MTFSF) {
342: nbp = (struct buf *)geteblk(MAXBSIZE);
343: bp->b_un.b_addr = nbp->b_un.b_addr;
344: bp->b_bcount = MAXBSIZE;
345: }
346: again:
347: bp->b_flags = B_BUSY;
348: if (cmd == MTBSF) {
349: sc->sc_blkno = sc->sc_eofs[sc->sc_eofp];
350: sc->sc_eofp--;
351: #ifdef DEBUG
352: if (ctdebug & CT_BSF)
353: printf("ct%d: backup eof pos %d blk %d\n",
354: UNIT(dev), sc->sc_eofp,
355: sc->sc_eofs[sc->sc_eofp]);
356: #endif
357: }
358: ctstrategy(bp);
359: iowait(bp);
360: if (--cnt > 0)
361: goto again;
362: bp->b_flags = 0;
363: sc->sc_flags &= ~CTF_CMD;
364: if (nbp)
365: brelse(nbp);
366: }
367:
368: ctstrategy(bp)
369: register struct buf *bp;
370: {
371: register struct buf *dp;
372: register int s, unit;
373:
374: unit = UNIT(bp->b_dev);
375: dp = &cttab[unit];
376: bp->av_forw = NULL;
377: s = splbio();
378: if (dp->b_actf == NULL)
379: dp->b_actf = bp;
380: else
381: dp->b_actl->av_forw = bp;
382: dp->b_actl = bp;
383: if (dp->b_active == 0) {
384: dp->b_active = 1;
385: ctustart(unit);
386: }
387: splx(s);
388: }
389:
390: ctustart(unit)
391: register int unit;
392: {
393: register struct ct_softc *sc = &ct_softc[unit];
394: register struct buf *bp;
395:
396: bp = cttab[unit].b_actf;
397: sc->sc_addr = bp->b_un.b_addr;
398: sc->sc_resid = bp->b_bcount;
399: if (hpibreq(&sc->sc_dq))
400: ctstart(unit);
401: }
402:
403: ctstart(unit)
404: register int unit;
405: {
406: register struct ct_softc *sc = &ct_softc[unit];
407: register struct buf *bp;
408: register int i;
409:
410: bp = cttab[unit].b_actf;
411: again:
412: if ((sc->sc_flags & CTF_CMD) && sc->sc_bp == bp) {
413: switch(sc->sc_cmd) {
414:
415: case MTFSF:
416: bp->b_flags |= B_READ;
417: goto mustio;
418:
419: case MTBSF:
420: goto gotaddr;
421:
422: case MTOFFL:
423: sc->sc_blkno = 0;
424: sc->sc_ul.unit = C_SUNIT(sc->sc_punit);
425: sc->sc_ul.cmd = C_UNLOAD;
426: hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
427: C_CMD, &sc->sc_ul, sizeof(sc->sc_ul));
428: break;
429:
430: case MTWEOF:
431: sc->sc_blkno++;
432: sc->sc_flags |= CTF_WRT;
433: sc->sc_wfm.unit = C_SUNIT(sc->sc_punit);
434: sc->sc_wfm.cmd = C_WFM;
435: hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
436: C_CMD, &sc->sc_wfm, sizeof(sc->sc_wfm));
437: ctaddeof(unit);
438: break;
439:
440: case MTBSR:
441: sc->sc_blkno--;
442: goto gotaddr;
443:
444: case MTFSR:
445: sc->sc_blkno++;
446: goto gotaddr;
447:
448: case MTREW:
449: sc->sc_blkno = 0;
450: #ifdef DEBUG
451: if(ctdebug & CT_BSF)
452: printf("ct%d: clearing eofs\n", unit);
453: #endif
454: for (i=0; i<EOFS; i++)
455: sc->sc_eofs[i] = 0;
456: sc->sc_eofp = 0;
457:
458: gotaddr:
459: sc->sc_ioc.saddr = C_SADDR;
460: sc->sc_ioc.addr0 = 0;
461: sc->sc_ioc.addr = sc->sc_blkno;
462: sc->sc_ioc.unit = C_SUNIT(sc->sc_punit);
463: sc->sc_ioc.nop2 = C_NOP;
464: sc->sc_ioc.slen = C_SLEN;
465: sc->sc_ioc.len = 0;
466: sc->sc_ioc.nop3 = C_NOP;
467: sc->sc_ioc.cmd = C_READ;
468: hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
469: C_CMD, &sc->sc_ioc, sizeof(sc->sc_ioc));
470: break;
471: }
472: }
473: else {
474: mustio:
475: if ((bp->b_flags & B_READ) &&
476: sc->sc_flags & (CTF_BEOF|CTF_EOT)) {
477: #ifdef DEBUG
478: if (ctdebug & CDB_FILES)
479: printf("ctstart: before flags %x\n", sc->sc_flags);
480: #endif
481: if (sc->sc_flags & CTF_BEOF) {
482: sc->sc_flags &= ~CTF_BEOF;
483: sc->sc_flags |= CTF_AEOF;
484: #ifdef DEBUG
485: if (ctdebug & CDB_FILES)
486: printf("ctstart: after flags %x\n", sc->sc_flags);
487: #endif
488: }
489: bp->b_resid = bp->b_bcount;
490: iodone(bp);
491: hpibfree(&sc->sc_dq);
492: cttab[unit].b_actf = bp = bp->av_forw;
493: if (bp == NULL) {
494: cttab[unit].b_active = 0;
495: return;
496: }
497: sc->sc_addr = bp->b_un.b_addr;
498: sc->sc_resid = bp->b_bcount;
499: if (hpibreq(&sc->sc_dq))
500: goto again;
501: return;
502: }
503: sc->sc_flags |= CTF_IO;
504: sc->sc_ioc.unit = C_SUNIT(sc->sc_punit);
505: sc->sc_ioc.saddr = C_SADDR;
506: sc->sc_ioc.addr0 = 0;
507: sc->sc_ioc.addr = sc->sc_blkno;
508: sc->sc_ioc.nop2 = C_NOP;
509: sc->sc_ioc.slen = C_SLEN;
510: sc->sc_ioc.len = sc->sc_resid;
511: sc->sc_ioc.nop3 = C_NOP;
512: if (bp->b_flags & B_READ)
513: sc->sc_ioc.cmd = C_READ;
514: else {
515: sc->sc_ioc.cmd = C_WRITE;
516: sc->sc_flags |= (CTF_WRT | CTF_WRTTN);
517: }
518: hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_CMD,
519: &sc->sc_ioc, sizeof(sc->sc_ioc));
520: }
521: hpibawait(sc->sc_hd->hp_ctlr);
522: }
523:
524: ctgo(unit)
525: register int unit;
526: {
527: register struct ct_softc *sc = &ct_softc[unit];
528: register struct buf *bp;
529:
530: bp = cttab[unit].b_actf;
531: hpibgo(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_EXEC,
532: sc->sc_addr, sc->sc_resid, bp->b_flags & B_READ);
533: }
534:
535: /*
536: * Hideous grue to handle EOF/EOT (mostly for reads)
537: */
538: cteof(sc, bp)
539: register struct ct_softc *sc;
540: register struct buf *bp;
541: {
542: long blks;
543:
544: /*
545: * EOT on a write is an error.
546: */
547: if ((bp->b_flags & B_READ) == 0) {
548: bp->b_resid = bp->b_bcount;
549: bp->b_flags |= B_ERROR;
550: bp->b_error = ENOSPC;
551: sc->sc_flags |= CTF_EOT;
552: return;
553: }
554: /*
555: * Use returned block position to determine how many blocks
556: * we really read and update b_resid.
557: */
558: blks = sc->sc_stat.c_blk - sc->sc_blkno - 1;
559: #ifdef DEBUG
560: if (ctdebug & CDB_FILES)
561: printf("cteof: bc %d oblk %d nblk %d read %d, resid %d\n",
562: bp->b_bcount, sc->sc_blkno, sc->sc_stat.c_blk,
563: blks, bp->b_bcount - CTKTOB(blks));
564: #endif
565: if (blks == -1) { /* 9145 on EOF does not change sc_stat.c_blk */
566: blks = 0;
567: sc->sc_blkno++;
568: }
569: else {
570: sc->sc_blkno = sc->sc_stat.c_blk;
571: }
572: bp->b_resid = bp->b_bcount - CTKTOB(blks);
573: /*
574: * If we are at physical EOV or were after an EOF,
575: * we are now at logical EOT.
576: */
577: if ((sc->sc_stat.c_aef & AEF_EOV) ||
578: (sc->sc_flags & CTF_AEOF)) {
579: sc->sc_flags |= CTF_EOT;
580: sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF);
581: }
582: /*
583: * If we were before an EOF or we have just completed a FSF,
584: * we are now after EOF.
585: */
586: else if ((sc->sc_flags & CTF_BEOF) ||
587: (sc->sc_flags & CTF_CMD) && sc->sc_cmd == MTFSF) {
588: sc->sc_flags |= CTF_AEOF;
589: sc->sc_flags &= ~CTF_BEOF;
590: }
591: /*
592: * Otherwise if we read something we are now before EOF
593: * (and no longer after EOF).
594: */
595: else if (blks) {
596: sc->sc_flags |= CTF_BEOF;
597: sc->sc_flags &= ~CTF_AEOF;
598: }
599: /*
600: * Finally, if we didn't read anything we just passed an EOF
601: */
602: else
603: sc->sc_flags |= CTF_AEOF;
604: #ifdef DEBUG
605: if (ctdebug & CDB_FILES)
606: printf("cteof: leaving flags %x\n", sc->sc_flags);
607: #endif
608: }
609:
610: ctintr(unit)
611: register int unit;
612: {
613: register struct ct_softc *sc = &ct_softc[unit];
614: register struct buf *bp;
615: u_char stat;
616:
617: bp = cttab[unit].b_actf;
618: if (bp == NULL) {
619: printf("ct%d: bp == NULL\n", unit);
620: return;
621: }
622: if (sc->sc_flags & CTF_IO) {
623: sc->sc_flags &= ~CTF_IO;
624: if (hpibustart(sc->sc_hd->hp_ctlr))
625: ctgo(unit);
626: return;
627: }
628: if ((sc->sc_flags & CTF_STATWAIT) == 0) {
629: if (hpibpptest(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave) == 0) {
630: sc->sc_flags |= CTF_STATWAIT;
631: hpibawait(sc->sc_hd->hp_ctlr);
632: return;
633: }
634: } else
635: sc->sc_flags &= ~CTF_STATWAIT;
636: hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_QSTAT, &stat, 1);
637: #ifdef DEBUG
638: if (ctdebug & CDB_FILES)
639: printf("ctintr: before flags %x\n", sc->sc_flags);
640: #endif
641: if (stat) {
642: sc->sc_rsc.unit = C_SUNIT(sc->sc_punit);
643: sc->sc_rsc.cmd = C_STATUS;
644: hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_CMD,
645: &sc->sc_rsc, sizeof(sc->sc_rsc));
646: hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_EXEC,
647: &sc->sc_stat, sizeof(sc->sc_stat));
648: hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_QSTAT,
649: &stat, 1);
650: #ifdef DEBUG
651: if (ctdebug & CDB_FILES)
652: printf("ctintr: return stat 0x%x, A%x F%x blk %d\n",
653: stat, sc->sc_stat.c_aef,
654: sc->sc_stat.c_fef, sc->sc_stat.c_blk);
655: #endif
656: if (stat == 0) {
657: if (sc->sc_stat.c_aef & (AEF_EOF | AEF_EOV)) {
658: cteof(sc, bp);
659: ctaddeof(unit);
660: goto done;
661: }
662: if (sc->sc_stat.c_fef & FEF_PF) {
663: ctreset(sc, sc->sc_hd);
664: ctstart(unit);
665: return;
666: }
667: if (sc->sc_stat.c_fef & FEF_REXMT) {
668: ctstart(unit);
669: return;
670: }
671: if (sc->sc_stat.c_aef & 0x5800) {
672: if (sc->sc_stat.c_aef & 0x4000)
673: tprintf(sc->sc_ctty,
674: "ct%d: uninitialized media\n",
675: unit);
676: if (sc->sc_stat.c_aef & 0x1000)
677: tprintf(sc->sc_ctty,
678: "ct%d: not ready\n", unit);
679: if (sc->sc_stat.c_aef & 0x0800)
680: tprintf(sc->sc_ctty,
681: "ct%d: write protect\n", unit);
682: } else {
683: printf("ct%d err: v%d u%d ru%d bn%d, ",
684: unit,
685: (sc->sc_stat.c_vu>>4)&0xF,
686: sc->sc_stat.c_vu&0xF,
687: sc->sc_stat.c_pend,
688: sc->sc_stat.c_blk);
689: printf("R0x%x F0x%x A0x%x I0x%x\n",
690: sc->sc_stat.c_ref,
691: sc->sc_stat.c_fef,
692: sc->sc_stat.c_aef,
693: sc->sc_stat.c_ief);
694: }
695: } else
696: printf("ct%d: request status failed\n", unit);
697: bp->b_flags |= B_ERROR;
698: bp->b_error = EIO;
699: goto done;
700: } else
701: bp->b_resid = 0;
702: if (sc->sc_flags & CTF_CMD) {
703: switch (sc->sc_cmd) {
704: case MTFSF:
705: sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF);
706: sc->sc_blkno += CTBTOK(sc->sc_resid);
707: ctstart(unit);
708: return;
709: case MTBSF:
710: sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF|CTF_EOT);
711: break;
712: case MTBSR:
713: sc->sc_flags &= ~CTF_BEOF;
714: if (sc->sc_flags & CTF_EOT) {
715: sc->sc_flags |= CTF_AEOF;
716: sc->sc_flags &= ~CTF_EOT;
717: } else if (sc->sc_flags & CTF_AEOF) {
718: sc->sc_flags |= CTF_BEOF;
719: sc->sc_flags &= ~CTF_AEOF;
720: }
721: break;
722: case MTWEOF:
723: sc->sc_flags &= ~CTF_BEOF;
724: if (sc->sc_flags & (CTF_AEOF|CTF_EOT)) {
725: sc->sc_flags |= CTF_EOT;
726: sc->sc_flags &= ~CTF_AEOF;
727: } else
728: sc->sc_flags |= CTF_AEOF;
729: break;
730: case MTREW:
731: case MTOFFL:
732: sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF|CTF_EOT);
733: break;
734: }
735: } else {
736: sc->sc_flags &= ~CTF_AEOF;
737: sc->sc_blkno += CTBTOK(sc->sc_resid);
738: }
739: done:
740: #ifdef DEBUG
741: if (ctdebug & CDB_FILES)
742: printf("ctintr: after flags %x\n", sc->sc_flags);
743: #endif
744: cttab[unit].b_actf = bp->av_forw;
745: iodone(bp);
746: hpibfree(&sc->sc_dq);
747: if (cttab[unit].b_actf == NULL) {
748: cttab[unit].b_active = 0;
749: return;
750: }
751: ctustart(unit);
752: }
753:
754: ctread(dev, uio)
755: dev_t dev;
756: struct uio *uio;
757: {
758: register int unit = UNIT(dev);
759:
760: return(physio(ctstrategy, &ctbuf[unit], dev, B_READ, minphys, uio));
761: }
762:
763: ctwrite(dev, uio)
764: dev_t dev;
765: struct uio *uio;
766: {
767: register int unit = UNIT(dev);
768:
769: return(physio(ctstrategy, &ctbuf[unit], dev, B_WRITE, minphys, uio));
770: }
771:
772: /*ARGSUSED*/
773: ctioctl(dev, cmd, data, flag)
774: dev_t dev;
775: caddr_t data;
776: {
777: register struct mtop *op;
778: register int cnt;
779:
780: switch (cmd) {
781:
782: case MTIOCTOP:
783: op = (struct mtop *)data;
784: switch(op->mt_op) {
785:
786: case MTWEOF:
787: case MTFSF:
788: case MTBSR:
789: case MTBSF:
790: case MTFSR:
791: cnt = op->mt_count;
792: break;
793:
794: case MTREW:
795: case MTOFFL:
796: cnt = 1;
797: break;
798:
799: default:
800: return(EINVAL);
801: }
802: ctcommand(dev, op->mt_op, cnt);
803: break;
804:
805: case MTIOCGET:
806: break;
807:
808: default:
809: return(EINVAL);
810: }
811: return(0);
812: }
813:
814: /*ARGSUSED*/
815: ctdump(dev)
816: dev_t dev;
817: {
818: return(ENXIO);
819: }
820:
821: ctaddeof(unit)
822: int unit;
823: {
824: register struct ct_softc *sc = &ct_softc[unit];
825:
826: if (sc->sc_eofp == EOFS - 1)
827: sc->sc_eofs[EOFS - 1]++;
828: else {
829: sc->sc_eofp++;
830: if (sc->sc_eofp == EOFS - 1)
831: sc->sc_eofs[EOFS - 1] = EOFS;
832: else
833: /* save blkno */
834: sc->sc_eofs[sc->sc_eofp] = sc->sc_blkno - 1;
835: }
836: #ifdef DEBUG
837: if (ctdebug & CT_BSF)
838: printf("ct%d: add eof pos %d blk %d\n",
839: unit, sc->sc_eofp,
840: sc->sc_eofs[sc->sc_eofp]);
841: #endif
842: }
843: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.