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