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