ct.c revision 1.18 1 /* $NetBSD: ct.c,v 1.18 1996/10/14 07:14:11 thorpej 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 /* XXX Set device class. */
172 hd->hp_dev.dv_class = DV_TAPE;
173 }
174
175 int
176 ctident(sc, hd, verbose)
177 register struct ct_softc *sc;
178 register struct hp_device *hd;
179 int verbose;
180 {
181 struct ct_describe desc;
182 u_char stat, cmd[3];
183 char name[7];
184 int id, i;
185
186 /*
187 * Read device id and verify that:
188 * 1. It is a CS80 device
189 * 2. It is one of our recognized tape devices
190 * 3. It has the proper physical unit number
191 */
192 id = hpibid(hd->hp_ctlr, hd->hp_slave);
193 if ((id & 0x200) == 0)
194 return(-1);
195 for (i = 0; i < nctinfo; i++)
196 if (id == ctinfo[i].hwid)
197 break;
198 if (i == nctinfo || sc->sc_punit != ctinfo[i].punit)
199 return(-1);
200 id = i;
201
202 /*
203 * Collect device description.
204 * Right now we only need this to differentiate 7945 from 7946.
205 * Note that we always issue the describe command to unit 0.
206 */
207 cmd[0] = C_SUNIT(0);
208 cmd[1] = C_SVOL(0);
209 cmd[2] = C_DESC;
210 hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, cmd, sizeof(cmd));
211 hpibrecv(hd->hp_ctlr, hd->hp_slave, C_EXEC, &desc, 37);
212 hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
213 bzero(name, sizeof(name));
214 if (!stat) {
215 register int n = desc.d_name;
216 for (i = 5; i >= 0; i--) {
217 name[i] = (n & 0xf) + '0';
218 n >>= 4;
219 }
220 }
221 switch (ctinfo[id].hwid) {
222 case CT7946ID:
223 if (bcmp(name, "079450", 6) == 0)
224 return(-1); /* not really a 7946 */
225 /* fall into... */
226 case CT9144ID:
227 case CT9145ID:
228 sc->sc_type = CT9144;
229 sc->sc_flags |= CTF_CANSTREAM;
230 break;
231
232 case CT7912PID:
233 case CT7914PID:
234 sc->sc_type = CT88140;
235 break;
236 }
237 if (verbose)
238 printf(": %s %stape\n", ctinfo[id].desc,
239 (sc->sc_flags & CTF_CANSTREAM) ? "streaming " : " ");
240 return(id);
241 }
242
243 ctreset(sc, hd)
244 register struct ct_softc *sc;
245 register struct hp_device *hd;
246 {
247 u_char stat;
248
249 sc->sc_clear.unit = C_SUNIT(sc->sc_punit);
250 sc->sc_clear.cmd = C_CLEAR;
251 hpibsend(hd->hp_ctlr, hd->hp_slave, C_TCMD, &sc->sc_clear,
252 sizeof(sc->sc_clear));
253 hpibswait(hd->hp_ctlr, hd->hp_slave);
254 hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
255 sc->sc_src.unit = C_SUNIT(CTCTLR);
256 sc->sc_src.nop = C_NOP;
257 sc->sc_src.cmd = C_SREL;
258 sc->sc_src.param = C_REL;
259 hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &sc->sc_src,
260 sizeof(sc->sc_src));
261 hpibswait(hd->hp_ctlr, hd->hp_slave);
262 hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
263 sc->sc_ssmc.unit = C_SUNIT(sc->sc_punit);
264 sc->sc_ssmc.cmd = C_SSM;
265 sc->sc_ssmc.refm = REF_MASK;
266 sc->sc_ssmc.fefm = FEF_MASK;
267 sc->sc_ssmc.aefm = AEF_MASK;
268 sc->sc_ssmc.iefm = IEF_MASK;
269 hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &sc->sc_ssmc,
270 sizeof(sc->sc_ssmc));
271 hpibswait(hd->hp_ctlr, hd->hp_slave);
272 hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
273 sc->sc_soptc.unit = C_SUNIT(sc->sc_punit);
274 sc->sc_soptc.nop = C_NOP;
275 sc->sc_soptc.cmd = C_SOPT;
276 sc->sc_soptc.opt = C_SPAR;
277 hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &sc->sc_soptc,
278 sizeof(sc->sc_soptc));
279 hpibswait(hd->hp_ctlr, hd->hp_slave);
280 hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
281 }
282
283 /*ARGSUSED*/
284 ctopen(dev, flag, type, p)
285 dev_t dev;
286 int flag, type;
287 struct proc *p;
288 {
289 register struct ct_softc *sc = &ct_softc[UNIT(dev)];
290 u_char stat;
291 int cc;
292
293 if (UNIT(dev) >= NCT || (sc->sc_flags & CTF_ALIVE) == 0)
294 return(ENXIO);
295 if (sc->sc_flags & CTF_OPEN)
296 return(EBUSY);
297 sc->sc_soptc.unit = C_SUNIT(sc->sc_punit);
298 sc->sc_soptc.nop = C_NOP;
299 sc->sc_soptc.cmd = C_SOPT;
300 if ((dev & CT_STREAM) && (sc->sc_flags & CTF_CANSTREAM))
301 sc->sc_soptc.opt = C_SPAR | C_IMRPT;
302 else
303 sc->sc_soptc.opt = C_SPAR;
304 /*
305 * Check the return of hpibsend() and hpibswait().
306 * Drive could be loading/unloading a tape. If not checked,
307 * driver hangs.
308 */
309 cc = hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
310 C_CMD, &sc->sc_soptc, sizeof(sc->sc_soptc));
311 if (cc != sizeof(sc->sc_soptc))
312 return(EBUSY);
313 hpibswait(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave);
314 cc = hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_QSTAT,
315 &stat, sizeof(stat));
316 if (cc != sizeof(stat))
317 return(EBUSY);
318 sc->sc_tpr = tprintf_open(p);
319 sc->sc_flags |= CTF_OPEN;
320 return(0);
321 }
322
323 /*ARGSUSED*/
324 ctclose(dev, flag)
325 dev_t dev;
326 int flag;
327 {
328 register struct ct_softc *sc = &ct_softc[UNIT(dev)];
329
330 if ((sc->sc_flags & (CTF_WRT|CTF_WRTTN)) == (CTF_WRT|CTF_WRTTN) &&
331 (sc->sc_flags & CTF_EOT) == 0 ) { /* XXX return error if EOT ?? */
332 ctcommand(dev, MTWEOF, 2);
333 ctcommand(dev, MTBSR, 1);
334 if (sc->sc_eofp == EOFS - 1)
335 sc->sc_eofs[EOFS - 1]--;
336 else
337 sc->sc_eofp--;
338 #ifdef DEBUG
339 if(ctdebug & CT_BSF)
340 printf("%s: ctclose backup eofs prt %d blk %d\n",
341 sc->sc_hd->hp_xname, sc->sc_eofp,
342 sc->sc_eofs[sc->sc_eofp]);
343 #endif
344 }
345 if ((minor(dev) & CT_NOREW) == 0)
346 ctcommand(dev, MTREW, 1);
347 sc->sc_flags &= ~(CTF_OPEN | CTF_WRT | CTF_WRTTN);
348 tprintf_close(sc->sc_tpr);
349 #ifdef DEBUG
350 if (ctdebug & CDB_FILES)
351 printf("ctclose: flags %x\n", sc->sc_flags);
352 #endif
353 return(0); /* XXX */
354 }
355
356 ctcommand(dev, cmd, cnt)
357 dev_t dev;
358 int cmd;
359 register int cnt;
360 {
361 register struct ct_softc *sc = &ct_softc[UNIT(dev)];
362 register struct buf *bp = &ctbuf[UNIT(dev)];
363 register struct buf *nbp = 0;
364
365 if (cmd == MTBSF && sc->sc_eofp == EOFS - 1) {
366 cnt = sc->sc_eofs[EOFS - 1] - cnt;
367 ctcommand(dev, MTREW, 1);
368 ctcommand(dev, MTFSF, cnt);
369 cnt = 2;
370 cmd = MTBSR;
371 }
372
373 if (cmd == MTBSF && sc->sc_eofp - cnt < 0) {
374 cnt = 1;
375 cmd = MTREW;
376 }
377
378 sc->sc_flags |= CTF_CMD;
379 sc->sc_bp = bp;
380 sc->sc_cmd = cmd;
381 bp->b_dev = dev;
382 if (cmd == MTFSF) {
383 nbp = (struct buf *)geteblk(MAXBSIZE);
384 bp->b_un.b_addr = nbp->b_un.b_addr;
385 bp->b_bcount = MAXBSIZE;
386 }
387
388 while (cnt-- > 0) {
389 bp->b_flags = B_BUSY;
390 if (cmd == MTBSF) {
391 sc->sc_blkno = sc->sc_eofs[sc->sc_eofp];
392 sc->sc_eofp--;
393 #ifdef DEBUG
394 if (ctdebug & CT_BSF)
395 printf("%s: backup eof pos %d blk %d\n",
396 sc->sc_hd->hp_xname, sc->sc_eofp,
397 sc->sc_eofs[sc->sc_eofp]);
398 #endif
399 }
400 ctstrategy(bp);
401 iowait(bp);
402 }
403 bp->b_flags = 0;
404 sc->sc_flags &= ~CTF_CMD;
405 if (nbp)
406 brelse(nbp);
407 }
408
409 void
410 ctstrategy(bp)
411 register struct buf *bp;
412 {
413 register struct buf *dp;
414 register int s, unit;
415
416 unit = UNIT(bp->b_dev);
417 dp = &cttab[unit];
418 bp->b_actf = NULL;
419 s = splbio();
420 bp->b_actb = dp->b_actb;
421 *dp->b_actb = bp;
422 dp->b_actb = &bp->b_actf;
423 if (dp->b_active == 0) {
424 dp->b_active = 1;
425 ctustart(unit);
426 }
427 splx(s);
428 }
429
430 ctustart(unit)
431 register int unit;
432 {
433 register struct ct_softc *sc = &ct_softc[unit];
434 register struct buf *bp;
435
436 bp = cttab[unit].b_actf;
437 sc->sc_addr = bp->b_un.b_addr;
438 sc->sc_resid = bp->b_bcount;
439 if (hpibreq(&sc->sc_dq))
440 ctstart(unit);
441 }
442
443 ctstart(unit)
444 register int unit;
445 {
446 register struct ct_softc *sc = &ct_softc[unit];
447 register struct buf *bp, *dp;
448 register int i;
449
450 bp = cttab[unit].b_actf;
451 if ((sc->sc_flags & CTF_CMD) && sc->sc_bp == bp) {
452 switch(sc->sc_cmd) {
453
454 case MTFSF:
455 bp->b_flags |= B_READ;
456 goto mustio;
457
458 case MTBSF:
459 goto gotaddr;
460
461 case MTOFFL:
462 sc->sc_blkno = 0;
463 sc->sc_ul.unit = C_SUNIT(sc->sc_punit);
464 sc->sc_ul.cmd = C_UNLOAD;
465 hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
466 C_CMD, &sc->sc_ul, sizeof(sc->sc_ul));
467 break;
468
469 case MTWEOF:
470 sc->sc_blkno++;
471 sc->sc_flags |= CTF_WRT;
472 sc->sc_wfm.unit = C_SUNIT(sc->sc_punit);
473 sc->sc_wfm.cmd = C_WFM;
474 hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
475 C_CMD, &sc->sc_wfm, sizeof(sc->sc_wfm));
476 ctaddeof(unit);
477 break;
478
479 case MTBSR:
480 sc->sc_blkno--;
481 goto gotaddr;
482
483 case MTFSR:
484 sc->sc_blkno++;
485 goto gotaddr;
486
487 case MTREW:
488 sc->sc_blkno = 0;
489 #ifdef DEBUG
490 if(ctdebug & CT_BSF)
491 printf("%s: clearing eofs\n",
492 sc->sc_hd->hp_xname);
493 #endif
494 for (i=0; i<EOFS; i++)
495 sc->sc_eofs[i] = 0;
496 sc->sc_eofp = 0;
497
498 gotaddr:
499 sc->sc_ioc.saddr = C_SADDR;
500 sc->sc_ioc.addr0 = 0;
501 sc->sc_ioc.addr = sc->sc_blkno;
502 sc->sc_ioc.unit = C_SUNIT(sc->sc_punit);
503 sc->sc_ioc.nop2 = C_NOP;
504 sc->sc_ioc.slen = C_SLEN;
505 sc->sc_ioc.len = 0;
506 sc->sc_ioc.nop3 = C_NOP;
507 sc->sc_ioc.cmd = C_READ;
508 hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
509 C_CMD, &sc->sc_ioc, sizeof(sc->sc_ioc));
510 break;
511 }
512 }
513 else {
514 mustio:
515 if ((bp->b_flags & B_READ) &&
516 sc->sc_flags & (CTF_BEOF|CTF_EOT)) {
517 #ifdef DEBUG
518 if (ctdebug & CDB_FILES)
519 printf("ctstart: before flags %x\n", sc->sc_flags);
520 #endif
521 if (sc->sc_flags & CTF_BEOF) {
522 sc->sc_flags &= ~CTF_BEOF;
523 sc->sc_flags |= CTF_AEOF;
524 #ifdef DEBUG
525 if (ctdebug & CDB_FILES)
526 printf("ctstart: after flags %x\n", sc->sc_flags);
527 #endif
528 }
529 bp->b_resid = bp->b_bcount;
530 ctdone(unit, bp);
531 return;
532 }
533 sc->sc_flags |= CTF_IO;
534 sc->sc_ioc.unit = C_SUNIT(sc->sc_punit);
535 sc->sc_ioc.saddr = C_SADDR;
536 sc->sc_ioc.addr0 = 0;
537 sc->sc_ioc.addr = sc->sc_blkno;
538 sc->sc_ioc.nop2 = C_NOP;
539 sc->sc_ioc.slen = C_SLEN;
540 sc->sc_ioc.len = sc->sc_resid;
541 sc->sc_ioc.nop3 = C_NOP;
542 if (bp->b_flags & B_READ)
543 sc->sc_ioc.cmd = C_READ;
544 else {
545 sc->sc_ioc.cmd = C_WRITE;
546 sc->sc_flags |= (CTF_WRT | CTF_WRTTN);
547 }
548 hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_CMD,
549 &sc->sc_ioc, sizeof(sc->sc_ioc));
550 }
551 hpibawait(sc->sc_hd->hp_ctlr);
552 }
553
554 ctgo(unit)
555 register int unit;
556 {
557 register struct ct_softc *sc = &ct_softc[unit];
558 register struct buf *bp;
559 int rw;
560
561 bp = cttab[unit].b_actf;
562 rw = bp->b_flags & B_READ;
563 hpibgo(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_EXEC,
564 sc->sc_addr, sc->sc_resid, rw, rw != 0);
565 }
566
567 /*
568 * Hideous grue to handle EOF/EOT (mostly for reads)
569 */
570 cteof(sc, bp)
571 register struct ct_softc *sc;
572 register struct buf *bp;
573 {
574 long blks;
575
576 /*
577 * EOT on a write is an error.
578 */
579 if ((bp->b_flags & B_READ) == 0) {
580 bp->b_resid = bp->b_bcount;
581 bp->b_flags |= B_ERROR;
582 bp->b_error = ENOSPC;
583 sc->sc_flags |= CTF_EOT;
584 return;
585 }
586 /*
587 * Use returned block position to determine how many blocks
588 * we really read and update b_resid.
589 */
590 blks = sc->sc_stat.c_blk - sc->sc_blkno - 1;
591 #ifdef DEBUG
592 if (ctdebug & CDB_FILES)
593 printf("cteof: bc %d oblk %d nblk %d read %d, resid %d\n",
594 bp->b_bcount, sc->sc_blkno, sc->sc_stat.c_blk,
595 blks, bp->b_bcount - CTKTOB(blks));
596 #endif
597 if (blks == -1) { /* 9145 on EOF does not change sc_stat.c_blk */
598 blks = 0;
599 sc->sc_blkno++;
600 }
601 else {
602 sc->sc_blkno = sc->sc_stat.c_blk;
603 }
604 bp->b_resid = bp->b_bcount - CTKTOB(blks);
605 /*
606 * If we are at physical EOV or were after an EOF,
607 * we are now at logical EOT.
608 */
609 if ((sc->sc_stat.c_aef & AEF_EOV) ||
610 (sc->sc_flags & CTF_AEOF)) {
611 sc->sc_flags |= CTF_EOT;
612 sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF);
613 }
614 /*
615 * If we were before an EOF or we have just completed a FSF,
616 * we are now after EOF.
617 */
618 else if ((sc->sc_flags & CTF_BEOF) ||
619 (sc->sc_flags & CTF_CMD) && sc->sc_cmd == MTFSF) {
620 sc->sc_flags |= CTF_AEOF;
621 sc->sc_flags &= ~CTF_BEOF;
622 }
623 /*
624 * Otherwise if we read something we are now before EOF
625 * (and no longer after EOF).
626 */
627 else if (blks) {
628 sc->sc_flags |= CTF_BEOF;
629 sc->sc_flags &= ~CTF_AEOF;
630 }
631 /*
632 * Finally, if we didn't read anything we just passed an EOF
633 */
634 else
635 sc->sc_flags |= CTF_AEOF;
636 #ifdef DEBUG
637 if (ctdebug & CDB_FILES)
638 printf("cteof: leaving flags %x\n", sc->sc_flags);
639 #endif
640 }
641
642 int
643 ctintr(arg)
644 void *arg;
645 {
646 register struct ct_softc *sc = arg;
647 register struct buf *bp, *dp;
648 u_char stat;
649 int unit = sc->sc_hd->hp_unit;
650
651 bp = cttab[unit].b_actf;
652 if (bp == NULL) {
653 printf("%s: bp == NULL\n", sc->sc_hd->hp_xname);
654 return;
655 }
656 if (sc->sc_flags & CTF_IO) {
657 sc->sc_flags &= ~CTF_IO;
658 if (hpibustart(sc->sc_hd->hp_ctlr))
659 ctgo(unit);
660 return;
661 }
662 if ((sc->sc_flags & CTF_STATWAIT) == 0) {
663 if (hpibpptest(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave) == 0) {
664 sc->sc_flags |= CTF_STATWAIT;
665 hpibawait(sc->sc_hd->hp_ctlr);
666 return;
667 }
668 } else
669 sc->sc_flags &= ~CTF_STATWAIT;
670 hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_QSTAT, &stat, 1);
671 #ifdef DEBUG
672 if (ctdebug & CDB_FILES)
673 printf("ctintr: before flags %x\n", sc->sc_flags);
674 #endif
675 if (stat) {
676 sc->sc_rsc.unit = C_SUNIT(sc->sc_punit);
677 sc->sc_rsc.cmd = C_STATUS;
678 hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_CMD,
679 &sc->sc_rsc, sizeof(sc->sc_rsc));
680 hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_EXEC,
681 &sc->sc_stat, sizeof(sc->sc_stat));
682 hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_QSTAT,
683 &stat, 1);
684 #ifdef DEBUG
685 if (ctdebug & CDB_FILES)
686 printf("ctintr: return stat 0x%x, A%x F%x blk %d\n",
687 stat, sc->sc_stat.c_aef,
688 sc->sc_stat.c_fef, sc->sc_stat.c_blk);
689 #endif
690 if (stat == 0) {
691 if (sc->sc_stat.c_aef & (AEF_EOF | AEF_EOV)) {
692 cteof(sc, bp);
693 ctaddeof(unit);
694 goto done;
695 }
696 if (sc->sc_stat.c_fef & FEF_PF) {
697 ctreset(sc, sc->sc_hd);
698 ctstart(unit);
699 return;
700 }
701 if (sc->sc_stat.c_fef & FEF_REXMT) {
702 ctstart(unit);
703 return;
704 }
705 if (sc->sc_stat.c_aef & 0x5800) {
706 if (sc->sc_stat.c_aef & 0x4000)
707 tprintf(sc->sc_tpr,
708 "%s: uninitialized media\n",
709 sc->sc_hd->hp_xname);
710 if (sc->sc_stat.c_aef & 0x1000)
711 tprintf(sc->sc_tpr,
712 "%s: not ready\n",
713 sc->sc_hd->hp_xname);
714 if (sc->sc_stat.c_aef & 0x0800)
715 tprintf(sc->sc_tpr,
716 "%s: write protect\n",
717 sc->sc_hd->hp_xname);
718 } else {
719 printf("%s err: v%d u%d ru%d bn%d, ",
720 sc->sc_hd->hp_xname,
721 (sc->sc_stat.c_vu>>4)&0xF,
722 sc->sc_stat.c_vu&0xF,
723 sc->sc_stat.c_pend,
724 sc->sc_stat.c_blk);
725 printf("R0x%x F0x%x A0x%x I0x%x\n",
726 sc->sc_stat.c_ref,
727 sc->sc_stat.c_fef,
728 sc->sc_stat.c_aef,
729 sc->sc_stat.c_ief);
730 }
731 } else
732 printf("%s: request status failed\n",
733 sc->sc_hd->hp_xname);
734 bp->b_flags |= B_ERROR;
735 bp->b_error = EIO;
736 goto done;
737 } else
738 bp->b_resid = 0;
739 if (sc->sc_flags & CTF_CMD) {
740 switch (sc->sc_cmd) {
741 case MTFSF:
742 sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF);
743 sc->sc_blkno += CTBTOK(sc->sc_resid);
744 ctstart(unit);
745 return;
746 case MTBSF:
747 sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF|CTF_EOT);
748 break;
749 case MTBSR:
750 sc->sc_flags &= ~CTF_BEOF;
751 if (sc->sc_flags & CTF_EOT) {
752 sc->sc_flags |= CTF_AEOF;
753 sc->sc_flags &= ~CTF_EOT;
754 } else if (sc->sc_flags & CTF_AEOF) {
755 sc->sc_flags |= CTF_BEOF;
756 sc->sc_flags &= ~CTF_AEOF;
757 }
758 break;
759 case MTWEOF:
760 sc->sc_flags &= ~CTF_BEOF;
761 if (sc->sc_flags & (CTF_AEOF|CTF_EOT)) {
762 sc->sc_flags |= CTF_EOT;
763 sc->sc_flags &= ~CTF_AEOF;
764 } else
765 sc->sc_flags |= CTF_AEOF;
766 break;
767 case MTREW:
768 case MTOFFL:
769 sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF|CTF_EOT);
770 break;
771 }
772 } else {
773 sc->sc_flags &= ~CTF_AEOF;
774 sc->sc_blkno += CTBTOK(sc->sc_resid);
775 }
776 done:
777 #ifdef DEBUG
778 if (ctdebug & CDB_FILES)
779 printf("ctintr: after flags %x\n", sc->sc_flags);
780 #endif
781 ctdone(unit, bp);
782 }
783
784 void
785 ctdone(unit, bp)
786 int unit;
787 register struct buf *bp;
788 {
789 register struct ct_softc *sc = &ct_softc[unit];
790 register struct buf *dp;
791
792 if (dp = bp->b_actf)
793 dp->b_actb = bp->b_actb;
794 else
795 cttab[unit].b_actb = bp->b_actb;
796 *bp->b_actb = dp;
797 biodone(bp);
798 hpibfree(&sc->sc_dq);
799 if (cttab[unit].b_actf == NULL) {
800 cttab[unit].b_active = 0;
801 return;
802 }
803 ctustart(unit);
804 }
805
806 int
807 ctread(dev, uio, flags)
808 dev_t dev;
809 struct uio *uio;
810 int flags;
811 {
812 return (physio(ctstrategy, NULL, dev, B_READ, minphys, uio));
813 }
814
815 int
816 ctwrite(dev, uio, flags)
817 dev_t dev;
818 struct uio *uio;
819 int flags;
820 {
821 /* XXX: check for hardware write-protect? */
822 return (physio(ctstrategy, NULL, dev, B_WRITE, minphys, uio));
823 }
824
825 /*ARGSUSED*/
826 ctioctl(dev, cmd, data, flag, p)
827 dev_t dev;
828 int cmd, flag;
829 caddr_t data;
830 struct proc *p;
831 {
832 register struct mtop *op;
833 register int cnt;
834
835 switch (cmd) {
836
837 case MTIOCTOP:
838 op = (struct mtop *)data;
839 switch(op->mt_op) {
840
841 case MTWEOF:
842 case MTFSF:
843 case MTBSR:
844 case MTBSF:
845 case MTFSR:
846 cnt = op->mt_count;
847 break;
848
849 case MTREW:
850 case MTOFFL:
851 cnt = 1;
852 break;
853
854 default:
855 return(EINVAL);
856 }
857 ctcommand(dev, op->mt_op, cnt);
858 break;
859
860 case MTIOCGET:
861 break;
862
863 default:
864 return(EINVAL);
865 }
866 return(0);
867 }
868
869 /*ARGSUSED*/
870 ctdump(dev)
871 dev_t dev;
872 {
873 return(ENXIO);
874 }
875
876 ctaddeof(unit)
877 int unit;
878 {
879 register struct ct_softc *sc = &ct_softc[unit];
880
881 if (sc->sc_eofp == EOFS - 1)
882 sc->sc_eofs[EOFS - 1]++;
883 else {
884 sc->sc_eofp++;
885 if (sc->sc_eofp == EOFS - 1)
886 sc->sc_eofs[EOFS - 1] = EOFS;
887 else
888 /* save blkno */
889 sc->sc_eofs[sc->sc_eofp] = sc->sc_blkno - 1;
890 }
891 #ifdef DEBUG
892 if (ctdebug & CT_BSF)
893 printf("%s: add eof pos %d blk %d\n",
894 sc->sc_hd->hp_xname, sc->sc_eofp,
895 sc->sc_eofs[sc->sc_eofp]);
896 #endif
897 }
898 #endif
899