xref: /netbsd-src/sys/arch/mac68k/nubus/if_ae_nubus.c (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
1 /*	$NetBSD: if_ae_nubus.c,v 1.41 2009/01/16 23:43:46 tsutsui Exp $	*/
2 
3 /*
4  * Copyright (C) 1997 Scott Reynolds
5  * 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  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 /*
30  * Some parts are derived from code adapted for MacBSD by Brad Parker
31  * <brad@fcr.com>.
32  *
33  * Currently supports:
34  *	Apple NB Ethernet Card
35  *	Apple NB Ethernet Card II
36  *	Interlan A310 NuBus Ethernet card
37  *	Cayman Systems GatorCard
38  *	Asante MacCon II/E
39  *	Kinetics EtherPort SE/30
40  */
41 
42 #include <sys/cdefs.h>
43 __KERNEL_RCSID(0, "$NetBSD: if_ae_nubus.c,v 1.41 2009/01/16 23:43:46 tsutsui Exp $");
44 
45 #include <sys/param.h>
46 #include <sys/device.h>
47 #include <sys/errno.h>
48 #include <sys/ioctl.h>
49 #include <sys/malloc.h>
50 #include <sys/socket.h>
51 #include <sys/syslog.h>
52 #include <sys/systm.h>
53 
54 #include <net/if.h>
55 #include <net/if_media.h>
56 #include <net/if_ether.h>
57 
58 #include <machine/bus.h>
59 #include <machine/viareg.h>
60 
61 #include <dev/ic/dp8390reg.h>
62 #include <dev/ic/dp8390var.h>
63 #include <mac68k/nubus/nubus.h>
64 #include <mac68k/dev/if_aevar.h>
65 #include <mac68k/dev/if_aereg.h>
66 
67 static int	ae_nubus_match(device_t, cfdata_t, void *);
68 static void	ae_nubus_attach(device_t, device_t, void *);
69 static int	ae_nb_card_vendor(bus_space_tag_t, bus_space_handle_t,
70 		    struct nubus_attach_args *);
71 static int	ae_nb_get_enaddr(bus_space_tag_t, bus_space_handle_t,
72 		    struct nubus_attach_args *, u_int8_t *);
73 #ifdef DEBUG
74 static void	ae_nb_watchdog(struct ifnet *);
75 #endif
76 
77 void		ae_nubus_intr(void *);
78 
79 CFATTACH_DECL_NEW(ae_nubus, sizeof(struct dp8390_softc),
80     ae_nubus_match, ae_nubus_attach, NULL, NULL);
81 
82 static int
83 ae_nubus_match(device_t parent, cfdata_t cf, void *aux)
84 {
85 	struct nubus_attach_args *na = aux;
86 	bus_space_handle_t bsh;
87 	int rv;
88 
89 	if (bus_space_map(na->na_tag, NUBUS_SLOT2PA(na->slot), NBMEMSIZE,
90 	    0, &bsh))
91 		return (0);
92 
93 	rv = 0;
94 
95 	if (na->category == NUBUS_CATEGORY_NETWORK &&
96 	    na->type == NUBUS_TYPE_ETHERNET) {
97 		switch (ae_nb_card_vendor(na->na_tag, bsh, na)) {
98 		case DP8390_VENDOR_APPLE:
99 		case DP8390_VENDOR_ASANTE:
100 		case DP8390_VENDOR_FARALLON:
101 		case DP8390_VENDOR_INTERLAN:
102 		case DP8390_VENDOR_KINETICS:
103 		case DP8390_VENDOR_CABLETRON:
104 			rv = 1;
105 			break;
106 		case DP8390_VENDOR_DAYNA:
107 			rv = UNSUPP;
108 			break;
109 		default:
110 			break;
111 		}
112 	}
113 
114 	bus_space_unmap(na->na_tag, bsh, NBMEMSIZE);
115 
116 	return rv;
117 }
118 
119 /*
120  * Install interface into kernel networking data structures
121  */
122 static void
123 ae_nubus_attach(device_t parent, device_t self, void *aux)
124 {
125 	struct dp8390_softc *sc = device_private(self);
126 	struct nubus_attach_args *na = aux;
127 #ifdef DEBUG
128 	struct ifnet *ifp = &sc->sc_ec.ec_if;
129 #endif
130 	bus_space_tag_t bst;
131 	bus_space_handle_t bsh;
132 	int i, success;
133 	const char *cardtype;
134 
135 	sc->sc_dev = self;
136 	bst = na->na_tag;
137 	if (bus_space_map(bst, NUBUS_SLOT2PA(na->slot), NBMEMSIZE,
138 	    0, &bsh)) {
139 		aprint_error(": can't map memory space\n");
140 		return;
141 	}
142 
143 	sc->sc_regt = sc->sc_buft = bst;
144 	sc->sc_flags = device_cfdata(self)->cf_flags;
145 
146 	cardtype = nubus_get_card_name(bst, bsh, na->fmt);
147 
148 	sc->is790 = 0;
149 
150 	sc->mem_start = 0;
151 	sc->mem_size = 0;
152 
153 	success = 0;
154 
155 	switch (ae_nb_card_vendor(bst, bsh, na)) {
156 	case DP8390_VENDOR_APPLE:	/* Apple-compatible cards */
157 	case DP8390_VENDOR_ASANTE:
158 		/* Map register offsets */
159 		for (i = 0; i < 16; i++) /* reverse order, longword aligned */
160 			sc->sc_reg_map[i] = (15 - i) << 2;
161 
162 		sc->dcr_reg = (ED_DCR_FT1 | ED_DCR_WTS | ED_DCR_LS);
163 		if (bus_space_subregion(bst, bsh,
164 		    AE_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) {
165 			aprint_error(": failed to map register space\n");
166 			break;
167 		}
168 		if ((sc->mem_size = ae_size_card_memory(bst, bsh,
169 		    AE_DATA_OFFSET)) == 0) {
170 			aprint_error(": failed to determine size of RAM.\n");
171 			break;
172 		}
173 		if (bus_space_subregion(bst, bsh,
174 		    AE_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) {
175 			aprint_error(": failed to map register space\n");
176 			break;
177 		}
178 #ifdef AE_OLD_GET_ENADDR
179 		/* Get station address from on-board ROM */
180 		for (i = 0; i < ETHER_ADDR_LEN; ++i)
181 			sc->sc_enaddr[i] =
182 			    bus_space_read_1(bst, bsh, (AE_ROM_OFFSET + i * 2));
183 #else
184 		if (ae_nb_get_enaddr(bst, bsh, na, sc->sc_enaddr)) {
185 			aprint_error(": can't find MAC address\n");
186 			break;
187 		}
188 #endif
189 
190 		success = 1;
191 		break;
192 
193 	case DP8390_VENDOR_DAYNA:
194 		/* Map register offsets */
195 		for (i = 0; i < 16; i++) /* normal order, longword aligned */
196 			sc->sc_reg_map[i] = i << 2;
197 
198 		sc->dcr_reg = (ED_DCR_FT1 | ED_DCR_WTS | ED_DCR_LS);
199 		if (bus_space_subregion(bst, bsh,
200 		    DP_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) {
201 			aprint_error(": failed to map register space\n");
202 			break;
203 		}
204 		sc->mem_size = 8192;
205 		if (bus_space_subregion(bst, bsh,
206 		    DP_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) {
207 			aprint_error(": failed to map register space\n");
208 			break;
209 		}
210 #ifdef AE_OLD_GET_ENADDR
211 		/* Get station address from on-board ROM */
212 		for (i = 0; i < ETHER_ADDR_LEN; ++i)
213 			sc->sc_enaddr[i] =
214 			    bus_space_read_1(bst, bsh, (DP_ROM_OFFSET + i * 2));
215 #else
216 		if (ae_nb_get_enaddr(bst, bsh, na, sc->sc_enaddr)) {
217 			aprint_error(": can't find MAC address\n");
218 			break;
219 		}
220 #endif
221 
222 		aprint_error(": unsupported Dayna hardware\n");
223 		break;
224 
225 	case DP8390_VENDOR_FARALLON:
226 		/* Map register offsets */
227 		for (i = 0; i < 16; i++) /* reverse order, longword aligned */
228 			sc->sc_reg_map[i] = (15 - i) << 2;
229 
230 		sc->dcr_reg = (ED_DCR_FT1 | ED_DCR_WTS | ED_DCR_LS);
231 		if (bus_space_subregion(bst, bsh,
232 		    AE_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) {
233 			aprint_error(": failed to map register space\n");
234 			break;
235 		}
236 		if ((sc->mem_size = ae_size_card_memory(bst, bsh,
237 		    AE_DATA_OFFSET)) == 0) {
238 			aprint_error(": failed to determine size of RAM.\n");
239 			break;
240 		}
241 		if (bus_space_subregion(bst, bsh,
242 		    AE_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) {
243 			aprint_error(": failed to map register space\n");
244 			break;
245 		}
246 #ifdef AE_OLD_GET_ENADDR
247 		/* Get station address from on-board ROM */
248 		for (i = 0; i < ETHER_ADDR_LEN; ++i)
249 			sc->sc_enaddr[i] =
250 			    bus_space_read_1(bst, bsh, (FE_ROM_OFFSET + i));
251 #else
252 		if (ae_nb_get_enaddr(bst, bsh, na, sc->sc_enaddr)) {
253 			aprint_error(": can't find MAC address\n");
254 			break;
255 		}
256 #endif
257 
258 		success = 1;
259 		break;
260 
261 	case DP8390_VENDOR_INTERLAN:
262 		/* Map register offsets */
263 		for (i = 0; i < 16; i++) /* normal order, longword aligned */
264 			sc->sc_reg_map[i] = i << 2;
265 
266 		sc->dcr_reg = (ED_DCR_FT1 | ED_DCR_WTS | ED_DCR_LS);
267 		if (bus_space_subregion(bst, bsh,
268 		    GC_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) {
269 			aprint_error(": failed to map register space\n");
270 			break;
271 		}
272 		if ((sc->mem_size = ae_size_card_memory(bst, bsh,
273 		    GC_DATA_OFFSET)) == 0) {
274 			aprint_error(": failed to determine size of RAM.\n");
275 			break;
276 		}
277 		if (bus_space_subregion(bst, bsh,
278 		    GC_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) {
279 			aprint_error(": failed to map register space\n");
280 			break;
281 		}
282 
283 		/* reset the NIC chip */
284 		bus_space_write_1(bst, bsh, GC_RESET_OFFSET, 0);
285 
286 		if (ae_nb_get_enaddr(bst, bsh, na, sc->sc_enaddr)) {
287 			/* Fall back to snarf directly from ROM.  Ick. */
288 			for (i = 0; i < ETHER_ADDR_LEN; ++i)
289 				sc->sc_enaddr[i] =
290 				    bus_space_read_1(bst, bsh,
291 				    (GC_ROM_OFFSET + i * 4));
292 		}
293 
294 		success = 1;
295 		break;
296 
297 	case DP8390_VENDOR_KINETICS:
298 		/* Map register offsets */
299 		for (i = 0; i < 16; i++) /* normal order, longword aligned */
300 			sc->sc_reg_map[i] = i << 2;
301 
302 		if (bus_space_subregion(bst, bsh,
303 		    KE_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) {
304 			aprint_error(": failed to map register space\n");
305 			break;
306 		}
307 		if ((sc->mem_size = ae_size_card_memory(bst, bsh,
308 		    KE_DATA_OFFSET)) == 0) {
309 			aprint_error(": failed to determine size of RAM.\n");
310 			break;
311 		}
312 		if (bus_space_subregion(bst, bsh,
313 		    KE_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) {
314 			aprint_error(": failed to map register space\n");
315 			break;
316 		}
317 		if (ae_nb_get_enaddr(bst, bsh, na, sc->sc_enaddr)) {
318 			aprint_error(": can't find MAC address\n");
319 			break;
320 		}
321 
322 		success = 1;
323 		break;
324 
325 	case DP8390_VENDOR_CABLETRON:
326 		/* Map register offsets */
327 		for (i = 0; i < 16; i++)
328   			sc->sc_reg_map[i] =  i << 1 ;  /* normal order, word aligned */
329   		sc->dcr_reg = (ED_DCR_FT1 | ED_DCR_WTS | ED_DCR_LS);
330 		if (bus_space_subregion(bst, bsh,
331 		    CT_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) {
332 			aprint_error(": failed to map register space\n");
333 			break;
334 		}
335 		if ((sc->mem_size = ae_size_card_memory(bst, bsh,
336 		    CT_DATA_OFFSET)) == 0) {
337 			aprint_error(": failed to determine size of RAM.\n");
338 			break;
339 		}
340 		if (bus_space_subregion(bst, bsh,
341 		    CT_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) {
342 			aprint_error(": failed to map register space\n");
343 			break;
344 		}
345 		if (ae_nb_get_enaddr(bst, bsh, na, sc->sc_enaddr)) {
346 			aprint_error(": can't find MAC address\n");
347 			break;
348 		}
349 		success = 1;
350 		break;
351 	default:
352 		break;
353 	}
354 
355 	if (!success) {
356 		bus_space_unmap(bst, bsh, NBMEMSIZE);
357 		return;
358 	}
359 
360 	/*
361 	 * Override test_mem and write_mbuf functions; other defaults
362 	 * already work properly.
363 	 */
364 	sc->test_mem = ae_test_mem;
365 	sc->write_mbuf = ae_write_mbuf;
366 #ifdef DEBUG
367 	ifp->if_watchdog = ae_nb_watchdog;	/* Override watchdog */
368 #endif
369 	sc->sc_media_init = dp8390_media_init;
370 
371 	/* Interface is always enabled. */
372 	sc->sc_enabled = 1;
373 
374 	aprint_normal(": %s, %dKB memory\n", cardtype, sc->mem_size / 1024);
375 
376 	if (dp8390_config(sc)) {
377 		bus_space_unmap(bst, bsh, NBMEMSIZE);
378 		return;
379 	}
380 
381 	/* make sure interrupts are vectored to us */
382 	add_nubus_intr(na->slot, ae_nubus_intr, sc);
383 }
384 
385 void
386 ae_nubus_intr(void *arg)
387 {
388 	struct dp8390_softc *sc = arg;
389 
390 	(void)dp8390_intr(sc);
391 }
392 
393 static int
394 ae_nb_card_vendor(bus_space_tag_t bst, bus_space_handle_t bsh,
395     struct nubus_attach_args *na)
396 {
397 	int vendor;
398 
399 	switch (na->drsw) {
400 	case NUBUS_DRSW_3COM:
401 		switch (na->drhw) {
402 		case NUBUS_DRHW_APPLE_SN:
403 		case NUBUS_DRHW_APPLE_SNT:
404 			vendor = DP8390_VENDOR_UNKNOWN;
405 			break;
406 		default:
407 			vendor = DP8390_VENDOR_APPLE;
408 			break;
409 		}
410 		break;
411 	case NUBUS_DRSW_APPLE:
412 		if (na->drhw == NUBUS_DRHW_ASANTE_LC) {
413 			vendor = DP8390_VENDOR_UNKNOWN;
414 			break;
415 		}
416 		/* FALLTHROUGH */
417 	case NUBUS_DRSW_DAYNA2:
418 	case NUBUS_DRSW_TECHWORKS:
419 	case NUBUS_DRSW_TFLLAN:
420 		if (na->drhw == NUBUS_DRHW_CABLETRON) {
421 			vendor = DP8390_VENDOR_CABLETRON;
422 		} else {
423 			vendor = DP8390_VENDOR_APPLE;
424 		}
425 		break;
426 	case NUBUS_DRSW_ASANTE:
427 		vendor = DP8390_VENDOR_ASANTE;
428 		break;
429 	case NUBUS_DRSW_FARALLON:
430 		vendor = DP8390_VENDOR_FARALLON;
431 		break;
432 	case NUBUS_DRSW_GATOR:
433 		switch (na->drhw) {
434 		default:
435 		case NUBUS_DRHW_INTERLAN:
436 			vendor = DP8390_VENDOR_INTERLAN;
437 			break;
438 		case NUBUS_DRHW_KINETICS:
439 			if (strncmp(nubus_get_card_name(bst, bsh, na->fmt),
440 			    "EtherPort", 9) == 0)
441 				vendor = DP8390_VENDOR_KINETICS;
442 			else
443 				vendor = DP8390_VENDOR_DAYNA;
444 			break;
445 		}
446 		break;
447 	default:
448 		vendor = DP8390_VENDOR_UNKNOWN;
449 	}
450 	return vendor;
451 }
452 
453 static int
454 ae_nb_get_enaddr(bus_space_tag_t bst, bus_space_handle_t bsh,
455     struct nubus_attach_args *na, u_int8_t *ep)
456 {
457 	nubus_dir dir;
458 	nubus_dirent dirent;
459 	int rv;
460 
461 	/*
462 	 * XXX - note hardwired resource IDs here; these are assumed to
463 	 * be used by all cards, but should be fixed when we find out
464 	 * more about Ethernet card resources.
465 	 */
466 	nubus_get_main_dir(na->fmt, &dir);
467 	switch (ae_nb_card_vendor(bst, bsh, na)) {
468 	case DP8390_VENDOR_APPLE:
469 		if (na->drsw == NUBUS_DRSW_TFLLAN) {	/* TFL LAN E410/E420 */
470 			rv = nubus_find_rsrc(bst, bsh, na->fmt,
471 			    &dir, 0x08, &dirent);
472 			break;
473 		}
474 		/*FALLTHROUGH*/
475 	default:
476 		rv = nubus_find_rsrc(bst, bsh, na->fmt, &dir, 0x80, &dirent);
477 		break;
478 	}
479 	if (rv <= 0)
480 		return 1;
481 	nubus_get_dir_from_rsrc(na->fmt, &dirent, &dir);
482 	if (nubus_find_rsrc(bst, bsh, na->fmt, &dir, 0x80, &dirent) <= 0)
483 		return 1;
484 	if (nubus_get_ind_data(bst, bsh,
485 	    na->fmt, &dirent, ep, ETHER_ADDR_LEN) <= 0)
486 		return 1;
487 
488 	return 0;
489 }
490 
491 #ifdef DEBUG
492 static void
493 ae_nb_watchdog(struct ifnet *ifp)
494 {
495 	struct dp8390_softc *sc = ifp->if_softc;
496 
497 /*
498  * This is a kludge!  The via code seems to miss slot interrupts
499  * sometimes.  This kludges around that by calling the handler
500  * by hand if the watchdog is activated. -- XXX (akb)
501  */
502 	(*via2itab[1])((void *)1);
503 
504 	log(LOG_ERR, "%s: device timeout\n", device_xname(sc->sc_dev));
505 	++ifp->if_oerrors;
506 
507 	dp8390_reset(sc);
508 }
509 #endif
510