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