xref: /csrg-svn/sys/vax/vax/rx50.c (revision 35045)
1*35045Skarels /*
2*35045Skarels  * Copyright (c) 1988 Regents of the University of California.
3*35045Skarels  * All rights reserved.
4*35045Skarels  *
5*35045Skarels  * This code is derived from software contributed to Berkeley by
6*35045Skarels  * Chris Torek.
7*35045Skarels  *
8*35045Skarels  * Redistribution and use in source and binary forms are permitted
9*35045Skarels  * provided that the above copyright notice and this paragraph are
10*35045Skarels  * duplicated in all such forms and that any documentation,
11*35045Skarels  * advertising materials, and other materials related to such
12*35045Skarels  * distribution and use acknowledge that the software was developed
13*35045Skarels  * by the University of California, Berkeley.  The name of the
14*35045Skarels  * University may not be used to endorse or promote products derived
15*35045Skarels  * from this software without specific prior written permission.
16*35045Skarels  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17*35045Skarels  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18*35045Skarels  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19*35045Skarels  *
20*35045Skarels  *	@(#)rx50.c	7.1 (Berkeley) 07/09/88
21*35045Skarels  */
22*35045Skarels 
23*35045Skarels #if VAX8200
24*35045Skarels 
25*35045Skarels /*
26*35045Skarels  * Routines to handle the console RX50.
27*35045Skarels  */
28*35045Skarels 
29*35045Skarels #include "param.h"
30*35045Skarels #include "time.h"
31*35045Skarels #include "kernel.h"
32*35045Skarels #include "vmmac.h"
33*35045Skarels #include "buf.h"
34*35045Skarels #include "errno.h"
35*35045Skarels #include "uio.h"
36*35045Skarels 
37*35045Skarels #include "cpu.h"
38*35045Skarels #include "rx50reg.h"
39*35045Skarels 
40*35045Skarels struct	rx50device rx50device;
41*35045Skarels 
42*35045Skarels #define	rx50unit(dev)	minor(dev)
43*35045Skarels 
44*35045Skarels struct rx50state {
45*35045Skarels 	short	rs_flags;	/* see below */
46*35045Skarels 	short	rs_drive;	/* current drive number */
47*35045Skarels 	u_int	rs_blkno;	/* current block number */
48*35045Skarels } rx50state;
49*35045Skarels 
50*35045Skarels /* flags */
51*35045Skarels #define	RS_0OPEN	0x01	/* drive 0 open -- must be first */
52*35045Skarels #define	RS_1OPEN	0x02	/* drive 1 open -- must be second */
53*35045Skarels #define	RS_BUSY		0x04	/* operation in progress */
54*35045Skarels #define	RS_WANT		0x08	/* wakeup when done */
55*35045Skarels #define	RS_DONE		0x20	/* I/O operation done */
56*35045Skarels #define	RS_ERROR	0x40	/* error bit set at interrupt */
57*35045Skarels 
58*35045Skarels /*
59*35045Skarels  * Open a console RX50.
60*35045Skarels  */
61*35045Skarels /*ARGSUSED*/
62*35045Skarels rx50open(dev, flags)
63*35045Skarels 	dev_t dev;
64*35045Skarels 	int flags;
65*35045Skarels {
66*35045Skarels 	int unit;
67*35045Skarels 
68*35045Skarels 	/* only on 8200 (yet) */
69*35045Skarels 	if (cpu != VAX_8200 || (unit = rx50unit(dev)) >= 2)
70*35045Skarels 		return (ENXIO);
71*35045Skarels 
72*35045Skarels 	/* enforce exclusive access */
73*35045Skarels 	if (rx50state.rs_flags & (1 << unit))
74*35045Skarels 		return (EBUSY);
75*35045Skarels 	rx50state.rs_flags |= 1 << unit;
76*35045Skarels 	return (0);
77*35045Skarels }
78*35045Skarels 
79*35045Skarels /*
80*35045Skarels  * Close a console RX50.
81*35045Skarels  */
82*35045Skarels /*ARGSUSED*/
83*35045Skarels rx50close(dev, flags)
84*35045Skarels 	dev_t dev;
85*35045Skarels 	int flags;
86*35045Skarels {
87*35045Skarels 
88*35045Skarels 	rx50state.rs_flags &= ~(1 << dev);	/* atomic */
89*35045Skarels }
90*35045Skarels 
91*35045Skarels /*
92*35045Skarels  * Perform a read (rw==UIO_READ) or write (rw==UIO_WRITE).
93*35045Skarels  */
94*35045Skarels rx50operation(dev, rw, uio)
95*35045Skarels 	dev_t dev;
96*35045Skarels 	enum uio_rw rw;
97*35045Skarels 	register struct uio *uio;
98*35045Skarels {
99*35045Skarels 	register struct rx50device *rxaddr;
100*35045Skarels 	register struct rx50state *rs;
101*35045Skarels 	register char *cp;
102*35045Skarels 	register int error, i, t;
103*35045Skarels 	char secbuf[512];
104*35045Skarels 	static char driveselect[2] = { RXCMD_DRIVE0, RXCMD_DRIVE1 };
105*35045Skarels 
106*35045Skarels 	/* enforce whole-sector I/O */
107*35045Skarels 	if ((uio->uio_offset & 511) || (uio->uio_resid & 511))
108*35045Skarels 		return (EINVAL);
109*35045Skarels 
110*35045Skarels 	rs = &rx50state;
111*35045Skarels 
112*35045Skarels 	/* lock out others */
113*35045Skarels 	i = spl4();
114*35045Skarels 	while (rs->rs_flags & RS_BUSY) {
115*35045Skarels 		rs->rs_flags |= RS_WANT;
116*35045Skarels 		sleep((caddr_t) &rx50state, PZERO - 1);
117*35045Skarels 	}
118*35045Skarels 	rs->rs_flags |= RS_BUSY;
119*35045Skarels 	rs->rs_drive = rx50unit(dev);
120*35045Skarels 	splx(i);
121*35045Skarels 
122*35045Skarels 	rxaddr = &rx50device;
123*35045Skarels 	error = 0;
124*35045Skarels 
125*35045Skarels 	while (uio->uio_resid) {
126*35045Skarels 		rs->rs_blkno = uio->uio_offset >> 9;
127*35045Skarels 		if (rs->rs_blkno >= RX50MAXSEC) {
128*35045Skarels 			if (rs->rs_blkno > RX50MAXSEC)
129*35045Skarels 				error = EINVAL;
130*35045Skarels 			else if (rw == UIO_WRITE)
131*35045Skarels 				error = ENOSPC;
132*35045Skarels 			/* else ``eof'' */
133*35045Skarels 			break;
134*35045Skarels 		}
135*35045Skarels 		rs->rs_flags &= ~(RS_ERROR | RS_DONE);
136*35045Skarels 		if (rw == UIO_WRITE) {
137*35045Skarels 			/* copy the data to the RX50 silo */
138*35045Skarels 			error = uiomove(secbuf, 512, UIO_WRITE, uio);
139*35045Skarels 			if (error)
140*35045Skarels 				break;
141*35045Skarels 			i = rxaddr->rxrda;
142*35045Skarels 			for (cp = secbuf, i = 512; --i >= 0;)
143*35045Skarels 				rxaddr->rxfdb = *cp++;
144*35045Skarels 			i = RXCMD_WRITE;
145*35045Skarels 		} else
146*35045Skarels 			i = RXCMD_READ;
147*35045Skarels 		rxaddr->rxcmd = i | driveselect[rs->rs_drive];
148*35045Skarels 		i = rs->rs_blkno - ((t = rs->rs_blkno / RX50SEC) * RX50SEC);
149*35045Skarels 		rxaddr->rxtrk = t == 79 ? 0 : t + 1;
150*35045Skarels #ifdef notdef
151*35045Skarels 		rxaddr->rxsec = "\1\3\5\7\11\1\3\5\7"[(2*t + i) % 5] + (i > 4);
152*35045Skarels #else
153*35045Skarels 		rxaddr->rxsec = RX50SKEW(i, t);
154*35045Skarels #endif
155*35045Skarels 		i = rxaddr->rxgo;	/* start it up */
156*35045Skarels 		i = spl4();
157*35045Skarels 		while ((rs->rs_flags & RS_DONE) == 0)
158*35045Skarels 			sleep((caddr_t) &rs->rs_blkno, PRIBIO);
159*35045Skarels 		splx(i);
160*35045Skarels 		if (rs->rs_flags & RS_ERROR) {
161*35045Skarels 			error = EIO;
162*35045Skarels 			break;
163*35045Skarels 		}
164*35045Skarels 		if (rw == UIO_READ) {
165*35045Skarels 			/* copy the data out of the silo */
166*35045Skarels 			i = rxaddr->rxrda;
167*35045Skarels 			for (cp = secbuf, i = 512; --i >= 0;)
168*35045Skarels 				*cp++ = rxaddr->rxedb;
169*35045Skarels 			error = uiomove(secbuf, 512, UIO_READ, uio);
170*35045Skarels 			if (error)
171*35045Skarels 				break;
172*35045Skarels 		}
173*35045Skarels 	}
174*35045Skarels 
175*35045Skarels 	/* let others in */
176*35045Skarels 	rs->rs_flags &= ~RS_BUSY;
177*35045Skarels 	if (rs->rs_flags & RS_WANT)
178*35045Skarels 		wakeup((caddr_t) rs);
179*35045Skarels 
180*35045Skarels 	return (error);
181*35045Skarels }
182*35045Skarels 
183*35045Skarels rx50read(dev, uio)
184*35045Skarels 	dev_t dev;
185*35045Skarels 	struct uio *uio;
186*35045Skarels {
187*35045Skarels 
188*35045Skarels 	return (rx50operation(dev, UIO_READ, uio));
189*35045Skarels }
190*35045Skarels 
191*35045Skarels rx50write(dev, uio)
192*35045Skarels 	dev_t dev;
193*35045Skarels 	struct uio *uio;
194*35045Skarels {
195*35045Skarels 
196*35045Skarels 	return (rx50operation(dev, UIO_WRITE, uio));
197*35045Skarels }
198*35045Skarels 
199*35045Skarels rx50intr()
200*35045Skarels {
201*35045Skarels 	register struct rx50device *rxaddr = &rx50device;
202*35045Skarels 	register struct rx50state *rs = &rx50state;
203*35045Skarels 	int i;
204*35045Skarels 
205*35045Skarels #ifdef lint
206*35045Skarels 	i = 0; i = i;
207*35045Skarels #endif
208*35045Skarels 
209*35045Skarels 	/* ignore spurious interrupts */
210*35045Skarels 	if ((rxaddr->rxcmd & RXCMD_DONE) == 0)
211*35045Skarels 		return;
212*35045Skarels 	if ((rs->rs_flags & RS_BUSY) == 0) {
213*35045Skarels 		printf("stray rx50 interrupt ignored\n");
214*35045Skarels 		return;
215*35045Skarels 	}
216*35045Skarels 	if (rxaddr->rxcmd & RXCMD_ERROR) {
217*35045Skarels 		printf(
218*35045Skarels 	"csa%d: hard error sn%d: cmd=%x trk=%x sec=%x csc=%x ict=%x ext=%x\n",
219*35045Skarels 			rs->rs_drive + 1, rs->rs_blkno,
220*35045Skarels 			rxaddr->rxcmd, rxaddr->rxtrk, rxaddr->rxsec,
221*35045Skarels 			rxaddr->rxcsc, rxaddr->rxict, rxaddr->rxext);
222*35045Skarels 		rxaddr->rxcmd = RXCMD_RESET;
223*35045Skarels 		i = rxaddr->rxgo;
224*35045Skarels 		rs->rs_flags |= RS_ERROR;
225*35045Skarels 	}
226*35045Skarels 	rs->rs_flags |= RS_DONE;
227*35045Skarels 	wakeup((caddr_t) &rs->rs_blkno);
228*35045Skarels }
229*35045Skarels #endif
230