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