1 /*
2 * Copyright (c) 1982, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 *
7 * @(#)ct.c 8.3 (Berkeley) 01/09/95
8 */
9
10 #include "ct.h"
11 #if NCT > 0
12 /*
13 * CS80 cartridge tape driver (9144, 88140, 9145)
14 *
15 * Reminder:
16 * C_CC bit (character count option) when used in the CS/80 command
17 * 'set options' will cause the tape not to stream.
18 *
19 * TODO:
20 * make filesystem compatible
21 * make block mode work according to mtio(4) spec. (if possible)
22 * merge with cs80 disk driver
23 * finish support of 9145
24 */
25
26 #include <sys/param.h>
27 #include <sys/buf.h>
28 #include <sys/ioctl.h>
29 #include <sys/mtio.h>
30 #include <sys/tprintf.h>
31 #include <sys/proc.h>
32
33 #include <hp/dev/device.h>
34
35 #include <hp300/dev/ctreg.h>
36
37 /* number of eof marks to remember */
38 #define EOFS 128
39
40 int ctinit(), ctstart(), ctgo(), ctintr();
41 void ctstrategy();
42 struct driver ctdriver = {
43 ctinit, "ct", ctstart, ctgo, ctintr,
44 };
45
46 struct ct_softc {
47 struct hp_device *sc_hd;
48 struct ct_iocmd sc_ioc;
49 struct ct_rscmd sc_rsc;
50 struct ct_stat sc_stat;
51 struct ct_ssmcmd sc_ssmc;
52 struct ct_srcmd sc_src;
53 struct ct_soptcmd sc_soptc;
54 struct ct_ulcmd sc_ul;
55 struct ct_wfmcmd sc_wfm;
56 struct ct_clearcmd sc_clear;
57 struct buf *sc_bp;
58 int sc_blkno;
59 int sc_cmd;
60 int sc_resid;
61 char *sc_addr;
62 int sc_flags;
63 short sc_type;
64 short sc_punit;
65 tpr_t sc_tpr;
66 struct devqueue sc_dq;
67 int sc_eofp;
68 int sc_eofs[EOFS];
69 } ct_softc[NCT];
70
71 /* flags */
72 #define CTF_OPEN 0x01
73 #define CTF_ALIVE 0x02
74 #define CTF_WRT 0x04
75 #define CTF_CMD 0x08
76 #define CTF_IO 0x10
77 #define CTF_BEOF 0x20
78 #define CTF_AEOF 0x40
79 #define CTF_EOT 0x80
80 #define CTF_STATWAIT 0x100
81 #define CTF_CANSTREAM 0x200
82 #define CTF_WRTTN 0x400
83
84 struct ctinfo {
85 short hwid;
86 short punit;
87 char *desc;
88 } ctinfo[] = {
89 CT7946ID, 1, "7946A",
90 CT7912PID, 1, "7912P",
91 CT7914PID, 1, "7914P",
92 CT9144ID, 0, "9144",
93 CT9145ID, 0, "9145",
94 };
95 int nctinfo = sizeof(ctinfo) / sizeof(ctinfo[0]);
96
97 struct buf cttab[NCT];
98 struct buf ctbuf[NCT];
99
100 #define CT_NOREW 4
101 #define CT_STREAM 8
102 #define UNIT(x) (minor(x) & 3)
103 #define ctpunit(x) ((x) & 7)
104
105 #ifdef DEBUG
106 int ctdebug = 0;
107 #define CDB_FILES 0x01
108 #define CT_BSF 0x02
109 #endif
110
ctinit(hd)111 ctinit(hd)
112 register struct hp_device *hd;
113 {
114 register struct ct_softc *sc = &ct_softc[hd->hp_unit];
115 register struct buf *bp;
116
117 for (bp = cttab; bp < &cttab[NCT]; bp++)
118 bp->b_actb = &bp->b_actf;
119 sc->sc_hd = hd;
120 sc->sc_punit = ctpunit(hd->hp_flags);
121 if (ctident(sc, hd) < 0)
122 return(0);
123 ctreset(sc, hd);
124 sc->sc_dq.dq_ctlr = hd->hp_ctlr;
125 sc->sc_dq.dq_unit = hd->hp_unit;
126 sc->sc_dq.dq_slave = hd->hp_slave;
127 sc->sc_dq.dq_driver = &ctdriver;
128 sc->sc_flags |= CTF_ALIVE;
129 return(1);
130 }
131
ctident(sc,hd)132 ctident(sc, hd)
133 register struct ct_softc *sc;
134 register struct hp_device *hd;
135 {
136 struct ct_describe desc;
137 u_char stat, cmd[3];
138 char name[7];
139 int id, i;
140
141 /*
142 * Read device id and verify that:
143 * 1. It is a CS80 device
144 * 2. It is one of our recognized tape devices
145 * 3. It has the proper physical unit number
146 */
147 id = hpibid(hd->hp_ctlr, hd->hp_slave);
148 if ((id & 0x200) == 0)
149 return(-1);
150 for (i = 0; i < nctinfo; i++)
151 if (id == ctinfo[i].hwid)
152 break;
153 if (i == nctinfo || sc->sc_punit != ctinfo[i].punit)
154 return(-1);
155 id = i;
156
157 /*
158 * Collect device description.
159 * Right now we only need this to differentiate 7945 from 7946.
160 * Note that we always issue the describe command to unit 0.
161 */
162 cmd[0] = C_SUNIT(0);
163 cmd[1] = C_SVOL(0);
164 cmd[2] = C_DESC;
165 hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, cmd, sizeof(cmd));
166 hpibrecv(hd->hp_ctlr, hd->hp_slave, C_EXEC, &desc, 37);
167 hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
168 bzero(name, sizeof(name));
169 if (!stat) {
170 register int n = desc.d_name;
171 for (i = 5; i >= 0; i--) {
172 name[i] = (n & 0xf) + '0';
173 n >>= 4;
174 }
175 }
176 switch (ctinfo[id].hwid) {
177 case CT7946ID:
178 if (bcmp(name, "079450", 6) == 0)
179 return(-1); /* not really a 7946 */
180 /* fall into... */
181 case CT9144ID:
182 case CT9145ID:
183 sc->sc_type = CT9144;
184 sc->sc_flags |= CTF_CANSTREAM;
185 break;
186
187 case CT7912PID:
188 case CT7914PID:
189 sc->sc_type = CT88140;
190 break;
191 }
192 printf("ct%d: %s %stape\n", hd->hp_unit, ctinfo[id].desc,
193 (sc->sc_flags & CTF_CANSTREAM) ? "streaming " : " ");
194 return(id);
195 }
196
ctreset(sc,hd)197 ctreset(sc, hd)
198 register struct ct_softc *sc;
199 register struct hp_device *hd;
200 {
201 u_char stat;
202
203 sc->sc_clear.unit = C_SUNIT(sc->sc_punit);
204 sc->sc_clear.cmd = C_CLEAR;
205 hpibsend(hd->hp_ctlr, hd->hp_slave, C_TCMD, &sc->sc_clear,
206 sizeof(sc->sc_clear));
207 hpibswait(hd->hp_ctlr, hd->hp_slave);
208 hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
209 sc->sc_src.unit = C_SUNIT(CTCTLR);
210 sc->sc_src.nop = C_NOP;
211 sc->sc_src.cmd = C_SREL;
212 sc->sc_src.param = C_REL;
213 hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &sc->sc_src,
214 sizeof(sc->sc_src));
215 hpibswait(hd->hp_ctlr, hd->hp_slave);
216 hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
217 sc->sc_ssmc.unit = C_SUNIT(sc->sc_punit);
218 sc->sc_ssmc.cmd = C_SSM;
219 sc->sc_ssmc.refm = REF_MASK;
220 sc->sc_ssmc.fefm = FEF_MASK;
221 sc->sc_ssmc.aefm = AEF_MASK;
222 sc->sc_ssmc.iefm = IEF_MASK;
223 hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &sc->sc_ssmc,
224 sizeof(sc->sc_ssmc));
225 hpibswait(hd->hp_ctlr, hd->hp_slave);
226 hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
227 sc->sc_soptc.unit = C_SUNIT(sc->sc_punit);
228 sc->sc_soptc.nop = C_NOP;
229 sc->sc_soptc.cmd = C_SOPT;
230 sc->sc_soptc.opt = C_SPAR;
231 hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &sc->sc_soptc,
232 sizeof(sc->sc_soptc));
233 hpibswait(hd->hp_ctlr, hd->hp_slave);
234 hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
235 }
236
237 /*ARGSUSED*/
ctopen(dev,flag,type,p)238 ctopen(dev, flag, type, p)
239 dev_t dev;
240 int flag, type;
241 struct proc *p;
242 {
243 register struct ct_softc *sc = &ct_softc[UNIT(dev)];
244 u_char stat;
245 int cc;
246
247 if (UNIT(dev) >= NCT || (sc->sc_flags & CTF_ALIVE) == 0)
248 return(ENXIO);
249 if (sc->sc_flags & CTF_OPEN)
250 return(EBUSY);
251 sc->sc_soptc.unit = C_SUNIT(sc->sc_punit);
252 sc->sc_soptc.nop = C_NOP;
253 sc->sc_soptc.cmd = C_SOPT;
254 if ((dev & CT_STREAM) && (sc->sc_flags & CTF_CANSTREAM))
255 sc->sc_soptc.opt = C_SPAR | C_IMRPT;
256 else
257 sc->sc_soptc.opt = C_SPAR;
258 /*
259 * Check the return of hpibsend() and hpibswait().
260 * Drive could be loading/unloading a tape. If not checked,
261 * driver hangs.
262 */
263 cc = hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
264 C_CMD, &sc->sc_soptc, sizeof(sc->sc_soptc));
265 if (cc != sizeof(sc->sc_soptc))
266 return(EBUSY);
267 hpibswait(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave);
268 cc = hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_QSTAT,
269 &stat, sizeof(stat));
270 if (cc != sizeof(stat))
271 return(EBUSY);
272 sc->sc_tpr = tprintf_open(p);
273 sc->sc_flags |= CTF_OPEN;
274 return(0);
275 }
276
277 /*ARGSUSED*/
ctclose(dev,flag)278 ctclose(dev, flag)
279 dev_t dev;
280 int flag;
281 {
282 register struct ct_softc *sc = &ct_softc[UNIT(dev)];
283
284 if ((sc->sc_flags & (CTF_WRT|CTF_WRTTN)) == (CTF_WRT|CTF_WRTTN) &&
285 (sc->sc_flags & CTF_EOT) == 0 ) { /* XXX return error if EOT ?? */
286 ctcommand(dev, MTWEOF, 2);
287 ctcommand(dev, MTBSR, 1);
288 if (sc->sc_eofp == EOFS - 1)
289 sc->sc_eofs[EOFS - 1]--;
290 else
291 sc->sc_eofp--;
292 #ifdef DEBUG
293 if(ctdebug & CT_BSF)
294 printf("ct%d: ctclose backup eofs prt %d blk %d\n",
295 UNIT(dev), sc->sc_eofp, sc->sc_eofs[sc->sc_eofp]);
296 #endif
297 }
298 if ((minor(dev) & CT_NOREW) == 0)
299 ctcommand(dev, MTREW, 1);
300 sc->sc_flags &= ~(CTF_OPEN | CTF_WRT | CTF_WRTTN);
301 tprintf_close(sc->sc_tpr);
302 #ifdef DEBUG
303 if (ctdebug & CDB_FILES)
304 printf("ctclose: flags %x\n", sc->sc_flags);
305 #endif
306 return(0); /* XXX */
307 }
308
ctcommand(dev,cmd,cnt)309 ctcommand(dev, cmd, cnt)
310 dev_t dev;
311 int cmd;
312 register int cnt;
313 {
314 register struct ct_softc *sc = &ct_softc[UNIT(dev)];
315 register struct buf *bp = &ctbuf[UNIT(dev)];
316 register struct buf *nbp = 0;
317
318 if (cmd == MTBSF && sc->sc_eofp == EOFS - 1) {
319 cnt = sc->sc_eofs[EOFS - 1] - cnt;
320 ctcommand(dev, MTREW, 1);
321 ctcommand(dev, MTFSF, cnt);
322 cnt = 2;
323 cmd = MTBSR;
324 }
325
326 if (cmd == MTBSF && sc->sc_eofp - cnt < 0) {
327 cnt = 1;
328 cmd = MTREW;
329 }
330
331 sc->sc_flags |= CTF_CMD;
332 sc->sc_bp = bp;
333 sc->sc_cmd = cmd;
334 bp->b_dev = dev;
335 if (cmd == MTFSF) {
336 nbp = (struct buf *)geteblk(MAXBSIZE);
337 bp->b_un.b_addr = nbp->b_un.b_addr;
338 bp->b_bcount = MAXBSIZE;
339 }
340 again:
341 bp->b_flags = B_BUSY;
342 if (cmd == MTBSF) {
343 sc->sc_blkno = sc->sc_eofs[sc->sc_eofp];
344 sc->sc_eofp--;
345 #ifdef DEBUG
346 if (ctdebug & CT_BSF)
347 printf("ct%d: backup eof pos %d blk %d\n",
348 UNIT(dev), sc->sc_eofp,
349 sc->sc_eofs[sc->sc_eofp]);
350 #endif
351 }
352 ctstrategy(bp);
353 iowait(bp);
354 if (--cnt > 0)
355 goto again;
356 bp->b_flags = 0;
357 sc->sc_flags &= ~CTF_CMD;
358 if (nbp)
359 brelse(nbp);
360 }
361
362 void
ctstrategy(bp)363 ctstrategy(bp)
364 register struct buf *bp;
365 {
366 register struct buf *dp;
367 register int s, unit;
368
369 unit = UNIT(bp->b_dev);
370 dp = &cttab[unit];
371 bp->b_actf = NULL;
372 s = splbio();
373 bp->b_actb = dp->b_actb;
374 *dp->b_actb = bp;
375 dp->b_actb = &bp->b_actf;
376 if (dp->b_active == 0) {
377 dp->b_active = 1;
378 ctustart(unit);
379 }
380 splx(s);
381 }
382
ctustart(unit)383 ctustart(unit)
384 register int unit;
385 {
386 register struct ct_softc *sc = &ct_softc[unit];
387 register struct buf *bp;
388
389 bp = cttab[unit].b_actf;
390 sc->sc_addr = bp->b_un.b_addr;
391 sc->sc_resid = bp->b_bcount;
392 if (hpibreq(&sc->sc_dq))
393 ctstart(unit);
394 }
395
ctstart(unit)396 ctstart(unit)
397 register int unit;
398 {
399 register struct ct_softc *sc = &ct_softc[unit];
400 register struct buf *bp, *dp;
401 register int i;
402
403 bp = cttab[unit].b_actf;
404 again:
405 if ((sc->sc_flags & CTF_CMD) && sc->sc_bp == bp) {
406 switch(sc->sc_cmd) {
407
408 case MTFSF:
409 bp->b_flags |= B_READ;
410 goto mustio;
411
412 case MTBSF:
413 goto gotaddr;
414
415 case MTOFFL:
416 sc->sc_blkno = 0;
417 sc->sc_ul.unit = C_SUNIT(sc->sc_punit);
418 sc->sc_ul.cmd = C_UNLOAD;
419 hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
420 C_CMD, &sc->sc_ul, sizeof(sc->sc_ul));
421 break;
422
423 case MTWEOF:
424 sc->sc_blkno++;
425 sc->sc_flags |= CTF_WRT;
426 sc->sc_wfm.unit = C_SUNIT(sc->sc_punit);
427 sc->sc_wfm.cmd = C_WFM;
428 hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
429 C_CMD, &sc->sc_wfm, sizeof(sc->sc_wfm));
430 ctaddeof(unit);
431 break;
432
433 case MTBSR:
434 sc->sc_blkno--;
435 goto gotaddr;
436
437 case MTFSR:
438 sc->sc_blkno++;
439 goto gotaddr;
440
441 case MTREW:
442 sc->sc_blkno = 0;
443 #ifdef DEBUG
444 if(ctdebug & CT_BSF)
445 printf("ct%d: clearing eofs\n", unit);
446 #endif
447 for (i=0; i<EOFS; i++)
448 sc->sc_eofs[i] = 0;
449 sc->sc_eofp = 0;
450
451 gotaddr:
452 sc->sc_ioc.saddr = C_SADDR;
453 sc->sc_ioc.addr0 = 0;
454 sc->sc_ioc.addr = sc->sc_blkno;
455 sc->sc_ioc.unit = C_SUNIT(sc->sc_punit);
456 sc->sc_ioc.nop2 = C_NOP;
457 sc->sc_ioc.slen = C_SLEN;
458 sc->sc_ioc.len = 0;
459 sc->sc_ioc.nop3 = C_NOP;
460 sc->sc_ioc.cmd = C_READ;
461 hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
462 C_CMD, &sc->sc_ioc, sizeof(sc->sc_ioc));
463 break;
464 }
465 }
466 else {
467 mustio:
468 if ((bp->b_flags & B_READ) &&
469 sc->sc_flags & (CTF_BEOF|CTF_EOT)) {
470 #ifdef DEBUG
471 if (ctdebug & CDB_FILES)
472 printf("ctstart: before flags %x\n", sc->sc_flags);
473 #endif
474 if (sc->sc_flags & CTF_BEOF) {
475 sc->sc_flags &= ~CTF_BEOF;
476 sc->sc_flags |= CTF_AEOF;
477 #ifdef DEBUG
478 if (ctdebug & CDB_FILES)
479 printf("ctstart: after flags %x\n", sc->sc_flags);
480 #endif
481 }
482 bp->b_resid = bp->b_bcount;
483 iodone(bp);
484 hpibfree(&sc->sc_dq);
485 if (dp = bp->b_actf)
486 dp->b_actb = bp->b_actb;
487 else
488 cttab[unit].b_actb = bp->b_actb;
489 *bp->b_actb = dp;
490 if ((bp = dp) == NULL) {
491 cttab[unit].b_active = 0;
492 return;
493 }
494 sc->sc_addr = bp->b_un.b_addr;
495 sc->sc_resid = bp->b_bcount;
496 if (hpibreq(&sc->sc_dq))
497 goto again;
498 return;
499 }
500 sc->sc_flags |= CTF_IO;
501 sc->sc_ioc.unit = C_SUNIT(sc->sc_punit);
502 sc->sc_ioc.saddr = C_SADDR;
503 sc->sc_ioc.addr0 = 0;
504 sc->sc_ioc.addr = sc->sc_blkno;
505 sc->sc_ioc.nop2 = C_NOP;
506 sc->sc_ioc.slen = C_SLEN;
507 sc->sc_ioc.len = sc->sc_resid;
508 sc->sc_ioc.nop3 = C_NOP;
509 if (bp->b_flags & B_READ)
510 sc->sc_ioc.cmd = C_READ;
511 else {
512 sc->sc_ioc.cmd = C_WRITE;
513 sc->sc_flags |= (CTF_WRT | CTF_WRTTN);
514 }
515 hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_CMD,
516 &sc->sc_ioc, sizeof(sc->sc_ioc));
517 }
518 hpibawait(sc->sc_hd->hp_ctlr);
519 }
520
ctgo(unit)521 ctgo(unit)
522 register int unit;
523 {
524 register struct ct_softc *sc = &ct_softc[unit];
525 register struct buf *bp;
526
527 bp = cttab[unit].b_actf;
528 hpibgo(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_EXEC,
529 sc->sc_addr, sc->sc_resid, bp->b_flags & B_READ);
530 }
531
532 /*
533 * Hideous grue to handle EOF/EOT (mostly for reads)
534 */
cteof(sc,bp)535 cteof(sc, bp)
536 register struct ct_softc *sc;
537 register struct buf *bp;
538 {
539 long blks;
540
541 /*
542 * EOT on a write is an error.
543 */
544 if ((bp->b_flags & B_READ) == 0) {
545 bp->b_resid = bp->b_bcount;
546 bp->b_flags |= B_ERROR;
547 bp->b_error = ENOSPC;
548 sc->sc_flags |= CTF_EOT;
549 return;
550 }
551 /*
552 * Use returned block position to determine how many blocks
553 * we really read and update b_resid.
554 */
555 blks = sc->sc_stat.c_blk - sc->sc_blkno - 1;
556 #ifdef DEBUG
557 if (ctdebug & CDB_FILES)
558 printf("cteof: bc %d oblk %d nblk %d read %d, resid %d\n",
559 bp->b_bcount, sc->sc_blkno, sc->sc_stat.c_blk,
560 blks, bp->b_bcount - CTKTOB(blks));
561 #endif
562 if (blks == -1) { /* 9145 on EOF does not change sc_stat.c_blk */
563 blks = 0;
564 sc->sc_blkno++;
565 }
566 else {
567 sc->sc_blkno = sc->sc_stat.c_blk;
568 }
569 bp->b_resid = bp->b_bcount - CTKTOB(blks);
570 /*
571 * If we are at physical EOV or were after an EOF,
572 * we are now at logical EOT.
573 */
574 if ((sc->sc_stat.c_aef & AEF_EOV) ||
575 (sc->sc_flags & CTF_AEOF)) {
576 sc->sc_flags |= CTF_EOT;
577 sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF);
578 }
579 /*
580 * If we were before an EOF or we have just completed a FSF,
581 * we are now after EOF.
582 */
583 else if ((sc->sc_flags & CTF_BEOF) ||
584 (sc->sc_flags & CTF_CMD) && sc->sc_cmd == MTFSF) {
585 sc->sc_flags |= CTF_AEOF;
586 sc->sc_flags &= ~CTF_BEOF;
587 }
588 /*
589 * Otherwise if we read something we are now before EOF
590 * (and no longer after EOF).
591 */
592 else if (blks) {
593 sc->sc_flags |= CTF_BEOF;
594 sc->sc_flags &= ~CTF_AEOF;
595 }
596 /*
597 * Finally, if we didn't read anything we just passed an EOF
598 */
599 else
600 sc->sc_flags |= CTF_AEOF;
601 #ifdef DEBUG
602 if (ctdebug & CDB_FILES)
603 printf("cteof: leaving flags %x\n", sc->sc_flags);
604 #endif
605 }
606
ctintr(unit)607 ctintr(unit)
608 register int unit;
609 {
610 register struct ct_softc *sc = &ct_softc[unit];
611 register struct buf *bp, *dp;
612 u_char stat;
613
614 bp = cttab[unit].b_actf;
615 if (bp == NULL) {
616 printf("ct%d: bp == NULL\n", unit);
617 return;
618 }
619 if (sc->sc_flags & CTF_IO) {
620 sc->sc_flags &= ~CTF_IO;
621 if (hpibustart(sc->sc_hd->hp_ctlr))
622 ctgo(unit);
623 return;
624 }
625 if ((sc->sc_flags & CTF_STATWAIT) == 0) {
626 if (hpibpptest(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave) == 0) {
627 sc->sc_flags |= CTF_STATWAIT;
628 hpibawait(sc->sc_hd->hp_ctlr);
629 return;
630 }
631 } else
632 sc->sc_flags &= ~CTF_STATWAIT;
633 hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_QSTAT, &stat, 1);
634 #ifdef DEBUG
635 if (ctdebug & CDB_FILES)
636 printf("ctintr: before flags %x\n", sc->sc_flags);
637 #endif
638 if (stat) {
639 sc->sc_rsc.unit = C_SUNIT(sc->sc_punit);
640 sc->sc_rsc.cmd = C_STATUS;
641 hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_CMD,
642 &sc->sc_rsc, sizeof(sc->sc_rsc));
643 hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_EXEC,
644 &sc->sc_stat, sizeof(sc->sc_stat));
645 hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_QSTAT,
646 &stat, 1);
647 #ifdef DEBUG
648 if (ctdebug & CDB_FILES)
649 printf("ctintr: return stat 0x%x, A%x F%x blk %d\n",
650 stat, sc->sc_stat.c_aef,
651 sc->sc_stat.c_fef, sc->sc_stat.c_blk);
652 #endif
653 if (stat == 0) {
654 if (sc->sc_stat.c_aef & (AEF_EOF | AEF_EOV)) {
655 cteof(sc, bp);
656 ctaddeof(unit);
657 goto done;
658 }
659 if (sc->sc_stat.c_fef & FEF_PF) {
660 ctreset(sc, sc->sc_hd);
661 ctstart(unit);
662 return;
663 }
664 if (sc->sc_stat.c_fef & FEF_REXMT) {
665 ctstart(unit);
666 return;
667 }
668 if (sc->sc_stat.c_aef & 0x5800) {
669 if (sc->sc_stat.c_aef & 0x4000)
670 tprintf(sc->sc_tpr,
671 "ct%d: uninitialized media\n",
672 unit);
673 if (sc->sc_stat.c_aef & 0x1000)
674 tprintf(sc->sc_tpr,
675 "ct%d: not ready\n", unit);
676 if (sc->sc_stat.c_aef & 0x0800)
677 tprintf(sc->sc_tpr,
678 "ct%d: write protect\n", unit);
679 } else {
680 printf("ct%d err: v%d u%d ru%d bn%d, ",
681 unit,
682 (sc->sc_stat.c_vu>>4)&0xF,
683 sc->sc_stat.c_vu&0xF,
684 sc->sc_stat.c_pend,
685 sc->sc_stat.c_blk);
686 printf("R0x%x F0x%x A0x%x I0x%x\n",
687 sc->sc_stat.c_ref,
688 sc->sc_stat.c_fef,
689 sc->sc_stat.c_aef,
690 sc->sc_stat.c_ief);
691 }
692 } else
693 printf("ct%d: request status failed\n", unit);
694 bp->b_flags |= B_ERROR;
695 bp->b_error = EIO;
696 goto done;
697 } else
698 bp->b_resid = 0;
699 if (sc->sc_flags & CTF_CMD) {
700 switch (sc->sc_cmd) {
701 case MTFSF:
702 sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF);
703 sc->sc_blkno += CTBTOK(sc->sc_resid);
704 ctstart(unit);
705 return;
706 case MTBSF:
707 sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF|CTF_EOT);
708 break;
709 case MTBSR:
710 sc->sc_flags &= ~CTF_BEOF;
711 if (sc->sc_flags & CTF_EOT) {
712 sc->sc_flags |= CTF_AEOF;
713 sc->sc_flags &= ~CTF_EOT;
714 } else if (sc->sc_flags & CTF_AEOF) {
715 sc->sc_flags |= CTF_BEOF;
716 sc->sc_flags &= ~CTF_AEOF;
717 }
718 break;
719 case MTWEOF:
720 sc->sc_flags &= ~CTF_BEOF;
721 if (sc->sc_flags & (CTF_AEOF|CTF_EOT)) {
722 sc->sc_flags |= CTF_EOT;
723 sc->sc_flags &= ~CTF_AEOF;
724 } else
725 sc->sc_flags |= CTF_AEOF;
726 break;
727 case MTREW:
728 case MTOFFL:
729 sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF|CTF_EOT);
730 break;
731 }
732 } else {
733 sc->sc_flags &= ~CTF_AEOF;
734 sc->sc_blkno += CTBTOK(sc->sc_resid);
735 }
736 done:
737 #ifdef DEBUG
738 if (ctdebug & CDB_FILES)
739 printf("ctintr: after flags %x\n", sc->sc_flags);
740 #endif
741 if (dp = bp->b_actf)
742 dp->b_actb = bp->b_actb;
743 else
744 cttab[unit].b_actb = bp->b_actb;
745 *bp->b_actb = dp;
746 iodone(bp);
747 hpibfree(&sc->sc_dq);
748 if (cttab[unit].b_actf == NULL) {
749 cttab[unit].b_active = 0;
750 return;
751 }
752 ctustart(unit);
753 }
754
ctread(dev,uio)755 ctread(dev, uio)
756 dev_t dev;
757 struct uio *uio;
758 {
759 register int unit = UNIT(dev);
760
761 return(physio(ctstrategy, &ctbuf[unit], dev, B_READ, minphys, uio));
762 }
763
ctwrite(dev,uio)764 ctwrite(dev, uio)
765 dev_t dev;
766 struct uio *uio;
767 {
768 register int unit = UNIT(dev);
769
770 return(physio(ctstrategy, &ctbuf[unit], dev, B_WRITE, minphys, uio));
771 }
772
773 /*ARGSUSED*/
ctioctl(dev,cmd,data,flag)774 ctioctl(dev, cmd, data, flag)
775 dev_t dev;
776 u_long cmd;
777 caddr_t data;
778 int flag;
779 {
780 register struct mtop *op;
781 register int cnt;
782
783 switch (cmd) {
784
785 case MTIOCTOP:
786 op = (struct mtop *)data;
787 switch(op->mt_op) {
788
789 case MTWEOF:
790 case MTFSF:
791 case MTBSR:
792 case MTBSF:
793 case MTFSR:
794 cnt = op->mt_count;
795 break;
796
797 case MTREW:
798 case MTOFFL:
799 cnt = 1;
800 break;
801
802 default:
803 return(EINVAL);
804 }
805 ctcommand(dev, op->mt_op, cnt);
806 break;
807
808 case MTIOCGET:
809 break;
810
811 default:
812 return(EINVAL);
813 }
814 return(0);
815 }
816
817 /*ARGSUSED*/
ctdump(dev)818 ctdump(dev)
819 dev_t dev;
820 {
821 return(ENXIO);
822 }
823
ctaddeof(unit)824 ctaddeof(unit)
825 int unit;
826 {
827 register struct ct_softc *sc = &ct_softc[unit];
828
829 if (sc->sc_eofp == EOFS - 1)
830 sc->sc_eofs[EOFS - 1]++;
831 else {
832 sc->sc_eofp++;
833 if (sc->sc_eofp == EOFS - 1)
834 sc->sc_eofs[EOFS - 1] = EOFS;
835 else
836 /* save blkno */
837 sc->sc_eofs[sc->sc_eofp] = sc->sc_blkno - 1;
838 }
839 #ifdef DEBUG
840 if (ctdebug & CT_BSF)
841 printf("ct%d: add eof pos %d blk %d\n",
842 unit, sc->sc_eofp,
843 sc->sc_eofs[sc->sc_eofp]);
844 #endif
845 }
846 #endif
847