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