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