Annotation of sys/arch/mac68k/dev/if_ae_nubus.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_ae_nubus.c,v 1.17 2007/01/22 13:17:45 martin Exp $ */
2: /* $NetBSD: if_ae_nubus.c,v 1.17 1997/05/01 18:17:16 briggs Exp $ */
3:
4: /*
5: * Copyright (C) 1997 Scott Reynolds
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. The name of the author may not be used to endorse or promote products
17: * derived from this software without specific prior written permission.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29: */
30: /*
31: * Some parts are derived from code adapted for MacBSD by Brad Parker
32: * <brad@fcr.com>.
33: *
34: * Currently supports:
35: * Apple NB Ethernet Card
36: * Apple NB Ethernet Card II
37: * Interlan A310 NuBus Ethernet card
38: * Cayman Systems GatorCard
39: * Asante MacCon II/E
40: * Kinetics EtherPort SE/30
41: */
42:
43: #define AE_OLD_GET_ENADDR
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:
55: #ifdef INET
56: #include <netinet/in.h>
57: #include <netinet/if_ether.h>
58: #endif
59:
60: #include <machine/bus.h>
61: #include <machine/viareg.h>
62:
63: #include <net/if_media.h>
64:
65: #include <dev/ic/dp8390reg.h>
66: #include <dev/ic/dp8390var.h>
67: #include <mac68k/dev/nubus.h>
68: #include <mac68k/dev/if_aevar.h>
69: #include <mac68k/dev/if_aereg.h>
70:
71: static int ae_nubus_match(struct device *, void *, void *);
72: static void ae_nubus_attach(struct device *, struct device *, void *);
73: static int ae_nb_card_vendor(bus_space_tag_t, bus_space_handle_t,
74: struct nubus_attach_args *);
75: static int ae_nb_get_enaddr(bus_space_tag_t, bus_space_handle_t,
76: struct nubus_attach_args *, u_int8_t *);
77: #ifdef DEBUG
78: static void ae_nb_watchdog(struct ifnet *);
79: #endif
80:
81: struct cfattach ae_nubus_ca = {
82: sizeof(struct dp8390_softc), ae_nubus_match, ae_nubus_attach
83: };
84:
85: static int
86: ae_nubus_match(parent, vcf, aux)
87: struct device *parent;
88: void *vcf;
89: void *aux;
90: {
91: struct nubus_attach_args *na = (struct nubus_attach_args *) aux;
92: bus_space_handle_t bsh;
93: int rv = 0;
94:
95: if (bus_space_map(na->na_tag, NUBUS_SLOT2PA(na->slot), NBMEMSIZE,
96: 0, &bsh))
97: return (0);
98:
99: if (na->category == NUBUS_CATEGORY_NETWORK &&
100: na->type == NUBUS_TYPE_ETHERNET) {
101: switch (ae_nb_card_vendor(na->na_tag, bsh, na)) {
102: case DP8390_VENDOR_APPLE:
103: case DP8390_VENDOR_ASANTE:
104: case DP8390_VENDOR_FARALLON:
105: case DP8390_VENDOR_INTERLAN:
106: case DP8390_VENDOR_KINETICS:
107: case DP8390_VENDOR_CABLETRON:
108: rv = 1;
109: break;
110: case DP8390_VENDOR_DAYNA:
111: case DP8390_VENDOR_FOCUS:
112: /* not supported yet */
113: /* FALLTHROUGH */
114: default:
115: rv = 0;
116: break;
117: }
118: }
119:
120: bus_space_unmap(na->na_tag, bsh, NBMEMSIZE);
121:
122: return (rv);
123: }
124:
125: /*
126: * Install interface into kernel networking data structures
127: */
128: static void
129: ae_nubus_attach(parent, self, aux)
130: struct device *parent, *self;
131: void *aux;
132: {
133: struct dp8390_softc *sc = (struct dp8390_softc *)self;
134: struct nubus_attach_args *na = (struct nubus_attach_args *) aux;
135: #ifdef DEBUG
136: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
137: #endif
138: bus_space_tag_t bst;
139: bus_space_handle_t bsh;
140: int i, success;
141: const char *cardtype;
142:
143: bst = na->na_tag;
144: if (bus_space_map(bst, NUBUS_SLOT2PA(na->slot), NBMEMSIZE,
145: 0, &bsh)) {
146: printf(": can't map memory space\n");
147: return;
148: }
149:
150: sc->sc_regt = sc->sc_buft = bst;
151: sc->sc_flags = self->dv_cfdata->cf_flags;
152:
153: cardtype = nubus_get_card_name(bst, bsh, na->fmt);
154:
155: sc->is790 = 0;
156:
157: sc->mem_start = 0;
158: sc->mem_size = 0;
159:
160: success = 0;
161:
162: switch (ae_nb_card_vendor(bst, bsh, na)) {
163: case DP8390_VENDOR_APPLE: /* Apple-compatible cards */
164: case DP8390_VENDOR_ASANTE:
165: /* Map register offsets */
166: for (i = 0; i < 16; i++) /* reverse order, longword aligned */
167: sc->sc_reg_map[i] = (15 - i) << 2;
168:
169: sc->dcr_reg = (ED_DCR_FT1 | ED_DCR_WTS | ED_DCR_LS);
170: if (bus_space_subregion(bst, bsh,
171: AE_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) {
172: printf(": failed to map register space\n");
173: break;
174: }
175: if ((sc->mem_size = ae_size_card_memory(bst, bsh,
176: AE_DATA_OFFSET)) == 0) {
177: printf(": failed to determine size of RAM.\n");
178: break;
179: }
180: if (bus_space_subregion(bst, bsh,
181: AE_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) {
182: printf(": failed to map register space\n");
183: break;
184: }
185: #ifdef AE_OLD_GET_ENADDR
186: /* Get station address from on-board ROM */
187: for (i = 0; i < ETHER_ADDR_LEN; ++i)
188: sc->sc_arpcom.ac_enaddr[i] =
189: bus_space_read_1(bst, bsh, (AE_ROM_OFFSET + i * 2));
190: #else
191: if (ae_nb_get_enaddr(bst, bsh, na, sc->sc_arpcom.ac_enaddr)) {
192: printf(": can't find MAC address\n");
193: break;
194: }
195: #endif
196:
197: success = 1;
198: break;
199:
200: case DP8390_VENDOR_DAYNA:
201: /* Map register offsets */
202: for (i = 0; i < 16; i++) /* normal order, longword aligned */
203: sc->sc_reg_map[i] = i << 2;
204:
205: sc->dcr_reg = (ED_DCR_FT1 | ED_DCR_WTS | ED_DCR_LS);
206: if (bus_space_subregion(bst, bsh,
207: DP_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) {
208: printf(": failed to map register space\n");
209: break;
210: }
211: sc->mem_size = 8192;
212: if (bus_space_subregion(bst, bsh,
213: DP_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) {
214: printf(": failed to map register space\n");
215: break;
216: }
217: #ifdef AE_OLD_GET_ENADDR
218: /* Get station address from on-board ROM */
219: for (i = 0; i < ETHER_ADDR_LEN; ++i)
220: sc->sc_arpcom.ac_enaddr[i] =
221: bus_space_read_1(bst, bsh, (DP_ROM_OFFSET + i * 2));
222: #else
223: if (ae_nb_get_enaddr(bst, bsh, na, sc->sc_arpcom.ac_enaddr)) {
224: printf(": can't find MAC address\n");
225: break;
226: }
227: #endif
228:
229: case DP8390_VENDOR_FARALLON:
230: /* Map register offsets */
231: for (i = 0; i < 16; i++) /* reverse order, longword aligned */
232: sc->sc_reg_map[i] = (15 - i) << 2;
233:
234: sc->dcr_reg = (ED_DCR_FT1 | ED_DCR_WTS | ED_DCR_LS);
235: if (bus_space_subregion(bst, bsh,
236: AE_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) {
237: printf(": failed to map register space\n");
238: break;
239: }
240: if ((sc->mem_size = ae_size_card_memory(bst, bsh,
241: AE_DATA_OFFSET)) == 0) {
242: printf(": failed to determine size of RAM.\n");
243: break;
244: }
245: if (bus_space_subregion(bst, bsh,
246: AE_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) {
247: printf(": failed to map register space\n");
248: break;
249: }
250: #ifdef AE_OLD_GET_ENADDR
251: /* Get station address from on-board ROM */
252: for (i = 0; i < ETHER_ADDR_LEN; ++i)
253: sc->sc_arpcom.ac_enaddr[i] =
254: bus_space_read_1(bst, bsh, (FE_ROM_OFFSET + i));
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: printf(": 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: printf(": 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: printf(": 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_arpcom.ac_enaddr)) {
286: /* Fall back to snarf directly from ROM. Ick. */
287: for (i = 0; i < ETHER_ADDR_LEN; ++i)
288: sc->sc_arpcom.ac_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: /* sc->use16bit = 0; */
302: if (bus_space_subregion(bst, bsh,
303: KE_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) {
304: printf(": 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: printf(": 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: printf(": failed to map register space\n");
315: break;
316: }
317: if (ae_nb_get_enaddr(bst, bsh, na, sc->sc_arpcom.ac_enaddr)) {
318: printf(": can't find MAC address\n");
319: break;
320: }
321:
322: success = 1;
323: break;
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:
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: printf(": 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: printf(": 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: printf(": failed to map register space\n");
343: break;
344: }
345: if (ae_nb_get_enaddr(bst, bsh, na, sc->sc_arpcom.ac_enaddr)) {
346: printf(": can't find MAC address\n");
347: break;
348: }
349: success = 1;
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: printf(": %s, %dKB memory", 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, dp8390_intr, sc, sc->sc_dev.dv_xname);
382: }
383:
384: static int
385: ae_nb_card_vendor(bst, bsh, na)
386: bus_space_tag_t bst;
387: bus_space_handle_t bsh;
388: struct nubus_attach_args *na;
389: {
390: int vendor;
391:
392: switch (na->drsw) {
393: case NUBUS_DRSW_3COM:
394: switch (na->drhw) {
395: case NUBUS_DRHW_APPLE_SN:
396: case NUBUS_DRHW_APPLE_SNT:
397: vendor = DP8390_VENDOR_UNKNOWN;
398: break;
399: default:
400: vendor = DP8390_VENDOR_APPLE;
401: break;
402: }
403: break;
404: case NUBUS_DRSW_APPLE:
405: if (na->drhw == NUBUS_DRHW_ASANTE_LC) {
406: vendor = DP8390_VENDOR_UNKNOWN;
407: break;
408: }
409: /* FALLTHROUGH */
410: case NUBUS_DRSW_DAYNA2:
411: case NUBUS_DRSW_TECHWORKS:
412: case NUBUS_DRSW_TFLLAN:
413: if (na->drhw == NUBUS_DRHW_CABLETRON) {
414: vendor = DP8390_VENDOR_CABLETRON;
415: } else {
416: vendor = DP8390_VENDOR_APPLE;
417: }
418: break;
419: case NUBUS_DRSW_ASANTE:
420: vendor = DP8390_VENDOR_ASANTE;
421: break;
422: case NUBUS_DRSW_FARALLON:
423: vendor = DP8390_VENDOR_FARALLON;
424: break;
425: case NUBUS_DRSW_FOCUS:
426: vendor = DP8390_VENDOR_FOCUS;
427: break;
428: case NUBUS_DRSW_GATOR:
429: switch (na->drhw) {
430: default:
431: case NUBUS_DRHW_INTERLAN:
432: vendor = DP8390_VENDOR_INTERLAN;
433: break;
434: case NUBUS_DRHW_KINETICS:
435: if (strncmp(nubus_get_card_name(bst, bsh, na->fmt),
436: "EtherPort", 9) == 0)
437: vendor = DP8390_VENDOR_KINETICS;
438: else
439: vendor = DP8390_VENDOR_DAYNA;
440: break;
441: }
442: break;
443: default:
444: vendor = DP8390_VENDOR_UNKNOWN;
445: }
446: return vendor;
447: }
448:
449: static int
450: ae_nb_get_enaddr(bst, bsh, na, ep)
451: bus_space_tag_t bst;
452: bus_space_handle_t bsh;
453: struct nubus_attach_args *na;
454: 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 (0x80); these are
462: * assumed to be used by all cards, but should be fixed when
463: * we find out 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, 0x80, &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
492: ae_nb_watchdog(ifp)
493: struct ifnet *ifp;
494: {
495: struct dp8390_softc *sc = ifp->if_softc;
496: extern via2hand_t via2intrs[7];
497:
498: /*
499: * This is a kludge! The via code seems to miss slot interrupts
500: * sometimes. This kludges around that by calling the handler
501: * by hand if the watchdog is activated. -- XXX (akb)
502: * XXX note that this assumes the nubus handler is first in the chain.
503: */
504: if (!SLIST_EMPTY(&via2intrs[1])) {
505: struct via2hand *vh = SLIST_FIRST(&via2intrs[1]);
506: (void)(*vh->vh_fn)(vh->vh_arg);
507: }
508:
509: log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
510: ++sc->sc_arpcom.ac_if.if_oerrors;
511:
512: dp8390_reset(sc);
513: }
514: #endif
CVSweb