if_ae_nubus.c revision 1.2 1 /* $NetBSD: if_ae_nubus.c,v 1.2 1997/02/24 07:34:19 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 "bpfilter.h"
35
36 #include <sys/param.h>
37 #include <sys/device.h>
38 #include <sys/errno.h>
39 #include <sys/ioctl.h>
40 #include <sys/socket.h>
41 #include <sys/systm.h>
42
43 #include <net/if.h>
44 #include <net/if_dl.h>
45 #include <net/if_types.h>
46 #include <net/netisr.h>
47
48 #ifdef INET
49 #include <netinet/in.h>
50 #include <netinet/in_systm.h>
51 #include <netinet/in_var.h>
52 #include <netinet/ip.h>
53 #include <netinet/if_ether.h>
54 #endif
55
56 #ifdef NS
57 #include <netns/ns.h>
58 #include <netns/ns_if.h>
59 #endif
60
61 #if NBPFILTER > 0
62 #include <net/bpf.h>
63 #include <net/bpfdesc.h>
64 #endif
65
66 #include <machine/bus.h>
67 #include <machine/viareg.h>
68
69 #include "nubus.h"
70 #include <dev/ic/dp8390reg.h>
71 #include "if_aereg.h"
72 #include "if_aevar.h"
73
74 static int ae_nubus_match __P((struct device *, struct cfdata *, void *));
75 static void ae_nubus_attach __P((struct device *, struct device *, void *));
76 static int ae_card_vendor __P((struct nubus_attach_args *na));
77
78 struct cfattach ae_nubus_ca = {
79 sizeof(struct ae_softc), ae_nubus_match, ae_nubus_attach
80 };
81
82 static int
83 ae_nubus_match(parent, cf, aux)
84 struct device *parent;
85 struct cfdata *cf;
86 void *aux;
87 {
88 struct nubus_attach_args *na = (struct nubus_attach_args *) aux;
89 bus_space_handle_t bsh;
90 int rv;
91
92 if (bus_space_map(na->na_tag, NUBUS_SLOT2PA(na->slot), NBMEMSIZE,
93 0, &bsh))
94 return (0);
95
96 rv = 0;
97
98 if (na->category == NUBUS_CATEGORY_NETWORK &&
99 na->type == NUBUS_TYPE_ETHERNET) {
100 switch (ae_card_vendor(na)) {
101 case AE_VENDOR_APPLE:
102 case AE_VENDOR_ASANTE:
103 case AE_VENDOR_FARALLON:
104 case AE_VENDOR_INTERLAN:
105 case AE_VENDOR_KINETICS:
106 rv = 1;
107 break;
108 case AE_VENDOR_DAYNA:
109 case AE_VENDOR_FOCUS:
110 rv = UNSUPP;
111 break;
112 default:
113 break;
114 }
115 }
116
117 bus_space_unmap(na->na_tag, bsh, NBMEMSIZE);
118
119 return rv;
120 }
121
122 /*
123 * Install interface into kernel networking data structures
124 */
125 static void
126 ae_nubus_attach(parent, self, aux)
127 struct device *parent, *self;
128 void *aux;
129 {
130 struct ae_softc *sc = (struct ae_softc *) self;
131 struct nubus_attach_args *na = (struct nubus_attach_args *) aux;
132 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
133 bus_space_tag_t bst;
134 bus_space_handle_t bsh;
135 int i, success;
136 int flags = 0;
137
138 bst = na->na_tag;
139 if (bus_space_map(bst, NUBUS_SLOT2PA(na->slot), NBMEMSIZE,
140 0, &bsh)) {
141 printf(": can't map memory space\n");
142 return;
143 }
144
145 sc->regs_rev = 0;
146 sc->use16bit = 1;
147 sc->vendor = ae_card_vendor(na);
148 strncpy(sc->type_str, nubus_get_card_name(na->fmt),
149 INTERFACE_NAME_LEN);
150 sc->type_str[INTERFACE_NAME_LEN-1] = '\0';
151 sc->mem_size = 0;
152
153 success = 0;
154
155 switch (sc->vendor) {
156 case AE_VENDOR_INTERLAN:
157 if (bus_space_subregion(bst, bsh,
158 GC_REG_OFFSET, AE_REG_SIZE, &sc->sc_reg_handle)) {
159 printf(": failed to map register space\n");
160 break;
161 }
162 if ((sc->mem_size = ae_size_card_memory(bst, bsh,
163 GC_DATA_OFFSET)) == 0) {
164 printf(": failed to determine size of RAM.\n");
165 break;
166 }
167 if (bus_space_subregion(bst, bsh,
168 GC_DATA_OFFSET, sc->mem_size, &sc->sc_buf_handle)) {
169 printf(": failed to map register space\n");
170 break;
171 }
172
173 /* reset the NIC chip */
174 bus_space_write_1(bst, bsh, GC_RESET_OFFSET, 0);
175
176 /* Get station address from on-board ROM */
177 for (i = 0; i < ETHER_ADDR_LEN; ++i)
178 sc->sc_arpcom.ac_enaddr[i] =
179 bus_space_read_1(bst, bsh, (GC_ROM_OFFSET + i * 4));
180
181 success = 1;
182 break;
183
184 /* Apple-compatible cards */
185 case AE_VENDOR_ASANTE:
186 case AE_VENDOR_APPLE:
187 sc->regs_rev = 1;
188 if (bus_space_subregion(bst, bsh,
189 AE_REG_OFFSET, AE_REG_SIZE, &sc->sc_reg_handle)) {
190 printf(": failed to map register space\n");
191 break;
192 }
193 if ((sc->mem_size = ae_size_card_memory(bst, bsh,
194 AE_DATA_OFFSET)) == 0) {
195 printf(": failed to determine size of RAM.\n");
196 break;
197 }
198 if (bus_space_subregion(bst, bsh,
199 AE_DATA_OFFSET, sc->mem_size, &sc->sc_buf_handle)) {
200 printf(": failed to map register space\n");
201 break;
202 }
203
204 /* Get station address from on-board ROM */
205 for (i = 0; i < ETHER_ADDR_LEN; ++i)
206 sc->sc_arpcom.ac_enaddr[i] =
207 bus_space_read_1(bst, bsh, (AE_ROM_OFFSET + i * 2));
208
209 success = 1;
210 break;
211
212 case AE_VENDOR_DAYNA:
213 if (bus_space_subregion(bst, bsh,
214 DP_REG_OFFSET, AE_REG_SIZE, &sc->sc_reg_handle)) {
215 printf(": failed to map register space\n");
216 break;
217 }
218 sc->mem_size = 8192;
219 if (bus_space_subregion(bst, bsh,
220 DP_DATA_OFFSET, sc->mem_size, &sc->sc_buf_handle)) {
221 printf(": failed to map register space\n");
222 break;
223 }
224
225 /* Get station address from on-board ROM */
226 for (i = 0; i < ETHER_ADDR_LEN; ++i)
227 sc->sc_arpcom.ac_enaddr[i] =
228 bus_space_read_1(bst, bsh, (DP_ROM_OFFSET + i * 2));
229
230 printf(": unsupported Dayna hardware\n");
231 break;
232
233 case AE_VENDOR_FARALLON:
234 sc->regs_rev = 1;
235 if (bus_space_subregion(bst, bsh,
236 AE_REG_OFFSET, AE_REG_SIZE, &sc->sc_reg_handle)) {
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_buf_handle)) {
247 printf(": failed to map register space\n");
248 break;
249 }
250
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
256 success = 1;
257 break;
258
259 case AE_VENDOR_FOCUS:
260 printf(": unsupported Focus hardware\n");
261 break;
262
263 case AE_VENDOR_KINETICS:
264 sc->use16bit = 0;
265 if (bus_space_subregion(bst, bsh,
266 KE_REG_OFFSET, AE_REG_SIZE, &sc->sc_reg_handle)) {
267 printf(": failed to map register space\n");
268 break;
269 }
270 if ((sc->mem_size = ae_size_card_memory(bst, bsh,
271 KE_DATA_OFFSET)) == 0) {
272 printf(": failed to determine size of RAM.\n");
273 break;
274 }
275 if (bus_space_subregion(bst, bsh,
276 KE_DATA_OFFSET, sc->mem_size, &sc->sc_buf_handle)) {
277 printf(": failed to map register space\n");
278 break;
279 }
280
281 /* Get station address from on-board ROM */
282 #if 0
283 for (i = 0; i < ETHER_ADDR_LEN; ++i)
284 sc->sc_arpcom.ac_enaddr[i] =
285 bus_space_read_1(bst, bsh, (KE_ROM_OFFSET + i));
286 #else
287 {
288 nubus_dir dir;
289 nubus_dirent dirent;
290
291 /* getting the MAC address */
292 nubus_get_main_dir(na->fmt, &dir);
293 if (nubus_find_rsrc(na->fmt, &dir, 0x80, &dirent) <= 0)
294 break;
295 nubus_get_dir_from_rsrc(na->fmt, &dirent, &dir);
296 if (nubus_find_rsrc(na->fmt, &dir, 0x80, &dirent) <= 0)
297 break;
298 if (nubus_get_ind_data(na->fmt, &dirent,
299 (caddr_t)sc->sc_arpcom.ac_enaddr,
300 ETHER_ADDR_LEN) <= 0)
301 break;
302 }
303 #endif
304
305 success = 1;
306 break;
307
308 default:
309 break;
310 }
311
312 if (!success) {
313 bus_space_unmap(bst, bsh, NBMEMSIZE);
314 return;
315 }
316
317 sc->sc_reg_tag = sc->sc_buf_tag = bst;
318
319 sc->cr_proto = ED_CR_RD2;
320
321 /* Allocate one xmit buffer if < 16k, two buffers otherwise. */
322 if ((sc->mem_size < 16384) || (flags & AE_FLAGS_NO_DOUBLE_BUFFERING))
323 sc->txb_cnt = 1;
324 else
325 sc->txb_cnt = 2;
326
327 sc->tx_page_start = 0;
328 sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE;
329 sc->rec_page_stop = sc->tx_page_start + (sc->mem_size >> ED_PAGE_SHIFT);
330 sc->mem_ring = sc->rec_page_start << ED_PAGE_SHIFT;
331
332 /* Now zero memory and verify that it is clear. */
333 bus_space_set_region_2(sc->sc_buf_tag, sc->sc_buf_handle, 0,
334 0, sc->mem_size / 2);
335
336 for (i = 0; i < sc->mem_size; ++i)
337 if (bus_space_read_1(sc->sc_buf_tag, sc->sc_buf_handle, i))
338 printf("%s: failed to clear shared memory - check configuration\n",
339 sc->sc_dev.dv_xname);
340
341 /* Set interface to stopped condition (reset). */
342 aestop(sc);
343
344 /* Initialize ifnet structure. */
345 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
346 ifp->if_softc = sc;
347 ifp->if_start = aestart;
348 ifp->if_ioctl = aeioctl;
349 ifp->if_watchdog = aewatchdog;
350 ifp->if_flags =
351 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
352
353 /* Attach the interface. */
354 if_attach(ifp);
355 ether_ifattach(ifp);
356
357 /* Print additional info when attached. */
358 printf(": address %s, ", ether_sprintf(sc->sc_arpcom.ac_enaddr));
359
360 printf("type %s, %dKB memory\n", sc->type_str, sc->mem_size / 1024);
361
362 #if NBPFILTER > 0
363 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
364 #endif
365
366 /* make sure interrupts are vectored to us */
367 add_nubus_intr(na->slot, aeintr, sc);
368
369 /*
370 * XXX -- enable nubus interrupts here. Should be done elsewhere,
371 * but that currently breaks with some nubus video cards'
372 * interrupts. So we only enable nubus interrupts if we
373 * have an ethernet card... i.e., we do it here.
374 */
375 enable_nubus_intr();
376 }
377
378 static int
379 ae_card_vendor(na)
380 struct nubus_attach_args *na;
381 {
382 int vendor;
383
384 switch (na->drsw) {
385 case NUBUS_DRSW_3COM:
386 case NUBUS_DRSW_APPLE:
387 case NUBUS_DRSW_TECHWORKS:
388 vendor = AE_VENDOR_APPLE;
389 break;
390 case NUBUS_DRSW_ASANTE:
391 vendor = AE_VENDOR_ASANTE;
392 break;
393 case NUBUS_DRSW_FARALLON:
394 vendor = AE_VENDOR_FARALLON;
395 break;
396 case NUBUS_DRSW_FOCUS:
397 vendor = AE_VENDOR_FOCUS;
398 break;
399 case NUBUS_DRSW_GATOR:
400 switch (na->drhw) {
401 default:
402 case NUBUS_DRHW_INTERLAN:
403 vendor = AE_VENDOR_INTERLAN;
404 break;
405 case NUBUS_DRHW_KINETICS:
406 if (strncmp(
407 nubus_get_card_name(na->fmt), "EtherPort", 9) == 0)
408 vendor = AE_VENDOR_KINETICS;
409 else
410 vendor = AE_VENDOR_DAYNA;
411 break;
412 }
413 break;
414 default:
415 #ifdef AE_DEBUG
416 printf("Unknown ethernet drsw: %x\n", na->drsw);
417 #endif
418 vendor = AE_VENDOR_UNKNOWN;
419 }
420 return vendor;
421 }
422