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