if_ae_nubus.c revision 1.12 1 /* $NetBSD: if_ae_nubus.c,v 1.12 1997/04/10 03:19:46 briggs 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. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Scott Reynolds for
18 * the NetBSD Project.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33 /*
34 * Some parts are derived from code adapted for MacBSD by Brad Parker
35 * <brad (at) fcr.com>.
36 *
37 * Currently supports:
38 * Apple NB Ethernet Card
39 * Apple NB Ethernet Card II
40 * Interlan A310 NuBus Ethernet card
41 * Cayman Systems GatorCard
42 * Asante MacCon II/E
43 * Kinetics EtherPort SE/30
44 */
45
46 #include <sys/param.h>
47 #include <sys/device.h>
48 #include <sys/errno.h>
49 #include <sys/ioctl.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_ether.h>
56
57 #ifdef INET
58 #include <netinet/in.h>
59 #include <netinet/if_inarp.h>
60 #endif
61
62 #include <machine/bus.h>
63 #include <machine/viareg.h>
64
65 #include "nubus.h"
66 #include <dev/ic/dp8390reg.h>
67 #include "if_aereg.h"
68 #include "if_aevar.h"
69
70 static int ae_nubus_match __P((struct device *, struct cfdata *, void *));
71 static void ae_nubus_attach __P((struct device *, struct device *, void *));
72 static int ae_nb_card_vendor __P((struct nubus_attach_args *));
73 static int ae_nb_get_enaddr __P((struct nubus_attach_args *, u_int8_t *));
74 #ifdef DEBUG
75 static void ae_nb_watchdog __P((struct ifnet *));
76 #endif
77
78 struct cfattach ae_nubus_ca = {
79 sizeof(struct ae_softc), ae_nubus_match, ae_nubus_attach
80 };
81
82 static int
83 ae_nubus_match(parent, cf, aux)
84 struct device *parent;
85 struct cfdata *cf;
86 void *aux;
87 {
88 struct nubus_attach_args *na = (struct nubus_attach_args *) aux;
89 bus_space_handle_t bsh;
90 int rv;
91
92 if (bus_space_map(na->na_tag, NUBUS_SLOT2PA(na->slot), NBMEMSIZE,
93 0, &bsh))
94 return (0);
95
96 rv = 0;
97
98 if (na->category == NUBUS_CATEGORY_NETWORK &&
99 na->type == NUBUS_TYPE_ETHERNET) {
100 switch (ae_nb_card_vendor(na)) {
101 case AE_VENDOR_APPLE:
102 case AE_VENDOR_ASANTE:
103 case AE_VENDOR_FARALLON:
104 case AE_VENDOR_INTERLAN:
105 case AE_VENDOR_KINETICS:
106 rv = 1;
107 break;
108 case AE_VENDOR_DAYNA:
109 case AE_VENDOR_FOCUS:
110 rv = UNSUPP;
111 break;
112 default:
113 break;
114 }
115 }
116
117 bus_space_unmap(na->na_tag, bsh, NBMEMSIZE);
118
119 return rv;
120 }
121
122 /*
123 * Install interface into kernel networking data structures
124 */
125 static void
126 ae_nubus_attach(parent, self, aux)
127 struct device *parent, *self;
128 void *aux;
129 {
130 struct ae_softc *sc = (struct ae_softc *) self;
131 struct nubus_attach_args *na = (struct nubus_attach_args *) aux;
132 #ifdef DEBUG
133 struct ifnet *ifp = &sc->sc_ec.ec_if;
134 #endif
135 bus_space_tag_t bst;
136 bus_space_handle_t bsh;
137 int i, success;
138 u_int8_t myaddr[ETHER_ADDR_LEN];
139
140 bst = na->na_tag;
141 if (bus_space_map(bst, NUBUS_SLOT2PA(na->slot), NBMEMSIZE,
142 0, &bsh)) {
143 printf(": can't map memory space\n");
144 return;
145 }
146
147 sc->sc_regt = sc->sc_buft = bst;
148 sc->sc_flags = self->dv_cfdata->cf_flags;
149 sc->use16bit = 1;
150 sc->vendor = ae_nb_card_vendor(na);
151 strncpy(sc->type_str, nubus_get_card_name(na->fmt),
152 INTERFACE_NAME_LEN);
153 sc->type_str[INTERFACE_NAME_LEN-1] = '\0';
154 sc->mem_size = 0;
155
156 success = 0;
157
158 switch (sc->vendor) {
159 case AE_VENDOR_APPLE: /* Apple-compatible cards */
160 case AE_VENDOR_ASANTE:
161 /* Map register offsets */
162 for (i = 0; i < 16; i++) /* reverse order, longword aligned */
163 sc->sc_reg_map[i] = (15 - i) << 2;
164
165 if (bus_space_subregion(bst, bsh,
166 AE_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) {
167 printf(": failed to map register space\n");
168 break;
169 }
170 if ((sc->mem_size = ae_size_card_memory(bst, bsh,
171 AE_DATA_OFFSET)) == 0) {
172 printf(": failed to determine size of RAM.\n");
173 break;
174 }
175 if (bus_space_subregion(bst, bsh,
176 AE_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) {
177 printf(": failed to map register space\n");
178 break;
179 }
180 #ifdef AE_OLD_GET_ENADDR
181 /* Get station address from on-board ROM */
182 for (i = 0; i < ETHER_ADDR_LEN; ++i)
183 myaddr[i] =
184 bus_space_read_1(bst, bsh, (AE_ROM_OFFSET + i * 2));
185 #else
186 if (ae_nb_get_enaddr(na, myaddr)) {
187 printf(": can't find MAC address\n");
188 break;
189 }
190 #endif
191
192 success = 1;
193 break;
194
195 case AE_VENDOR_DAYNA:
196 /* Map register offsets */
197 for (i = 0; i < 16; i++) /* normal order, longword aligned */
198 sc->sc_reg_map[i] = i << 2;
199
200 if (bus_space_subregion(bst, bsh,
201 DP_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) {
202 printf(": failed to map register space\n");
203 break;
204 }
205 sc->mem_size = 8192;
206 if (bus_space_subregion(bst, bsh,
207 DP_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) {
208 printf(": failed to map register space\n");
209 break;
210 }
211 #ifdef AE_OLD_GET_ENADDR
212 /* Get station address from on-board ROM */
213 for (i = 0; i < ETHER_ADDR_LEN; ++i)
214 myaddr[i] =
215 bus_space_read_1(bst, bsh, (DP_ROM_OFFSET + i * 2));
216 #else
217 if (ae_nb_get_enaddr(na, myaddr)) {
218 printf(": can't find MAC address\n");
219 break;
220 }
221 #endif
222
223 printf(": unsupported Dayna hardware\n");
224 break;
225
226 case AE_VENDOR_FARALLON:
227 /* Map register offsets */
228 for (i = 0; i < 16; i++) /* reverse order, longword aligned */
229 sc->sc_reg_map[i] = (15 - i) << 2;
230
231 if (bus_space_subregion(bst, bsh,
232 AE_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) {
233 printf(": 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 printf(": 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 printf(": 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 myaddr[i] =
250 bus_space_read_1(bst, bsh, (FE_ROM_OFFSET + i));
251 #else
252 if (ae_nb_get_enaddr(na, myaddr)) {
253 printf(": can't find MAC address\n");
254 break;
255 }
256 #endif
257
258 success = 1;
259 break;
260
261 case AE_VENDOR_FOCUS:
262 printf(": unsupported Focus hardware\n");
263 break;
264
265 case AE_VENDOR_INTERLAN:
266 /* Map register offsets */
267 for (i = 0; i < 16; i++) /* normal order, longword aligned */
268 sc->sc_reg_map[i] = i << 2;
269
270 if (bus_space_subregion(bst, bsh,
271 GC_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) {
272 printf(": failed to map register space\n");
273 break;
274 }
275 if ((sc->mem_size = ae_size_card_memory(bst, bsh,
276 GC_DATA_OFFSET)) == 0) {
277 printf(": failed to determine size of RAM.\n");
278 break;
279 }
280 if (bus_space_subregion(bst, bsh,
281 GC_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) {
282 printf(": failed to map register space\n");
283 break;
284 }
285
286 /* reset the NIC chip */
287 bus_space_write_1(bst, bsh, GC_RESET_OFFSET, 0);
288
289 if (ae_nb_get_enaddr(na, myaddr)) {
290 /* Fall back to snarf directly from ROM. Ick. */
291 for (i = 0; i < ETHER_ADDR_LEN; ++i)
292 myaddr[i] =
293 bus_space_read_1(bst, bsh,
294 (GC_ROM_OFFSET + i * 4));
295 }
296
297 success = 1;
298 break;
299
300 case AE_VENDOR_KINETICS:
301 /* Map register offsets */
302 for (i = 0; i < 16; i++) /* normal order, longword aligned */
303 sc->sc_reg_map[i] = i << 2;
304
305 sc->use16bit = 0;
306 if (bus_space_subregion(bst, bsh,
307 KE_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) {
308 printf(": failed to map register space\n");
309 break;
310 }
311 if ((sc->mem_size = ae_size_card_memory(bst, bsh,
312 KE_DATA_OFFSET)) == 0) {
313 printf(": failed to determine size of RAM.\n");
314 break;
315 }
316 if (bus_space_subregion(bst, bsh,
317 KE_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) {
318 printf(": failed to map register space\n");
319 break;
320 }
321 if (ae_nb_get_enaddr(na, myaddr)) {
322 printf(": can't find MAC address\n");
323 break;
324 }
325
326 success = 1;
327 break;
328
329 default:
330 break;
331 }
332
333 if (!success) {
334 bus_space_unmap(bst, bsh, NBMEMSIZE);
335 return;
336 }
337
338 #ifdef DEBUG
339 ifp->if_watchdog = ae_nb_watchdog; /* Override watchdog */
340 #endif
341 if (aesetup(sc, myaddr)) {
342 bus_space_unmap(bst, bsh, NBMEMSIZE);
343 return;
344 }
345
346 /* make sure interrupts are vectored to us */
347 add_nubus_intr(na->slot, aeintr, sc);
348 }
349
350 static int
351 ae_nb_card_vendor(na)
352 struct nubus_attach_args *na;
353 {
354 int vendor;
355
356 switch (na->drsw) {
357 case NUBUS_DRSW_3COM:
358 switch (na->drhw) {
359 case NUBUS_DRHW_APPLE_SN:
360 vendor = AE_VENDOR_UNKNOWN;
361 break;
362 default:
363 vendor = AE_VENDOR_APPLE;
364 break;
365 }
366 break;
367 case NUBUS_DRSW_APPLE:
368 case NUBUS_DRSW_TECHWORKS:
369 vendor = AE_VENDOR_APPLE;
370 break;
371 case NUBUS_DRSW_ASANTE:
372 vendor = AE_VENDOR_ASANTE;
373 break;
374 case NUBUS_DRSW_FARALLON:
375 vendor = AE_VENDOR_FARALLON;
376 break;
377 case NUBUS_DRSW_FOCUS:
378 vendor = AE_VENDOR_FOCUS;
379 break;
380 case NUBUS_DRSW_GATOR:
381 switch (na->drhw) {
382 default:
383 case NUBUS_DRHW_INTERLAN:
384 vendor = AE_VENDOR_INTERLAN;
385 break;
386 case NUBUS_DRHW_KINETICS:
387 if (strncmp(
388 nubus_get_card_name(na->fmt), "EtherPort", 9) == 0)
389 vendor = AE_VENDOR_KINETICS;
390 else
391 vendor = AE_VENDOR_DAYNA;
392 break;
393 }
394 break;
395 default:
396 #ifdef AE_DEBUG
397 printf("Unknown ethernet drsw: %x\n", na->drsw);
398 #endif
399 vendor = AE_VENDOR_UNKNOWN;
400 }
401 return vendor;
402 }
403
404 static int
405 ae_nb_get_enaddr(na, ep)
406 struct nubus_attach_args *na;
407 u_int8_t *ep;
408 {
409 nubus_dir dir;
410 nubus_dirent dirent;
411
412 /*
413 * XXX - note hardwired resource IDs here (0x80); these are
414 * assumed to be used by all cards, but should be fixed when
415 * we find out more about Ethernet card resources.
416 */
417 nubus_get_main_dir(na->fmt, &dir);
418 if (nubus_find_rsrc(na->fmt, &dir, 0x80, &dirent) <= 0)
419 return 1;
420 nubus_get_dir_from_rsrc(na->fmt, &dirent, &dir);
421 if (nubus_find_rsrc(na->fmt, &dir, 0x80, &dirent) <= 0)
422 return 1;
423 if (nubus_get_ind_data(na->fmt, &dirent, ep, ETHER_ADDR_LEN) <= 0)
424 return 1;
425
426 return 0;
427 }
428
429 #ifdef DEBUG
430 static void
431 ae_nb_watchdog(ifp)
432 struct ifnet *ifp;
433 {
434 struct ae_softc *sc = ifp->if_softc;
435
436 /*
437 * This is a kludge! The via code seems to miss slot interrupts
438 * sometimes. This kludges around that by calling the handler
439 * by hand if the watchdog is activated. -- XXX (akb)
440 */
441 (*via2itab[1])((void *) 1);
442
443 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
444 ++ifp->if_oerrors;
445
446 aereset(sc);
447 }
448 #endif
449