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