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