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