1 /* $NetBSD: ct.c,v 1.16 2008/06/11 18:46:24 cegger 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.16 2008/06/11 18:46:24 cegger 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_t dev, int flag, int type, struct lwp *l) 376 { 377 struct ct_softc *sc; 378 u_int8_t opt; 379 380 sc = device_lookup_private(&ct_cd, CTUNIT(dev)); 381 if (sc == NULL || (sc->sc_flags & CTF_ALIVE) == 0) 382 return (ENXIO); 383 384 if (sc->sc_flags & CTF_OPEN) 385 return (EBUSY); 386 387 if ((dev & CT_STREAM) && (sc->sc_flags & CTF_CANSTREAM)) 388 opt = C_SPAR | C_IMRPT; 389 else 390 opt = C_SPAR; 391 392 if (cs80setoptions(device_parent(&sc->sc_dev), sc->sc_slave, 393 sc->sc_punit, opt)) 394 return (EBUSY); 395 396 sc->sc_tpr = tprintf_open(l->l_proc); 397 sc->sc_flags |= CTF_OPEN; 398 399 return (0); 400 } 401 402 /*ARGSUSED*/ 403 int 404 ctclose(dev_t dev, int flag, int fmt, struct lwp *l) 405 { 406 struct ct_softc *sc; 407 408 sc = device_lookup_private(&ct_cd, CTUNIT(dev)); 409 if (sc == NULL) 410 return (ENXIO); 411 412 if ((sc->sc_flags & (CTF_WRT|CTF_WRTTN)) == (CTF_WRT|CTF_WRTTN) && 413 (sc->sc_flags & CTF_EOT) == 0 ) { /* XXX return error if EOT ?? */ 414 ctcommand(dev, MTWEOF, 2); 415 ctcommand(dev, MTBSR, 1); 416 if (sc->sc_eofp == EOFS - 1) 417 sc->sc_eofs[EOFS - 1]--; 418 else 419 sc->sc_eofp--; 420 DPRINTF(CDB_BSF, ("%s: ctclose backup eofs prt %d blk %d\n", 421 device_xname(&sc->sc_dev), sc->sc_eofp, 422 sc->sc_eofs[sc->sc_eofp])); 423 } 424 425 if ((minor(dev) & CT_NOREW) == 0) 426 ctcommand(dev, MTREW, 1); 427 sc->sc_flags &= ~(CTF_OPEN | CTF_WRT | CTF_WRTTN); 428 tprintf_close(sc->sc_tpr); 429 DPRINTF(CDB_FILES, ("ctclose: flags %x\n", sc->sc_flags)); 430 431 return (0); /* XXX */ 432 } 433 434 void 435 ctcommand(dev_t dev, int cmd, int cnt) 436 { 437 struct ct_softc *sc; 438 struct buf *bp; 439 struct buf *nbp = 0; 440 441 sc = device_lookup_private(&ct_cd, CTUNIT(dev)); 442 bp = &sc->sc_bufstore; 443 444 DPRINTF(CDB_FOLLOW, ("ctcommand: called\n")); 445 446 if (cmd == MTBSF && sc->sc_eofp == EOFS - 1) { 447 cnt = sc->sc_eofs[EOFS - 1] - cnt; 448 ctcommand(dev, MTREW, 1); 449 ctcommand(dev, MTFSF, cnt); 450 cnt = 2; 451 cmd = MTBSR; 452 } 453 454 if (cmd == MTBSF && sc->sc_eofp - cnt < 0) { 455 cnt = 1; 456 cmd = MTREW; 457 } 458 459 sc->sc_flags |= CTF_CMD; 460 sc->sc_bp = bp; 461 sc->sc_cmd = cmd; 462 bp->b_dev = dev; 463 bp->b_objlock = &buffer_lock; 464 if (cmd == MTFSF) { 465 nbp = (struct buf *)geteblk(MAXBSIZE); 466 bp->b_data = nbp->b_data; 467 bp->b_bcount = MAXBSIZE; 468 } 469 470 while (cnt-- > 0) { 471 bp->b_flags = 0; 472 bp->b_cflags = BC_BUSY; 473 bp->b_oflags = 0; 474 if (cmd == MTBSF) { 475 sc->sc_blkno = sc->sc_eofs[sc->sc_eofp]; 476 sc->sc_eofp--; 477 DPRINTF(CDB_BSF, ("%s: backup eof pos %d blk %d\n", 478 device_xname(&sc->sc_dev), sc->sc_eofp, 479 sc->sc_eofs[sc->sc_eofp])); 480 } 481 ctstrategy(bp); 482 biowait(bp); 483 } 484 bp->b_flags = 0; 485 sc->sc_flags &= ~CTF_CMD; 486 if (nbp) 487 brelse(nbp, 0); 488 } 489 490 void 491 ctstrategy(struct buf *bp) 492 { 493 struct ct_softc *sc; 494 int s; 495 496 DPRINTF(CDB_FOLLOW, ("cdstrategy(%p): dev %x, bn %x, bcount %lx, %c\n", 497 bp, bp->b_dev, bp->b_blkno, bp->b_bcount, 498 (bp->b_flags & B_READ) ? 'R' : 'W')); 499 500 sc = device_lookup_private(&ct_cd, CTUNIT(bp->b_dev)); 501 502 s = splbio(); 503 BUFQ_PUT(sc->sc_tab, bp); 504 if (sc->sc_active == 0) { 505 sc->sc_active = 1; 506 ctustart(sc); 507 } 508 splx(s); 509 } 510 511 void 512 ctustart(sc) 513 struct ct_softc *sc; 514 { 515 struct buf *bp; 516 517 bp = BUFQ_PEEK(sc->sc_tab); 518 sc->sc_addr = bp->b_data; 519 sc->sc_resid = bp->b_bcount; 520 if (gpibrequest(sc->sc_ic, sc->sc_hdl)) 521 ctstart(sc); 522 } 523 524 void 525 ctstart(sc) 526 struct ct_softc *sc; 527 { 528 struct buf *bp; 529 struct ct_ulcmd ul; 530 struct ct_wfmcmd wfm; 531 int i, slave, punit; 532 533 slave = sc->sc_slave; 534 punit = sc->sc_punit; 535 536 bp = BUFQ_PEEK(sc->sc_tab); 537 if ((sc->sc_flags & CTF_CMD) && sc->sc_bp == bp) { 538 switch(sc->sc_cmd) { 539 case MTFSF: 540 bp->b_flags |= B_READ; 541 goto mustio; 542 543 case MTBSF: 544 goto gotaddr; 545 546 case MTOFFL: 547 sc->sc_blkno = 0; 548 ul.unit = CS80CMD_SUNIT(punit); 549 ul.cmd = CS80CMD_UNLOAD; 550 (void) cs80send(device_parent(&sc->sc_dev), slave, 551 punit, CS80CMD_SCMD, &ul, sizeof(ul)); 552 break; 553 554 case MTWEOF: 555 sc->sc_blkno++; 556 sc->sc_flags |= CTF_WRT; 557 wfm.unit = CS80CMD_SUNIT(sc->sc_punit); 558 wfm.cmd = CS80CMD_WFM; 559 (void) cs80send(device_parent(&sc->sc_dev), slave, 560 punit, CS80CMD_SCMD, &wfm, sizeof(wfm)); 561 ctaddeof(sc); 562 break; 563 564 case MTBSR: 565 sc->sc_blkno--; 566 goto gotaddr; 567 568 case MTFSR: 569 sc->sc_blkno++; 570 goto gotaddr; 571 572 case MTREW: 573 sc->sc_blkno = 0; 574 DPRINTF(CDB_BSF, ("%s: clearing eofs\n", 575 device_xname(&sc->sc_dev))); 576 for (i=0; i<EOFS; i++) 577 sc->sc_eofs[i] = 0; 578 sc->sc_eofp = 0; 579 580 gotaddr: 581 sc->sc_ioc.unit = CS80CMD_SUNIT(sc->sc_punit); 582 sc->sc_ioc.saddr = CS80CMD_SADDR; 583 sc->sc_ioc.addr0 = 0; 584 sc->sc_ioc.addr = htobe32(sc->sc_blkno); 585 sc->sc_ioc.nop2 = CS80CMD_NOP; 586 sc->sc_ioc.slen = CS80CMD_SLEN; 587 sc->sc_ioc.len = htobe32(0); 588 sc->sc_ioc.nop3 = CS80CMD_NOP; 589 sc->sc_ioc.cmd = CS80CMD_READ; 590 (void) cs80send(device_parent(&sc->sc_dev), slave, 591 punit, CS80CMD_SCMD, &sc->sc_ioc, 592 sizeof(sc->sc_ioc)); 593 break; 594 } 595 } else { 596 mustio: 597 if ((bp->b_flags & B_READ) && 598 sc->sc_flags & (CTF_BEOF|CTF_EOT)) { 599 DPRINTF(CDB_FILES, ("ctstart: before %x\n", 600 sc->sc_flags)); 601 if (sc->sc_flags & CTF_BEOF) { 602 sc->sc_flags &= ~CTF_BEOF; 603 sc->sc_flags |= CTF_AEOF; 604 DPRINTF(CDB_FILES, ("ctstart: after %x\n", 605 sc->sc_flags)); 606 } 607 bp->b_resid = bp->b_bcount; 608 ctdone(sc, bp); 609 return; 610 } 611 sc->sc_flags |= CTF_IO; 612 sc->sc_ioc.unit = CS80CMD_SUNIT(sc->sc_punit); 613 sc->sc_ioc.saddr = CS80CMD_SADDR; 614 sc->sc_ioc.addr0 = 0; 615 sc->sc_ioc.addr = htobe32(sc->sc_blkno); 616 sc->sc_ioc.nop2 = CS80CMD_NOP; 617 sc->sc_ioc.slen = CS80CMD_SLEN; 618 sc->sc_ioc.len = htobe32(sc->sc_resid); 619 sc->sc_ioc.nop3 = CS80CMD_NOP; 620 if (bp->b_flags & B_READ) 621 sc->sc_ioc.cmd = CS80CMD_READ; 622 else { 623 sc->sc_ioc.cmd = CS80CMD_WRITE; 624 sc->sc_flags |= (CTF_WRT | CTF_WRTTN); 625 } 626 (void) cs80send(device_parent(&sc->sc_dev), slave, punit, 627 CS80CMD_SCMD, &sc->sc_ioc, sizeof(sc->sc_ioc)); 628 } 629 gpibawait(sc->sc_ic); 630 } 631 632 /* 633 * Hideous grue to handle EOF/EOT (mostly for reads) 634 */ 635 void 636 cteof(sc, bp) 637 struct ct_softc *sc; 638 struct buf *bp; 639 { 640 long blks; 641 642 /* 643 * EOT on a write is an error. 644 */ 645 if ((bp->b_flags & B_READ) == 0) { 646 bp->b_resid = bp->b_bcount; 647 bp->b_error = ENOSPC; 648 sc->sc_flags |= CTF_EOT; 649 return; 650 } 651 /* 652 * Use returned block position to determine how many blocks 653 * we really read and update b_resid. 654 */ 655 blks = sc->sc_stat.c_blk - sc->sc_blkno - 1; 656 DPRINTF(CDB_FILES, ("cteof: bc %ld oblk %d nblk %d read %ld, resid %ld\n", 657 bp->b_bcount, sc->sc_blkno, sc->sc_stat.c_blk, 658 blks, bp->b_bcount - CTKTOB(blks))); 659 if (blks == -1) { /* 9145 on EOF does not change sc_stat.c_blk */ 660 blks = 0; 661 sc->sc_blkno++; 662 } 663 else { 664 sc->sc_blkno = sc->sc_stat.c_blk; 665 } 666 bp->b_resid = bp->b_bcount - CTKTOB(blks); 667 /* 668 * If we are at physical EOV or were after an EOF, 669 * we are now at logical EOT. 670 */ 671 if ((sc->sc_stat.c_aef & AEF_EOV) || 672 (sc->sc_flags & CTF_AEOF)) { 673 sc->sc_flags |= CTF_EOT; 674 sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF); 675 } 676 /* 677 * If we were before an EOF or we have just completed a FSF, 678 * we are now after EOF. 679 */ 680 else if ((sc->sc_flags & CTF_BEOF) || 681 ((sc->sc_flags & CTF_CMD) && sc->sc_cmd == MTFSF)) { 682 sc->sc_flags |= CTF_AEOF; 683 sc->sc_flags &= ~CTF_BEOF; 684 } 685 /* 686 * Otherwise if we read something we are now before EOF 687 * (and no longer after EOF). 688 */ 689 else if (blks) { 690 sc->sc_flags |= CTF_BEOF; 691 sc->sc_flags &= ~CTF_AEOF; 692 } 693 /* 694 * Finally, if we didn't read anything we just passed an EOF 695 */ 696 else 697 sc->sc_flags |= CTF_AEOF; 698 DPRINTF(CDB_FILES, ("cteof: leaving flags %x\n", sc->sc_flags)); 699 } 700 701 702 void 703 ctcallback(v, action) 704 void *v; 705 int action; 706 { 707 struct ct_softc *sc = v; 708 709 DPRINTF(CDB_FOLLOW, ("ctcallback: v=%p, action=%d\n", v, action)); 710 711 switch (action) { 712 case GPIBCBF_START: 713 ctstart(sc); 714 break; 715 case GPIBCBF_INTR: 716 ctintr(sc); 717 break; 718 #ifdef DEBUG 719 default: 720 DPRINTF(CDB_FAIL, ("ctcallback: unknown action %d\n", action)); 721 break; 722 #endif 723 } 724 } 725 726 void 727 ctintr(sc) 728 struct ct_softc *sc; 729 { 730 struct buf *bp; 731 u_int8_t stat; 732 int slave, punit; 733 int dir; 734 735 slave = sc->sc_slave; 736 punit = sc->sc_punit; 737 738 bp = BUFQ_PEEK(sc->sc_tab); 739 if (bp == NULL) { 740 aprint_error_dev(&sc->sc_dev, "bp == NULL\n"); 741 return; 742 } 743 if (sc->sc_flags & CTF_IO) { 744 sc->sc_flags &= ~CTF_IO; 745 dir = (bp->b_flags & B_READ ? GPIB_READ : GPIB_WRITE); 746 gpibxfer(sc->sc_ic, slave, CS80CMD_EXEC, sc->sc_addr, 747 sc->sc_resid, dir, dir == GPIB_READ); 748 return; 749 } 750 if ((sc->sc_flags & CTF_STATWAIT) == 0) { 751 if (gpibpptest(sc->sc_ic, slave) == 0) { 752 sc->sc_flags |= CTF_STATWAIT; 753 gpibawait(sc->sc_ic); 754 return; 755 } 756 } else 757 sc->sc_flags &= ~CTF_STATWAIT; 758 (void) gpibrecv(sc->sc_ic, slave, CS80CMD_QSTAT, &stat, 1); 759 DPRINTF(CDB_FILES, ("ctintr: before flags %x\n", sc->sc_flags)); 760 if (stat) { 761 sc->sc_rsc.unit = CS80CMD_SUNIT(punit); 762 sc->sc_rsc.cmd = CS80CMD_STATUS; 763 (void) gpibsend(sc->sc_ic, slave, CS80CMD_SCMD, &sc->sc_rsc, 764 sizeof(sc->sc_rsc)); 765 (void) gpibrecv(sc->sc_ic, slave, CS80CMD_EXEC, &sc->sc_stat, 766 sizeof(sc->sc_stat)); 767 (void) gpibrecv(sc->sc_ic, slave, CS80CMD_QSTAT, &stat, 1); 768 DPRINTF(CDB_FILES, ("ctintr: return stat 0x%x, A%x F%x blk %d\n", 769 stat, sc->sc_stat.c_aef, 770 sc->sc_stat.c_fef, sc->sc_stat.c_blk)); 771 if (stat == 0) { 772 if (sc->sc_stat.c_aef & (AEF_EOF | AEF_EOV)) { 773 cteof(sc, bp); 774 ctaddeof(sc); 775 goto done; 776 } 777 if (sc->sc_stat.c_fef & FEF_PF) { 778 cs80reset(sc, slave, punit); 779 ctstart(sc); 780 return; 781 } 782 if (sc->sc_stat.c_fef & FEF_REXMT) { 783 ctstart(sc); 784 return; 785 } 786 if (sc->sc_stat.c_aef & 0x5800) { 787 if (sc->sc_stat.c_aef & 0x4000) 788 tprintf(sc->sc_tpr, 789 "%s: uninitialized media\n", 790 device_xname(&sc->sc_dev)); 791 if (sc->sc_stat.c_aef & 0x1000) 792 tprintf(sc->sc_tpr, 793 "%s: not ready\n", 794 device_xname(&sc->sc_dev)); 795 if (sc->sc_stat.c_aef & 0x0800) 796 tprintf(sc->sc_tpr, 797 "%s: write protect\n", 798 device_xname(&sc->sc_dev)); 799 } else { 800 printf("%s err: v%d u%d ru%d bn%d, ", 801 device_xname(&sc->sc_dev), 802 (sc->sc_stat.c_vu>>4)&0xF, 803 sc->sc_stat.c_vu&0xF, 804 sc->sc_stat.c_pend, 805 sc->sc_stat.c_blk); 806 printf("R0x%x F0x%x A0x%x I0x%x\n", 807 sc->sc_stat.c_ref, 808 sc->sc_stat.c_fef, 809 sc->sc_stat.c_aef, 810 sc->sc_stat.c_ief); 811 } 812 } else 813 aprint_error_dev(&sc->sc_dev, "request status failed\n"); 814 bp->b_error = EIO; 815 goto done; 816 } else 817 bp->b_resid = 0; 818 if (sc->sc_flags & CTF_CMD) { 819 switch (sc->sc_cmd) { 820 case MTFSF: 821 sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF); 822 sc->sc_blkno += CTBTOK(sc->sc_resid); 823 ctstart(sc); 824 return; 825 case MTBSF: 826 sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF|CTF_EOT); 827 break; 828 case MTBSR: 829 sc->sc_flags &= ~CTF_BEOF; 830 if (sc->sc_flags & CTF_EOT) { 831 sc->sc_flags |= CTF_AEOF; 832 sc->sc_flags &= ~CTF_EOT; 833 } else if (sc->sc_flags & CTF_AEOF) { 834 sc->sc_flags |= CTF_BEOF; 835 sc->sc_flags &= ~CTF_AEOF; 836 } 837 break; 838 case MTWEOF: 839 sc->sc_flags &= ~CTF_BEOF; 840 if (sc->sc_flags & (CTF_AEOF|CTF_EOT)) { 841 sc->sc_flags |= CTF_EOT; 842 sc->sc_flags &= ~CTF_AEOF; 843 } else 844 sc->sc_flags |= CTF_AEOF; 845 break; 846 case MTREW: 847 case MTOFFL: 848 sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF|CTF_EOT); 849 break; 850 } 851 } else { 852 sc->sc_flags &= ~CTF_AEOF; 853 sc->sc_blkno += CTBTOK(sc->sc_resid); 854 } 855 done: 856 DPRINTF(CDB_FILES, ("ctintr: after flags %x\n", sc->sc_flags)); 857 ctdone(sc, bp); 858 } 859 860 void 861 ctdone(sc, bp) 862 struct ct_softc *sc; 863 struct buf *bp; 864 { 865 866 (void)BUFQ_GET(sc->sc_tab); 867 biodone(bp); 868 gpibrelease(sc->sc_ic, sc->sc_hdl); 869 if (BUFQ_PEEK(sc->sc_tab) == NULL) { 870 sc->sc_active = 0; 871 return; 872 } 873 ctustart(sc); 874 } 875 876 int 877 ctread(dev, uio, flags) 878 dev_t dev; 879 struct uio *uio; 880 int flags; 881 { 882 return (physio(ctstrategy, NULL, dev, B_READ, minphys, uio)); 883 } 884 885 int 886 ctwrite(dev, uio, flags) 887 dev_t dev; 888 struct uio *uio; 889 int flags; 890 { 891 /* XXX: check for hardware write-protect? */ 892 return (physio(ctstrategy, NULL, dev, B_WRITE, minphys, uio)); 893 } 894 895 /*ARGSUSED*/ 896 int 897 ctioctl(dev, cmd, data, flag, l) 898 dev_t dev; 899 u_long cmd; 900 int flag; 901 void *data; 902 struct lwp *l; 903 { 904 struct mtop *op; 905 int cnt; 906 907 switch (cmd) { 908 909 case MTIOCTOP: 910 op = (struct mtop *)data; 911 switch(op->mt_op) { 912 913 case MTWEOF: 914 case MTFSF: 915 case MTBSR: 916 case MTBSF: 917 case MTFSR: 918 cnt = op->mt_count; 919 break; 920 921 case MTREW: 922 case MTOFFL: 923 cnt = 1; 924 break; 925 926 default: 927 return (EINVAL); 928 } 929 ctcommand(dev, op->mt_op, cnt); 930 break; 931 932 case MTIOCGET: 933 break; 934 935 default: 936 return (EINVAL); 937 } 938 return (0); 939 } 940 941 void 942 ctaddeof(sc) 943 struct ct_softc *sc; 944 { 945 946 if (sc->sc_eofp == EOFS - 1) 947 sc->sc_eofs[EOFS - 1]++; 948 else { 949 sc->sc_eofp++; 950 if (sc->sc_eofp == EOFS - 1) 951 sc->sc_eofs[EOFS - 1] = EOFS; 952 else 953 /* save blkno */ 954 sc->sc_eofs[sc->sc_eofp] = sc->sc_blkno - 1; 955 } 956 DPRINTF(CDB_BSF, ("%s: add eof pos %d blk %d\n", 957 device_xname(&sc->sc_dev), sc->sc_eofp, 958 sc->sc_eofs[sc->sc_eofp])); 959 } 960