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