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