xref: /netbsd-src/sys/arch/vax/vax/crl.c (revision eabd5e1de9134b019f6c05d7673b0c02764ff5e4)
1 /*	$NetBSD: crl.c,v 1.34 2017/03/31 08:38:13 msaitoh Exp $	*/
2 /*-
3  * Copyright (c) 1982, 1986 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the University nor the names of its contributors
15  *    may be used to endorse or promote products derived from this software
16  *    without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  *	@(#)crl.c	7.5 (Berkeley) 5/9/91
31  */
32 
33 /*
34  * Bugfix by Johnny Billquist 2010
35  */
36 
37 /*
38  * TO DO (tef  7/18/85):
39  *	1) change printf's to log() instead???
40  */
41 
42 #include <sys/cdefs.h>
43 __KERNEL_RCSID(0, "$NetBSD: crl.c,v 1.34 2017/03/31 08:38:13 msaitoh Exp $");
44 
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/conf.h>
48 #include <sys/cpu.h>
49 #include <sys/device.h>
50 #include <sys/proc.h>
51 #include <sys/buf.h>
52 
53 #include <machine/sid.h>
54 #include <machine/scb.h>
55 
56 #include <vax/vax/crl.h>
57 
58 struct {
59 	short	crl_state;		/* open and busy flags */
60 	short	crl_active;		/* driver state flag */
61 	struct	buf *crl_buf;		/* buffer we're using */
62 	ushort *crl_xaddr;		/* transfer address */
63 	short	crl_errcnt;
64 } crltab;
65 
66 struct {
67 	int	crl_cs;		/* saved controller status */
68 	int	crl_ds;		/* saved drive status */
69 } crlstat;
70 
71 void	crlintr(void *);
72 void	crlattach(void);
73 
74 static void crlstart(void);
75 static dev_type_open(crlopen);
76 static dev_type_close(crlclose);
77 static dev_type_read(crlrw);
78 
79 const struct cdevsw crl_cdevsw = {
80 	.d_open = crlopen,
81 	.d_close = crlclose,
82 	.d_read = crlrw,
83 	.d_write = crlrw,
84 	.d_ioctl = noioctl,
85 	.d_stop = nostop,
86 	.d_tty = notty,
87 	.d_poll = nopoll,
88 	.d_mmap = nommap,
89 	.d_kqfilter = nokqfilter,
90 	.d_discard = nodiscard,
91 	.d_flag = 0
92 };
93 
94 struct evcnt crl_ev = EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "crl", "intr");
95 EVCNT_ATTACH_STATIC(crl_ev);
96 
97 void
crlattach(void)98 crlattach(void)
99 {
100 	scb_vecalloc(0xF0, crlintr, NULL, SCB_ISTACK, &crl_ev);
101 }
102 
103 /*ARGSUSED*/
104 int
crlopen(dev_t dev,int flag,int mode,struct lwp * l)105 crlopen(dev_t dev, int flag, int mode, struct lwp *l)
106 {
107 	if (vax_cputype != VAX_8600)
108 		return (ENXIO);
109 	if (crltab.crl_state != CRL_IDLE)
110 		return (EALREADY);
111 	crltab.crl_state = CRL_OPEN;
112 	crltab.crl_buf = geteblk(512);
113 	return (0);
114 }
115 
116 /*ARGSUSED*/
117 int
crlclose(dev_t dev,int flag,int mode,struct lwp * l)118 crlclose(dev_t dev, int flag, int mode, struct lwp *l)
119 {
120 	brelse(crltab.crl_buf, 0);
121 	crltab.crl_state = CRL_IDLE;
122 	return 0;
123 }
124 
125 /*ARGSUSED*/
126 int
crlrw(dev_t dev,struct uio * uio,int flag)127 crlrw(dev_t dev, struct uio *uio, int flag)
128 {
129 	struct buf *bp;
130 	int i;
131 	int s;
132 	int error;
133 
134 	if (uio->uio_resid == 0)
135 		return (0);
136 	s = splconsmedia();
137 	while (crltab.crl_state & CRL_BUSY)
138 		(void) tsleep(&crltab, PRIBIO, "crlbusy", 0);
139 	crltab.crl_state |= CRL_BUSY;
140 	splx(s);
141 
142 	bp = crltab.crl_buf;
143 	error = 0;
144 	while ((i = imin(CRLBYSEC, uio->uio_resid)) > 0) {
145 		bp->b_blkno = uio->uio_offset>>9;
146 		if (bp->b_blkno >= MAXSEC || (uio->uio_offset & 0x1FF) != 0) {
147 			error = EIO;
148 			break;
149 		}
150 		if (uio->uio_rw == UIO_WRITE) {
151 			error = uiomove(bp->b_data, i, uio);
152 			if (error)
153 				break;
154 		}
155 		if (uio->uio_rw == UIO_WRITE) {
156 			bp->b_oflags &= ~(BO_DONE);
157 			bp->b_flags &= ~(B_READ);
158 			bp->b_flags |= B_WRITE;
159 		} else {
160 			bp->b_oflags &= ~(BO_DONE);
161 			bp->b_flags &= ~(B_WRITE);
162 			bp->b_flags |= B_READ;
163 		}
164 		s = splconsmedia();
165 		crlstart();
166                 while ((bp->b_oflags & BO_DONE) == 0)
167                   (void) tsleep(bp, PRIBIO, "crlxfer", 0);
168 		splx(s);
169 		if (bp->b_error != 0) {
170 			error = bp->b_error;
171 			break;
172 		}
173 		if (uio->uio_rw == UIO_READ) {
174 			error = uiomove(bp->b_data, i, uio);
175 			if (error)
176 				break;
177 		}
178 	}
179 	crltab.crl_state &= ~CRL_BUSY;
180 	wakeup((void *)&crltab);
181 	return (error);
182 }
183 
184 void
crlstart(void)185 crlstart(void)
186 {
187 	struct buf *bp;
188 
189 	bp = crltab.crl_buf;
190 	crltab.crl_errcnt = 0;
191 	crltab.crl_xaddr = (ushort *) bp->b_data;
192 	bp->b_resid = 0;
193 
194 	if ((mfpr(PR_STXCS) & STXCS_RDY) == 0)
195 		/* not ready to receive order */
196 		return;
197 	if ((bp->b_flags&(B_READ|B_WRITE)) == B_READ) {
198 		crltab.crl_active = CRL_F_READ;
199 		mtpr(bp->b_blkno<<8 | STXCS_IE | CRL_F_READ, PR_STXCS);
200 	} else {
201 		crltab.crl_active = CRL_F_WRITE;
202 		mtpr(bp->b_blkno<<8 | STXCS_IE | CRL_F_WRITE, PR_STXCS);
203 	}
204 #ifdef lint
205 	crlintr(NULL);
206 #endif
207 }
208 
209 void
crlintr(void * arg)210 crlintr(void *arg)
211 {
212 	struct buf *bp;
213 	int i;
214 
215 	bp = crltab.crl_buf;
216 	i = mfpr(PR_STXCS);
217 	switch ((i>>24) & 0xFF) {
218 
219 	case CRL_S_XCMPLT:
220 		switch (crltab.crl_active) {
221 
222 		case CRL_F_RETSTS:
223 			{
224 				char sbuf[256], sbuf2[256];
225 
226 				crlstat.crl_ds = mfpr(PR_STXDB);
227 
228 				snprintb(sbuf, sizeof(sbuf), CRLCS_BITS,
229 				    crlstat.crl_cs);
230 				snprintb(sbuf2, sizeof(sbuf2), CRLDS_BITS,
231 				    crlstat.crl_ds);
232 				printf("crlcs=%s, crlds=%s\n", sbuf, sbuf2);
233 				break;
234 			}
235 
236 		case CRL_F_READ:
237 		case CRL_F_WRITE:
238 			bp->b_oflags |= BO_DONE;
239 		}
240 		crltab.crl_active = 0;
241 		wakeup(bp);
242 		break;
243 
244 	case CRL_S_XCONT:
245 		switch (crltab.crl_active) {
246 
247 		case CRL_F_WRITE:
248 			mtpr(*crltab.crl_xaddr++, PR_STXDB);
249 			mtpr(bp->b_blkno<<8 | STXCS_IE | CRL_F_WRITE, PR_STXCS);
250 			break;
251 
252 		case CRL_F_READ:
253 			*crltab.crl_xaddr++ = mfpr(PR_STXDB);
254 			mtpr(bp->b_blkno<<8 | STXCS_IE | CRL_F_READ, PR_STXCS);
255 		}
256 		break;
257 
258 	case CRL_S_ABORT:
259 		crltab.crl_active = CRL_F_RETSTS;
260 		mtpr(STXCS_IE | CRL_F_RETSTS, PR_STXCS);
261 		bp->b_oflags |= BO_DONE;
262 		bp->b_error = EIO;
263 		break;
264 
265 	case CRL_S_RETSTS:
266 		crlstat.crl_cs = mfpr(PR_STXDB);
267 		mtpr(STXCS_IE | CRL_S_RETSTS, PR_STXCS);
268 		break;
269 
270 	case CRL_S_HNDSHK:
271 		printf("crl: hndshk error\n");	/* dump out some status too? */
272 		crltab.crl_active = 0;
273 		bp->b_oflags |= BO_DONE;
274 		bp->b_error = EIO;
275 		cv_broadcast(&bp->b_done);
276 		break;
277 
278 	case CRL_S_HWERR:
279 		printf("crl: hard error sn%" PRId64 "\n", bp->b_blkno);
280 		crltab.crl_active = CRL_F_ABORT;
281 		mtpr(STXCS_IE | CRL_F_ABORT, PR_STXCS);
282 		break;
283 	}
284 }
285