if_ae_nubus.c revision 1.4 1 /* $NetBSD: if_ae_nubus.c,v 1.4 1997/02/28 07:52:45 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. 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 #include <sys/param.h>
35 #include <sys/device.h>
36 #include <sys/errno.h>
37 #include <sys/ioctl.h>
38 #include <sys/socket.h>
39 #include <sys/syslog.h>
40 #include <sys/systm.h>
41
42 #include <net/if.h>
43
44 #ifdef INET
45 #include <netinet/in.h>
46 #include <netinet/if_ether.h>
47 #endif
48
49 #include <machine/bus.h>
50 #include <machine/viareg.h>
51
52 #include "nubus.h"
53 #include <dev/ic/dp8390reg.h>
54 #include "if_aereg.h"
55 #include "if_aevar.h"
56
57 static int ae_nubus_match __P((struct device *, struct cfdata *, void *));
58 static void ae_nubus_attach __P((struct device *, struct device *, void *));
59 static int ae_nb_card_vendor __P((struct nubus_attach_args *));
60 static int ae_nb_get_enaddr __P((struct nubus_attach_args *, u_int8_t *));
61 static void ae_nb_watchdog __P((struct ifnet *));
62
63 struct cfattach ae_nubus_ca = {
64 sizeof(struct ae_softc), ae_nubus_match, ae_nubus_attach
65 };
66
67 static int
68 ae_nubus_match(parent, cf, aux)
69 struct device *parent;
70 struct cfdata *cf;
71 void *aux;
72 {
73 struct nubus_attach_args *na = (struct nubus_attach_args *) aux;
74 bus_space_handle_t bsh;
75 int rv;
76
77 if (bus_space_map(na->na_tag, NUBUS_SLOT2PA(na->slot), NBMEMSIZE,
78 0, &bsh))
79 return (0);
80
81 rv = 0;
82
83 if (na->category == NUBUS_CATEGORY_NETWORK &&
84 na->type == NUBUS_TYPE_ETHERNET) {
85 switch (ae_nb_card_vendor(na)) {
86 case AE_VENDOR_APPLE:
87 case AE_VENDOR_ASANTE:
88 case AE_VENDOR_FARALLON:
89 case AE_VENDOR_INTERLAN:
90 case AE_VENDOR_KINETICS:
91 rv = 1;
92 break;
93 case AE_VENDOR_DAYNA:
94 case AE_VENDOR_FOCUS:
95 rv = UNSUPP;
96 break;
97 default:
98 break;
99 }
100 }
101
102 bus_space_unmap(na->na_tag, bsh, NBMEMSIZE);
103
104 return rv;
105 }
106
107 /*
108 * Install interface into kernel networking data structures
109 */
110 static void
111 ae_nubus_attach(parent, self, aux)
112 struct device *parent, *self;
113 void *aux;
114 {
115 struct ae_softc *sc = (struct ae_softc *) self;
116 struct nubus_attach_args *na = (struct nubus_attach_args *) aux;
117 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
118 bus_space_tag_t bst;
119 bus_space_handle_t bsh;
120 int success;
121 #ifdef AE_OLD_GET_ENADDR
122 int i;
123 #endif
124
125 bst = na->na_tag;
126 if (bus_space_map(bst, NUBUS_SLOT2PA(na->slot), NBMEMSIZE,
127 0, &bsh)) {
128 printf(": can't map memory space\n");
129 return;
130 }
131
132 sc->sc_regt = sc->sc_buft = bst;
133 sc->sc_flags = self->dv_cfdata->cf_flags;
134 sc->regs_rev = 0;
135 sc->use16bit = 1;
136 sc->vendor = ae_nb_card_vendor(na);
137 strncpy(sc->type_str, nubus_get_card_name(na->fmt),
138 INTERFACE_NAME_LEN);
139 sc->type_str[INTERFACE_NAME_LEN-1] = '\0';
140 sc->mem_size = 0;
141
142 success = 0;
143
144 switch (sc->vendor) {
145 case AE_VENDOR_APPLE: /* Apple-compatible cards */
146 case AE_VENDOR_ASANTE:
147 sc->regs_rev = 1;
148 if (bus_space_subregion(bst, bsh,
149 AE_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) {
150 printf(": failed to map register space\n");
151 break;
152 }
153 if ((sc->mem_size = ae_size_card_memory(bst, bsh,
154 AE_DATA_OFFSET)) == 0) {
155 printf(": failed to determine size of RAM.\n");
156 break;
157 }
158 if (bus_space_subregion(bst, bsh,
159 AE_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) {
160 printf(": failed to map register space\n");
161 break;
162 }
163 #ifdef AE_OLD_GET_ENADDR
164 /* Get station address from on-board ROM */
165 for (i = 0; i < ETHER_ADDR_LEN; ++i)
166 sc->sc_arpcom.ac_enaddr[i] =
167 bus_space_read_1(bst, bsh, (AE_ROM_OFFSET + i * 2));
168 #else
169 if (ae_nb_get_enaddr(na, sc->sc_arpcom.ac_enaddr)) {
170 printf(": can't find MAC address\n");
171 break;
172 }
173 #endif
174
175 success = 1;
176 break;
177
178 case AE_VENDOR_DAYNA:
179 if (bus_space_subregion(bst, bsh,
180 DP_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) {
181 printf(": failed to map register space\n");
182 break;
183 }
184 sc->mem_size = 8192;
185 if (bus_space_subregion(bst, bsh,
186 DP_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) {
187 printf(": failed to map register space\n");
188 break;
189 }
190 #ifdef AE_OLD_GET_ENADDR
191 /* Get station address from on-board ROM */
192 for (i = 0; i < ETHER_ADDR_LEN; ++i)
193 sc->sc_arpcom.ac_enaddr[i] =
194 bus_space_read_1(bst, bsh, (DP_ROM_OFFSET + i * 2));
195 #else
196 if (ae_nb_get_enaddr(na, sc->sc_arpcom.ac_enaddr)) {
197 printf(": can't find MAC address\n");
198 break;
199 }
200 #endif
201
202 printf(": unsupported Dayna hardware\n");
203 break;
204
205 case AE_VENDOR_FARALLON:
206 sc->regs_rev = 1;
207 if (bus_space_subregion(bst, bsh,
208 AE_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) {
209 printf(": failed to map register space\n");
210 break;
211 }
212 if ((sc->mem_size = ae_size_card_memory(bst, bsh,
213 AE_DATA_OFFSET)) == 0) {
214 printf(": failed to determine size of RAM.\n");
215 break;
216 }
217 if (bus_space_subregion(bst, bsh,
218 AE_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) {
219 printf(": failed to map register space\n");
220 break;
221 }
222 #ifdef AE_OLD_GET_ENADDR
223 /* Get station address from on-board ROM */
224 for (i = 0; i < ETHER_ADDR_LEN; ++i)
225 sc->sc_arpcom.ac_enaddr[i] =
226 bus_space_read_1(bst, bsh, (FE_ROM_OFFSET + i));
227 #endif
228
229 success = 1;
230 break;
231
232 case AE_VENDOR_FOCUS:
233 printf(": unsupported Focus hardware\n");
234 break;
235
236 case AE_VENDOR_INTERLAN:
237 if (bus_space_subregion(bst, bsh,
238 GC_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 GC_DATA_OFFSET)) == 0) {
244 printf(": failed to determine size of RAM.\n");
245 break;
246 }
247 if (bus_space_subregion(bst, bsh,
248 GC_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) {
249 printf(": failed to map register space\n");
250 break;
251 }
252
253 /* reset the NIC chip */
254 bus_space_write_1(bst, bsh, GC_RESET_OFFSET, 0);
255
256 #ifdef AE_OLD_GET_ENADDR
257 /* Get station address from on-board ROM */
258 for (i = 0; i < ETHER_ADDR_LEN; ++i)
259 sc->sc_arpcom.ac_enaddr[i] =
260 bus_space_read_1(bst, bsh, (GC_ROM_OFFSET + i * 4));
261 #else
262 if (ae_nb_get_enaddr(na, sc->sc_arpcom.ac_enaddr)) {
263 printf(": can't find MAC address\n");
264 break;
265 }
266 #endif
267
268 success = 1;
269 break;
270
271 case AE_VENDOR_KINETICS:
272 sc->use16bit = 0;
273 if (bus_space_subregion(bst, bsh,
274 KE_REG_OFFSET, AE_REG_SIZE, &sc->sc_regh)) {
275 printf(": failed to map register space\n");
276 break;
277 }
278 if ((sc->mem_size = ae_size_card_memory(bst, bsh,
279 KE_DATA_OFFSET)) == 0) {
280 printf(": failed to determine size of RAM.\n");
281 break;
282 }
283 if (bus_space_subregion(bst, bsh,
284 KE_DATA_OFFSET, sc->mem_size, &sc->sc_bufh)) {
285 printf(": failed to map register space\n");
286 break;
287 }
288 if (ae_nb_get_enaddr(na, sc->sc_arpcom.ac_enaddr)) {
289 printf(": can't find MAC address\n");
290 break;
291 }
292
293 success = 1;
294 break;
295
296 default:
297 break;
298 }
299
300 if (!success) {
301 bus_space_unmap(bst, bsh, NBMEMSIZE);
302 return;
303 }
304
305 ifp->if_watchdog = ae_nb_watchdog; /* Override watchdog */
306 aesetup(sc);
307
308 /* make sure interrupts are vectored to us */
309 add_nubus_intr(na->slot, aeintr, sc);
310
311 #ifdef MAC68K_BROKEN_VIDEO
312 /*
313 * XXX -- enable nubus interrupts here. Should be done elsewhere,
314 * but that currently breaks with some nubus video cards'
315 * interrupts. So we only enable nubus interrupts if we
316 * have an ethernet card... i.e., we do it here.
317 */
318 enable_nubus_intr();
319 #endif
320 }
321
322 static int
323 ae_nb_card_vendor(na)
324 struct nubus_attach_args *na;
325 {
326 int vendor;
327
328 switch (na->drsw) {
329 case NUBUS_DRSW_3COM:
330 case NUBUS_DRSW_APPLE:
331 case NUBUS_DRSW_TECHWORKS:
332 vendor = AE_VENDOR_APPLE;
333 break;
334 case NUBUS_DRSW_ASANTE:
335 vendor = AE_VENDOR_ASANTE;
336 break;
337 case NUBUS_DRSW_FARALLON:
338 vendor = AE_VENDOR_FARALLON;
339 break;
340 case NUBUS_DRSW_FOCUS:
341 vendor = AE_VENDOR_FOCUS;
342 break;
343 case NUBUS_DRSW_GATOR:
344 switch (na->drhw) {
345 default:
346 case NUBUS_DRHW_INTERLAN:
347 vendor = AE_VENDOR_INTERLAN;
348 break;
349 case NUBUS_DRHW_KINETICS:
350 if (strncmp(
351 nubus_get_card_name(na->fmt), "EtherPort", 9) == 0)
352 vendor = AE_VENDOR_KINETICS;
353 else
354 vendor = AE_VENDOR_DAYNA;
355 break;
356 }
357 break;
358 default:
359 #ifdef AE_DEBUG
360 printf("Unknown ethernet drsw: %x\n", na->drsw);
361 #endif
362 vendor = AE_VENDOR_UNKNOWN;
363 }
364 return vendor;
365 }
366
367 static int
368 ae_nb_get_enaddr(na, ep)
369 struct nubus_attach_args *na;
370 u_int8_t *ep;
371 {
372 nubus_dir dir;
373 nubus_dirent dirent;
374
375 /*
376 * XXX - note hardwired resource IDs here (0x80); these are
377 * assumed to be used by all cards, but should be fixed when
378 * we find out more about Ethernet card resources.
379 */
380 nubus_get_main_dir(na->fmt, &dir);
381 if (nubus_find_rsrc(na->fmt, &dir, 0x80, &dirent) <= 0)
382 return 1;
383 nubus_get_dir_from_rsrc(na->fmt, &dirent, &dir);
384 if (nubus_find_rsrc(na->fmt, &dir, 0x80, &dirent) <= 0)
385 return 1;
386 if (nubus_get_ind_data(na->fmt, &dirent, ep, ETHER_ADDR_LEN) <= 0)
387 return 1;
388
389 return 0;
390 }
391
392 static void
393 ae_nb_watchdog(ifp)
394 struct ifnet *ifp;
395 {
396 struct ae_softc *sc = ifp->if_softc;
397
398 #if 1
399 /*
400 * This is a kludge! The via code seems to miss slot interrupts
401 * sometimes. This kludges around that by calling the handler
402 * by hand if the watchdog is activated. -- XXX (akb)
403 */
404 (*via2itab[1])((void *) 1);
405 #endif
406
407 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
408 ++sc->sc_arpcom.ac_if.if_oerrors;
409
410 aereset(sc);
411 }
412