1 1.44 mrg /* $NetBSD: mscp_tape.c,v 1.44 2024/01/11 06:19:49 mrg Exp $ */ 2 1.1 ragge /* 3 1.1 ragge * Copyright (c) 1996 Ludd, University of Lule}, Sweden. 4 1.1 ragge * All rights reserved. 5 1.1 ragge * 6 1.1 ragge * Redistribution and use in source and binary forms, with or without 7 1.1 ragge * modification, are permitted provided that the following conditions 8 1.1 ragge * are met: 9 1.1 ragge * 1. Redistributions of source code must retain the above copyright 10 1.1 ragge * notice, this list of conditions and the following disclaimer. 11 1.1 ragge * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 ragge * notice, this list of conditions and the following disclaimer in the 13 1.1 ragge * documentation and/or other materials provided with the distribution. 14 1.1 ragge * 3. All advertising materials mentioning features or use of this software 15 1.1 ragge * must display the following acknowledgement: 16 1.24 perry * This product includes software developed at Ludd, University of 17 1.9 ragge * Lule}, Sweden and its contributors. 18 1.1 ragge * 4. The name of the author may not be used to endorse or promote products 19 1.1 ragge * derived from this software without specific prior written permission 20 1.1 ragge * 21 1.1 ragge * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 1.1 ragge * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 1.1 ragge * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 1.1 ragge * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 1.1 ragge * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 1.1 ragge * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 1.1 ragge * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 1.1 ragge * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 1.1 ragge * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 1.1 ragge * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 1.1 ragge */ 32 1.1 ragge 33 1.1 ragge 34 1.1 ragge /* 35 1.1 ragge * MSCP tape device driver 36 1.1 ragge */ 37 1.1 ragge 38 1.1 ragge /* 39 1.1 ragge * TODO 40 1.1 ragge * Write status handling code. 41 1.1 ragge */ 42 1.16 lukem 43 1.16 lukem #include <sys/cdefs.h> 44 1.44 mrg __KERNEL_RCSID(0, "$NetBSD: mscp_tape.c,v 1.44 2024/01/11 06:19:49 mrg Exp $"); 45 1.1 ragge 46 1.1 ragge #include <sys/param.h> 47 1.1 ragge #include <sys/device.h> 48 1.1 ragge #include <sys/kernel.h> 49 1.1 ragge #include <sys/buf.h> 50 1.22 he #include <sys/bufq.h> 51 1.1 ragge #include <sys/ioccom.h> 52 1.1 ragge #include <sys/mtio.h> 53 1.1 ragge #include <sys/fcntl.h> 54 1.1 ragge #include <sys/malloc.h> 55 1.1 ragge #include <sys/systm.h> 56 1.1 ragge #include <sys/proc.h> 57 1.17 gehenna #include <sys/conf.h> 58 1.1 ragge 59 1.32 ad #include <sys/bus.h> 60 1.32 ad #include <sys/cpu.h> 61 1.10 ragge 62 1.14 ragge #include <dev/mscp/mscp.h> 63 1.14 ragge #include <dev/mscp/mscpreg.h> 64 1.14 ragge #include <dev/mscp/mscpvar.h> 65 1.1 ragge 66 1.6 jtk #include "locators.h" 67 1.6 jtk 68 1.1 ragge /* 69 1.1 ragge * Drive status, per drive 70 1.1 ragge */ 71 1.1 ragge struct mt_softc { 72 1.39 chs device_t mt_dev; /* Autoconf struct */ 73 1.1 ragge int mt_state; /* open/closed state */ 74 1.1 ragge int mt_hwunit; /* Hardware unit number */ 75 1.1 ragge int mt_inuse; /* Locks the tape drive for others */ 76 1.1 ragge int mt_waswrite; /* Last operation was a write op */ 77 1.1 ragge int mt_serex; /* Got serious exception */ 78 1.5 ragge int mt_ioctlerr; /* Error after last ioctl */ 79 1.1 ragge }; 80 1.1 ragge 81 1.9 ragge #define MT_OFFLINE 0 82 1.9 ragge #define MT_ONLINE 1 83 1.1 ragge 84 1.38 cegger int mtmatch(device_t, cfdata_t, void *); 85 1.38 cegger void mtattach(device_t, device_t, void *); 86 1.38 cegger void mtdgram(device_t, struct mscp *, struct mscp_softc *); 87 1.38 cegger void mtiodone(device_t, struct buf *); 88 1.38 cegger int mtonline(device_t, struct mscp *); 89 1.38 cegger int mtgotstatus(device_t, struct mscp *); 90 1.38 cegger int mtioerror(device_t, struct mscp *, struct buf *); 91 1.23 perry void mtfillin(struct buf *, struct mscp *); 92 1.23 perry int mtcmd(struct mt_softc *, int, int, int); 93 1.38 cegger void mtcmddone(device_t, struct mscp *); 94 1.23 perry int mt_putonline(struct mt_softc *); 95 1.1 ragge 96 1.1 ragge struct mscp_device mt_device = { 97 1.1 ragge mtdgram, 98 1.1 ragge mtiodone, 99 1.1 ragge mtonline, 100 1.44 mrg NULL, 101 1.1 ragge mtgotstatus, 102 1.1 ragge 0, 103 1.1 ragge mtioerror, 104 1.1 ragge 0, 105 1.1 ragge mtfillin, 106 1.1 ragge mtcmddone, 107 1.1 ragge }; 108 1.1 ragge 109 1.1 ragge /* This is not good, should allow more than 4 tapes/device type */ 110 1.9 ragge #define mtunit(dev) (minor(dev) & T_UNIT) 111 1.9 ragge #define mtnorewind(dev) (dev & T_NOREWIND) 112 1.9 ragge #define mthdensity(dev) (dev & T_1600BPI) 113 1.1 ragge 114 1.39 chs CFATTACH_DECL_NEW(mt, sizeof(struct mt_softc), 115 1.20 thorpej mtmatch, mtattach, NULL, NULL); 116 1.7 thorpej 117 1.7 thorpej extern struct cfdriver mt_cd; 118 1.1 ragge 119 1.17 gehenna dev_type_open(mtopen); 120 1.17 gehenna dev_type_close(mtclose); 121 1.17 gehenna dev_type_read(mtread); 122 1.17 gehenna dev_type_write(mtwrite); 123 1.17 gehenna dev_type_ioctl(mtioctl); 124 1.17 gehenna dev_type_strategy(mtstrategy); 125 1.17 gehenna dev_type_dump(mtdump); 126 1.17 gehenna 127 1.17 gehenna const struct bdevsw mt_bdevsw = { 128 1.41 dholland .d_open = mtopen, 129 1.41 dholland .d_close = mtclose, 130 1.41 dholland .d_strategy = mtstrategy, 131 1.41 dholland .d_ioctl = mtioctl, 132 1.41 dholland .d_dump = mtdump, 133 1.41 dholland .d_psize = nosize, 134 1.42 dholland .d_discard = nodiscard, 135 1.41 dholland .d_flag = D_TAPE 136 1.17 gehenna }; 137 1.17 gehenna 138 1.17 gehenna const struct cdevsw mt_cdevsw = { 139 1.41 dholland .d_open = mtopen, 140 1.41 dholland .d_close = mtclose, 141 1.41 dholland .d_read = mtread, 142 1.41 dholland .d_write = mtwrite, 143 1.41 dholland .d_ioctl = mtioctl, 144 1.41 dholland .d_stop = nostop, 145 1.41 dholland .d_tty = notty, 146 1.41 dholland .d_poll = nopoll, 147 1.41 dholland .d_mmap = nommap, 148 1.41 dholland .d_kqfilter = nokqfilter, 149 1.43 dholland .d_discard = nodiscard, 150 1.41 dholland .d_flag = D_TAPE 151 1.17 gehenna }; 152 1.17 gehenna 153 1.1 ragge /* 154 1.1 ragge * More driver definitions, for generic MSCP code. 155 1.1 ragge */ 156 1.1 ragge 157 1.1 ragge int 158 1.38 cegger mtmatch(device_t parent, cfdata_t cf, void *aux) 159 1.1 ragge { 160 1.1 ragge struct drive_attach_args *da = aux; 161 1.1 ragge struct mscp *mp = da->da_mp; 162 1.1 ragge 163 1.1 ragge if ((da->da_typ & MSCPBUS_TAPE) == 0) 164 1.1 ragge return 0; 165 1.6 jtk if (cf->cf_loc[MSCPBUSCF_DRIVE] != MSCPBUSCF_DRIVE_DEFAULT && 166 1.6 jtk cf->cf_loc[MSCPBUSCF_DRIVE] != mp->mscp_unit) 167 1.1 ragge return 0; 168 1.1 ragge return 1; 169 1.1 ragge } 170 1.1 ragge 171 1.1 ragge /* 172 1.1 ragge * The attach routine only checks and prints drive type. 173 1.1 ragge */ 174 1.1 ragge void 175 1.38 cegger mtattach(device_t parent, device_t self, void *aux) 176 1.1 ragge { 177 1.29 thorpej struct mt_softc *mt = device_private(self); 178 1.1 ragge struct drive_attach_args *da = aux; 179 1.1 ragge struct mscp *mp = da->da_mp; 180 1.39 chs struct mscp_softc *mi = device_private(parent); 181 1.1 ragge 182 1.39 chs mt->mt_dev = self; 183 1.1 ragge mt->mt_hwunit = mp->mscp_unit; 184 1.1 ragge mi->mi_dp[mp->mscp_unit] = self; 185 1.1 ragge 186 1.4 ragge disk_printtype(mp->mscp_unit, mp->mscp_guse.guse_mediaid); 187 1.1 ragge } 188 1.1 ragge 189 1.24 perry /* 190 1.1 ragge * (Try to) put the drive online. This is done the first time the 191 1.1 ragge * drive is opened, or if it has fallen offline. 192 1.1 ragge */ 193 1.1 ragge int 194 1.35 dsl mt_putonline(struct mt_softc *mt) 195 1.1 ragge { 196 1.1 ragge struct mscp *mp; 197 1.28 thorpej struct mscp_softc *mi = 198 1.39 chs device_private(device_parent(mt->mt_dev)); 199 1.1 ragge 200 1.27 matt ((volatile struct mt_softc *) mt)->mt_state = MT_OFFLINE; 201 1.1 ragge mp = mscp_getcp(mi, MSCP_WAIT); 202 1.1 ragge mp->mscp_opcode = M_OP_ONLINE; 203 1.1 ragge mp->mscp_unit = mt->mt_hwunit; 204 1.1 ragge mp->mscp_cmdref = (long)&mt->mt_state; 205 1.1 ragge *mp->mscp_addr |= MSCP_OWN | MSCP_INT; 206 1.1 ragge 207 1.1 ragge /* Poll away */ 208 1.40 martin bus_space_read_2(mi->mi_iot, mi->mi_iph, 0); 209 1.1 ragge if (tsleep(&mt->mt_state, PRIBIO, "mtonline", 240 * hz)) 210 1.1 ragge return MSCP_FAILED; 211 1.1 ragge 212 1.11 ragge if ((volatile int)mt->mt_state != MT_ONLINE) 213 1.1 ragge return MSCP_FAILED; 214 1.1 ragge 215 1.1 ragge return MSCP_DONE; 216 1.1 ragge } 217 1.1 ragge /* 218 1.1 ragge * Open a drive. 219 1.1 ragge */ 220 1.1 ragge /*ARGSUSED*/ 221 1.1 ragge int 222 1.36 dsl mtopen(dev_t dev, int flag, int fmt, struct lwp *l) 223 1.1 ragge { 224 1.15 augustss struct mt_softc *mt; 225 1.1 ragge int unit; 226 1.1 ragge 227 1.1 ragge /* 228 1.1 ragge * Make sure this is a reasonable open request. 229 1.1 ragge */ 230 1.1 ragge unit = mtunit(dev); 231 1.34 drochner mt = device_lookup_private(&mt_cd, unit); 232 1.34 drochner if (!mt) 233 1.1 ragge return ENXIO; 234 1.1 ragge 235 1.1 ragge if (mt->mt_inuse) 236 1.1 ragge return EBUSY; 237 1.1 ragge mt->mt_inuse = 1; 238 1.1 ragge 239 1.12 ragge if (mt_putonline(mt) == MSCP_FAILED) { 240 1.12 ragge mt->mt_inuse = 0; 241 1.1 ragge return EIO; 242 1.12 ragge } 243 1.1 ragge 244 1.1 ragge return 0; 245 1.1 ragge } 246 1.1 ragge 247 1.1 ragge /* ARGSUSED */ 248 1.1 ragge int 249 1.36 dsl mtclose(dev_t dev, int flags, int fmt, struct lwp *l) 250 1.1 ragge { 251 1.1 ragge int unit = mtunit(dev); 252 1.34 drochner struct mt_softc *mt = device_lookup_private(&mt_cd, unit); 253 1.1 ragge 254 1.1 ragge /* 255 1.1 ragge * If we just have finished a writing, write EOT marks. 256 1.1 ragge */ 257 1.1 ragge if ((flags & FWRITE) && mt->mt_waswrite) { 258 1.5 ragge mtcmd(mt, MTWEOF, 0, 0); 259 1.5 ragge mtcmd(mt, MTWEOF, 0, 0); 260 1.5 ragge mtcmd(mt, MTBSR, 1, 0); 261 1.1 ragge } 262 1.1 ragge if (mtnorewind(dev) == 0) 263 1.5 ragge mtcmd(mt, MTREW, 0, 1); 264 1.1 ragge if (mt->mt_serex) 265 1.5 ragge mtcmd(mt, -1, 0, 0); 266 1.1 ragge 267 1.1 ragge mt->mt_inuse = 0; /* Release the tape */ 268 1.1 ragge return 0; 269 1.1 ragge } 270 1.1 ragge 271 1.1 ragge void 272 1.35 dsl mtstrategy(struct buf *bp) 273 1.1 ragge { 274 1.15 augustss int unit; 275 1.15 augustss struct mt_softc *mt; 276 1.1 ragge 277 1.1 ragge /* 278 1.1 ragge * Make sure this is a reasonable drive to use. 279 1.1 ragge */ 280 1.1 ragge unit = mtunit(bp->b_dev); 281 1.34 drochner if ((mt = device_lookup_private(&mt_cd, unit)) == NULL) { 282 1.1 ragge bp->b_error = ENXIO; 283 1.31 ad biodone(bp); 284 1.31 ad return; 285 1.1 ragge } 286 1.1 ragge 287 1.5 ragge mt->mt_waswrite = bp->b_flags & B_READ ? 0 : 1; 288 1.39 chs mscp_strategy(bp, device_parent(mt->mt_dev)); 289 1.1 ragge return; 290 1.1 ragge } 291 1.1 ragge 292 1.1 ragge int 293 1.35 dsl mtread(dev_t dev, struct uio *uio, int flag) 294 1.1 ragge { 295 1.1 ragge 296 1.9 ragge return (physio(mtstrategy, NULL, dev, B_READ, minphys, uio)); 297 1.1 ragge } 298 1.1 ragge 299 1.1 ragge int 300 1.35 dsl mtwrite(dev_t dev, struct uio *uio, int flag) 301 1.1 ragge { 302 1.1 ragge 303 1.9 ragge return (physio(mtstrategy, NULL, dev, B_WRITE, minphys, uio)); 304 1.1 ragge } 305 1.1 ragge 306 1.1 ragge void 307 1.38 cegger mtiodone(device_t usc, struct buf *bp) 308 1.1 ragge { 309 1.1 ragge 310 1.1 ragge biodone(bp); 311 1.1 ragge } 312 1.1 ragge 313 1.1 ragge /* 314 1.1 ragge * Fill in drive addresses in a mscp packet waiting for transfer. 315 1.1 ragge */ 316 1.1 ragge void 317 1.35 dsl mtfillin(struct buf *bp, struct mscp *mp) 318 1.1 ragge { 319 1.1 ragge int unit = mtunit(bp->b_dev); 320 1.34 drochner struct mt_softc *mt = device_lookup_private(&mt_cd, unit); 321 1.1 ragge 322 1.1 ragge mp->mscp_unit = mt->mt_hwunit; 323 1.1 ragge if (mt->mt_serex == 2) { 324 1.1 ragge mp->mscp_modifier = M_MD_CLSEX; 325 1.1 ragge mt->mt_serex = 0; 326 1.1 ragge } else 327 1.1 ragge mp->mscp_modifier = 0; 328 1.1 ragge 329 1.1 ragge mp->mscp_seq.seq_bytecount = bp->b_bcount; 330 1.1 ragge } 331 1.1 ragge 332 1.1 ragge /* 333 1.1 ragge * Handle an error datagram. 334 1.1 ragge */ 335 1.1 ragge void 336 1.38 cegger mtdgram(device_t usc, struct mscp *mp, struct mscp_softc *mi) 337 1.1 ragge { 338 1.33 cegger if (mscp_decodeerror(usc == NULL?"unconf mt" : device_xname(usc), mp, mi)) 339 1.1 ragge return; 340 1.1 ragge } 341 1.1 ragge 342 1.1 ragge /* 343 1.1 ragge * A drive came on line, make sure it really _is_ on line before 344 1.1 ragge * trying to use it. 345 1.1 ragge */ 346 1.1 ragge int 347 1.38 cegger mtonline(device_t usc, struct mscp *mp) 348 1.1 ragge { 349 1.15 augustss struct mt_softc *mt = (void *)usc; 350 1.1 ragge 351 1.30 christos wakeup((void *)&mt->mt_state); 352 1.24 perry if ((mp->mscp_status & M_ST_MASK) == M_ST_SUCCESS) 353 1.1 ragge mt->mt_state = MT_ONLINE; 354 1.1 ragge 355 1.1 ragge return (MSCP_DONE); 356 1.1 ragge } 357 1.1 ragge 358 1.1 ragge /* 359 1.1 ragge * We got some (configured) unit's status. Return DONE. 360 1.1 ragge */ 361 1.1 ragge int 362 1.38 cegger mtgotstatus(device_t usc, struct mscp *mp) 363 1.1 ragge { 364 1.1 ragge return (MSCP_DONE); 365 1.1 ragge } 366 1.1 ragge 367 1.25 ragge static const char *mt_ioerrs[] = { 368 1.1 ragge "invalid command", /* 1 M_ST_INVALCMD */ 369 1.1 ragge "command aborted", /* 2 M_ST_ABORTED */ 370 1.1 ragge "unit offline", /* 3 M_ST_OFFLINE */ 371 1.1 ragge "unknown", /* 4 M_ST_AVAILABLE */ 372 1.1 ragge "unknown", /* 5 M_ST_MFMTERR */ 373 1.9 ragge "unit write protected", /* 6 M_ST_WRPROT */ 374 1.1 ragge "compare error", /* 7 M_ST_COMPERR */ 375 1.9 ragge "data error", /* 8 M_ST_DATAERR */ 376 1.9 ragge "host buffer access error", /* 9 M_ST_HOSTBUFERR */ 377 1.1 ragge "controller error", /* 10 M_ST_CTLRERR */ 378 1.9 ragge "drive error", /* 11 M_ST_DRIVEERR */ 379 1.1 ragge "formatter error", /* 12 M_ST_FORMATTERR */ 380 1.1 ragge "BOT encountered", /* 13 M_ST_BOT */ 381 1.1 ragge "tape mark encountered",/* 14 M_ST_TAPEMARK */ 382 1.1 ragge "unknown", /* 15 */ 383 1.1 ragge "record data truncated",/* 16 M_ST_RDTRUNC */ 384 1.1 ragge }; 385 1.1 ragge 386 1.1 ragge /* 387 1.1 ragge * An I/O error, may be because of a tapemark encountered. 388 1.1 ragge * Check that before failing. 389 1.1 ragge */ 390 1.1 ragge /*ARGSUSED*/ 391 1.1 ragge int 392 1.38 cegger mtioerror(device_t usc, struct mscp *mp, struct buf *bp) 393 1.1 ragge { 394 1.1 ragge struct mt_softc *mt = (void *)usc; 395 1.1 ragge int st = mp->mscp_status & M_ST_MASK; 396 1.1 ragge 397 1.1 ragge if (mp->mscp_flags & M_EF_SEREX) 398 1.1 ragge mt->mt_serex = 1; 399 1.1 ragge if (st == M_ST_TAPEMARK) 400 1.1 ragge mt->mt_serex = 2; 401 1.1 ragge else { 402 1.1 ragge if (st && st < 17) 403 1.39 chs printf("%s: error %d (%s)\n", device_xname(mt->mt_dev), st, 404 1.1 ragge mt_ioerrs[st-1]); 405 1.1 ragge else 406 1.39 chs printf("%s: error %d\n", device_xname(mt->mt_dev), st); 407 1.11 ragge bp->b_error = EROFS; 408 1.1 ragge } 409 1.1 ragge 410 1.1 ragge return (MSCP_DONE); 411 1.1 ragge } 412 1.1 ragge 413 1.1 ragge /* 414 1.1 ragge * I/O controls. 415 1.1 ragge */ 416 1.1 ragge int 417 1.35 dsl mtioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 418 1.1 ragge { 419 1.15 augustss int unit = mtunit(dev); 420 1.34 drochner struct mt_softc *mt = device_lookup_private(&mt_cd, unit); 421 1.27 matt struct mtop *mtop; 422 1.27 matt int error = 0; 423 1.1 ragge 424 1.1 ragge switch (cmd) { 425 1.1 ragge 426 1.1 ragge case MTIOCTOP: 427 1.1 ragge mtop = (void *)data; 428 1.5 ragge if (mtop->mt_op == MTWEOF) { 429 1.5 ragge while (mtop->mt_count-- > 0) 430 1.5 ragge if ((error = mtcmd(mt, mtop->mt_op, 0, 0))) 431 1.5 ragge break; 432 1.5 ragge } else 433 1.5 ragge error = mtcmd(mt, mtop->mt_op, mtop->mt_count, 0); 434 1.1 ragge 435 1.1 ragge case MTIOCGET: 436 1.27 matt ((struct mtget *)data)->mt_type = MT_ISTMSCP; 437 1.1 ragge /* XXX we need to fill in more fields here */ 438 1.1 ragge break; 439 1.1 ragge 440 1.1 ragge default: 441 1.1 ragge error = ENXIO; 442 1.1 ragge break; 443 1.1 ragge } 444 1.1 ragge return (error); 445 1.1 ragge } 446 1.1 ragge 447 1.1 ragge /* 448 1.1 ragge * No crash dump support... 449 1.1 ragge */ 450 1.1 ragge int 451 1.35 dsl mtdump(dev_t dev, daddr_t blkno, void *va, size_t size) 452 1.1 ragge { 453 1.1 ragge return -1; 454 1.1 ragge } 455 1.1 ragge 456 1.1 ragge /* 457 1.1 ragge * Send a command to the tape drive. Wait until the command is 458 1.1 ragge * finished before returning. 459 1.5 ragge * This routine must only be called when there are no data transfer 460 1.5 ragge * active on this device. Can we be sure of this? Or does the ctlr 461 1.5 ragge * queue up all command packets and take them in sequential order? 462 1.5 ragge * It sure would be nice if my manual stated this... /ragge 463 1.1 ragge */ 464 1.5 ragge int 465 1.36 dsl mtcmd(struct mt_softc *mt, int cmd, int count, int complete) 466 1.1 ragge { 467 1.1 ragge struct mscp *mp; 468 1.39 chs struct mscp_softc *mi = device_private(device_parent(mt->mt_dev)); 469 1.1 ragge 470 1.1 ragge mp = mscp_getcp(mi, MSCP_WAIT); 471 1.1 ragge 472 1.5 ragge mt->mt_ioctlerr = 0; 473 1.1 ragge mp->mscp_unit = mt->mt_hwunit; 474 1.1 ragge mp->mscp_cmdref = -1; 475 1.1 ragge *mp->mscp_addr |= MSCP_OWN | MSCP_INT; 476 1.1 ragge 477 1.1 ragge switch (cmd) { 478 1.1 ragge case MTWEOF: 479 1.1 ragge mp->mscp_opcode = M_OP_WRITM; 480 1.1 ragge break; 481 1.1 ragge 482 1.1 ragge case MTBSF: 483 1.1 ragge mp->mscp_modifier = M_MD_REVERSE; 484 1.1 ragge case MTFSF: 485 1.1 ragge mp->mscp_opcode = M_OP_POS; 486 1.5 ragge mp->mscp_seq.seq_buffer = count; 487 1.1 ragge break; 488 1.1 ragge 489 1.1 ragge case MTBSR: 490 1.1 ragge mp->mscp_modifier = M_MD_REVERSE; 491 1.1 ragge case MTFSR: 492 1.1 ragge mp->mscp_opcode = M_OP_POS; 493 1.1 ragge mp->mscp_modifier |= M_MD_OBJCOUNT; 494 1.5 ragge mp->mscp_seq.seq_bytecount = count; 495 1.1 ragge break; 496 1.1 ragge 497 1.1 ragge case MTREW: 498 1.1 ragge mp->mscp_opcode = M_OP_POS; 499 1.1 ragge mp->mscp_modifier = M_MD_REWIND | M_MD_CLSEX; 500 1.5 ragge if (complete) 501 1.5 ragge mp->mscp_modifier |= M_MD_IMMEDIATE; 502 1.1 ragge mt->mt_serex = 0; 503 1.1 ragge break; 504 1.1 ragge 505 1.5 ragge case MTOFFL: 506 1.5 ragge mp->mscp_opcode = M_OP_AVAILABLE; 507 1.5 ragge mp->mscp_modifier = M_MD_UNLOAD | M_MD_CLSEX; 508 1.5 ragge mt->mt_serex = 0; 509 1.5 ragge break; 510 1.5 ragge 511 1.5 ragge case MTNOP: 512 1.5 ragge mp->mscp_opcode = M_OP_GETUNITST; 513 1.5 ragge break; 514 1.5 ragge 515 1.1 ragge case -1: /* Clear serious exception only */ 516 1.1 ragge mp->mscp_opcode = M_OP_POS; 517 1.1 ragge mp->mscp_modifier = M_MD_CLSEX; 518 1.1 ragge mt->mt_serex = 0; 519 1.1 ragge break; 520 1.1 ragge 521 1.1 ragge default: 522 1.3 christos printf("Bad ioctl %x\n", cmd); 523 1.1 ragge mp->mscp_opcode = M_OP_POS; 524 1.1 ragge break; 525 1.1 ragge } 526 1.1 ragge 527 1.40 martin bus_space_read_2(mi->mi_iot, mi->mi_iph, 0); 528 1.1 ragge tsleep(&mt->mt_inuse, PRIBIO, "mtioctl", 0); 529 1.5 ragge return mt->mt_ioctlerr; 530 1.1 ragge } 531 1.1 ragge 532 1.1 ragge /* 533 1.1 ragge * Called from bus routines whenever a non-data transfer is finished. 534 1.1 ragge */ 535 1.1 ragge void 536 1.38 cegger mtcmddone(device_t usc, struct mscp *mp) 537 1.1 ragge { 538 1.1 ragge struct mt_softc *mt = (void *)usc; 539 1.1 ragge 540 1.5 ragge if (mp->mscp_status) { 541 1.5 ragge mt->mt_ioctlerr = EIO; 542 1.39 chs printf("%s: bad status %x\n", device_xname(mt->mt_dev), 543 1.1 ragge mp->mscp_status); 544 1.5 ragge } 545 1.1 ragge wakeup(&mt->mt_inuse); 546 1.1 ragge } 547