xref: /netbsd-src/sys/arch/amiga/dev/if_le.c (revision d0fed6c87ddc40a8bffa6f99e7433ddfc864dd83)
1 /*	$NetBSD: if_le.c,v 1.26 1997/03/27 21:15:13 veego Exp $	*/
2 
3 /*-
4  * Copyright (c) 1997 Jason R. Thorpe and Bernd Ernesti.  All rights reserved.
5  * Copyright (c) 1995 Charles M. Hannum.  All rights reserved.
6  * Copyright (c) 1992, 1993
7  *	The Regents of the University of California.  All rights reserved.
8  *
9  * This code is derived from software contributed to Berkeley by
10  * Ralph Campbell and Rick Macklem.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:
22  *	This product includes software developed for the NetBSD Project
23  *	by Bernd Ernesti and Jason R. Thorpe.
24  *	This product includes software developed by the University of
25  *	California, Berkeley and its contributors.
26  * 4. Neither the name of the University nor the names of its contributors
27  *    may be used to endorse or promote products derived from this software
28  *    without specific prior written permission.
29  *
30  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40  * SUCH DAMAGE.
41  *
42  *	@(#)if_le.c	8.2 (Berkeley) 11/16/93
43  */
44 
45 #include "bpfilter.h"
46 
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/mbuf.h>
50 #include <sys/syslog.h>
51 #include <sys/socket.h>
52 #include <sys/device.h>
53 
54 #include <net/if.h>
55 #include <net/if_ether.h>
56 #include <net/if_media.h>
57 
58 #ifdef INET
59 #include <netinet/in.h>
60 #include <netinet/if_inarp.h>
61 #endif
62 
63 #include <machine/cpu.h>
64 #include <machine/mtpr.h>
65 
66 #include <amiga/amiga/device.h>
67 #include <amiga/amiga/isr.h>
68 
69 #include <dev/ic/am7990reg.h>
70 #include <dev/ic/am7990var.h>
71 
72 #include <amiga/dev/zbusvar.h>
73 #include <amiga/dev/if_levar.h>
74 
75 int le_zbus_match __P((struct device *, struct cfdata *, void *));
76 void le_zbus_attach __P((struct device *, struct device *, void *));
77 
78 struct cfattach le_zbus_ca = {
79 	sizeof(struct le_softc), le_zbus_match, le_zbus_attach
80 };
81 
82 hide void lepcnet_reset __P((struct am7990_softc *));
83 hide void lewrcsr __P((struct am7990_softc *, u_int16_t, u_int16_t));
84 hide u_int16_t lerdcsr __P((struct am7990_softc *, u_int16_t));
85 
86 hide u_int16_t ariadne_swapreg __P((u_int16_t));
87 hide void ariadne_wrcsr __P((struct am7990_softc *, u_int16_t, u_int16_t));
88 hide u_int16_t ariadne_rdcsr __P((struct am7990_softc *, u_int16_t));
89 hide void ariadne_wribcr __P((struct am7990_softc *, u_int16_t, u_int16_t));
90 integrate void ariadne_copytodesc_word __P((struct am7990_softc *, void *, int, int));
91 integrate void ariadne_copyfromdesc_word __P((struct am7990_softc *, void *, int, int));
92 integrate void ariadne_copytobuf_word __P((struct am7990_softc *, void *, int, int));
93 integrate void ariadne_copyfrombuf_word __P((struct am7990_softc *, void *, int, int));
94 integrate void ariadne_zerobuf_word __P((struct am7990_softc *, int, int));
95 void ariadne_autoselect __P((struct am7990_softc *, int));
96 int ariadne_mediachange __P((struct am7990_softc *));
97 void ariadne_hwinit __P((struct am7990_softc *));
98 
99 /*
100  * Media types supported by the Ariadne.
101  */
102 int lemedia_ariadne[] = {
103 	IFM_ETHER | IFM_10_T,
104 	IFM_ETHER | IFM_10_2,
105 	IFM_ETHER | IFM_AUTO,
106 };
107 #define NLEMEDIA_ARIADNE (sizeof(lemedia_ariadne) / sizeof(lemedia_ariadne[0]))
108 
109 
110 hide u_int16_t
111 ariadne_swapreg(val)
112 	u_int16_t val;
113 {
114 
115 	return (((val & 0xff) << 8 ) | (( val >> 8) & 0xff));
116 }
117 
118 hide void
119 ariadne_wrcsr(sc, port, val)
120 	struct am7990_softc *sc;
121 	u_int16_t port, val;
122 {
123 	struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1;
124 
125 	ler1->ler1_rap = ariadne_swapreg(port);
126 	ler1->ler1_rdp = ariadne_swapreg(val);
127 }
128 
129 hide u_int16_t
130 ariadne_rdcsr(sc, port)
131 	struct am7990_softc *sc;
132 	u_int16_t port;
133 {
134 	struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1;
135 	u_int16_t val;
136 
137 	ler1->ler1_rap = ariadne_swapreg(port);
138 	val = ariadne_swapreg(ler1->ler1_rdp);
139 	return (val);
140 }
141 
142 hide void
143 ariadne_wribcr(sc, port, val)
144 	struct am7990_softc *sc;
145 	u_int16_t port, val;
146 {
147 	struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1;
148 
149 	ler1->ler1_rap = ariadne_swapreg(port);
150 	ler1->ler1_idp = ariadne_swapreg(val);
151 }
152 
153 hide void
154 lewrcsr(sc, port, val)
155 	struct am7990_softc *sc;
156 	u_int16_t port, val;
157 {
158 	struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1;
159 
160 	ler1->ler1_rap = port;
161 	ler1->ler1_rdp = val;
162 }
163 
164 hide u_int16_t
165 lerdcsr(sc, port)
166 	struct am7990_softc *sc;
167 	u_int16_t port;
168 {
169 	struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1;
170 	u_int16_t val;
171 
172 	ler1->ler1_rap = port;
173 	val = ler1->ler1_rdp;
174 	return (val);
175 }
176 
177 hide void
178 lepcnet_reset(sc)
179 	struct am7990_softc *sc;
180 {
181 	struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1;
182 	volatile int dummy;
183 
184 	dummy = ler1->ler1_reset;	/* Reset PCNet-ISA */
185 }
186 
187 void
188 ariadne_autoselect(sc, on)
189 	struct am7990_softc *sc;
190 	int on;
191 {
192 
193 	/*
194 	 * on = 0: autoselect disabled
195 	 * on = 1: autoselect enabled
196 	 */
197 	if (on == 0)
198 		ariadne_wribcr(sc, LE_BCR_MC, 0x0000);
199 	else
200 		ariadne_wribcr(sc, LE_BCR_MC, LE_MC_ASEL);
201 }
202 
203 int
204 ariadne_mediachange(sc)
205 	struct am7990_softc *sc;
206 {
207 	struct ifmedia *ifm = &sc->sc_media;
208 
209 	if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
210 		return (EINVAL);
211 
212 	/*
213 	 * Switch to the selected media.  If autoselect is
214 	 * set, switch it on otherwise disable it.  We'll
215 	 * switch to the other media when we detect loss of
216 	 * carrier.
217 	 */
218 	switch (IFM_SUBTYPE(ifm->ifm_media)) {
219 	    case IFM_10_T:
220 		sc->sc_initmodemedia = 1;
221 		am7990_init(sc);
222 		break;
223 
224 	    case IFM_10_2:
225 		sc->sc_initmodemedia = 0;
226 		am7990_init(sc);
227 		break;
228 
229 	    case IFM_AUTO:
230 		sc->sc_initmodemedia = 2;
231 		ariadne_hwinit(sc);
232 		break;
233 
234 	    default:
235 		return (EINVAL);
236 	}
237 
238 	return (0);
239 }
240 
241 void
242 ariadne_hwinit(sc)
243 	struct am7990_softc *sc;
244 {
245 
246 	/*
247 	 * Re-program LEDs to match meaning used on the Ariadne board.
248          */
249 	ariadne_wribcr(sc, LE_BCR_LED1, 0x0090);
250 	ariadne_wribcr(sc, LE_BCR_LED2, 0x0081);
251 	ariadne_wribcr(sc, LE_BCR_LED3, 0x0084);
252 
253 	/*
254 	 * Enabel/Disable auto selection
255 	 */
256 	if (sc->sc_initmodemedia == 2)
257 		ariadne_autoselect(sc, 1);
258 	else
259 		ariadne_autoselect(sc, 0);
260 }
261 
262 int
263 le_zbus_match(parent, cfp, aux)
264 	struct device *parent;
265 	struct cfdata *cfp;
266 	void *aux;
267 {
268 	struct zbus_args *zap = aux;
269 
270 	/* Commodore ethernet card */
271 	if (zap->manid == 514 && zap->prodid == 112)
272 		return (1);
273 
274 	/* Ameristar ethernet card */
275 	if (zap->manid == 1053 && zap->prodid == 1)
276 		return (1);
277 
278 	/* Ariadne ethernet card */
279 	if (zap->manid == 2167 && zap->prodid == 201)
280 		return (1);
281 
282 	return (0);
283 }
284 
285 void
286 le_zbus_attach(parent, self, aux)
287 	struct device *parent, *self;
288 	void *aux;
289 {
290 	struct le_softc *lesc = (struct le_softc *)self;
291 	struct am7990_softc *sc = &lesc->sc_am7990;
292 	struct zbus_args *zap = aux;
293 	u_long ser;
294 
295 	/* This has no effect on PCnet-ISA LANCE chips */
296 	sc->sc_conf3 = LE_C3_BSWP;
297 
298 	/*
299 	 * Manufacturer decides the 3 first bytes, i.e. ethernet vendor ID.
300 	 */
301 	switch (zap->manid) {
302 	    case 514:
303 		/* Commodore */
304 		sc->sc_memsize = 32768;
305 		sc->sc_enaddr[0] = 0x00;
306 		sc->sc_enaddr[1] = 0x80;
307 		sc->sc_enaddr[2] = 0x10;
308 		lesc->sc_r1 = (struct lereg1 *)(0x4000 + (int)zap->va);
309 		sc->sc_mem = (void *)(0x8000 + (int)zap->va);
310 		sc->sc_addr = 0x8000;
311 		sc->sc_copytodesc = am7990_copytobuf_contig;
312 		sc->sc_copyfromdesc = am7990_copyfrombuf_contig;
313 		sc->sc_copytobuf = am7990_copytobuf_contig;
314 		sc->sc_copyfrombuf = am7990_copyfrombuf_contig;
315 		sc->sc_zerobuf = am7990_zerobuf_contig;
316 		sc->sc_rdcsr = lerdcsr;
317 		sc->sc_wrcsr = lewrcsr;
318 		sc->sc_hwreset = NULL;
319 		sc->sc_hwinit = NULL;
320 		break;
321 
322 	    case 1053:
323 		/* Ameristar */
324 		sc->sc_memsize = 32768;
325 		sc->sc_enaddr[0] = 0x00;
326 		sc->sc_enaddr[1] = 0x00;
327 		sc->sc_enaddr[2] = 0x9f;
328 		lesc->sc_r1 = (struct lereg1 *)(0x4000 + (int)zap->va);
329 		sc->sc_mem = (void *)(0x8000 + (int)zap->va);
330 		sc->sc_addr = 0x8000;
331 		sc->sc_copytodesc = am7990_copytobuf_contig;
332 		sc->sc_copyfromdesc = am7990_copyfrombuf_contig;
333 		sc->sc_copytobuf = am7990_copytobuf_contig;
334 		sc->sc_copyfrombuf = am7990_copyfrombuf_contig;
335 		sc->sc_zerobuf = am7990_zerobuf_contig;
336 		sc->sc_rdcsr = lerdcsr;
337 		sc->sc_wrcsr = lewrcsr;
338 		sc->sc_hwreset = NULL;
339 		sc->sc_hwinit = NULL;
340 		break;
341 
342 	    case 2167:
343 		/* Village Tronic */
344 		sc->sc_memsize = 32768;
345 		sc->sc_enaddr[0] = 0x00;
346 		sc->sc_enaddr[1] = 0x60;
347 		sc->sc_enaddr[2] = 0x30;
348 		lesc->sc_r1 = (struct lereg1 *)(0x0370 + (int)zap->va);
349 		sc->sc_mem = (void *)(0x8000 + (int)zap->va);
350 		sc->sc_addr = 0x8000;
351 		sc->sc_copytodesc = ariadne_copytodesc_word;
352 		sc->sc_copyfromdesc = ariadne_copyfromdesc_word;
353 		sc->sc_copytobuf = ariadne_copytobuf_word;
354 		sc->sc_copyfrombuf = ariadne_copyfrombuf_word;
355 		sc->sc_zerobuf = ariadne_zerobuf_word;
356 		sc->sc_rdcsr = ariadne_rdcsr;
357 		sc->sc_wrcsr = ariadne_wrcsr;
358 		sc->sc_hwreset = lepcnet_reset;
359 		sc->sc_hwinit = ariadne_hwinit;
360 		sc->sc_mediachange = ariadne_mediachange;
361 		sc->sc_supmedia = lemedia_ariadne;
362 		sc->sc_nsupmedia = NLEMEDIA_ARIADNE;
363 		sc->sc_defaultmedia = IFM_ETHER | IFM_AUTO;
364 		sc->sc_initmodemedia = 2;
365 		break;
366 
367 	    default:
368 		panic("le_zbus_attach: bad manid");
369 	}
370 
371 	/*
372 	 * Serial number for board is used as host ID.
373 	 */
374 	ser = (u_long)zap->serno;
375 	sc->sc_enaddr[3] = (ser >> 16) & 0xff;
376 	sc->sc_enaddr[4] = (ser >>  8) & 0xff;
377 	sc->sc_enaddr[5] = (ser      ) & 0xff;
378 
379 	am7990_config(sc);
380 
381 	lesc->sc_isr.isr_intr = am7990_intr;
382 	lesc->sc_isr.isr_arg = sc;
383 	lesc->sc_isr.isr_ipl = 2;
384 	add_isr(&lesc->sc_isr);
385 }
386 
387 
388 integrate void
389 ariadne_copytodesc_word(sc, from, boff, len)
390 	struct am7990_softc *sc;
391 	void *from;
392 	int boff, len;
393 {
394 	u_short *b1 = from;
395 	volatile u_short *b2 = sc->sc_mem + boff;
396 
397 	for (len >>= 1; len > 0; len--)
398 		*b2++ = ariadne_swapreg(*b1++);
399 }
400 
401 integrate void
402 ariadne_copyfromdesc_word(sc, to, boff, len)
403 	struct am7990_softc *sc;
404 	void *to;
405 	int boff, len;
406 {
407 	volatile u_short *b1 = sc->sc_mem + boff;
408 	u_short *b2 = to;
409 
410 	for (len >>= 1; len > 0; len--)
411 		*b2++ = ariadne_swapreg(*b1++);
412 }
413 
414 #define	isodd(n)	((n) & 1)
415 
416 integrate void
417 ariadne_copytobuf_word(sc, from, boff, len)
418 	struct am7990_softc *sc;
419 	void *from;
420 	int boff, len;
421 {
422 	u_char *a1 = from;
423 	volatile u_char *a2 = sc->sc_mem + boff;
424 	u_short *b1;
425 	volatile u_short *b2;
426 	int i;
427 
428 	if (len > 0 && isodd(boff)) {
429 		b1 = (u_short *)(a1 + 1);
430 		b2 = (u_short *)(a2 + 1);
431 		b2[-1] = (b2[-1] & 0xff00) | (b1[-1] & 0x00ff);
432 		--len;
433 	} else {
434 		b1 = (u_short *)a1;
435 		b2 = (u_short *)a2;
436 	}
437 
438 	for (i = len >> 1; i > 0; i--)
439 		*b2++ = *b1++;
440 
441 	if (isodd(len))
442 		*b2 = (*b2 & 0x00ff) | (*b1 & 0xff00);
443 }
444 
445 integrate void
446 ariadne_copyfrombuf_word(sc, to, boff, len)
447 	struct am7990_softc *sc;
448 	void *to;
449 	int boff, len;
450 {
451 	volatile u_char *a1 = sc->sc_mem + boff;
452 	u_char *a2 = to;
453 	volatile u_short *b1;
454 	u_short *b2;
455 	int i;
456 
457 	if (len > 0 && isodd(boff)) {
458 		b1 = (u_short *)(a1 + 1);
459 		b2 = (u_short *)(a2 + 1);
460 		b2[-1] = (b2[-1] & 0xff00) | (b1[-1] & 0x00ff);
461 		--len;
462 	} else {
463 		b1 = (u_short *)a1;
464 		b2 = (u_short *)a2;
465 	}
466 
467 	for (i = len >> 1; i > 0; i--)
468 		*b2++ = *b1++;
469 
470 	if (isodd(len))
471 		*b2 = (*b2 & 0x00ff) | (*b1 & 0xff00);
472 }
473 
474 integrate void
475 ariadne_zerobuf_word(sc, boff, len)
476 	struct am7990_softc *sc;
477 	int boff, len;
478 {
479 	volatile u_char *a1 = sc->sc_mem + boff;
480 	volatile u_short *b1;
481 	int i;
482 
483 	if (len > 0 && isodd(boff)) {
484 		b1 = (u_short *)(a1 + 1);
485 		b1[-1] &= 0xff00;
486 		--len;
487 	} else {
488 		b1 = (u_short *)a1;
489 	}
490 
491 	for (i = len >> 1; i > 0; i--)
492 		*b1++ = 0;
493 
494 	if (isodd(len))
495 		*b1 &= 0x00ff;
496 }
497