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