xref: /netbsd/sys/arch/vax/boot/boot/if_qe.c (revision bf9ec67e)
1 /*	$NetBSD: if_qe.c,v 1.3 2000/05/20 13:30:03 ragge Exp $ */
2 
3 /*
4  * Copyright (c) 1998 Roar Thron�s.  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. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *	This product includes software developed by Roar Thron�s.
17  * 4. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  *	Standalone routine for the DEQNA.
32  */
33 
34 #include <sys/param.h>
35 #include <sys/types.h>
36 
37 #include <netinet/in.h>
38 #include <netinet/in_systm.h>
39 
40 #include <lib/libsa/netif.h>
41 #include <lib/libsa/stand.h>
42 
43 #include "lib/libkern/libkern.h"
44 
45 #include <dev/qbus/if_qereg.h>
46 
47 #include "../include/rpb.h"
48 
49 #include "vaxstand.h"
50 
51 static int qe_get(struct iodesc *desc, void *pkt, size_t, time_t timeout);
52 static int qe_put(struct iodesc *desc, void *pkt, size_t);
53 static void qe_init(u_char *eaddr);
54 
55 struct netif_driver qe_driver = {
56 	0, 0, 0, 0, qe_get, qe_put,
57 };
58 
59 #define NRCV	1		       /* Receive descriptors	       */
60 #define NXMT	1			/* Transmit descriptors		*/
61 
62 #define QE_INTS	       (QE_RCV_INT | QE_XMIT_INT)
63 #define MAXPACKETSIZE  0x800		/* Because of (buggy) DEQNA */
64 
65 static struct  qe_softc {
66 	struct	qe_ring rring[NRCV+2];	/* Receive ring descriptors	*/
67 	struct	qe_ring tring[NXMT+2];	/* Xmit ring descriptors	*/
68 	u_char	setup_pkt[16][8];	/* Setup packet			*/
69 	char	qein[2048], qeout[2048];/* Packet buffers		*/
70 } qe_softc;
71 
72 static	struct qe_softc *sc = &qe_softc;
73 static	int addr;
74 
75 #define QE_WCSR(csr, val) \
76 	(*((volatile u_short *)(addr + (csr))) = (val))
77 #define QE_RCSR(csr) \
78 	*((volatile u_short *)(addr + (csr)))
79 #define DELAY(x)		{volatile int i = x;while (--i);}
80 #define LOWORD(x)	((int)(x) & 0xffff)
81 #define HIWORD(x)	(((int)(x) >> 16) & 0x3f)
82 #define qereg(x) ((x) & 017777)
83 
84 int
85 qeopen(struct open_file *f, int adapt, int ctlr, int unit, int part) {
86 	u_char eaddr[6];
87 
88 	if (askname == 0)
89 		addr = bootrpb.csrphy;	/* Autoboot; use RPB instead */
90 	else {
91 		addr = 0x20000000;
92 		if (unit == 0)
93 			addr += qereg(0774440); /* XQA0 */
94 		else if (unit == 1)
95 			addr += qereg(0174460); /* XQB0 */
96 		else
97 			return ECTLR;
98 	}
99 
100 	qe_init(eaddr);
101 
102 	net_devinit(f, &qe_driver, eaddr);
103 	return 0;
104 }
105 
106 void
107 qe_init(u_char *eaddr)
108 {
109 	int i,j;
110 
111 	QE_WCSR(QE_CSR_CSR, QE_RESET);
112 	QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) & ~QE_RESET);
113 
114 	for (i = 0; i < 6; i++) {
115 		sc->setup_pkt[i][1] = QE_RCSR(i * 2);
116 		sc->setup_pkt[i+8][1] = QE_RCSR(i * 2);
117 		sc->setup_pkt[i][2] = 0xff;
118 		sc->setup_pkt[i+8][2] = QE_RCSR(i * 2);
119 		for (j=3; j < 8; j++) {
120 			sc->setup_pkt[i][j] = QE_RCSR(i * 2);
121 			sc->setup_pkt[i+8][j] = QE_RCSR(i * 2);
122 		}
123 		eaddr[i] = QE_RCSR(i * 2);
124 	}
125 
126 	bzero((caddr_t)sc->rring, sizeof(struct qe_ring));
127 	sc->rring->qe_buf_len = -64;
128 	sc->rring->qe_addr_lo = (short)((int)sc->setup_pkt);
129 	sc->rring->qe_addr_hi = (short)((int)sc->setup_pkt >> 16);
130 
131 	bzero((caddr_t)sc->tring, sizeof(struct qe_ring));
132 	sc->tring->qe_buf_len = -64;
133 	sc->tring->qe_addr_lo = (short)((int)sc->setup_pkt);
134 	sc->tring->qe_addr_hi = (short)((int)sc->setup_pkt >> 16);
135 
136 	sc->rring[0].qe_flag = sc->rring[0].qe_status1 = QE_NOTYET;
137 	sc->rring->qe_addr_hi |= QE_VALID;
138 
139 	sc->tring[0].qe_flag = sc->tring[0].qe_status1 = QE_NOTYET;
140 	sc->tring->qe_addr_hi |= QE_VALID | QE_SETUP | QE_EOMSG;
141 
142 	QE_WCSR(QE_CSR_CSR, QE_XMIT_INT | QE_RCV_INT);
143 
144 	QE_WCSR(QE_CSR_RCLL, LOWORD(sc->rring));
145 	QE_WCSR(QE_CSR_RCLH, HIWORD(sc->rring));
146 	QE_WCSR(QE_CSR_XMTL, LOWORD(sc->tring));
147 	QE_WCSR(QE_CSR_XMTH, HIWORD(sc->tring));
148 
149 	while ((QE_RCSR(QE_CSR_CSR) & QE_INTS) != QE_INTS)
150 		;
151 	QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) | QE_INTS);
152 	QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) & ~(QE_INT_ENABLE|QE_ELOOP));
153 	QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) | QE_ILOOP);
154 
155 	sc->rring[0].qe_addr_lo = (short)((int)sc->qein & 0xffff);
156 	sc->rring[0].qe_addr_hi = (short)((int)sc->qein >> 16);
157 	sc->rring[0].qe_buf_len=-MAXPACKETSIZE/2;
158 	sc->rring[0].qe_addr_hi |= QE_VALID;
159 	sc->rring[0].qe_flag=sc->rring[0].qe_status1=QE_NOTYET;
160 	sc->rring[0].qe_status2=1;
161 
162 	sc->rring[1].qe_addr_lo = 0;
163 	sc->rring[1].qe_addr_hi = 0;
164 	sc->rring[1].qe_flag=sc->rring[1].qe_status1=QE_NOTYET;
165 	sc->rring[1].qe_status2=1;
166 
167 	sc->tring[0].qe_addr_lo = (short)((int)sc->qeout & 0xffff);
168 	sc->tring[0].qe_addr_hi = (short)((int)sc->qeout >> 16);
169 	sc->tring[0].qe_buf_len=0;
170 	sc->tring[0].qe_flag=sc->tring[0].qe_status1=QE_NOTYET;
171 	sc->tring[0].qe_addr_hi |= QE_EOMSG|QE_VALID;
172 
173 	sc->tring[1].qe_flag=sc->tring[1].qe_status1=QE_NOTYET;
174 	sc->tring[1].qe_addr_lo = 0;
175 	sc->tring[1].qe_addr_hi = 0;
176 
177 	QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) | QE_RCV_ENABLE);
178 	QE_WCSR(QE_CSR_RCLL, LOWORD(sc->rring));
179 	QE_WCSR(QE_CSR_RCLH, HIWORD(sc->rring));
180 }
181 
182 int
183 qe_get(struct iodesc *desc, void *pkt, size_t maxlen, time_t timeout) {
184 	int len, j;
185 
186 retry:
187 	for(j = 0x10000;j && (QE_RCSR(QE_CSR_CSR) & QE_RCV_INT) == 0; j--)
188 		;
189 
190 	if ((QE_RCSR(QE_CSR_CSR) & QE_RCV_INT) == 0)
191 		goto fail;
192 
193 	QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) & ~(QE_RCV_ENABLE|QE_XMIT_INT));
194 
195 	len= ((sc->rring[0].qe_status1 & QE_RBL_HI) |
196 	    (sc->rring[0].qe_status2 & QE_RBL_LO)) + 60;
197 
198 	if (sc->rring[0].qe_status1 & 0xc000)
199 		goto fail;
200 
201 	if (len == 0)
202 		goto retry;
203 
204 	bcopy((void*)sc->qein,pkt,len);
205 
206 
207 end:
208 	sc->rring[0].qe_status2 = sc->rring[1].qe_status2 = 1;
209 	sc->rring[0].qe_flag=sc->rring[0].qe_status1=QE_NOTYET;
210 	sc->rring[1].qe_flag=sc->rring[1].qe_status1=QE_NOTYET;
211 	QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) | QE_RCV_ENABLE);
212 
213 	QE_WCSR(QE_CSR_RCLL, LOWORD(sc->rring));
214 	QE_WCSR(QE_CSR_RCLH, HIWORD(sc->rring));
215 	return len;
216 
217 fail:	len = -1;
218 	goto end;
219 }
220 
221 int
222 qe_put(struct iodesc *desc, void *pkt, size_t len) {
223 	int j;
224 
225 	bcopy(pkt, (char *)sc->qeout, len);
226 	sc->tring[0].qe_buf_len=-len/2;
227 	sc->tring[0].qe_flag=sc->tring[0].qe_status1=QE_NOTYET;
228 	sc->tring[1].qe_flag=sc->tring[1].qe_status1=QE_NOTYET;
229 
230 	QE_WCSR(QE_CSR_XMTL, LOWORD(sc->tring));
231 	QE_WCSR(QE_CSR_XMTH, HIWORD(sc->tring));
232 
233 	for(j = 0; (j < 0x10000) && ((QE_RCSR(QE_CSR_CSR) & QE_XMIT_INT) == 0); j++)
234 		;
235 
236 	if ((QE_RCSR(QE_CSR_CSR) & QE_XMIT_INT) == 0) {
237 		char eaddr[6];
238 
239 		qe_init(eaddr);
240 		return -1;
241 	}
242 	QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) & ~QE_RCV_INT);
243 
244 	if (sc->tring[0].qe_status1 & 0xc000) {
245 		char eaddr[6];
246 
247 		qe_init(eaddr);
248 		return -1;
249 	}
250 	return len;
251 }
252 
253 int
254 qeclose(struct open_file *nif)
255 {
256 	QE_WCSR(QE_CSR_CSR, QE_RESET);
257 	QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) & ~QE_RESET);
258 
259 	return 0;
260 }
261