xref: /netbsd/sys/arch/vax/boot/boot/if_le.c (revision 2d5d8524)
1 /*	$NetBSD: if_le.c,v 1.13 2017/05/22 16:59:32 ragge Exp $ */
2 /*
3  * Copyright (c) 1997, 1999 Ludd, University of Lule}, Sweden.
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  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 /*
28  * Standalone routine for MicroVAX LANCE chip.
29  */
30 
31 #include <sys/param.h>
32 #include <sys/types.h>
33 #include <sys/queue.h>
34 #include <sys/socket.h>
35 
36 #include <net/if.h>
37 #include <net/if_ether.h>
38 
39 #include <netinet/in.h>
40 #include <netinet/in_systm.h>
41 
42 #include <../include/sid.h>
43 #include <../include/rpb.h>
44 
45 #include <lib/libsa/netif.h>
46 #include <lib/libsa/stand.h>
47 
48 #include <dev/ic/lancereg.h>
49 #include <dev/ic/am7990reg.h>
50 
51 #include "vaxstand.h"
52 
53 /*
54  * Buffer sizes.
55  */
56 #define TLEN    1
57 #define NTBUF   (1 << TLEN)
58 #define RLEN    3
59 #define NRBUF   (1 << RLEN)
60 #define BUFSIZE 1518
61 
62 #define	QW_ALLOC(x)	(((uintptr_t)alloc((x) + 7) + 7) & ~7)
63 
64 static int le_get(struct iodesc *, void *, size_t, saseconds_t);
65 static int le_put(struct iodesc *, void *, size_t);
66 static void copyout(void *from, int dest, int len);
67 static void copyin(int src, void *to, int len);
68 
69 struct netif_driver le_driver = {
70 	0, 0, 0, 0, le_get, le_put,
71 };
72 
73 /*
74  * Init block & buffer descriptors according to DEC system
75  * specification documentation.
76  */
77 struct initblock {
78 	short	ib_mode;
79 	char	ib_padr[6]; /* Ethernet address */
80 	int	ib_ladrf1;
81 	int	ib_ladrf2;
82 	int	ib_rdr; /* Receive address */
83 	int	ib_tdr; /* Transmit address */
84 } *initblock = NULL;
85 
86 struct nireg {
87 	volatile u_short ni_rdp;       /* data port */
88 	volatile short ni_pad0;
89 	volatile short ni_rap;       /* register select port */
90 } *nireg;
91 
92 
93 volatile struct	buffdesc {
94 	int	bd_adrflg;
95 	short	bd_bcnt;
96 	short	bd_mcnt;
97 } *rdesc, *tdesc;
98 
99 static	int addoff, kopiera = 0;
100 
101 /* Flags in the address field */
102 #define	BR_OWN	0x80000000
103 #define	BR_ERR	0x40000000
104 #define	BR_FRAM	0x20000000
105 #define	BR_OFLO	0x10000000
106 #define	BR_CRC	0x08000000
107 #define	BR_BUFF	0x04000000
108 #define	BR_STP	0x02000000
109 #define	BR_ENP	0x01000000
110 
111 #define	BT_OWN	0x80000000
112 #define	BT_ERR	0x40000000
113 #define	BT_MORE	0x10000000
114 #define	BT_ONE	0x08000000
115 #define	BT_DEF	0x04000000
116 #define	BT_STP	0x02000000
117 #define	BT_ENP	0x01000000
118 
119 int	next_rdesc, next_tdesc;
120 
121 #define	LEWRCSR(port, val) { \
122 	nireg->ni_rap = (port); \
123 	nireg->ni_rdp = (val); \
124 }
125 
126 #define	LERDCSR(port) \
127 	(nireg->ni_rap = port, nireg->ni_rdp)
128 
129 int
leopen(struct open_file * f,int adapt,int ctlr,int unit,int part)130 leopen(struct open_file *f, int adapt, int ctlr, int unit, int part)
131 {
132 	int i, *ea;
133 	volatile int to = 100000;
134 	u_char eaddr[6];
135 
136 	next_rdesc = next_tdesc = 0;
137 
138 	if (vax_boardtype == VAX_BTYP_650 &&
139 	    ((vax_siedata >> 8) & 0xff) == VAX_SIE_KA640) {
140 		kopiera = 1;
141 		ea = (void *)0x20084200;
142 		nireg = (void *)0x20084400;
143 	} else {
144 		*(int *)0x20080014 = 0; /* Be sure we do DMA in low 16MB */
145 		ea = (void *)0x20090000; /* XXX ethernetaddress */
146 		nireg = (void *)0x200e0000;
147 	}
148 	if (askname == 0) /* Override if autoboot */
149 		nireg = (void *)bootrpb.csrphy;
150 	else /* Tell kernel from where we booted */
151 		bootrpb.csrphy = (int)nireg;
152 
153 	if (vax_boardtype == VAX_BTYP_43)
154 		addoff = 0x28000000;
155 	else
156 		addoff = 0;
157 igen:
158 	LEWRCSR(LE_CSR0, LE_C0_STOP);
159 	while (to--)
160 		;
161 
162 	for (i = 0; i < 6; i++)
163 		eaddr[i] = ea[i] & 0377;
164 
165 	if (initblock == NULL) {
166 		initblock = (struct initblock *)
167 			(QW_ALLOC(sizeof(struct initblock)) + addoff);
168 		initblock->ib_mode = LE_MODE_NORMAL;
169 		memcpy(initblock->ib_padr, eaddr, 6);
170 		initblock->ib_ladrf1 = 0;
171 		initblock->ib_ladrf2 = 0;
172 
173 		rdesc = (struct buffdesc *)
174 			(QW_ALLOC(sizeof(struct buffdesc) * NRBUF) + addoff);
175 		initblock->ib_rdr = (RLEN << 29) | (int)rdesc;
176 		if (kopiera)
177 			initblock->ib_rdr -= (int)initblock;
178 		tdesc = (struct buffdesc *)
179 			(QW_ALLOC(sizeof(struct buffdesc) * NTBUF) + addoff);
180 		initblock->ib_tdr = (TLEN << 29) | (int)tdesc;
181 		if (kopiera)
182 			initblock->ib_tdr -= (int)initblock;
183 		if (kopiera)
184 			copyout(initblock, 0, sizeof(struct initblock));
185 
186 		for (i = 0; i < NRBUF; i++) {
187 			rdesc[i].bd_adrflg = QW_ALLOC(BUFSIZE) | BR_OWN;
188 			if (kopiera)
189 				rdesc[i].bd_adrflg -= (int)initblock;
190 			rdesc[i].bd_bcnt = -BUFSIZE;
191 			rdesc[i].bd_mcnt = 0;
192 		}
193 		if (kopiera)
194 			copyout((void *)rdesc, (int)rdesc - (int)initblock,
195 			    sizeof(struct buffdesc) * NRBUF);
196 
197 		for (i = 0; i < NTBUF; i++) {
198 			tdesc[i].bd_adrflg = QW_ALLOC(BUFSIZE);
199 			if (kopiera)
200 				tdesc[i].bd_adrflg -= (int)initblock;
201 			tdesc[i].bd_bcnt = 0xf000;
202 			tdesc[i].bd_mcnt = 0;
203 		}
204 		if (kopiera)
205 			copyout((void *)tdesc, (int)tdesc - (int)initblock,
206 			    sizeof(struct buffdesc) * NTBUF);
207 	}
208 
209 	if (kopiera) {
210 		LEWRCSR(LE_CSR1, 0);
211 		LEWRCSR(LE_CSR2, 0);
212 	} else {
213 		LEWRCSR(LE_CSR1, (int)initblock & 0xffff);
214 		LEWRCSR(LE_CSR2, ((int)initblock >> 16) & 0xff);
215 	}
216 
217 	LEWRCSR(LE_CSR0, LE_C0_INIT);
218 
219 	to = 100000;
220 	while (to--) {
221 		if (LERDCSR(LE_CSR0) & LE_C0_IDON)
222 			break;
223 		if (LERDCSR(LE_CSR0) & LE_C0_ERR) {
224 			printf("lance init error: csr0 %x\n", LERDCSR(LE_CSR0));
225 			goto igen;
226 		}
227 	}
228 
229 	LEWRCSR(LE_CSR0, LE_C0_INEA | LE_C0_STRT | LE_C0_IDON);
230 
231 	net_devinit(f, &le_driver, eaddr);
232 	return 0;
233 }
234 
235 int
le_get(struct iodesc * desc,void * pkt,size_t maxlen,saseconds_t timeout)236 le_get(struct iodesc *desc, void *pkt, size_t maxlen, saseconds_t timeout)
237 {
238 	int csr, len;
239 	volatile int to = 100000 * timeout;
240 
241 retry:
242 	if (to-- == 0)
243 		return 0;
244 
245 	csr = LERDCSR(LE_CSR0);
246 	LEWRCSR(LE_CSR0, csr & (LE_C0_BABL|LE_C0_MISS|LE_C0_MERR|LE_C0_RINT));
247 
248 	if (kopiera)
249 		copyin((int)&rdesc[next_rdesc] - (int)initblock,
250 		    (void *)&rdesc[next_rdesc], sizeof(struct buffdesc));
251 	if (rdesc[next_rdesc].bd_adrflg & BR_OWN)
252 		goto retry;
253 
254         if (rdesc[next_rdesc].bd_adrflg & BR_ERR)
255                 len = 0;
256         else {
257 		if ((len = rdesc[next_rdesc].bd_mcnt - 4) > maxlen)
258 			len = maxlen;
259 
260 		if (kopiera)
261 			copyin((rdesc[next_rdesc].bd_adrflg&0xffffff),
262 			    pkt, len);
263 		else
264 			memcpy(pkt,
265 			    (char *)(rdesc[next_rdesc].bd_adrflg&0xffffff) +
266 			    addoff, len);
267 	}
268 
269 	rdesc[next_rdesc].bd_mcnt = 0;
270 	rdesc[next_rdesc].bd_adrflg |= BR_OWN;
271 	if (kopiera)
272 		copyout((void *)&rdesc[next_rdesc], (int)&rdesc[next_rdesc] -
273 		    (int)initblock, sizeof(struct buffdesc));
274 	if (++next_rdesc >= NRBUF)
275 		next_rdesc = 0;
276 
277 
278 	if (len == 0)
279 		goto retry;
280 	return len;
281 }
282 
283 int
le_put(struct iodesc * desc,void * pkt,size_t len)284 le_put(struct iodesc *desc, void *pkt, size_t len)
285 {
286 	volatile int to = 100000;
287 	int csr;
288 
289 retry:
290 	if (--to == 0)
291 		return -1;
292 
293 	csr = LERDCSR(LE_CSR0);
294 	LEWRCSR(LE_CSR0, csr & (LE_C0_MISS|LE_C0_CERR|LE_C0_TINT));
295 
296 	if (kopiera)
297 		copyin((int)&tdesc[next_tdesc] - (int)initblock,
298 		    (void *)&tdesc[next_tdesc], sizeof(struct buffdesc));
299 	if (tdesc[next_tdesc].bd_adrflg & BT_OWN)
300 		goto retry;
301 
302 	if (kopiera)
303 		copyout(pkt, (tdesc[next_tdesc].bd_adrflg & 0xffffff), len);
304 	else
305 		memcpy((char *)(tdesc[next_tdesc].bd_adrflg & 0xffffff) +
306 		    addoff, pkt, len);
307 	tdesc[next_tdesc].bd_bcnt =
308 	    (len < ETHER_MIN_LEN ? -ETHER_MIN_LEN : -len);
309 	tdesc[next_tdesc].bd_mcnt = 0;
310 	tdesc[next_tdesc].bd_adrflg |= BT_OWN | BT_STP | BT_ENP;
311 	if (kopiera)
312 		copyout((void *)&tdesc[next_tdesc], (int)&tdesc[next_tdesc] -
313 		    (int)initblock, sizeof(struct buffdesc));
314 
315 	LEWRCSR(LE_CSR0, LE_C0_TDMD);
316 
317 	to = 100000;
318 	while (((LERDCSR(LE_CSR0) & LE_C0_TINT) == 0) && --to)
319 		;
320 
321 	LEWRCSR(LE_CSR0, LE_C0_TINT);
322 	if (++next_tdesc >= NTBUF)
323 		next_tdesc = 0;
324 
325 	if (to)
326 		return len;
327 
328 	return -1;
329 }
330 
331 int
leclose(struct open_file * f)332 leclose(struct open_file *f)
333 {
334 	LEWRCSR(LE_CSR0, LE_C0_STOP);
335 
336 	return 0;
337 }
338 
339 void
copyout(void * f,int dest,int len)340 copyout(void *f, int dest, int len)
341 {
342 	short *from = f;
343 	short *toaddr;
344 
345 	toaddr = (short *)0x20120000 + dest;
346 
347 	while (len > 0) {
348 		*toaddr = *from++;
349 		toaddr += 2;
350 		len -= 2;
351 	}
352 }
353 
354 void
copyin(int src,void * f,int len)355 copyin(int src, void *f, int len)
356 {
357 	short *to = f;
358 	short *fromaddr;
359 
360 	fromaddr = (short *)0x20120000 + src;
361 
362 	while (len > 0) {
363 		*to++ = *fromaddr;
364 		fromaddr += 2;
365 		len -= 2;
366 	}
367 }
368