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