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