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