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