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