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