1 /* $NetBSD: ct.c,v 1.23 2011/02/08 20:20:27 rmind 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.23 2011/02/08 20:20:27 rmind 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 /* number of eof marks to remember */ 104 #define EOFS 128 105 106 #ifdef DEBUG 107 int ctdebug = 0xff; 108 #define CDB_FILES 0x01 109 #define CDB_BSF 0x02 110 #define CDB_IDENT 0x04 111 #define CDB_FAIL 0x08 112 #define CDB_FOLLOW 0x10 113 #define DPRINTF(mask, str) if (ctdebug & (mask)) printf str 114 #else 115 #define DPRINTF(mask, str) /* nothing */ 116 #endif 117 118 struct ct_softc { 119 struct device sc_dev; 120 121 gpib_chipset_tag_t sc_ic; 122 gpib_handle_t sc_hdl; 123 124 int sc_slave; /* GPIB slave ID */ 125 int sc_punit; /* physical unit */ 126 struct ct_iocmd sc_ioc; 127 struct ct_rscmd sc_rsc; 128 struct cs80_stat sc_stat; 129 struct bufq_state *sc_tab; 130 int sc_active; 131 struct buf *sc_bp; 132 struct buf sc_bufstore; /* XXX */ 133 int sc_blkno; 134 int sc_cmd; 135 int sc_resid; 136 char *sc_addr; 137 int sc_flags; 138 #define CTF_OPEN 0x01 139 #define CTF_ALIVE 0x02 140 #define CTF_WRT 0x04 141 #define CTF_CMD 0x08 142 #define CTF_IO 0x10 143 #define CTF_BEOF 0x20 144 #define CTF_AEOF 0x40 145 #define CTF_EOT 0x80 146 #define CTF_STATWAIT 0x100 147 #define CTF_CANSTREAM 0x200 148 #define CTF_WRTTN 0x400 149 short sc_type; 150 tpr_t sc_tpr; 151 int sc_eofp; 152 int sc_eofs[EOFS]; 153 }; 154 155 int ctmatch(device_t, cfdata_t, void *); 156 void ctattach(device_t, device_t, void *); 157 158 CFATTACH_DECL(ct, sizeof(struct ct_softc), 159 ctmatch, ctattach, NULL, NULL); 160 161 int ctident(device_t, struct ct_softc *, 162 struct cs80bus_attach_args *); 163 164 int ctlookup(int, int, int); 165 void ctaddeof(struct ct_softc *); 166 void ctustart(struct ct_softc *); 167 void cteof(struct ct_softc *, struct buf *); 168 void ctdone(struct ct_softc *, struct buf *); 169 170 void ctcallback(void *, int); 171 void ctstart(struct ct_softc *); 172 void ctintr(struct ct_softc *); 173 174 void ctcommand(dev_t, int, int); 175 176 dev_type_open(ctopen); 177 dev_type_close(ctclose); 178 dev_type_read(ctread); 179 dev_type_write(ctwrite); 180 dev_type_ioctl(ctioctl); 181 dev_type_strategy(ctstrategy); 182 183 const struct bdevsw ct_bdevsw = { 184 ctopen, ctclose, ctstrategy, ctioctl, nodump, nosize, D_TAPE 185 }; 186 187 const struct cdevsw ct_cdevsw = { 188 ctopen, ctclose, ctread, ctwrite, ctioctl, 189 nostop, notty, nopoll, nommap, nokqfilter, D_TAPE 190 }; 191 192 extern struct cfdriver ct_cd; 193 194 struct ctinfo { 195 short hwid; 196 short punit; 197 const char *desc; 198 } ctinfo[] = { 199 { CT7946ID, 1, "7946A" }, 200 { CT7912PID, 1, "7912P" }, 201 { CT7914PID, 1, "7914P" }, 202 { CT9144ID, 0, "9144" }, 203 { CT9145ID, 0, "9145" }, 204 { CT35401ID, 0, "35401A"}, 205 }; 206 int nctinfo = sizeof(ctinfo) / sizeof(ctinfo[0]); 207 208 #define CT_NOREW 4 209 #define CT_STREAM 8 210 #define CTUNIT(x) (minor(x) & 0x03) 211 212 int 213 ctlookup(int id, int slave, int punit) 214 { 215 int i; 216 217 for (i = 0; i < nctinfo; i++) 218 if (ctinfo[i].hwid == id) 219 break; 220 if (i == nctinfo) 221 return (-1); 222 return (i); 223 } 224 225 int 226 ctmatch(device_t parent, cfdata_t match, void *aux) 227 { 228 struct cs80bus_attach_args *ca = aux; 229 int i; 230 231 if ((i = ctlookup(ca->ca_id, ca->ca_slave, ca->ca_punit)) < 0) 232 return (0); 233 ca->ca_punit = ctinfo[i].punit; 234 return (1); 235 } 236 237 void 238 ctattach(device_t parent, device_t self, void *aux) 239 { 240 struct ct_softc *sc = device_private(self); 241 struct cs80bus_attach_args *ca = aux; 242 struct cs80_description csd; 243 char name[7]; 244 int type, i, n, canstream = 0; 245 246 sc->sc_ic = ca->ca_ic; 247 sc->sc_slave = ca->ca_slave; 248 sc->sc_punit = ca->ca_punit; 249 250 if ((type = ctlookup(ca->ca_id, ca->ca_slave, ca->ca_punit)) < 0) 251 return; 252 253 if (cs80reset(parent, sc->sc_slave, sc->sc_punit)) { 254 aprint_normal("\n"); 255 aprint_error_dev(&sc->sc_dev, "can't reset device\n"); 256 return; 257 } 258 259 if (cs80describe(parent, sc->sc_slave, sc->sc_punit, &csd)) { 260 aprint_normal("\n"); 261 aprint_error_dev(&sc->sc_dev, "didn't respond to describe command\n"); 262 return; 263 } 264 memset(name, 0, sizeof(name)); 265 for (i=0, n=0; i<3; i++) { 266 name[n++] = (csd.d_name[i] >> 4) + '0'; 267 name[n++] = (csd.d_name[i] & 0x0f) + '0'; 268 } 269 270 #ifdef DEBUG 271 if (ctdebug & CDB_IDENT) { 272 printf("\n%s: name: ('%s')\n", 273 device_xname(&sc->sc_dev),name); 274 printf(" iuw %x, maxxfr %d, ctype %d\n", 275 csd.d_iuw, csd.d_cmaxxfr, csd.d_ctype); 276 printf(" utype %d, bps %d, blkbuf %d, burst %d, blktime %d\n", 277 csd.d_utype, csd.d_sectsize, 278 csd.d_blkbuf, csd.d_burstsize, csd.d_blocktime); 279 printf(" avxfr %d, ort %d, atp %d, maxint %d, fv %x, rv %x\n", 280 csd.d_uavexfr, csd.d_retry, csd.d_access, 281 csd.d_maxint, csd.d_fvbyte, csd.d_rvbyte); 282 printf(" maxcyl/head/sect %d/%d/%d, maxvsect %d, inter %d\n", 283 csd.d_maxcylhead >> 8 , csd.d_maxcylhead & 0xff, 284 csd.d_maxsect, csd.d_maxvsectl, csd.d_interleave); 285 printf("%s", device_xname(&sc->sc_dev)); 286 } 287 #endif 288 289 switch (ca->ca_id) { 290 case CT7946ID: 291 if (memcmp(name, "079450", 6) == 0) 292 return; /* not really a 7946 */ 293 /* fall into... */ 294 case CT9144ID: 295 case CT9145ID: 296 case CT35401ID: 297 sc->sc_type = CT9144; 298 canstream = 1; 299 break; 300 301 case CT7912PID: 302 case CT7914PID: 303 sc->sc_type = CT88140; 304 break; 305 default: 306 sc->sc_type = type; 307 break; 308 } 309 310 sc->sc_type = type; 311 sc->sc_flags = canstream ? CTF_CANSTREAM : 0; 312 printf(": %s %stape\n", ctinfo[type].desc, 313 canstream ? "streaming " : ""); 314 315 bufq_alloc(&sc->sc_tab, "fcfs", 0); 316 317 if (gpibregister(sc->sc_ic, sc->sc_slave, ctcallback, sc, 318 &sc->sc_hdl)) { 319 aprint_error_dev(&sc->sc_dev, "can't register callback\n"); 320 return; 321 } 322 323 sc->sc_flags |= CTF_ALIVE; 324 } 325 326 /*ARGSUSED*/ 327 int 328 ctopen(dev_t dev, int flag, int type, struct lwp *l) 329 { 330 struct ct_softc *sc; 331 u_int8_t opt; 332 333 sc = device_lookup_private(&ct_cd, CTUNIT(dev)); 334 if (sc == NULL || (sc->sc_flags & CTF_ALIVE) == 0) 335 return (ENXIO); 336 337 if (sc->sc_flags & CTF_OPEN) 338 return (EBUSY); 339 340 if ((dev & CT_STREAM) && (sc->sc_flags & CTF_CANSTREAM)) 341 opt = C_SPAR | C_IMRPT; 342 else 343 opt = C_SPAR; 344 345 if (cs80setoptions(device_parent(&sc->sc_dev), sc->sc_slave, 346 sc->sc_punit, opt)) 347 return (EBUSY); 348 349 sc->sc_tpr = tprintf_open(l->l_proc); 350 sc->sc_flags |= CTF_OPEN; 351 352 return (0); 353 } 354 355 /*ARGSUSED*/ 356 int 357 ctclose(dev_t dev, int flag, int fmt, struct lwp *l) 358 { 359 struct ct_softc *sc; 360 361 sc = device_lookup_private(&ct_cd, CTUNIT(dev)); 362 if (sc == NULL) 363 return (ENXIO); 364 365 if ((sc->sc_flags & (CTF_WRT|CTF_WRTTN)) == (CTF_WRT|CTF_WRTTN) && 366 (sc->sc_flags & CTF_EOT) == 0 ) { /* XXX return error if EOT ?? */ 367 ctcommand(dev, MTWEOF, 2); 368 ctcommand(dev, MTBSR, 1); 369 if (sc->sc_eofp == EOFS - 1) 370 sc->sc_eofs[EOFS - 1]--; 371 else 372 sc->sc_eofp--; 373 DPRINTF(CDB_BSF, ("%s: ctclose backup eofs prt %d blk %d\n", 374 device_xname(&sc->sc_dev), sc->sc_eofp, 375 sc->sc_eofs[sc->sc_eofp])); 376 } 377 378 if ((minor(dev) & CT_NOREW) == 0) 379 ctcommand(dev, MTREW, 1); 380 sc->sc_flags &= ~(CTF_OPEN | CTF_WRT | CTF_WRTTN); 381 tprintf_close(sc->sc_tpr); 382 DPRINTF(CDB_FILES, ("ctclose: flags %x\n", sc->sc_flags)); 383 384 return (0); /* XXX */ 385 } 386 387 void 388 ctcommand(dev_t dev, int cmd, int cnt) 389 { 390 struct ct_softc *sc; 391 struct buf *bp; 392 struct buf *nbp = 0; 393 394 sc = device_lookup_private(&ct_cd, CTUNIT(dev)); 395 bp = &sc->sc_bufstore; 396 397 DPRINTF(CDB_FOLLOW, ("ctcommand: called\n")); 398 399 if (cmd == MTBSF && sc->sc_eofp == EOFS - 1) { 400 cnt = sc->sc_eofs[EOFS - 1] - cnt; 401 ctcommand(dev, MTREW, 1); 402 ctcommand(dev, MTFSF, cnt); 403 cnt = 2; 404 cmd = MTBSR; 405 } 406 407 if (cmd == MTBSF && sc->sc_eofp - cnt < 0) { 408 cnt = 1; 409 cmd = MTREW; 410 } 411 412 sc->sc_flags |= CTF_CMD; 413 sc->sc_bp = bp; 414 sc->sc_cmd = cmd; 415 bp->b_dev = dev; 416 bp->b_objlock = &buffer_lock; 417 if (cmd == MTFSF) { 418 nbp = (struct buf *)geteblk(MAXBSIZE); 419 bp->b_data = nbp->b_data; 420 bp->b_bcount = MAXBSIZE; 421 } 422 423 while (cnt-- > 0) { 424 bp->b_flags = 0; 425 bp->b_cflags = BC_BUSY; 426 bp->b_oflags = 0; 427 if (cmd == MTBSF) { 428 sc->sc_blkno = sc->sc_eofs[sc->sc_eofp]; 429 sc->sc_eofp--; 430 DPRINTF(CDB_BSF, ("%s: backup eof pos %d blk %d\n", 431 device_xname(&sc->sc_dev), sc->sc_eofp, 432 sc->sc_eofs[sc->sc_eofp])); 433 } 434 ctstrategy(bp); 435 biowait(bp); 436 } 437 bp->b_flags = 0; 438 sc->sc_flags &= ~CTF_CMD; 439 if (nbp) 440 brelse(nbp, 0); 441 } 442 443 void 444 ctstrategy(struct buf *bp) 445 { 446 struct ct_softc *sc; 447 int s; 448 449 DPRINTF(CDB_FOLLOW, ("cdstrategy(%p): dev %" PRIx64 ", bn %" PRIx64 450 ", bcount %x, %c\n", 451 bp, bp->b_dev, bp->b_blkno, bp->b_bcount, 452 (bp->b_flags & B_READ) ? 'R' : 'W')); 453 454 sc = device_lookup_private(&ct_cd, CTUNIT(bp->b_dev)); 455 456 s = splbio(); 457 bufq_put(sc->sc_tab, bp); 458 if (sc->sc_active == 0) { 459 sc->sc_active = 1; 460 ctustart(sc); 461 } 462 splx(s); 463 } 464 465 void 466 ctustart(struct ct_softc *sc) 467 { 468 struct buf *bp; 469 470 bp = bufq_peek(sc->sc_tab); 471 sc->sc_addr = bp->b_data; 472 sc->sc_resid = bp->b_bcount; 473 if (gpibrequest(sc->sc_ic, sc->sc_hdl)) 474 ctstart(sc); 475 } 476 477 void 478 ctstart(struct ct_softc *sc) 479 { 480 struct buf *bp; 481 struct ct_ulcmd ul; 482 struct ct_wfmcmd wfm; 483 int i, slave, punit; 484 485 slave = sc->sc_slave; 486 punit = sc->sc_punit; 487 488 bp = bufq_peek(sc->sc_tab); 489 if ((sc->sc_flags & CTF_CMD) && sc->sc_bp == bp) { 490 switch(sc->sc_cmd) { 491 case MTFSF: 492 bp->b_flags |= B_READ; 493 goto mustio; 494 495 case MTBSF: 496 goto gotaddr; 497 498 case MTOFFL: 499 sc->sc_blkno = 0; 500 ul.unit = CS80CMD_SUNIT(punit); 501 ul.cmd = CS80CMD_UNLOAD; 502 (void) cs80send(device_parent(&sc->sc_dev), slave, 503 punit, CS80CMD_SCMD, &ul, sizeof(ul)); 504 break; 505 506 case MTWEOF: 507 sc->sc_blkno++; 508 sc->sc_flags |= CTF_WRT; 509 wfm.unit = CS80CMD_SUNIT(sc->sc_punit); 510 wfm.cmd = CS80CMD_WFM; 511 (void) cs80send(device_parent(&sc->sc_dev), slave, 512 punit, CS80CMD_SCMD, &wfm, sizeof(wfm)); 513 ctaddeof(sc); 514 break; 515 516 case MTBSR: 517 sc->sc_blkno--; 518 goto gotaddr; 519 520 case MTFSR: 521 sc->sc_blkno++; 522 goto gotaddr; 523 524 case MTREW: 525 sc->sc_blkno = 0; 526 DPRINTF(CDB_BSF, ("%s: clearing eofs\n", 527 device_xname(&sc->sc_dev))); 528 for (i=0; i<EOFS; i++) 529 sc->sc_eofs[i] = 0; 530 sc->sc_eofp = 0; 531 532 gotaddr: 533 sc->sc_ioc.unit = CS80CMD_SUNIT(sc->sc_punit); 534 sc->sc_ioc.saddr = CS80CMD_SADDR; 535 sc->sc_ioc.addr0 = 0; 536 sc->sc_ioc.addr = htobe32(sc->sc_blkno); 537 sc->sc_ioc.nop2 = CS80CMD_NOP; 538 sc->sc_ioc.slen = CS80CMD_SLEN; 539 sc->sc_ioc.len = htobe32(0); 540 sc->sc_ioc.nop3 = CS80CMD_NOP; 541 sc->sc_ioc.cmd = CS80CMD_READ; 542 (void) cs80send(device_parent(&sc->sc_dev), slave, 543 punit, CS80CMD_SCMD, &sc->sc_ioc, 544 sizeof(sc->sc_ioc)); 545 break; 546 } 547 } else { 548 mustio: 549 if ((bp->b_flags & B_READ) && 550 sc->sc_flags & (CTF_BEOF|CTF_EOT)) { 551 DPRINTF(CDB_FILES, ("ctstart: before %x\n", 552 sc->sc_flags)); 553 if (sc->sc_flags & CTF_BEOF) { 554 sc->sc_flags &= ~CTF_BEOF; 555 sc->sc_flags |= CTF_AEOF; 556 DPRINTF(CDB_FILES, ("ctstart: after %x\n", 557 sc->sc_flags)); 558 } 559 bp->b_resid = bp->b_bcount; 560 ctdone(sc, bp); 561 return; 562 } 563 sc->sc_flags |= CTF_IO; 564 sc->sc_ioc.unit = CS80CMD_SUNIT(sc->sc_punit); 565 sc->sc_ioc.saddr = CS80CMD_SADDR; 566 sc->sc_ioc.addr0 = 0; 567 sc->sc_ioc.addr = htobe32(sc->sc_blkno); 568 sc->sc_ioc.nop2 = CS80CMD_NOP; 569 sc->sc_ioc.slen = CS80CMD_SLEN; 570 sc->sc_ioc.len = htobe32(sc->sc_resid); 571 sc->sc_ioc.nop3 = CS80CMD_NOP; 572 if (bp->b_flags & B_READ) 573 sc->sc_ioc.cmd = CS80CMD_READ; 574 else { 575 sc->sc_ioc.cmd = CS80CMD_WRITE; 576 sc->sc_flags |= (CTF_WRT | CTF_WRTTN); 577 } 578 (void) cs80send(device_parent(&sc->sc_dev), slave, punit, 579 CS80CMD_SCMD, &sc->sc_ioc, sizeof(sc->sc_ioc)); 580 } 581 gpibawait(sc->sc_ic); 582 } 583 584 /* 585 * Hideous grue to handle EOF/EOT (mostly for reads) 586 */ 587 void 588 cteof(struct ct_softc *sc, struct buf *bp) 589 { 590 long blks; 591 592 /* 593 * EOT on a write is an error. 594 */ 595 if ((bp->b_flags & B_READ) == 0) { 596 bp->b_resid = bp->b_bcount; 597 bp->b_error = ENOSPC; 598 sc->sc_flags |= CTF_EOT; 599 return; 600 } 601 /* 602 * Use returned block position to determine how many blocks 603 * we really read and update b_resid. 604 */ 605 blks = sc->sc_stat.c_blk - sc->sc_blkno - 1; 606 DPRINTF(CDB_FILES, ("cteof: bc %d oblk %d nblk %d read %ld, resid %ld\n", 607 bp->b_bcount, sc->sc_blkno, sc->sc_stat.c_blk, 608 blks, bp->b_bcount - CTKTOB(blks))); 609 if (blks == -1) { /* 9145 on EOF does not change sc_stat.c_blk */ 610 blks = 0; 611 sc->sc_blkno++; 612 } 613 else { 614 sc->sc_blkno = sc->sc_stat.c_blk; 615 } 616 bp->b_resid = bp->b_bcount - CTKTOB(blks); 617 /* 618 * If we are at physical EOV or were after an EOF, 619 * we are now at logical EOT. 620 */ 621 if ((sc->sc_stat.c_aef & AEF_EOV) || 622 (sc->sc_flags & CTF_AEOF)) { 623 sc->sc_flags |= CTF_EOT; 624 sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF); 625 } 626 /* 627 * If we were before an EOF or we have just completed a FSF, 628 * we are now after EOF. 629 */ 630 else if ((sc->sc_flags & CTF_BEOF) || 631 ((sc->sc_flags & CTF_CMD) && sc->sc_cmd == MTFSF)) { 632 sc->sc_flags |= CTF_AEOF; 633 sc->sc_flags &= ~CTF_BEOF; 634 } 635 /* 636 * Otherwise if we read something we are now before EOF 637 * (and no longer after EOF). 638 */ 639 else if (blks) { 640 sc->sc_flags |= CTF_BEOF; 641 sc->sc_flags &= ~CTF_AEOF; 642 } 643 /* 644 * Finally, if we didn't read anything we just passed an EOF 645 */ 646 else 647 sc->sc_flags |= CTF_AEOF; 648 DPRINTF(CDB_FILES, ("cteof: leaving flags %x\n", sc->sc_flags)); 649 } 650 651 652 void 653 ctcallback(void *v, int action) 654 { 655 struct ct_softc *sc = v; 656 657 DPRINTF(CDB_FOLLOW, ("ctcallback: v=%p, action=%d\n", v, action)); 658 659 switch (action) { 660 case GPIBCBF_START: 661 ctstart(sc); 662 break; 663 case GPIBCBF_INTR: 664 ctintr(sc); 665 break; 666 #ifdef DEBUG 667 default: 668 DPRINTF(CDB_FAIL, ("ctcallback: unknown action %d\n", action)); 669 break; 670 #endif 671 } 672 } 673 674 void 675 ctintr(struct ct_softc *sc) 676 { 677 struct buf *bp; 678 u_int8_t stat; 679 int slave, punit; 680 int dir; 681 682 slave = sc->sc_slave; 683 punit = sc->sc_punit; 684 685 bp = bufq_peek(sc->sc_tab); 686 if (bp == NULL) { 687 aprint_error_dev(&sc->sc_dev, "bp == NULL\n"); 688 return; 689 } 690 if (sc->sc_flags & CTF_IO) { 691 sc->sc_flags &= ~CTF_IO; 692 dir = (bp->b_flags & B_READ ? GPIB_READ : GPIB_WRITE); 693 gpibxfer(sc->sc_ic, slave, CS80CMD_EXEC, sc->sc_addr, 694 sc->sc_resid, dir, dir == GPIB_READ); 695 return; 696 } 697 if ((sc->sc_flags & CTF_STATWAIT) == 0) { 698 if (gpibpptest(sc->sc_ic, slave) == 0) { 699 sc->sc_flags |= CTF_STATWAIT; 700 gpibawait(sc->sc_ic); 701 return; 702 } 703 } else 704 sc->sc_flags &= ~CTF_STATWAIT; 705 (void) gpibrecv(sc->sc_ic, slave, CS80CMD_QSTAT, &stat, 1); 706 DPRINTF(CDB_FILES, ("ctintr: before flags %x\n", sc->sc_flags)); 707 if (stat) { 708 sc->sc_rsc.unit = CS80CMD_SUNIT(punit); 709 sc->sc_rsc.cmd = CS80CMD_STATUS; 710 (void) gpibsend(sc->sc_ic, slave, CS80CMD_SCMD, &sc->sc_rsc, 711 sizeof(sc->sc_rsc)); 712 (void) gpibrecv(sc->sc_ic, slave, CS80CMD_EXEC, &sc->sc_stat, 713 sizeof(sc->sc_stat)); 714 (void) gpibrecv(sc->sc_ic, slave, CS80CMD_QSTAT, &stat, 1); 715 DPRINTF(CDB_FILES, ("ctintr: return stat 0x%x, A%x F%x blk %d\n", 716 stat, sc->sc_stat.c_aef, 717 sc->sc_stat.c_fef, sc->sc_stat.c_blk)); 718 if (stat == 0) { 719 if (sc->sc_stat.c_aef & (AEF_EOF | AEF_EOV)) { 720 cteof(sc, bp); 721 ctaddeof(sc); 722 goto done; 723 } 724 if (sc->sc_stat.c_fef & FEF_PF) { 725 cs80reset(sc, slave, punit); 726 ctstart(sc); 727 return; 728 } 729 if (sc->sc_stat.c_fef & FEF_REXMT) { 730 ctstart(sc); 731 return; 732 } 733 if (sc->sc_stat.c_aef & 0x5800) { 734 if (sc->sc_stat.c_aef & 0x4000) 735 tprintf(sc->sc_tpr, 736 "%s: uninitialized media\n", 737 device_xname(&sc->sc_dev)); 738 if (sc->sc_stat.c_aef & 0x1000) 739 tprintf(sc->sc_tpr, 740 "%s: not ready\n", 741 device_xname(&sc->sc_dev)); 742 if (sc->sc_stat.c_aef & 0x0800) 743 tprintf(sc->sc_tpr, 744 "%s: write protect\n", 745 device_xname(&sc->sc_dev)); 746 } else { 747 printf("%s err: v%d u%d ru%d bn%d, ", 748 device_xname(&sc->sc_dev), 749 (sc->sc_stat.c_vu>>4)&0xF, 750 sc->sc_stat.c_vu&0xF, 751 sc->sc_stat.c_pend, 752 sc->sc_stat.c_blk); 753 printf("R0x%x F0x%x A0x%x I0x%x\n", 754 sc->sc_stat.c_ref, 755 sc->sc_stat.c_fef, 756 sc->sc_stat.c_aef, 757 sc->sc_stat.c_ief); 758 } 759 } else 760 aprint_error_dev(&sc->sc_dev, "request status failed\n"); 761 bp->b_error = EIO; 762 goto done; 763 } else 764 bp->b_resid = 0; 765 if (sc->sc_flags & CTF_CMD) { 766 switch (sc->sc_cmd) { 767 case MTFSF: 768 sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF); 769 sc->sc_blkno += CTBTOK(sc->sc_resid); 770 ctstart(sc); 771 return; 772 case MTBSF: 773 sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF|CTF_EOT); 774 break; 775 case MTBSR: 776 sc->sc_flags &= ~CTF_BEOF; 777 if (sc->sc_flags & CTF_EOT) { 778 sc->sc_flags |= CTF_AEOF; 779 sc->sc_flags &= ~CTF_EOT; 780 } else if (sc->sc_flags & CTF_AEOF) { 781 sc->sc_flags |= CTF_BEOF; 782 sc->sc_flags &= ~CTF_AEOF; 783 } 784 break; 785 case MTWEOF: 786 sc->sc_flags &= ~CTF_BEOF; 787 if (sc->sc_flags & (CTF_AEOF|CTF_EOT)) { 788 sc->sc_flags |= CTF_EOT; 789 sc->sc_flags &= ~CTF_AEOF; 790 } else 791 sc->sc_flags |= CTF_AEOF; 792 break; 793 case MTREW: 794 case MTOFFL: 795 sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF|CTF_EOT); 796 break; 797 } 798 } else { 799 sc->sc_flags &= ~CTF_AEOF; 800 sc->sc_blkno += CTBTOK(sc->sc_resid); 801 } 802 done: 803 DPRINTF(CDB_FILES, ("ctintr: after flags %x\n", sc->sc_flags)); 804 ctdone(sc, bp); 805 } 806 807 void 808 ctdone(struct ct_softc *sc, struct buf *bp) 809 { 810 811 (void)bufq_get(sc->sc_tab); 812 biodone(bp); 813 gpibrelease(sc->sc_ic, sc->sc_hdl); 814 if (bufq_peek(sc->sc_tab) == NULL) { 815 sc->sc_active = 0; 816 return; 817 } 818 ctustart(sc); 819 } 820 821 int 822 ctread(dev_t dev, struct uio *uio, int flags) 823 { 824 return (physio(ctstrategy, NULL, dev, B_READ, minphys, uio)); 825 } 826 827 int 828 ctwrite(dev_t dev, struct uio *uio, int flags) 829 { 830 /* XXX: check for hardware write-protect? */ 831 return (physio(ctstrategy, NULL, dev, B_WRITE, minphys, uio)); 832 } 833 834 /*ARGSUSED*/ 835 int 836 ctioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 837 { 838 struct mtop *op; 839 int cnt; 840 841 switch (cmd) { 842 843 case MTIOCTOP: 844 op = (struct mtop *)data; 845 switch(op->mt_op) { 846 847 case MTWEOF: 848 case MTFSF: 849 case MTBSR: 850 case MTBSF: 851 case MTFSR: 852 cnt = op->mt_count; 853 break; 854 855 case MTREW: 856 case MTOFFL: 857 cnt = 1; 858 break; 859 860 default: 861 return (EINVAL); 862 } 863 ctcommand(dev, op->mt_op, cnt); 864 break; 865 866 case MTIOCGET: 867 break; 868 869 default: 870 return (EINVAL); 871 } 872 return (0); 873 } 874 875 void 876 ctaddeof(struct ct_softc *sc) 877 { 878 879 if (sc->sc_eofp == EOFS - 1) 880 sc->sc_eofs[EOFS - 1]++; 881 else { 882 sc->sc_eofp++; 883 if (sc->sc_eofp == EOFS - 1) 884 sc->sc_eofs[EOFS - 1] = EOFS; 885 else 886 /* save blkno */ 887 sc->sc_eofs[sc->sc_eofp] = sc->sc_blkno - 1; 888 } 889 DPRINTF(CDB_BSF, ("%s: add eof pos %d blk %d\n", 890 device_xname(&sc->sc_dev), sc->sc_eofp, 891 sc->sc_eofs[sc->sc_eofp])); 892 } 893