xref: /netbsd/sys/arch/vax/vax/crx.c (revision c4a72b64)
1 /*	$NetBSD: crx.c,v 1.7 2002/10/23 09:12:37 jdolecek Exp $	*/
2 /*
3  * Copyright (c) 1988 Regents of the University of California.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * Chris Torek.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *	This product includes software developed by the University of
20  *	California, Berkeley and its contributors.
21  * 4. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  *	@(#)rx50.c	7.5 (Berkeley) 12/16/90
38  */
39 
40 /*
41  * Routines to handle the console RX50.
42  */
43 
44 #include <sys/param.h>
45 #include <sys/time.h>
46 #include <sys/proc.h>
47 #include <sys/kernel.h>
48 #include <sys/buf.h>
49 #include <sys/errno.h>
50 #include <sys/uio.h>
51 #include <sys/device.h>
52 #include <sys/systm.h>
53 #include <sys/conf.h>
54 
55 #include <machine/ka820.h>
56 #include <vax/vax/crx.h>
57 
58 dev_type_open(crxopen);
59 dev_type_close(crxclose);
60 dev_type_read(crxrw);
61 
62 const struct cdevsw crx_cdevsw = {
63 	crxopen, crxclose, crxrw, crxrw, noioctl,
64 	nostop, notty, nopoll, nommap, nokqfilter,
65 };
66 
67 extern struct	rx50device *rx50device_ptr;
68 #define rxaddr	rx50device_ptr
69 extern struct	ka820port *ka820port_ptr;
70 
71 #define	rx50unit(dev)	minor(dev)
72 
73 struct rx50state {
74 	short	rs_flags;	/* see below */
75 	short	rs_drive;	/* current drive number */
76 	u_int	rs_blkno;	/* current block number */
77 } rx50state;
78 
79 /* flags */
80 #define	RS_0OPEN	0x01	/* drive 0 open -- must be first */
81 #define	RS_1OPEN	0x02	/* drive 1 open -- must be second */
82 #define	RS_BUSY		0x04	/* operation in progress */
83 #define	RS_WANT		0x08	/* wakeup when done */
84 #define	RS_DONE		0x20	/* I/O operation done */
85 #define	RS_ERROR	0x40	/* error bit set at interrupt */
86 
87 #if 0
88 #define CRXDEBUG	1
89 #endif
90 
91 /*
92  * Open a console RX50.
93  */
94 /*ARGSUSED*/
95 int
96 crxopen(dev, flags, fmt, p)
97 	dev_t dev;
98 	int flags, fmt;
99 	struct proc *p;
100 {
101 	int unit;
102 
103 #if	CRXDEBUG
104 	printf("crxopen(csa%d)\n", minor(dev));
105 #endif
106 	if ((unit = rx50unit(dev)) >= 2)
107 		return (ENXIO);
108 
109 	/* enforce exclusive access */
110 	if (rx50state.rs_flags & (1 << unit))
111 		return (EBUSY);
112 	rx50state.rs_flags |= 1 << unit;
113 
114 	return (0);
115 }
116 
117 /*
118  * Close a console RX50.
119  */
120 /*ARGSUSED*/
121 int
122 crxclose(dev, flags, fmt, p)
123 	dev_t dev;
124 	int flags, fmt;
125 	struct proc *p;
126 {
127 #if	CRXDEBUG
128 	printf("crxclose(csa%d)\n", minor(dev));
129 #endif
130 
131 	rx50state.rs_flags &= ~(1 << dev);	/* atomic */
132 	return 0;
133 }
134 
135 /*
136  * Perform a read (uio->uio_rw==UIO_READ) or write (uio->uio_rw==UIO_WRITE).
137  */
138 int
139 crxrw(dev, uio, flags)
140 	dev_t dev;
141 	register struct uio *uio;
142 	int flags;
143 {
144 	register struct rx50state *rs;
145 	register char *cp;
146 	register int error, i, t;
147 	char secbuf[512];
148 	static char driveselect[2] = { RXCMD_DRIVE0, RXCMD_DRIVE1 };
149 
150 #if	CRXDEBUG
151 	printf("crxrw(csa%d): %s\n",
152 		minor(dev), uio->uio_rw==UIO_READ?"read":"write");
153 	printf("crxrw: ka820port = %x\n", ka820port_ptr->csr);
154 #endif
155 	/* enforce whole-sector I/O */
156 	if ((uio->uio_offset & 511) || (uio->uio_resid & 511))
157 		return (EINVAL);
158 
159 	rs = &rx50state;
160 
161 	/* lock out others */
162 	i = spl4();
163 	while (rs->rs_flags & RS_BUSY) {
164 		rs->rs_flags |= RS_WANT;
165 		(void) tsleep(&rx50state, PRIBIO, "crxbusy", 0);
166 	}
167 	rs->rs_flags |= RS_BUSY;
168 	rs->rs_drive = rx50unit(dev);
169 	splx(i);
170 
171 	rxaddr = rx50device_ptr;
172 	error = 0;
173 
174 	while (uio->uio_resid) {
175 		rs->rs_blkno = uio->uio_offset >> 9;
176 		if (rs->rs_blkno >= RX50MAXSEC) {
177 			if (rs->rs_blkno > RX50MAXSEC)
178 				error = EINVAL;
179 			else if (uio->uio_rw == UIO_WRITE)
180 				error = ENOSPC;
181 			/* else ``eof'' */
182 			break;
183 		}
184 		rs->rs_flags &= ~(RS_ERROR | RS_DONE);
185 		if (uio->uio_rw == UIO_WRITE) {
186 			/* copy the data to the RX50 silo */
187 			error = uiomove(secbuf, 512, uio);
188 			if (error)
189 				break;
190 			i = rxaddr->rxrda;
191 			for (cp = secbuf, i = 512; --i >= 0;)
192 				rxaddr->rxfdb = *cp++;
193 			i = RXCMD_WRITE;
194 		} else
195 			i = RXCMD_READ;
196 		rxaddr->rxcmd = i | driveselect[rs->rs_drive];
197 		i = rs->rs_blkno - ((t = rs->rs_blkno / RX50SEC) * RX50SEC);
198 		rxaddr->rxtrk = t == 79 ? 0 : t + 1;
199 #ifdef notdef
200 		rxaddr->rxsec = "\1\3\5\7\11\1\3\5\7"[(2*t + i) % 5] + (i > 4);
201 #else
202 		rxaddr->rxsec = RX50SKEW(i, t);
203 #endif
204 #if	CRXDEBUG
205 		printf("crx: going off\n");
206 		printf("crxrw: ka820port = %x\n", ka820port_ptr->csr);
207 #endif
208 		rxaddr->rxgo = 0;	/* start it up */
209 		ka820port_ptr->csr |= KA820PORT_RXIRQ;
210 		i = spl4();
211 		while ((rs->rs_flags & RS_DONE) == 0) {
212 #if	CRXDEBUG
213 			printf("crx: sleeping on I/O\n");
214 			printf("crxopen: ka820port = %x\n", ka820port_ptr->csr);
215 #endif
216 			(void) tsleep(&rs->rs_blkno, PRIBIO, "crxrw", 0);
217 		}
218 		splx(i);
219 		if (rs->rs_flags & RS_ERROR) {
220 			error = EIO;
221 			break;
222 		}
223 		if (uio->uio_rw == UIO_READ) {
224 			/* copy the data out of the silo */
225 			i = rxaddr->rxrda;
226 			for (cp = secbuf, i = 512; --i >= 0;)
227 				*cp++ = rxaddr->rxedb;
228 			error = uiomove(secbuf, 512, uio);
229 			if (error)
230 				break;
231 		}
232 	}
233 
234 	/* let others in */
235 #if	CRXDEBUG
236 	printf("crx: let others in\n");
237 #endif
238 	rs->rs_flags &= ~RS_BUSY;
239 	if (rs->rs_flags & RS_WANT)
240 		wakeup((caddr_t) rs);
241 
242 	return (error);
243 }
244 
245 void
246 crxintr(arg)
247 	void *arg;
248 {
249 	register struct rx50state *rs = &rx50state;
250 
251 	/* ignore spurious interrupts */
252 	if ((rxaddr->rxcmd & RXCMD_DONE) == 0)
253 		return;
254 	if ((rs->rs_flags & RS_BUSY) == 0) {
255 		printf("stray rx50 interrupt ignored (rs_flags: 0x%x, rxcmd: 0x%x)\n",
256 			rs->rs_flags, rxaddr->rxcmd);
257 		return;
258 	}
259 	if (rxaddr->rxcmd & RXCMD_ERROR) {
260 		printf(
261 	"csa%d: hard error sn%d: cmd=%x trk=%x sec=%x csc=%x ict=%x ext=%x\n",
262 			rs->rs_drive + 1, rs->rs_blkno,
263 			rxaddr->rxcmd, rxaddr->rxtrk, rxaddr->rxsec,
264 			rxaddr->rxcsc, rxaddr->rxict, rxaddr->rxext);
265 		rxaddr->rxcmd = RXCMD_RESET;
266 		rxaddr->rxgo = 0;
267 		rs->rs_flags |= RS_ERROR;
268 	}
269 	rs->rs_flags |= RS_DONE;
270 	wakeup((caddr_t) &rs->rs_blkno);
271 }
272