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