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