if_ae_nubus.c revision 1.1 1 /* $NetBSD: if_ae_nubus.c,v 1.1 1997/02/24 06:03:58 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 rv = 1;
106 break;
107 case AE_VENDOR_DAYNA:
108 case AE_VENDOR_FOCUS:
109 rv = UNSUPP;
110 break;
111 default:
112 break;
113 }
114 }
115
116 bus_space_unmap(na->na_tag, bsh, NBMEMSIZE);
117
118 return rv;
119 }
120
121 /*
122 * Install interface into kernel networking data structures
123 */
124 static void
125 ae_nubus_attach(parent, self, aux)
126 struct device *parent, *self;
127 void *aux;
128 {
129 struct ae_softc *sc = (struct ae_softc *) self;
130 struct nubus_attach_args *na = (struct nubus_attach_args *) aux;
131 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
132 bus_space_tag_t bst;
133 bus_space_handle_t bsh;
134 int i, success;
135 int flags = 0;
136
137 bst = na->na_tag;
138 if (bus_space_map(bst, NUBUS_SLOT2PA(na->slot), NBMEMSIZE,
139 0, &bsh)) {
140 printf(": can't map memory space\n");
141 return;
142 }
143
144 sc->regs_rev = 0;
145 sc->vendor = ae_card_vendor(na);
146 strncpy(sc->type_str, nubus_get_card_name(na->fmt),
147 INTERFACE_NAME_LEN);
148 sc->type_str[INTERFACE_NAME_LEN-1] = '\0';
149 sc->mem_size = 0;
150
151 success = 0;
152
153 switch (sc->vendor) {
154 case AE_VENDOR_INTERLAN:
155 if (bus_space_subregion(bst, bsh,
156 GC_REG_OFFSET, AE_REG_SIZE, &sc->sc_reg_handle)) {
157 printf(": failed to map register space\n");
158 break;
159 }
160 if ((sc->mem_size = ae_size_card_memory(bst, bsh,
161 GC_DATA_OFFSET)) == 0) {
162 printf(": failed to determine size of RAM.\n");
163 break;
164 }
165 if (bus_space_subregion(bst, bsh,
166 GC_DATA_OFFSET, sc->mem_size, &sc->sc_buf_handle)) {
167 printf(": failed to map register space\n");
168 break;
169 }
170
171 /* reset the NIC chip */
172 bus_space_write_1(bst, bsh, GC_RESET_OFFSET, 0);
173
174 /* Get station address from on-board ROM */
175 for (i = 0; i < ETHER_ADDR_LEN; ++i)
176 sc->sc_arpcom.ac_enaddr[i] =
177 bus_space_read_1(bst, bsh, (GC_ROM_OFFSET + i * 4));
178
179 success = 1;
180 break;
181
182 /* Apple-compatible cards */
183 case AE_VENDOR_ASANTE:
184 case AE_VENDOR_APPLE:
185 sc->regs_rev = 1;
186 if (bus_space_subregion(bst, bsh,
187 AE_REG_OFFSET, AE_REG_SIZE, &sc->sc_reg_handle)) {
188 printf(": failed to map register space\n");
189 break;
190 }
191 if ((sc->mem_size = ae_size_card_memory(bst, bsh,
192 AE_DATA_OFFSET)) == 0) {
193 printf(": failed to determine size of RAM.\n");
194 break;
195 }
196 if (bus_space_subregion(bst, bsh,
197 AE_DATA_OFFSET, sc->mem_size, &sc->sc_buf_handle)) {
198 printf(": failed to map register space\n");
199 break;
200 }
201
202 /* Get station address from on-board ROM */
203 for (i = 0; i < ETHER_ADDR_LEN; ++i)
204 sc->sc_arpcom.ac_enaddr[i] =
205 bus_space_read_1(bst, bsh, (AE_ROM_OFFSET + i * 2));
206
207 success = 1;
208 break;
209
210 case AE_VENDOR_DAYNA:
211 if (bus_space_subregion(bst, bsh,
212 DP_REG_OFFSET, AE_REG_SIZE, &sc->sc_reg_handle)) {
213 printf(": failed to map register space\n");
214 break;
215 }
216 sc->mem_size = 8192;
217 if (bus_space_subregion(bst, bsh,
218 DP_DATA_OFFSET, sc->mem_size, &sc->sc_buf_handle)) {
219 printf(": failed to map register space\n");
220 break;
221 }
222
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, (DP_ROM_OFFSET + i * 2));
227
228 printf(": unsupported Dayna hardware\n");
229 break;
230
231 case AE_VENDOR_FARALLON:
232 sc->regs_rev = 1;
233 if (bus_space_subregion(bst, bsh,
234 AE_REG_OFFSET, AE_REG_SIZE, &sc->sc_reg_handle)) {
235 printf(": failed to map register space\n");
236 break;
237 }
238 if ((sc->mem_size = ae_size_card_memory(bst, bsh,
239 AE_DATA_OFFSET)) == 0) {
240 printf(": failed to determine size of RAM.\n");
241 break;
242 }
243 if (bus_space_subregion(bst, bsh,
244 AE_DATA_OFFSET, sc->mem_size, &sc->sc_buf_handle)) {
245 printf(": failed to map register space\n");
246 break;
247 }
248
249 /* Get station address from on-board ROM */
250 for (i = 0; i < ETHER_ADDR_LEN; ++i)
251 sc->sc_arpcom.ac_enaddr[i] =
252 bus_space_read_1(bst, bsh, (FE_ROM_OFFSET + i));
253
254 success = 1;
255 break;
256
257 case AE_VENDOR_FOCUS:
258 printf(": unsupported Focus hardware\n");
259 break;
260
261 default:
262 break;
263 }
264
265 if (!success) {
266 bus_space_unmap(bst, bsh, NBMEMSIZE);
267 return;
268 }
269
270 sc->sc_reg_tag = sc->sc_buf_tag = bst;
271
272 sc->cr_proto = ED_CR_RD2;
273
274 /* Allocate one xmit buffer if < 16k, two buffers otherwise. */
275 if ((sc->mem_size < 16384) || (flags & AE_FLAGS_NO_DOUBLE_BUFFERING))
276 sc->txb_cnt = 1;
277 else
278 sc->txb_cnt = 2;
279
280 sc->tx_page_start = 0;
281 sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE;
282 sc->rec_page_stop = sc->tx_page_start + (sc->mem_size >> ED_PAGE_SHIFT);
283 sc->mem_ring = sc->rec_page_start << ED_PAGE_SHIFT;
284
285 /* Now zero memory and verify that it is clear. */
286 bus_space_set_region_2(sc->sc_buf_tag, sc->sc_buf_handle, 0,
287 0, sc->mem_size / 2);
288
289 for (i = 0; i < sc->mem_size; ++i)
290 if (bus_space_read_1(sc->sc_buf_tag, sc->sc_buf_handle, i))
291 printf("%s: failed to clear shared memory - check configuration\n",
292 sc->sc_dev.dv_xname);
293
294 /* Set interface to stopped condition (reset). */
295 aestop(sc);
296
297 /* Initialize ifnet structure. */
298 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
299 ifp->if_softc = sc;
300 ifp->if_start = aestart;
301 ifp->if_ioctl = aeioctl;
302 ifp->if_watchdog = aewatchdog;
303 ifp->if_flags =
304 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
305
306 /* Attach the interface. */
307 if_attach(ifp);
308 ether_ifattach(ifp);
309
310 /* Print additional info when attached. */
311 printf(": address %s, ", ether_sprintf(sc->sc_arpcom.ac_enaddr));
312
313 printf("type %s, %dKB memory\n", sc->type_str, sc->mem_size / 1024);
314
315 #if NBPFILTER > 0
316 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
317 #endif
318
319 /* make sure interrupts are vectored to us */
320 add_nubus_intr(na->slot, aeintr, sc);
321
322 /*
323 * XXX -- enable nubus interrupts here. Should be done elsewhere,
324 * but that currently breaks with some nubus video cards'
325 * interrupts. So we only enable nubus interrupts if we
326 * have an ethernet card... i.e., we do it here.
327 */
328 enable_nubus_intr();
329 }
330
331 static int
332 ae_card_vendor(na)
333 struct nubus_attach_args *na;
334 {
335 int vendor;
336
337 switch (na->drsw) {
338 case NUBUS_DRSW_3COM:
339 case NUBUS_DRSW_APPLE:
340 case NUBUS_DRSW_TECHWORKS:
341 vendor = AE_VENDOR_APPLE;
342 break;
343 case NUBUS_DRSW_ASANTE:
344 vendor = AE_VENDOR_ASANTE;
345 break;
346 case NUBUS_DRSW_FARALLON:
347 vendor = AE_VENDOR_FARALLON;
348 break;
349 case NUBUS_DRSW_FOCUS:
350 vendor = AE_VENDOR_FOCUS;
351 break;
352 case NUBUS_DRSW_GATOR:
353 switch (na->drhw) {
354 default:
355 case NUBUS_DRHW_INTERLAN:
356 vendor = AE_VENDOR_INTERLAN;
357 break;
358 case NUBUS_DRHW_KINETICS:
359 vendor = AE_VENDOR_DAYNA;
360 break;
361 }
362 break;
363 default:
364 #ifdef AE_DEBUG
365 printf("Unknown ethernet drsw: %x\n", na->drsw);
366 #endif
367 vendor = AE_VENDOR_UNKNOWN;
368 }
369 return vendor;
370 }
371