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