xref: /netbsd-src/sys/arch/luna68k/stand/boot/lance.c (revision e067b4e4e4a2aee9510843306e58a9a5714a094d)
1 /*	$NetBSD: lance.c,v 1.5 2021/12/05 03:04:41 msaitoh Exp $	*/
2 
3 /*
4  * Copyright (c) 2013 Izumi Tsutsui.  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  * Copyright (c) 2004 The NetBSD Foundation, Inc.
28  * All rights reserved.
29  *
30  * This code is derived from software contributed to The NetBSD Foundation
31  * by UCHIYAMA Yasushi.
32  *
33  * Redistribution and use in source and binary forms, with or without
34  * modification, are permitted provided that the following conditions
35  * are met:
36  * 1. Redistributions of source code must retain the above copyright
37  *    notice, this list of conditions and the following disclaimer.
38  * 2. Redistributions in binary form must reproduce the above copyright
39  *    notice, this list of conditions and the following disclaimer in the
40  *    documentation and/or other materials provided with the distribution.
41  *
42  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
43  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
44  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
45  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
46  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
47  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
48  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
49  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
50  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
52  * POSSIBILITY OF SUCH DAMAGE.
53  */
54 
55 /*
56  * LANCE driver for LUNA
57  * based on sys/arch/ews4800mips/stand/common/lance.c
58  */
59 
60 #include <lib/libsa/stand.h>
61 #include <lib/libkern/libkern.h>
62 
63 #include <dev/ic/am7990reg.h>
64 #include <dev/ic/lancereg.h>
65 
66 #include <luna68k/stand/boot/samachdep.h>
67 #include <luna68k/stand/boot/lance.h>
68 
69 static void lance_setup(struct le_softc *);
70 static bool lance_set_initblock(struct le_softc *);
71 static bool lance_do_initialize(struct le_softc *);
72 
73 #define NLE	1	/* XXX for now */
74 static struct le_softc lesc[NLE];
75 
76 void *
lance_attach(int unit,void * reg,void * mem,uint8_t * eaddr)77 lance_attach(int unit, void *reg, void *mem, uint8_t *eaddr)
78 {
79 	struct le_softc *sc;
80 
81 	if (unit >= NLE) {
82 		printf("%s: invalid unit number\n", __func__);
83 		return NULL;
84 	}
85 	sc = &lesc[unit];
86 
87 	if (sc->sc_reg != NULL) {
88 		printf("%s: unit %d is already attached\n", __func__, unit);
89 		return NULL;
90 	}
91 	sc->sc_reg = reg;
92 	sc->sc_mem = mem;
93 	memcpy(sc->sc_enaddr, eaddr, 6);
94 
95 	return sc;
96 }
97 
98 void *
lance_cookie(int unit)99 lance_cookie(int unit)
100 {
101 	struct le_softc *sc;
102 
103 	if (unit >= NLE)
104 		return NULL;
105 
106 	sc = &lesc[unit];
107 
108 	if (sc->sc_reg == NULL)
109 		return NULL;
110 
111 	return sc;
112 }
113 
114 uint8_t *
lance_eaddr(void * cookie)115 lance_eaddr(void *cookie)
116 {
117 	struct le_softc *sc = cookie;
118 
119 	if (sc == NULL || sc->sc_reg == NULL)
120 		return NULL;
121 
122 	return sc->sc_enaddr;
123 }
124 
125 bool
lance_init(void * cookie)126 lance_init(void *cookie)
127 {
128 	struct le_softc *sc = cookie;
129 
130 	lance_setup(sc);
131 
132 	if (!lance_set_initblock(sc))
133 		return false;
134 
135 	if (!lance_do_initialize(sc))
136 		return false;
137 
138 	return true;
139 }
140 
141 int
lance_get(void * cookie,void * data,size_t maxlen)142 lance_get(void *cookie, void *data, size_t maxlen)
143 {
144 	struct le_softc *sc = cookie;
145 	struct lereg *lereg = sc->sc_reg;
146 	struct lemem *lemem = sc->sc_mem;
147 	struct lermd_v *rmd;
148 	uint16_t csr __unused;
149 	int len = -1;
150 
151 	lereg->ler_rap = LE_CSR0;
152 	if ((lereg->ler_rdp & LE_C0_RINT) != 0)
153 		lereg->ler_rdp = LE_C0_RINT;
154 	rmd = &lemem->lem_rmd[sc->sc_currmd];
155 	if ((rmd->rmd1_bits & LE_R1_OWN) != 0)
156 		return -1;
157 
158 	csr = lereg->ler_rdp;
159 #if 0
160 	if ((csr & LE_C0_ERR) != 0)
161 		printf("%s: RX poll error (CSR=0x%x)\n", __func__, csr);
162 #endif
163 	if ((rmd->rmd1_bits & LE_R1_ERR) != 0) {
164 		printf("%s: RX error (rmd status=0x%x)\n", __func__,
165 		    rmd->rmd1_bits);
166 		goto out;
167 	}
168 
169 	len = rmd->rmd3;
170 	if (len < LEMINSIZE + 4 || len > LEMTU) {
171 		printf("%s: RX error (bad length %d)\n", __func__, len);
172 		goto out;
173 	}
174 	len -= 4;
175 	memcpy(data, (void *)lemem->lem_rbuf[sc->sc_currmd], uimin(len, maxlen));
176 
177  out:
178 	rmd->rmd2 = -LEMTU;
179 	rmd->rmd1_bits = LE_R1_OWN;	/* return to LANCE */
180 	sc->sc_currmd = LE_NEXTRMD(sc->sc_currmd);
181 
182 	return len;
183 }
184 
185 bool
lance_put(void * cookie,void * data,size_t len)186 lance_put(void *cookie, void *data, size_t len)
187 {
188 	struct le_softc *sc = cookie;
189 	struct lereg *lereg = sc->sc_reg;
190 	struct lemem *lemem = sc->sc_mem;
191 	struct letmd_v *tmd;
192 	uint16_t stat;
193 	int timeout;
194 
195 	lereg->ler_rap = LE_CSR0;
196 	stat = lereg->ler_rdp;
197 	lereg->ler_rdp =
198 	    stat & (LE_C0_BABL | LE_C0_CERR | LE_C0_MISS | LE_C0_TINT);
199 #if 0
200 	if (stat & (LE_C0_BABL | LE_C0_CERR | LE_C0_MISS | LE_C0_MERR))
201 		printf("%s: TX error before xmit csr0=0x%x\n",
202 		    __func__, stat);
203 #endif
204 
205 	/* setup TX descriptor */
206 	tmd = &lemem->lem_tmd[sc->sc_curtmd];
207 	while (tmd->tmd1_bits & LE_T1_OWN)
208 		continue;
209 	tmd->tmd1_bits = LE_T1_STP | LE_T1_ENP;
210 	memcpy((void *)lemem->lem_tbuf[sc->sc_curtmd], data, len);
211 	tmd->tmd2 = -uimax(len, LEMINSIZE);
212 	tmd->tmd3 = 0;
213 
214 	/* start TX */
215 	tmd->tmd1_bits |= LE_T1_OWN;
216 	lereg->ler_rap = LE_CSR0;
217 	lereg->ler_rdp = LE_C0_TDMD;
218 
219 	/* check TX complete */
220 	timeout = 0;
221 	do {
222 		lereg->ler_rap = LE_CSR0;
223 		stat = lereg->ler_rdp;
224 #if 0
225 		if (stat & LE_C0_ERR) {
226 			printf("%s: TX error (CSR0=%x)\n", __func__, stat);
227 			if (stat & LE_C0_CERR) {
228 				lereg->ler_rdp = LE_C0_CERR;
229 			}
230 		}
231 #endif
232 		if (timeout++ > 1000) {
233 			printf("%s: TX timeout (CSR0=%x)\n", __func__, stat);
234 			return false;
235 		}
236 	} while ((stat & LE_C0_TINT) == 0);
237 
238 	lereg->ler_rdp = LE_C0_TINT;
239 
240 	sc->sc_curtmd = LE_NEXTTMD(sc->sc_curtmd);
241 
242 	return true;
243 }
244 
245 bool
lance_end(void * cookie)246 lance_end(void *cookie)
247 {
248 	struct le_softc *sc = cookie;
249 	struct lereg *lereg = sc->sc_reg;
250 
251 	lereg->ler_rap = LE_CSR0;
252 	lereg->ler_rdp = LE_C0_STOP;
253 
254 	return true;
255 }
256 
257 /* XXX */
258 int
lance_intr(void)259 lance_intr(void)
260 {
261 
262 	return 1;
263 }
264 
265 static bool
lance_set_initblock(struct le_softc * sc)266 lance_set_initblock(struct le_softc *sc)
267 {
268 	struct lereg *lereg = sc->sc_reg;
269 	uint32_t addr = (uint32_t)sc->sc_mem;
270 
271 	lereg->ler_rap = LE_CSR0;
272 	lereg->ler_rdp = LE_C0_STOP;	/* disable all external activity */
273 	DELAY(100);
274 
275 	/* Set the correct byte swapping mode */
276 	lereg->ler_rap = LE_CSR3;
277 	lereg->ler_rdp = LE_C3_BSWP;
278 
279 	/* Low address of init block */
280 	lereg->ler_rap = LE_CSR1;
281 	lereg->ler_rdp = addr & 0xfffe;
282 
283 	/* High address of init block */
284 	lereg->ler_rap = LE_CSR2;
285 	lereg->ler_rdp = (addr >> 16) & 0x00ff;
286 	DELAY(100);
287 
288 	return true;
289 }
290 
291 static bool
lance_do_initialize(struct le_softc * sc)292 lance_do_initialize(struct le_softc *sc)
293 {
294 	struct lereg *lereg = sc->sc_reg;
295 	uint16_t reg;
296 	int timeout;
297 
298 	sc->sc_curtmd = 0;
299 	sc->sc_currmd = 0;
300 
301 	/* Initialize LANCE */
302 	lereg->ler_rap = LE_CSR0;
303 	lereg->ler_rdp = LE_C0_INIT;
304 
305 	/* Wait interrupt */
306 	timeout = 1000000;
307 	do {
308 		lereg->ler_rap = LE_CSR0;
309 		reg = lereg->ler_rdp;
310 		if (--timeout == 0) {
311 			printf("le: init timeout (CSR=0x%x)\n", reg);
312 			return false;
313 		}
314 		DELAY(1);
315 	} while ((reg & LE_C0_IDON) == 0);
316 
317 	lereg->ler_rap = LE_CSR0;
318 	lereg->ler_rdp = LE_C0_STRT | LE_C0_IDON;
319 
320 	return true;
321 }
322 
323 static void
lance_setup(struct le_softc * sc)324 lance_setup(struct le_softc *sc)
325 {
326 	struct lereg *lereg = sc->sc_reg;
327 	struct lemem *lemem = sc->sc_mem;
328 	uint32_t addr;
329 	int i;
330 
331 	/* make sure to stop LANCE chip before setup memory */
332 	lereg->ler_rap = LE_CSR0;
333 	lereg->ler_rdp = LE_C0_STOP;
334 
335 	memset(lemem, 0, sizeof *lemem);
336 
337 	/* Init block */
338 	lemem->lem_mode = LE_MODE_NORMAL;
339 	lemem->lem_padr[0] = (sc->sc_enaddr[1] << 8) | sc->sc_enaddr[0];
340 	lemem->lem_padr[1] = (sc->sc_enaddr[3] << 8) | sc->sc_enaddr[2];
341 	lemem->lem_padr[2] = (sc->sc_enaddr[5] << 8) | sc->sc_enaddr[4];
342 	/* Logical address filter */
343 	for (i = 0; i < 4; i++)
344 		lemem->lem_ladrf[i] = 0x0000;
345 
346 	/* Location of Rx descriptor ring */
347 	addr = (uint32_t)lemem->lem_rmd;
348 	lemem->lem_rdra = addr & 0xffff;
349 	lemem->lem_rlen = LE_RLEN | ((addr >> 16) & 0xff);
350 
351 	/* Location of Tx descriptor ring */
352 	addr = (uint32_t)lemem->lem_tmd;
353 	lemem->lem_tdra = addr & 0xffff;
354 	lemem->lem_tlen = LE_TLEN | ((addr >> 16) & 0xff);
355 
356 	/* Rx descriptor */
357 	for (i = 0; i < LERBUF; i++) {
358 		addr = (uint32_t)lemem->lem_rbuf[i];
359 		lemem->lem_rmd[i].rmd0 = addr & 0xffff;
360 		lemem->lem_rmd[i].rmd1_hadr = (addr >> 16) & 0xff;
361 		lemem->lem_rmd[i].rmd1_bits = LE_R1_OWN;
362 		lemem->lem_rmd[i].rmd2 = LE_XMD2_ONES | -LEMTU;
363 		lemem->lem_rmd[i].rmd3 = 0;
364 	}
365 
366 	/* Tx descriptor */
367 	for (i = 0; i < LETBUF; i++) {
368 		addr = (uint32_t)lemem->lem_tbuf[i];
369 		lemem->lem_tmd[i].tmd0 = addr & 0xffff;
370 		lemem->lem_tmd[i].tmd1_hadr = (addr >> 16) & 0xff;
371 		lemem->lem_tmd[i].tmd1_bits = 0;
372 		lemem->lem_tmd[i].tmd2 = LE_XMD2_ONES | 0;
373 		lemem->lem_tmd[i].tmd3 = 0;
374 	}
375 }
376