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