mscp_tape.c revision 1.35 1 1.35 dsl /* $NetBSD: mscp_tape.c,v 1.35 2009/03/14 15:36:19 dsl 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.35 dsl __KERNEL_RCSID(0, "$NetBSD: mscp_tape.c,v 1.35 2009/03/14 15:36:19 dsl 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.1 ragge struct device 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.23 perry int mtmatch(struct device *, struct cfdata *, void *);
85 1.23 perry void mtattach(struct device *, struct device *, void *);
86 1.23 perry void mtdgram(struct device *, struct mscp *, struct mscp_softc *);
87 1.23 perry void mtiodone(struct device *, struct buf *);
88 1.23 perry int mtonline(struct device *, struct mscp *);
89 1.23 perry int mtgotstatus(struct device *, struct mscp *);
90 1.23 perry int mtioerror(struct device *, 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.23 perry void mtcmddone(struct device *, 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.1 ragge mtgotstatus,
101 1.1 ragge 0,
102 1.1 ragge mtioerror,
103 1.1 ragge 0,
104 1.1 ragge mtfillin,
105 1.1 ragge mtcmddone,
106 1.1 ragge };
107 1.1 ragge
108 1.1 ragge /* This is not good, should allow more than 4 tapes/device type */
109 1.9 ragge #define mtunit(dev) (minor(dev) & T_UNIT)
110 1.9 ragge #define mtnorewind(dev) (dev & T_NOREWIND)
111 1.9 ragge #define mthdensity(dev) (dev & T_1600BPI)
112 1.1 ragge
113 1.19 thorpej CFATTACH_DECL(mt, sizeof(struct mt_softc),
114 1.20 thorpej mtmatch, mtattach, NULL, NULL);
115 1.7 thorpej
116 1.7 thorpej extern struct cfdriver mt_cd;
117 1.1 ragge
118 1.17 gehenna dev_type_open(mtopen);
119 1.17 gehenna dev_type_close(mtclose);
120 1.17 gehenna dev_type_read(mtread);
121 1.17 gehenna dev_type_write(mtwrite);
122 1.17 gehenna dev_type_ioctl(mtioctl);
123 1.17 gehenna dev_type_strategy(mtstrategy);
124 1.17 gehenna dev_type_dump(mtdump);
125 1.17 gehenna
126 1.17 gehenna const struct bdevsw mt_bdevsw = {
127 1.17 gehenna mtopen, mtclose, mtstrategy, mtioctl, mtdump, nosize, D_TAPE
128 1.17 gehenna };
129 1.17 gehenna
130 1.17 gehenna const struct cdevsw mt_cdevsw = {
131 1.17 gehenna mtopen, mtclose, mtread, mtwrite, mtioctl,
132 1.21 jdolecek nostop, notty, nopoll, nommap, nokqfilter, D_TAPE
133 1.17 gehenna };
134 1.17 gehenna
135 1.1 ragge /*
136 1.1 ragge * More driver definitions, for generic MSCP code.
137 1.1 ragge */
138 1.1 ragge
139 1.1 ragge int
140 1.35 dsl mtmatch(struct device *parent, struct cfdata *cf, void *aux)
141 1.1 ragge {
142 1.1 ragge struct drive_attach_args *da = aux;
143 1.1 ragge struct mscp *mp = da->da_mp;
144 1.1 ragge
145 1.1 ragge if ((da->da_typ & MSCPBUS_TAPE) == 0)
146 1.1 ragge return 0;
147 1.6 jtk if (cf->cf_loc[MSCPBUSCF_DRIVE] != MSCPBUSCF_DRIVE_DEFAULT &&
148 1.6 jtk cf->cf_loc[MSCPBUSCF_DRIVE] != mp->mscp_unit)
149 1.1 ragge return 0;
150 1.1 ragge return 1;
151 1.1 ragge }
152 1.1 ragge
153 1.1 ragge /*
154 1.1 ragge * The attach routine only checks and prints drive type.
155 1.1 ragge */
156 1.1 ragge void
157 1.1 ragge mtattach(parent, self, aux)
158 1.1 ragge struct device *parent, *self;
159 1.24 perry void *aux;
160 1.1 ragge {
161 1.29 thorpej struct mt_softc *mt = device_private(self);
162 1.1 ragge struct drive_attach_args *da = aux;
163 1.1 ragge struct mscp *mp = da->da_mp;
164 1.1 ragge struct mscp_softc *mi = (void *)parent;
165 1.1 ragge
166 1.1 ragge mt->mt_hwunit = mp->mscp_unit;
167 1.1 ragge mi->mi_dp[mp->mscp_unit] = self;
168 1.1 ragge
169 1.4 ragge disk_printtype(mp->mscp_unit, mp->mscp_guse.guse_mediaid);
170 1.1 ragge }
171 1.1 ragge
172 1.24 perry /*
173 1.1 ragge * (Try to) put the drive online. This is done the first time the
174 1.1 ragge * drive is opened, or if it has fallen offline.
175 1.1 ragge */
176 1.1 ragge int
177 1.35 dsl mt_putonline(struct mt_softc *mt)
178 1.1 ragge {
179 1.1 ragge struct mscp *mp;
180 1.28 thorpej struct mscp_softc *mi =
181 1.28 thorpej (struct mscp_softc *)device_parent(&mt->mt_dev);
182 1.1 ragge volatile int i;
183 1.1 ragge
184 1.27 matt ((volatile struct mt_softc *) mt)->mt_state = MT_OFFLINE;
185 1.1 ragge mp = mscp_getcp(mi, MSCP_WAIT);
186 1.1 ragge mp->mscp_opcode = M_OP_ONLINE;
187 1.1 ragge mp->mscp_unit = mt->mt_hwunit;
188 1.1 ragge mp->mscp_cmdref = (long)&mt->mt_state;
189 1.1 ragge *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
190 1.1 ragge
191 1.1 ragge /* Poll away */
192 1.14 ragge i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
193 1.1 ragge if (tsleep(&mt->mt_state, PRIBIO, "mtonline", 240 * hz))
194 1.1 ragge return MSCP_FAILED;
195 1.1 ragge
196 1.11 ragge if ((volatile int)mt->mt_state != MT_ONLINE)
197 1.1 ragge return MSCP_FAILED;
198 1.1 ragge
199 1.1 ragge return MSCP_DONE;
200 1.1 ragge }
201 1.1 ragge /*
202 1.1 ragge * Open a drive.
203 1.1 ragge */
204 1.1 ragge /*ARGSUSED*/
205 1.1 ragge int
206 1.26 christos mtopen(dev, flag, fmt, l)
207 1.1 ragge dev_t dev;
208 1.1 ragge int flag, fmt;
209 1.26 christos struct lwp *l;
210 1.1 ragge {
211 1.15 augustss struct mt_softc *mt;
212 1.1 ragge int unit;
213 1.1 ragge
214 1.1 ragge /*
215 1.1 ragge * Make sure this is a reasonable open request.
216 1.1 ragge */
217 1.1 ragge unit = mtunit(dev);
218 1.34 drochner mt = device_lookup_private(&mt_cd, unit);
219 1.34 drochner if (!mt)
220 1.1 ragge return ENXIO;
221 1.1 ragge
222 1.1 ragge if (mt->mt_inuse)
223 1.1 ragge return EBUSY;
224 1.1 ragge mt->mt_inuse = 1;
225 1.1 ragge
226 1.12 ragge if (mt_putonline(mt) == MSCP_FAILED) {
227 1.12 ragge mt->mt_inuse = 0;
228 1.1 ragge return EIO;
229 1.12 ragge }
230 1.1 ragge
231 1.1 ragge return 0;
232 1.1 ragge }
233 1.1 ragge
234 1.1 ragge /* ARGSUSED */
235 1.1 ragge int
236 1.26 christos mtclose(dev, flags, fmt, l)
237 1.1 ragge dev_t dev;
238 1.1 ragge int flags, fmt;
239 1.26 christos struct lwp *l;
240 1.1 ragge {
241 1.1 ragge int unit = mtunit(dev);
242 1.34 drochner struct mt_softc *mt = device_lookup_private(&mt_cd, unit);
243 1.1 ragge
244 1.1 ragge /*
245 1.1 ragge * If we just have finished a writing, write EOT marks.
246 1.1 ragge */
247 1.1 ragge if ((flags & FWRITE) && mt->mt_waswrite) {
248 1.5 ragge mtcmd(mt, MTWEOF, 0, 0);
249 1.5 ragge mtcmd(mt, MTWEOF, 0, 0);
250 1.5 ragge mtcmd(mt, MTBSR, 1, 0);
251 1.1 ragge }
252 1.1 ragge if (mtnorewind(dev) == 0)
253 1.5 ragge mtcmd(mt, MTREW, 0, 1);
254 1.1 ragge if (mt->mt_serex)
255 1.5 ragge mtcmd(mt, -1, 0, 0);
256 1.1 ragge
257 1.1 ragge mt->mt_inuse = 0; /* Release the tape */
258 1.1 ragge return 0;
259 1.1 ragge }
260 1.1 ragge
261 1.1 ragge void
262 1.35 dsl mtstrategy(struct buf *bp)
263 1.1 ragge {
264 1.15 augustss int unit;
265 1.15 augustss struct mt_softc *mt;
266 1.1 ragge
267 1.1 ragge /*
268 1.1 ragge * Make sure this is a reasonable drive to use.
269 1.1 ragge */
270 1.1 ragge unit = mtunit(bp->b_dev);
271 1.34 drochner if ((mt = device_lookup_private(&mt_cd, unit)) == NULL) {
272 1.1 ragge bp->b_error = ENXIO;
273 1.31 ad biodone(bp);
274 1.31 ad return;
275 1.1 ragge }
276 1.1 ragge
277 1.5 ragge mt->mt_waswrite = bp->b_flags & B_READ ? 0 : 1;
278 1.28 thorpej mscp_strategy(bp, device_parent(&mt->mt_dev));
279 1.1 ragge return;
280 1.1 ragge }
281 1.1 ragge
282 1.1 ragge int
283 1.35 dsl mtread(dev_t dev, struct uio *uio, int flag)
284 1.1 ragge {
285 1.1 ragge
286 1.9 ragge return (physio(mtstrategy, NULL, dev, B_READ, minphys, uio));
287 1.1 ragge }
288 1.1 ragge
289 1.1 ragge int
290 1.35 dsl mtwrite(dev_t dev, struct uio *uio, int flag)
291 1.1 ragge {
292 1.1 ragge
293 1.9 ragge return (physio(mtstrategy, NULL, dev, B_WRITE, minphys, uio));
294 1.1 ragge }
295 1.1 ragge
296 1.1 ragge void
297 1.35 dsl mtiodone(struct device *usc, struct buf *bp)
298 1.1 ragge {
299 1.1 ragge
300 1.1 ragge biodone(bp);
301 1.1 ragge }
302 1.1 ragge
303 1.1 ragge /*
304 1.1 ragge * Fill in drive addresses in a mscp packet waiting for transfer.
305 1.1 ragge */
306 1.1 ragge void
307 1.35 dsl mtfillin(struct buf *bp, struct mscp *mp)
308 1.1 ragge {
309 1.1 ragge int unit = mtunit(bp->b_dev);
310 1.34 drochner struct mt_softc *mt = device_lookup_private(&mt_cd, unit);
311 1.1 ragge
312 1.1 ragge mp->mscp_unit = mt->mt_hwunit;
313 1.1 ragge if (mt->mt_serex == 2) {
314 1.1 ragge mp->mscp_modifier = M_MD_CLSEX;
315 1.1 ragge mt->mt_serex = 0;
316 1.1 ragge } else
317 1.1 ragge mp->mscp_modifier = 0;
318 1.1 ragge
319 1.1 ragge mp->mscp_seq.seq_bytecount = bp->b_bcount;
320 1.1 ragge }
321 1.1 ragge
322 1.1 ragge /*
323 1.1 ragge * Handle an error datagram.
324 1.1 ragge */
325 1.1 ragge void
326 1.35 dsl mtdgram(struct device *usc, struct mscp *mp, struct mscp_softc *mi)
327 1.1 ragge {
328 1.33 cegger if (mscp_decodeerror(usc == NULL?"unconf mt" : device_xname(usc), mp, mi))
329 1.1 ragge return;
330 1.1 ragge }
331 1.1 ragge
332 1.1 ragge /*
333 1.1 ragge * A drive came on line, make sure it really _is_ on line before
334 1.1 ragge * trying to use it.
335 1.1 ragge */
336 1.1 ragge int
337 1.35 dsl mtonline(struct device *usc, struct mscp *mp)
338 1.1 ragge {
339 1.15 augustss struct mt_softc *mt = (void *)usc;
340 1.1 ragge
341 1.30 christos wakeup((void *)&mt->mt_state);
342 1.24 perry if ((mp->mscp_status & M_ST_MASK) == M_ST_SUCCESS)
343 1.1 ragge mt->mt_state = MT_ONLINE;
344 1.1 ragge
345 1.1 ragge return (MSCP_DONE);
346 1.1 ragge }
347 1.1 ragge
348 1.1 ragge /*
349 1.1 ragge * We got some (configured) unit's status. Return DONE.
350 1.1 ragge */
351 1.1 ragge int
352 1.35 dsl mtgotstatus(struct device *usc, struct mscp *mp)
353 1.1 ragge {
354 1.1 ragge return (MSCP_DONE);
355 1.1 ragge }
356 1.1 ragge
357 1.25 ragge static const char *mt_ioerrs[] = {
358 1.1 ragge "invalid command", /* 1 M_ST_INVALCMD */
359 1.1 ragge "command aborted", /* 2 M_ST_ABORTED */
360 1.1 ragge "unit offline", /* 3 M_ST_OFFLINE */
361 1.1 ragge "unknown", /* 4 M_ST_AVAILABLE */
362 1.1 ragge "unknown", /* 5 M_ST_MFMTERR */
363 1.9 ragge "unit write protected", /* 6 M_ST_WRPROT */
364 1.1 ragge "compare error", /* 7 M_ST_COMPERR */
365 1.9 ragge "data error", /* 8 M_ST_DATAERR */
366 1.9 ragge "host buffer access error", /* 9 M_ST_HOSTBUFERR */
367 1.1 ragge "controller error", /* 10 M_ST_CTLRERR */
368 1.9 ragge "drive error", /* 11 M_ST_DRIVEERR */
369 1.1 ragge "formatter error", /* 12 M_ST_FORMATTERR */
370 1.1 ragge "BOT encountered", /* 13 M_ST_BOT */
371 1.1 ragge "tape mark encountered",/* 14 M_ST_TAPEMARK */
372 1.1 ragge "unknown", /* 15 */
373 1.1 ragge "record data truncated",/* 16 M_ST_RDTRUNC */
374 1.1 ragge };
375 1.1 ragge
376 1.1 ragge /*
377 1.1 ragge * An I/O error, may be because of a tapemark encountered.
378 1.1 ragge * Check that before failing.
379 1.1 ragge */
380 1.1 ragge /*ARGSUSED*/
381 1.1 ragge int
382 1.35 dsl mtioerror(struct device *usc, struct mscp *mp, struct buf *bp)
383 1.1 ragge {
384 1.1 ragge struct mt_softc *mt = (void *)usc;
385 1.1 ragge int st = mp->mscp_status & M_ST_MASK;
386 1.1 ragge
387 1.1 ragge if (mp->mscp_flags & M_EF_SEREX)
388 1.1 ragge mt->mt_serex = 1;
389 1.1 ragge if (st == M_ST_TAPEMARK)
390 1.1 ragge mt->mt_serex = 2;
391 1.1 ragge else {
392 1.1 ragge if (st && st < 17)
393 1.33 cegger printf("%s: error %d (%s)\n", device_xname(&mt->mt_dev), st,
394 1.1 ragge mt_ioerrs[st-1]);
395 1.1 ragge else
396 1.33 cegger printf("%s: error %d\n", device_xname(&mt->mt_dev), st);
397 1.11 ragge bp->b_error = EROFS;
398 1.1 ragge }
399 1.1 ragge
400 1.1 ragge return (MSCP_DONE);
401 1.1 ragge }
402 1.1 ragge
403 1.1 ragge /*
404 1.1 ragge * I/O controls.
405 1.1 ragge */
406 1.1 ragge int
407 1.35 dsl mtioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
408 1.1 ragge {
409 1.15 augustss int unit = mtunit(dev);
410 1.34 drochner struct mt_softc *mt = device_lookup_private(&mt_cd, unit);
411 1.27 matt struct mtop *mtop;
412 1.27 matt int error = 0;
413 1.1 ragge
414 1.1 ragge switch (cmd) {
415 1.1 ragge
416 1.1 ragge case MTIOCTOP:
417 1.1 ragge mtop = (void *)data;
418 1.5 ragge if (mtop->mt_op == MTWEOF) {
419 1.5 ragge while (mtop->mt_count-- > 0)
420 1.5 ragge if ((error = mtcmd(mt, mtop->mt_op, 0, 0)))
421 1.5 ragge break;
422 1.5 ragge } else
423 1.5 ragge error = mtcmd(mt, mtop->mt_op, mtop->mt_count, 0);
424 1.1 ragge
425 1.1 ragge case MTIOCGET:
426 1.27 matt ((struct mtget *)data)->mt_type = MT_ISTMSCP;
427 1.1 ragge /* XXX we need to fill in more fields here */
428 1.1 ragge break;
429 1.1 ragge
430 1.1 ragge default:
431 1.1 ragge error = ENXIO;
432 1.1 ragge break;
433 1.1 ragge }
434 1.1 ragge return (error);
435 1.1 ragge }
436 1.1 ragge
437 1.1 ragge /*
438 1.1 ragge * No crash dump support...
439 1.1 ragge */
440 1.1 ragge int
441 1.35 dsl mtdump(dev_t dev, daddr_t blkno, void *va, size_t size)
442 1.1 ragge {
443 1.1 ragge return -1;
444 1.1 ragge }
445 1.1 ragge
446 1.1 ragge /*
447 1.1 ragge * Send a command to the tape drive. Wait until the command is
448 1.1 ragge * finished before returning.
449 1.5 ragge * This routine must only be called when there are no data transfer
450 1.5 ragge * active on this device. Can we be sure of this? Or does the ctlr
451 1.5 ragge * queue up all command packets and take them in sequential order?
452 1.5 ragge * It sure would be nice if my manual stated this... /ragge
453 1.1 ragge */
454 1.5 ragge int
455 1.5 ragge mtcmd(mt, cmd, count, complete)
456 1.1 ragge struct mt_softc *mt;
457 1.5 ragge int cmd, count, complete;
458 1.1 ragge {
459 1.1 ragge struct mscp *mp;
460 1.28 thorpej struct mscp_softc *mi = (void *)device_parent(&mt->mt_dev);
461 1.1 ragge volatile int i;
462 1.1 ragge
463 1.1 ragge mp = mscp_getcp(mi, MSCP_WAIT);
464 1.1 ragge
465 1.5 ragge mt->mt_ioctlerr = 0;
466 1.1 ragge mp->mscp_unit = mt->mt_hwunit;
467 1.1 ragge mp->mscp_cmdref = -1;
468 1.1 ragge *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
469 1.1 ragge
470 1.1 ragge switch (cmd) {
471 1.1 ragge case MTWEOF:
472 1.1 ragge mp->mscp_opcode = M_OP_WRITM;
473 1.1 ragge break;
474 1.1 ragge
475 1.1 ragge case MTBSF:
476 1.1 ragge mp->mscp_modifier = M_MD_REVERSE;
477 1.1 ragge case MTFSF:
478 1.1 ragge mp->mscp_opcode = M_OP_POS;
479 1.5 ragge mp->mscp_seq.seq_buffer = count;
480 1.1 ragge break;
481 1.1 ragge
482 1.1 ragge case MTBSR:
483 1.1 ragge mp->mscp_modifier = M_MD_REVERSE;
484 1.1 ragge case MTFSR:
485 1.1 ragge mp->mscp_opcode = M_OP_POS;
486 1.1 ragge mp->mscp_modifier |= M_MD_OBJCOUNT;
487 1.5 ragge mp->mscp_seq.seq_bytecount = count;
488 1.1 ragge break;
489 1.1 ragge
490 1.1 ragge case MTREW:
491 1.1 ragge mp->mscp_opcode = M_OP_POS;
492 1.1 ragge mp->mscp_modifier = M_MD_REWIND | M_MD_CLSEX;
493 1.5 ragge if (complete)
494 1.5 ragge mp->mscp_modifier |= M_MD_IMMEDIATE;
495 1.1 ragge mt->mt_serex = 0;
496 1.1 ragge break;
497 1.1 ragge
498 1.5 ragge case MTOFFL:
499 1.5 ragge mp->mscp_opcode = M_OP_AVAILABLE;
500 1.5 ragge mp->mscp_modifier = M_MD_UNLOAD | M_MD_CLSEX;
501 1.5 ragge mt->mt_serex = 0;
502 1.5 ragge break;
503 1.5 ragge
504 1.5 ragge case MTNOP:
505 1.5 ragge mp->mscp_opcode = M_OP_GETUNITST;
506 1.5 ragge break;
507 1.5 ragge
508 1.1 ragge case -1: /* Clear serious exception only */
509 1.1 ragge mp->mscp_opcode = M_OP_POS;
510 1.1 ragge mp->mscp_modifier = M_MD_CLSEX;
511 1.1 ragge mt->mt_serex = 0;
512 1.1 ragge break;
513 1.1 ragge
514 1.1 ragge default:
515 1.3 christos printf("Bad ioctl %x\n", cmd);
516 1.1 ragge mp->mscp_opcode = M_OP_POS;
517 1.1 ragge break;
518 1.1 ragge }
519 1.1 ragge
520 1.14 ragge i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
521 1.1 ragge tsleep(&mt->mt_inuse, PRIBIO, "mtioctl", 0);
522 1.5 ragge return mt->mt_ioctlerr;
523 1.1 ragge }
524 1.1 ragge
525 1.1 ragge /*
526 1.1 ragge * Called from bus routines whenever a non-data transfer is finished.
527 1.1 ragge */
528 1.1 ragge void
529 1.35 dsl mtcmddone(struct device *usc, struct mscp *mp)
530 1.1 ragge {
531 1.1 ragge struct mt_softc *mt = (void *)usc;
532 1.1 ragge
533 1.5 ragge if (mp->mscp_status) {
534 1.5 ragge mt->mt_ioctlerr = EIO;
535 1.33 cegger printf("%s: bad status %x\n", device_xname(&mt->mt_dev),
536 1.1 ragge mp->mscp_status);
537 1.5 ragge }
538 1.1 ragge wakeup(&mt->mt_inuse);
539 1.1 ragge }
540