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