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