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