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