if_ae.c revision 1.19 1 1.19 briggs /* $NetBSD: if_ae.c,v 1.19 1995/04/08 13:17:55 briggs Exp $ */
2 1.14 cgd
3 1.1 briggs /*
4 1.1 briggs * Device driver for National Semiconductor DS8390 based ethernet adapters.
5 1.1 briggs *
6 1.1 briggs * Based on original ISA bus driver by David Greenman, 29-April-1993
7 1.1 briggs *
8 1.1 briggs * Copyright (C) 1993, David Greenman. This software may be used, modified,
9 1.1 briggs * copied, distributed, and sold, in both source and binary form provided
10 1.1 briggs * that the above copyright and these terms are retained. Under no
11 1.1 briggs * circumstances is the author responsible for the proper functioning
12 1.1 briggs * of this software, nor does the author assume any responsibility
13 1.1 briggs * for damages incurred with its use.
14 1.1 briggs *
15 1.1 briggs * Adapted for MacBSD by Brad Parker <brad (at) fcr.com>
16 1.1 briggs *
17 1.1 briggs * Currently supports:
18 1.1 briggs * Apples NB Ethernet card
19 1.1 briggs * Interlan A310 Nubus Ethernet card
20 1.1 briggs * Cayman Systems GatorCard
21 1.15 briggs * Asante MacCon II/E
22 1.1 briggs */
23 1.1 briggs
24 1.15 briggs /*
25 1.19 briggs * $Id: if_ae.c,v 1.19 1995/04/08 13:17:55 briggs Exp $
26 1.15 briggs */
27 1.15 briggs
28 1.1 briggs #include "ae.h"
29 1.1 briggs /* bpfilter included here in case it is needed in future net includes */
30 1.1 briggs #include "bpfilter.h"
31 1.1 briggs
32 1.9 briggs #include <sys/param.h>
33 1.9 briggs #include <sys/systm.h>
34 1.9 briggs #include <sys/errno.h>
35 1.9 briggs #include <sys/ioctl.h>
36 1.9 briggs #include <sys/mbuf.h>
37 1.9 briggs #include <sys/socket.h>
38 1.9 briggs #include <sys/syslog.h>
39 1.1 briggs
40 1.5 briggs #include <net/if.h>
41 1.5 briggs #include <net/if_dl.h>
42 1.5 briggs #include <net/if_types.h>
43 1.5 briggs #include <net/netisr.h>
44 1.1 briggs
45 1.1 briggs #ifdef INET
46 1.5 briggs #include <netinet/in.h>
47 1.5 briggs #include <netinet/in_systm.h>
48 1.5 briggs #include <netinet/in_var.h>
49 1.5 briggs #include <netinet/ip.h>
50 1.5 briggs #include <netinet/if_ether.h>
51 1.1 briggs #endif
52 1.1 briggs
53 1.1 briggs #ifdef NS
54 1.5 briggs #include <netns/ns.h>
55 1.5 briggs #include <netns/ns_if.h>
56 1.1 briggs #endif
57 1.1 briggs
58 1.1 briggs #if NBPFILTER > 0
59 1.5 briggs #include <net/bpf.h>
60 1.5 briggs #include <net/bpfdesc.h>
61 1.1 briggs #endif
62 1.1 briggs
63 1.5 briggs #include <sys/device.h>
64 1.18 briggs #include "../mac68k/via.h"
65 1.3 briggs #include "nubus.h"
66 1.1 briggs #include "if_aereg.h"
67 1.1 briggs
68 1.3 briggs struct ae_device {
69 1.3 briggs struct device ae_dev;
70 1.3 briggs /* struct nubusdev ae_nu;
71 1.3 briggs struct intrhand ae_ih; */
72 1.3 briggs };
73 1.3 briggs
74 1.1 briggs /*
75 1.1 briggs * ae_softc: per line info and status
76 1.1 briggs */
77 1.1 briggs struct ae_softc {
78 1.3 briggs struct ae_device *sc_ae;
79 1.3 briggs
80 1.1 briggs struct arpcom arpcom; /* ethernet common */
81 1.1 briggs
82 1.1 briggs char *type_str; /* pointer to type string */
83 1.1 briggs u_char vendor; /* interface vendor */
84 1.1 briggs u_char type; /* interface type code */
85 1.15 briggs u_char regs_rev; /* registers are reversed */
86 1.15 briggs
87 1.15 briggs #define REG_MAP(sc, reg) ((sc)->regs_rev ? (0x0f-(reg))<<2 : (reg)<<2)
88 1.1 briggs #define NIC_GET(sc, reg) ((sc)->nic_addr[REG_MAP(sc, reg)])
89 1.1 briggs #define NIC_PUT(sc, reg, val) ((sc)->nic_addr[REG_MAP(sc, reg)] = (val))
90 1.1 briggs volatile caddr_t nic_addr; /* NIC (DS8390) I/O bus address */
91 1.1 briggs caddr_t rom_addr; /* on board prom address */
92 1.1 briggs caddr_t smem_start; /* shared memory start address */
93 1.1 briggs caddr_t smem_end; /* shared memory end address */
94 1.1 briggs u_long smem_size; /* total shared memory size */
95 1.15 briggs u_char smem_wr_short; /* card memory requires int16 writes */
96 1.1 briggs caddr_t smem_ring; /* start of RX ring-buffer (in smem) */
97 1.1 briggs
98 1.1 briggs caddr_t bpf; /* BPF "magic cookie" */
99 1.1 briggs
100 1.1 briggs u_char xmit_busy; /* transmitter is busy */
101 1.1 briggs u_char txb_cnt; /* Number of transmit buffers */
102 1.1 briggs u_char txb_next; /* Pointer to next buffer ready to xmit */
103 1.1 briggs u_short txb_next_len; /* next xmit buffer length */
104 1.15 briggs u_char data_buffered; /* data has been buffered in interface mem */
105 1.1 briggs u_char tx_page_start; /* first page of TX buffer area */
106 1.1 briggs
107 1.1 briggs u_char rec_page_start; /* first page of RX ring-buffer */
108 1.1 briggs u_char rec_page_stop; /* last page of RX ring-buffer */
109 1.1 briggs u_char next_packet; /* pointer to next unread RX packet */
110 1.1 briggs } ae_softc[NAE];
111 1.1 briggs
112 1.18 briggs void ae_find(), ae_attach();
113 1.17 briggs int ae_init(), ae_ioctl(), ae_probe(),
114 1.18 briggs ae_start(), ae_reset(), ae_watchdog(), aeintr();
115 1.1 briggs
116 1.3 briggs struct cfdriver aecd =
117 1.3 briggs { NULL, "ae", ae_probe, ae_attach, DV_IFNET, sizeof(struct ae_device), NULL, 0 };
118 1.3 briggs
119 1.1 briggs static void ae_stop();
120 1.1 briggs static inline void ae_rint();
121 1.1 briggs static inline void ae_xmit();
122 1.1 briggs static inline char *ae_ring_copy();
123 1.1 briggs
124 1.1 briggs extern int ether_output();
125 1.1 briggs
126 1.1 briggs #define ETHER_MIN_LEN 64
127 1.1 briggs #define ETHER_MAX_LEN 1518
128 1.1 briggs #define ETHER_ADDR_LEN 6
129 1.1 briggs #define ETHER_HDR_SIZE 14
130 1.1 briggs
131 1.1 briggs char ae_name[] = "8390 Nubus Ethernet card";
132 1.1 briggs static char zero = 0;
133 1.1 briggs static u_char ones = 0xff;
134 1.1 briggs
135 1.8 briggs struct vendor_S {
136 1.8 briggs char *manu;
137 1.8 briggs int len;
138 1.8 briggs int vendor;
139 1.8 briggs } vend[] = {
140 1.8 briggs { "Apple", 5, AE_VENDOR_APPLE },
141 1.8 briggs { "3Com", 4, AE_VENDOR_APPLE },
142 1.8 briggs { "Dayna", 5, AE_VENDOR_DAYNA },
143 1.8 briggs { "Inter", 5, AE_VENDOR_INTERLAN },
144 1.15 briggs { "Asant", 5, AE_VENDOR_ASANTE },
145 1.8 briggs };
146 1.8 briggs
147 1.8 briggs static int numvend = sizeof(vend)/sizeof(vend[0]);
148 1.8 briggs
149 1.12 lkestel /*
150 1.12 lkestel * XXX These two should be moved to locore, and maybe changed to use shorts
151 1.12 lkestel * instead of bytes. The reason for these is that bcopy and bzero use longs,
152 1.12 lkestel * which the ethernet cards can't handle.
153 1.12 lkestel */
154 1.12 lkestel
155 1.12 lkestel void
156 1.15 briggs bszero (u_short *addr, int len)
157 1.12 lkestel {
158 1.12 lkestel while (len--) {
159 1.12 lkestel *addr++ = 0;
160 1.12 lkestel }
161 1.12 lkestel }
162 1.12 lkestel
163 1.12 lkestel void
164 1.12 lkestel bbcopy (char *src, char *dest, int len)
165 1.12 lkestel {
166 1.12 lkestel while (len--) {
167 1.12 lkestel *dest++ = *src++;
168 1.12 lkestel }
169 1.12 lkestel }
170 1.12 lkestel
171 1.15 briggs /*
172 1.15 briggs short copy; assume destination is always aligned
173 1.15 briggs and last byte of odd length copy is not important
174 1.15 briggs */
175 1.15 briggs
176 1.15 briggs void
177 1.15 briggs bscopy (char *src, char *dest, int len)
178 1.15 briggs {
179 1.15 briggs u_short *d = (u_short *)dest;
180 1.15 briggs u_short *s = (u_short *)src;
181 1.15 briggs char b1, b2;
182 1.15 briggs
183 1.15 briggs /* odd case, src addr is unaligned */
184 1.15 briggs if ( ((u_long)src) & 1 ) {
185 1.15 briggs while (len > 0) {
186 1.15 briggs b1 = *src++;
187 1.15 briggs b2 = len > 1 ? *src++ : (*d & 0xff);
188 1.15 briggs *d++ = (b1 << 8) | b2;
189 1.15 briggs len -= 2;
190 1.15 briggs }
191 1.15 briggs return;
192 1.15 briggs }
193 1.15 briggs
194 1.15 briggs /* normal case, aligned src & dst */
195 1.15 briggs while (len > 0) {
196 1.15 briggs *d++ = *s++;
197 1.15 briggs len -= 2;
198 1.15 briggs }
199 1.15 briggs }
200 1.15 briggs
201 1.8 briggs void
202 1.8 briggs ae_id_card(nu, sc)
203 1.8 briggs struct nubus_hw *nu;
204 1.8 briggs struct ae_softc *sc;
205 1.8 briggs {
206 1.8 briggs int i;
207 1.8 briggs
208 1.8 briggs /*
209 1.8 briggs * Try to determine what type of card this is...
210 1.8 briggs */
211 1.8 briggs sc->vendor = AE_VENDOR_UNKNOWN;
212 1.8 briggs for (i=0 ; i<numvend ; i++) {
213 1.15 briggs if (!strncmp(nu->Slot.manufacturer, vend[i].manu, vend[i].len))
214 1.15 briggs {
215 1.8 briggs sc->vendor = vend[i].vendor;
216 1.8 briggs break;
217 1.8 briggs }
218 1.8 briggs }
219 1.9 briggs sc->type_str = (char *) (nu->Slot.manufacturer);
220 1.8 briggs
221 1.15 briggs }
222 1.15 briggs
223 1.15 briggs int
224 1.15 briggs ae_size_card_memory(sc)
225 1.15 briggs struct ae_softc *sc;
226 1.15 briggs {
227 1.15 briggs u_short *p;
228 1.15 briggs u_short i1, i2, i3, i4;
229 1.15 briggs int size;
230 1.15 briggs
231 1.15 briggs p = (u_short *)sc->smem_start;
232 1.15 briggs
233 1.15 briggs /*
234 1.15 briggs * very simple size memory, assuming it's installed in 8k
235 1.15 briggs * banks; also assume it will generally mirror in upper banks
236 1.15 briggs * if not installed.
237 1.15 briggs */
238 1.15 briggs i1 = (8192*0)/2;
239 1.15 briggs i2 = (8192*1)/2;
240 1.15 briggs i3 = (8192*2)/2;
241 1.15 briggs i4 = (8192*3)/2;
242 1.15 briggs
243 1.15 briggs p[i1] = 0x1111;
244 1.15 briggs p[i2] = 0x2222;
245 1.15 briggs p[i3] = 0x3333;
246 1.15 briggs p[i4] = 0x4444;
247 1.15 briggs
248 1.15 briggs size = 0;
249 1.15 briggs if (p[i1] == 0x1111 && p[i2] == 0x2222 &&
250 1.15 briggs p[i3] == 0x3333 && p[i4] == 0x4444)
251 1.15 briggs size = 8192*4;
252 1.15 briggs else
253 1.15 briggs if ((p[i1] == 0x1111 && p[i2] == 0x2222) ||
254 1.15 briggs (p[i1] == 0x3333 && p[i2] == 0x4444))
255 1.15 briggs size = 8192*2;
256 1.15 briggs else
257 1.15 briggs if (p[i1] == 0x1111 || p[i1] == 0x4444)
258 1.15 briggs size = 8192;
259 1.15 briggs
260 1.15 briggs if (size == 0)
261 1.15 briggs return 0;
262 1.15 briggs
263 1.15 briggs return size;
264 1.8 briggs }
265 1.8 briggs
266 1.1 briggs int
267 1.3 briggs ae_probe(parent, cf, aux)
268 1.3 briggs struct cfdriver *parent;
269 1.3 briggs struct cfdata *cf;
270 1.3 briggs void *aux;
271 1.1 briggs {
272 1.3 briggs register struct nubus_hw *nu = (struct nubus_hw *) aux;
273 1.3 briggs struct ae_softc *sc = &ae_softc[cf->cf_unit];
274 1.1 briggs int i, memsize;
275 1.1 briggs int flags = 0;
276 1.1 briggs
277 1.3 briggs if (nu->Slot.type != NUBUS_NETWORK)
278 1.3 briggs return 0;
279 1.3 briggs
280 1.8 briggs ae_id_card(nu, sc);
281 1.1 briggs
282 1.15 briggs sc->regs_rev = 0;
283 1.15 briggs sc->smem_wr_short = 0;
284 1.15 briggs
285 1.1 briggs switch (sc->vendor) {
286 1.1 briggs case AE_VENDOR_INTERLAN:
287 1.1 briggs sc->nic_addr = nu->addr + GC_NIC_OFFSET;
288 1.1 briggs sc->rom_addr = nu->addr + GC_ROM_OFFSET;
289 1.1 briggs sc->smem_start = nu->addr + GC_DATA_OFFSET;
290 1.15 briggs if ((memsize = ae_size_card_memory(sc)) == 0)
291 1.15 briggs return 0;
292 1.1 briggs
293 1.1 briggs /* reset the NIC chip */
294 1.1 briggs *((caddr_t)nu->addr + GC_RESET_OFFSET) = (char)zero;
295 1.1 briggs
296 1.1 briggs /* Get station address from on-board ROM */
297 1.1 briggs for (i = 0; i < ETHER_ADDR_LEN; ++i)
298 1.1 briggs sc->arpcom.ac_enaddr[i] = *(sc->rom_addr + i*4);
299 1.1 briggs break;
300 1.1 briggs
301 1.15 briggs case AE_VENDOR_ASANTE:
302 1.15 briggs /* memory writes require *(u_short *) */
303 1.15 briggs sc->smem_wr_short = 1;
304 1.15 briggs /* otherwise, pretend to be an apple card (fall through) */
305 1.15 briggs
306 1.1 briggs case AE_VENDOR_APPLE:
307 1.15 briggs sc->regs_rev = 1;
308 1.1 briggs sc->nic_addr = nu->addr + AE_NIC_OFFSET;
309 1.1 briggs sc->rom_addr = nu->addr + AE_ROM_OFFSET;
310 1.1 briggs sc->smem_start = nu->addr + AE_DATA_OFFSET;
311 1.15 briggs if ((memsize = ae_size_card_memory(sc)) == 0)
312 1.15 briggs return 0;
313 1.1 briggs
314 1.1 briggs /* Get station address from on-board ROM */
315 1.1 briggs for (i = 0; i < ETHER_ADDR_LEN; ++i)
316 1.1 briggs sc->arpcom.ac_enaddr[i] = *(sc->rom_addr + i*2);
317 1.1 briggs break;
318 1.8 briggs
319 1.8 briggs case AE_VENDOR_DAYNA:
320 1.9 briggs printf("We think we are a Dayna card, but ");
321 1.10 briggs sc->nic_addr = nu->addr + DP_NIC_OFFSET;
322 1.10 briggs sc->rom_addr = nu->addr + DP_ROM_OFFSET;
323 1.10 briggs sc->smem_start = nu->addr + DP_DATA_OFFSET;
324 1.8 briggs memsize = 8192;
325 1.8 briggs
326 1.8 briggs /* Get station address from on-board ROM */
327 1.8 briggs for (i = 0; i < ETHER_ADDR_LEN; ++i)
328 1.8 briggs sc->arpcom.ac_enaddr[i] = *(sc->rom_addr + i*2);
329 1.9 briggs printf("it is dangerous to continue.\n");
330 1.8 briggs return 0; /* Since we don't work yet... */
331 1.8 briggs break;
332 1.8 briggs
333 1.8 briggs default:
334 1.8 briggs return 0;
335 1.8 briggs break;
336 1.1 briggs }
337 1.7 briggs
338 1.1 briggs /*
339 1.1 briggs * allocate one xmit buffer if < 16k, two buffers otherwise
340 1.1 briggs */
341 1.1 briggs if ((memsize < 16384) || (flags & AE_FLAGS_NO_DOUBLE_BUFFERING)) {
342 1.15 briggs sc->smem_ring =
343 1.15 briggs sc->smem_start + (AE_PAGE_SIZE * AE_TXBUF_SIZE);
344 1.1 briggs sc->txb_cnt = 1;
345 1.1 briggs sc->rec_page_start = AE_TXBUF_SIZE;
346 1.1 briggs } else {
347 1.15 briggs sc->smem_ring =
348 1.15 briggs sc->smem_start + (AE_PAGE_SIZE * AE_TXBUF_SIZE * 2);
349 1.1 briggs sc->txb_cnt = 2;
350 1.1 briggs sc->rec_page_start = AE_TXBUF_SIZE * 2;
351 1.1 briggs }
352 1.1 briggs
353 1.1 briggs sc->smem_size = memsize;
354 1.1 briggs sc->smem_end = sc->smem_start + memsize;
355 1.1 briggs sc->rec_page_stop = memsize / AE_PAGE_SIZE;
356 1.1 briggs sc->tx_page_start = 0;
357 1.1 briggs
358 1.1 briggs /*
359 1.1 briggs * Now zero memory and verify that it is clear
360 1.1 briggs */
361 1.15 briggs bszero((u_short *)sc->smem_start, memsize / 2);
362 1.1 briggs
363 1.1 briggs for (i = 0; i < memsize; ++i)
364 1.1 briggs if (sc->smem_start[i]) {
365 1.15 briggs printf("ae: failed to clear shared memory at %x\n",
366 1.3 briggs sc->smem_start + i);
367 1.1 briggs
368 1.1 briggs return(0);
369 1.1 briggs }
370 1.1 briggs
371 1.1 briggs #ifdef DEBUG_PRINT
372 1.1 briggs printf("nic_addr %x, rom_addr %x\n",
373 1.1 briggs sc->nic_addr, sc->rom_addr);
374 1.1 briggs printf("smem_size %d\n", sc->smem_size);
375 1.1 briggs printf("smem_start %x, smem_ring %x, smem_end %x\n",
376 1.1 briggs sc->smem_start, sc->smem_ring, sc->smem_end);
377 1.1 briggs printf("phys address %02x:%02x:%02x:%02x:%02x:%02x\n",
378 1.1 briggs sc->arpcom.ac_enaddr[0],
379 1.1 briggs sc->arpcom.ac_enaddr[1],
380 1.1 briggs sc->arpcom.ac_enaddr[2],
381 1.1 briggs sc->arpcom.ac_enaddr[3],
382 1.1 briggs sc->arpcom.ac_enaddr[4],
383 1.1 briggs sc->arpcom.ac_enaddr[5]);
384 1.1 briggs #endif
385 1.1 briggs
386 1.1 briggs return(1);
387 1.1 briggs }
388 1.1 briggs
389 1.1 briggs /*
390 1.1 briggs * Install interface into kernel networking data structures
391 1.1 briggs */
392 1.9 briggs void
393 1.3 briggs ae_attach(parent, self, aux)
394 1.3 briggs struct cfdriver *parent, *self;
395 1.3 briggs void *aux;
396 1.1 briggs {
397 1.3 briggs struct nubus_hw *nu = aux;
398 1.3 briggs struct ae_device *ae = (struct ae_device *) self;
399 1.3 briggs struct ae_softc *sc = &ae_softc[ae->ae_dev.dv_unit];
400 1.3 briggs struct cfdata *cf = ae->ae_dev.dv_cfdata;
401 1.1 briggs struct ifnet *ifp = &sc->arpcom.ac_if;
402 1.1 briggs struct ifaddr *ifa;
403 1.1 briggs struct sockaddr_dl *sdl;
404 1.1 briggs
405 1.3 briggs sc->sc_ae = ae;
406 1.3 briggs
407 1.1 briggs /*
408 1.1 briggs * Set interface to stopped condition (reset)
409 1.1 briggs */
410 1.3 briggs ae_stop(sc);
411 1.1 briggs
412 1.1 briggs /*
413 1.1 briggs * Initialize ifnet structure
414 1.1 briggs */
415 1.3 briggs ifp->if_unit = ae->ae_dev.dv_unit;
416 1.3 briggs ifp->if_name = aecd.cd_name;
417 1.1 briggs ifp->if_mtu = ETHERMTU;
418 1.3 briggs ifp->if_output = ether_output;
419 1.1 briggs ifp->if_start = ae_start;
420 1.1 briggs ifp->if_ioctl = ae_ioctl;
421 1.1 briggs ifp->if_reset = ae_reset;
422 1.1 briggs ifp->if_watchdog = ae_watchdog;
423 1.1 briggs ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS);
424 1.1 briggs
425 1.3 briggs #if 0
426 1.3 briggs /*
427 1.3 briggs * Set default state for ALTPHYS flag (used to disable the transceiver
428 1.3 briggs * for AUI operation), based on compile-time config option.
429 1.3 briggs */
430 1.3 briggs if (cf->cf_flags & AE_FLAGS_DISABLE_TRANSCEIVER)
431 1.3 briggs ifp->if_flags |= IFF_ALTPHYS;
432 1.3 briggs #endif
433 1.3 briggs
434 1.1 briggs /*
435 1.1 briggs * Attach the interface
436 1.1 briggs */
437 1.1 briggs if_attach(ifp);
438 1.1 briggs
439 1.1 briggs /*
440 1.1 briggs * Search down the ifa address list looking for the AF_LINK type entry
441 1.1 briggs */
442 1.1 briggs ifa = ifp->if_addrlist;
443 1.1 briggs while ((ifa != 0) && (ifa->ifa_addr != 0) &&
444 1.1 briggs (ifa->ifa_addr->sa_family != AF_LINK))
445 1.1 briggs ifa = ifa->ifa_next;
446 1.1 briggs /*
447 1.1 briggs * If we find an AF_LINK type entry we fill in the hardware address.
448 1.1 briggs * This is useful for netstat(1) to keep track of which interface
449 1.1 briggs * is which.
450 1.1 briggs */
451 1.1 briggs if ((ifa != 0) && (ifa->ifa_addr != 0)) {
452 1.1 briggs /*
453 1.1 briggs * Fill in the link-level address for this interface
454 1.1 briggs */
455 1.1 briggs sdl = (struct sockaddr_dl *)ifa->ifa_addr;
456 1.1 briggs sdl->sdl_type = IFT_ETHER;
457 1.1 briggs sdl->sdl_alen = ETHER_ADDR_LEN;
458 1.1 briggs sdl->sdl_slen = 0;
459 1.12 lkestel bbcopy(sc->arpcom.ac_enaddr, LLADDR(sdl), ETHER_ADDR_LEN);
460 1.1 briggs }
461 1.1 briggs
462 1.1 briggs /*
463 1.1 briggs * Print additional info when attached
464 1.1 briggs */
465 1.3 briggs printf(": address %s, ", ether_sprintf(sc->arpcom.ac_enaddr));
466 1.1 briggs
467 1.1 briggs if (sc->type_str && (*sc->type_str != 0))
468 1.15 briggs printf("type %s", sc->type_str);
469 1.1 briggs else
470 1.15 briggs printf("type unknown (0x%x)", sc->type);
471 1.15 briggs
472 1.15 briggs printf(", %dk mem", sc->smem_size / 1024);
473 1.1 briggs
474 1.1 briggs printf("\n");
475 1.1 briggs
476 1.1 briggs /*
477 1.1 briggs * If BPF is in the kernel, call the attach for it
478 1.1 briggs */
479 1.1 briggs #if NBPFILTER > 0
480 1.1 briggs bpfattach(&sc->bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
481 1.1 briggs #endif
482 1.3 briggs }
483 1.1 briggs
484 1.1 briggs /*
485 1.1 briggs * Reset interface.
486 1.1 briggs */
487 1.1 briggs int
488 1.3 briggs ae_reset(sc)
489 1.3 briggs struct ae_softc *sc;
490 1.1 briggs {
491 1.1 briggs int s;
492 1.1 briggs
493 1.1 briggs s = splnet();
494 1.1 briggs
495 1.1 briggs /*
496 1.1 briggs * Stop interface and re-initialize.
497 1.1 briggs */
498 1.3 briggs ae_stop(sc);
499 1.3 briggs ae_init(sc);
500 1.1 briggs
501 1.1 briggs (void) splx(s);
502 1.1 briggs }
503 1.1 briggs
504 1.1 briggs /*
505 1.1 briggs * Take interface offline.
506 1.1 briggs */
507 1.1 briggs void
508 1.3 briggs ae_stop(sc)
509 1.3 briggs struct ae_softc *sc;
510 1.1 briggs {
511 1.1 briggs int n = 5000;
512 1.1 briggs
513 1.1 briggs /*
514 1.1 briggs * Stop everything on the interface, and select page 0 registers.
515 1.1 briggs */
516 1.1 briggs NIC_PUT(sc, AE_P0_CR, AE_CR_RD2|AE_CR_STP);
517 1.1 briggs
518 1.1 briggs /*
519 1.1 briggs * Wait for interface to enter stopped state, but limit # of checks
520 1.1 briggs * to 'n' (about 5ms). It shouldn't even take 5us on modern
521 1.1 briggs * DS8390's, but just in case it's an old one.
522 1.1 briggs */
523 1.1 briggs while (((NIC_GET(sc, AE_P0_ISR) & AE_ISR_RST) == 0) && --n);
524 1.1 briggs }
525 1.1 briggs
526 1.1 briggs /*
527 1.1 briggs * Device timeout/watchdog routine. Entered if the device neglects to
528 1.1 briggs * generate an interrupt after a transmit has been started on it.
529 1.1 briggs */
530 1.18 briggs static int aeintr_ctr=0;
531 1.1 briggs int
532 1.1 briggs ae_watchdog(unit)
533 1.3 briggs short unit;
534 1.1 briggs {
535 1.15 briggs struct ae_softc *sc = &ae_softc[unit];
536 1.15 briggs
537 1.18 briggs #if 1
538 1.18 briggs /*
539 1.18 briggs * This is a kludge! The via code seems to miss slot interrupts
540 1.18 briggs * sometimes. This kludges around that by calling the handler
541 1.18 briggs * by hand if the watchdog is activated. -- XXX (akb)
542 1.18 briggs */
543 1.18 briggs int i;
544 1.18 briggs
545 1.18 briggs i = aeintr_ctr;
546 1.18 briggs
547 1.18 briggs (*via2itab[1])(1);
548 1.18 briggs
549 1.19 briggs if (i != aeintr_ctr) {
550 1.19 briggs log(LOG_ERR, "ae%d: device timeout, recovered\n", unit);
551 1.18 briggs return;
552 1.19 briggs }
553 1.18 briggs #endif
554 1.18 briggs
555 1.1 briggs log(LOG_ERR, "ae%d: device timeout\n", unit);
556 1.15 briggs ae_reset(sc);
557 1.1 briggs }
558 1.1 briggs
559 1.1 briggs /*
560 1.1 briggs * Initialize device.
561 1.1 briggs */
562 1.3 briggs ae_init(sc)
563 1.3 briggs struct ae_softc *sc;
564 1.1 briggs {
565 1.1 briggs struct ifnet *ifp = &sc->arpcom.ac_if;
566 1.1 briggs int i, s;
567 1.1 briggs u_char command;
568 1.1 briggs
569 1.1 briggs /* address not known */
570 1.1 briggs if (ifp->if_addrlist == (struct ifaddr *)0) return;
571 1.1 briggs
572 1.1 briggs /*
573 1.1 briggs * Initialize the NIC in the exact order outlined in the NS manual.
574 1.1 briggs * This init procedure is "mandatory"...don't change what or when
575 1.1 briggs * things happen.
576 1.1 briggs */
577 1.1 briggs s = splnet();
578 1.1 briggs
579 1.1 briggs /* reset transmitter flags */
580 1.1 briggs sc->data_buffered = 0;
581 1.1 briggs sc->xmit_busy = 0;
582 1.1 briggs sc->arpcom.ac_if.if_timer = 0;
583 1.1 briggs
584 1.1 briggs sc->txb_next = 0;
585 1.1 briggs
586 1.1 briggs /* This variable is used below - don't move this assignment */
587 1.1 briggs sc->next_packet = sc->rec_page_start + 1;
588 1.1 briggs
589 1.1 briggs #ifdef DEBUG_PRINT
590 1.1 briggs printf("page_start %d, page_stop %d, next %d\n",
591 1.1 briggs sc->rec_page_start, sc->rec_page_stop, sc->next_packet);
592 1.1 briggs #endif
593 1.1 briggs
594 1.1 briggs /*
595 1.1 briggs * Set interface for page 0, Remote DMA complete, Stopped
596 1.1 briggs */
597 1.1 briggs NIC_PUT(sc, AE_P0_CR, AE_CR_RD2|AE_CR_STP);
598 1.1 briggs
599 1.1 briggs /*
600 1.1 briggs * Set FIFO threshold to 4, No auto-init Remote DMA, Burst mode,
601 1.1 briggs * byte order=80x86, word-wide DMA xfers,
602 1.1 briggs */
603 1.1 briggs NIC_PUT(sc, AE_P0_DCR, AE_DCR_FT1|AE_DCR_BMS|AE_DCR_WTS);
604 1.1 briggs
605 1.1 briggs /*
606 1.1 briggs * Clear Remote Byte Count Registers
607 1.1 briggs */
608 1.1 briggs NIC_PUT(sc, AE_P0_RBCR0, zero);
609 1.1 briggs NIC_PUT(sc, AE_P0_RBCR1, zero);
610 1.1 briggs
611 1.1 briggs /*
612 1.1 briggs * Enable reception of broadcast packets
613 1.1 briggs */
614 1.1 briggs NIC_PUT(sc, AE_P0_RCR, AE_RCR_AB);
615 1.1 briggs
616 1.1 briggs /*
617 1.1 briggs * Place NIC in internal loopback mode
618 1.1 briggs */
619 1.1 briggs NIC_PUT(sc, AE_P0_TCR, AE_TCR_LB0);
620 1.1 briggs
621 1.1 briggs /*
622 1.1 briggs * Initialize transmit/receive (ring-buffer) Page Start
623 1.1 briggs */
624 1.1 briggs NIC_PUT(sc, AE_P0_TPSR, sc->tx_page_start);
625 1.1 briggs NIC_PUT(sc, AE_P0_PSTART, sc->rec_page_start);
626 1.1 briggs
627 1.1 briggs /*
628 1.1 briggs * Initialize Receiver (ring-buffer) Page Stop and Boundry
629 1.1 briggs */
630 1.1 briggs NIC_PUT(sc, AE_P0_PSTOP, sc->rec_page_stop);
631 1.1 briggs NIC_PUT(sc, AE_P0_BNRY, sc->rec_page_start);
632 1.1 briggs
633 1.1 briggs /*
634 1.1 briggs * Clear all interrupts. A '1' in each bit position clears the
635 1.1 briggs * corresponding flag.
636 1.1 briggs */
637 1.1 briggs NIC_PUT(sc, AE_P0_ISR, ones);
638 1.1 briggs
639 1.15 briggs /* make sure interrupts are vectored to us */
640 1.15 briggs add_nubus_intr((int)sc->rom_addr & 0xFF000000, aeintr, sc - ae_softc);
641 1.15 briggs
642 1.1 briggs /*
643 1.1 briggs * Enable the following interrupts: receive/transmit complete,
644 1.1 briggs * receive/transmit error, and Receiver OverWrite.
645 1.1 briggs *
646 1.1 briggs * Counter overflow and Remote DMA complete are *not* enabled.
647 1.1 briggs */
648 1.1 briggs NIC_PUT(sc, AE_P0_IMR,
649 1.1 briggs AE_IMR_PRXE|AE_IMR_PTXE|AE_IMR_RXEE|AE_IMR_TXEE|AE_IMR_OVWE);
650 1.1 briggs
651 1.1 briggs /*
652 1.1 briggs * Program Command Register for page 1
653 1.1 briggs */
654 1.1 briggs NIC_PUT(sc, AE_P0_CR, AE_CR_PAGE_1|AE_CR_RD2|AE_CR_STP);
655 1.1 briggs
656 1.1 briggs /*
657 1.1 briggs * Copy out our station address
658 1.1 briggs */
659 1.1 briggs for (i = 0; i < ETHER_ADDR_LEN; ++i)
660 1.1 briggs NIC_PUT(sc, AE_P1_PAR0 + i, sc->arpcom.ac_enaddr[i]);
661 1.1 briggs
662 1.1 briggs #if NBPFILTER > 0
663 1.1 briggs /*
664 1.1 briggs * Initialize multicast address hashing registers to accept
665 1.1 briggs * all multicasts (only used when in promiscuous mode)
666 1.1 briggs */
667 1.1 briggs for (i = 0; i < 8; ++i)
668 1.1 briggs NIC_PUT(sc, AE_P1_MAR0 + i, 0xff);
669 1.1 briggs #endif
670 1.1 briggs
671 1.1 briggs /*
672 1.1 briggs * Set Current Page pointer to next_packet (initialized above)
673 1.1 briggs */
674 1.1 briggs NIC_PUT(sc, AE_P1_CURR, sc->next_packet);
675 1.1 briggs
676 1.1 briggs /*
677 1.1 briggs * Set Command Register for page 0, Remote DMA complete,
678 1.1 briggs * and interface Start.
679 1.1 briggs */
680 1.1 briggs NIC_PUT(sc, AE_P1_CR, AE_CR_RD2|AE_CR_STA);
681 1.1 briggs
682 1.1 briggs /*
683 1.1 briggs * Take interface out of loopback
684 1.1 briggs */
685 1.1 briggs NIC_PUT(sc, AE_P0_TCR, zero);
686 1.1 briggs
687 1.1 briggs /*
688 1.1 briggs * Set 'running' flag, and clear output active flag.
689 1.1 briggs */
690 1.1 briggs ifp->if_flags |= IFF_RUNNING;
691 1.1 briggs ifp->if_flags &= ~IFF_OACTIVE;
692 1.1 briggs
693 1.1 briggs /*
694 1.1 briggs * ...and attempt to start output
695 1.1 briggs */
696 1.1 briggs ae_start(ifp);
697 1.1 briggs
698 1.1 briggs (void) splx(s);
699 1.1 briggs }
700 1.1 briggs
701 1.1 briggs /*
702 1.1 briggs * This routine actually starts the transmission on the interface
703 1.1 briggs */
704 1.1 briggs static inline void ae_xmit(ifp)
705 1.1 briggs struct ifnet *ifp;
706 1.1 briggs {
707 1.1 briggs struct ae_softc *sc = &ae_softc[ifp->if_unit];
708 1.1 briggs u_short len = sc->txb_next_len;
709 1.1 briggs
710 1.1 briggs /*
711 1.1 briggs * Set NIC for page 0 register access
712 1.1 briggs */
713 1.1 briggs NIC_PUT(sc, AE_P0_CR, AE_CR_RD2|AE_CR_STA);
714 1.1 briggs
715 1.1 briggs /*
716 1.1 briggs * Set TX buffer start page
717 1.1 briggs */
718 1.1 briggs NIC_PUT(sc, AE_P0_TPSR, sc->tx_page_start +
719 1.1 briggs sc->txb_next * AE_TXBUF_SIZE);
720 1.1 briggs
721 1.1 briggs /*
722 1.1 briggs * Set TX length
723 1.1 briggs */
724 1.1 briggs NIC_PUT(sc, AE_P0_TBCR0, len & 0xff);
725 1.1 briggs NIC_PUT(sc, AE_P0_TBCR1, len >> 8);
726 1.1 briggs
727 1.1 briggs /*
728 1.1 briggs * Set page 0, Remote DMA complete, Transmit Packet, and *Start*
729 1.1 briggs */
730 1.1 briggs NIC_PUT(sc, AE_P0_CR, AE_CR_RD2|AE_CR_TXP|AE_CR_STA);
731 1.1 briggs
732 1.1 briggs sc->xmit_busy = 1;
733 1.1 briggs sc->data_buffered = 0;
734 1.1 briggs
735 1.1 briggs /*
736 1.1 briggs * Switch buffers if we are doing double-buffered transmits
737 1.1 briggs */
738 1.1 briggs if ((sc->txb_next == 0) && (sc->txb_cnt > 1))
739 1.1 briggs sc->txb_next = 1;
740 1.1 briggs else
741 1.1 briggs sc->txb_next = 0;
742 1.1 briggs
743 1.1 briggs /*
744 1.1 briggs * Set a timer just in case we never hear from the board again
745 1.1 briggs */
746 1.18 briggs ifp->if_timer = 2;
747 1.1 briggs }
748 1.1 briggs
749 1.1 briggs /*
750 1.1 briggs * Start output on interface.
751 1.1 briggs * We make two assumptions here:
752 1.1 briggs * 1) that the current priority is set to splnet _before_ this code
753 1.1 briggs * is called *and* is returned to the appropriate priority after
754 1.1 briggs * return
755 1.1 briggs * 2) that the IFF_OACTIVE flag is checked before this code is called
756 1.1 briggs * (i.e. that the output part of the interface is idle)
757 1.1 briggs */
758 1.1 briggs int
759 1.1 briggs ae_start(ifp)
760 1.1 briggs struct ifnet *ifp;
761 1.1 briggs {
762 1.1 briggs struct ae_softc *sc = &ae_softc[ifp->if_unit];
763 1.1 briggs struct mbuf *m0, *m;
764 1.1 briggs caddr_t buffer;
765 1.1 briggs int len;
766 1.1 briggs
767 1.1 briggs outloop:
768 1.1 briggs /*
769 1.1 briggs * See if there is room to send more data (i.e. one or both of the
770 1.1 briggs * buffers is empty).
771 1.1 briggs */
772 1.1 briggs if (sc->data_buffered)
773 1.1 briggs if (sc->xmit_busy) {
774 1.1 briggs /*
775 1.1 briggs * No room. Indicate this to the outside world
776 1.1 briggs * and exit.
777 1.1 briggs */
778 1.1 briggs ifp->if_flags |= IFF_OACTIVE;
779 1.1 briggs return;
780 1.1 briggs } else {
781 1.1 briggs /*
782 1.1 briggs * Data is buffered, but we're not transmitting, so
783 1.1 briggs * start the xmit on the buffered data.
784 1.1 briggs * Note that ae_xmit() resets the data_buffered flag
785 1.1 briggs * before returning.
786 1.1 briggs */
787 1.1 briggs ae_xmit(ifp);
788 1.1 briggs }
789 1.1 briggs
790 1.1 briggs IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
791 1.1 briggs if (m == 0) {
792 1.1 briggs /*
793 1.1 briggs * The following isn't pretty; we are using the !OACTIVE flag to
794 1.1 briggs * indicate to the outside world that we can accept an additional
795 1.1 briggs * packet rather than that the transmitter is _actually_
796 1.1 briggs * active. Indeed, the transmitter may be active, but if we haven't
797 1.1 briggs * filled the secondary buffer with data then we still want to
798 1.1 briggs * accept more.
799 1.1 briggs * Note that it isn't necessary to test the data_buffered flag -
800 1.1 briggs * we wouldn't have tried to de-queue the packet in the first place
801 1.1 briggs * if it was set.
802 1.1 briggs */
803 1.1 briggs ifp->if_flags &= ~IFF_OACTIVE;
804 1.1 briggs return;
805 1.1 briggs }
806 1.1 briggs
807 1.1 briggs /*
808 1.1 briggs * Copy the mbuf chain into the transmit buffer
809 1.1 briggs */
810 1.1 briggs buffer = sc->smem_start + (sc->txb_next * AE_TXBUF_SIZE * AE_PAGE_SIZE);
811 1.1 briggs len = 0;
812 1.1 briggs for (m0 = m; m != 0; m = m->m_next) {
813 1.1 briggs /*printf("ae: copy %d bytes @ %x\n", m->m_len, buffer);*/
814 1.15 briggs bscopy(mtod(m, caddr_t), buffer, m->m_len);
815 1.1 briggs buffer += m->m_len;
816 1.1 briggs len += m->m_len;
817 1.1 briggs }
818 1.15 briggs if (len & 1) len++;
819 1.1 briggs
820 1.13 briggs sc->txb_next_len = max(len, ETHER_MIN_LEN);
821 1.1 briggs
822 1.1 briggs if (sc->txb_cnt > 1)
823 1.1 briggs /*
824 1.1 briggs * only set 'buffered' flag if doing multiple buffers
825 1.1 briggs */
826 1.1 briggs sc->data_buffered = 1;
827 1.1 briggs
828 1.1 briggs if (sc->xmit_busy == 0)
829 1.1 briggs ae_xmit(ifp);
830 1.1 briggs /*
831 1.1 briggs * If there is BPF support in the configuration, tap off here.
832 1.1 briggs * The following has support for converting trailer packets
833 1.1 briggs * back to normal.
834 1.1 briggs */
835 1.1 briggs #if NBPFILTER > 0
836 1.1 briggs if (sc->bpf) {
837 1.1 briggs u_short etype;
838 1.1 briggs int off, datasize, resid;
839 1.1 briggs struct ether_header *eh;
840 1.1 briggs struct trailer_header {
841 1.1 briggs u_short ether_type;
842 1.1 briggs u_short ether_residual;
843 1.1 briggs } trailer_header;
844 1.1 briggs char ether_packet[ETHER_MAX_LEN];
845 1.1 briggs char *ep;
846 1.1 briggs
847 1.1 briggs ep = ether_packet;
848 1.1 briggs
849 1.1 briggs /*
850 1.1 briggs * We handle trailers below:
851 1.1 briggs * Copy ether header first, then residual data,
852 1.1 briggs * then data. Put all this in a temporary buffer
853 1.1 briggs * 'ether_packet' and send off to bpf. Since the
854 1.1 briggs * system has generated this packet, we assume
855 1.1 briggs * that all of the offsets in the packet are
856 1.1 briggs * correct; if they're not, the system will almost
857 1.1 briggs * certainly crash in m_copydata.
858 1.1 briggs * We make no assumptions about how the data is
859 1.1 briggs * arranged in the mbuf chain (i.e. how much
860 1.1 briggs * data is in each mbuf, if mbuf clusters are
861 1.1 briggs * used, etc.), which is why we use m_copydata
862 1.1 briggs * to get the ether header rather than assume
863 1.1 briggs * that this is located in the first mbuf.
864 1.1 briggs */
865 1.1 briggs /* copy ether header */
866 1.1 briggs m_copydata(m0, 0, sizeof(struct ether_header), ep);
867 1.1 briggs eh = (struct ether_header *) ep;
868 1.1 briggs ep += sizeof(struct ether_header);
869 1.1 briggs etype = ntohs(eh->ether_type);
870 1.1 briggs if (etype >= ETHERTYPE_TRAIL &&
871 1.1 briggs etype < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
872 1.1 briggs datasize = ((etype - ETHERTYPE_TRAIL) << 9);
873 1.1 briggs off = datasize + sizeof(struct ether_header);
874 1.1 briggs
875 1.1 briggs /* copy trailer_header into a data structure */
876 1.1 briggs m_copydata(m0, off, sizeof(struct trailer_header),
877 1.1 briggs &trailer_header.ether_type);
878 1.1 briggs
879 1.1 briggs /* copy residual data */
880 1.1 briggs m_copydata(m0, off+sizeof(struct trailer_header),
881 1.1 briggs resid = ntohs(trailer_header.ether_residual) -
882 1.1 briggs sizeof(struct trailer_header), ep);
883 1.1 briggs ep += resid;
884 1.1 briggs
885 1.1 briggs /* copy data */
886 1.1 briggs m_copydata(m0, sizeof(struct ether_header),
887 1.1 briggs datasize, ep);
888 1.1 briggs ep += datasize;
889 1.1 briggs
890 1.1 briggs /* restore original ether packet type */
891 1.1 briggs eh->ether_type = trailer_header.ether_type;
892 1.1 briggs
893 1.1 briggs bpf_tap(sc->bpf, ether_packet, ep - ether_packet);
894 1.1 briggs } else
895 1.1 briggs bpf_mtap(sc->bpf, m0);
896 1.1 briggs }
897 1.1 briggs #endif
898 1.1 briggs
899 1.1 briggs m_freem(m0);
900 1.1 briggs
901 1.1 briggs /*
902 1.1 briggs * If we are doing double-buffering, a buffer might be free to
903 1.1 briggs * fill with another packet, so loop back to the top.
904 1.1 briggs */
905 1.1 briggs if (sc->txb_cnt > 1)
906 1.1 briggs goto outloop;
907 1.1 briggs else {
908 1.1 briggs ifp->if_flags |= IFF_OACTIVE;
909 1.1 briggs return;
910 1.1 briggs }
911 1.1 briggs }
912 1.1 briggs
913 1.1 briggs /*
914 1.1 briggs * Ethernet interface receiver interrupt.
915 1.1 briggs */
916 1.1 briggs static inline void
917 1.1 briggs ae_rint(unit)
918 1.1 briggs int unit;
919 1.1 briggs {
920 1.1 briggs register struct ae_softc *sc = &ae_softc[unit];
921 1.1 briggs u_char boundry, current;
922 1.1 briggs u_short len;
923 1.1 briggs struct ae_ring *packet_ptr;
924 1.1 briggs
925 1.1 briggs /*
926 1.1 briggs * Set NIC to page 1 registers to get 'current' pointer
927 1.1 briggs */
928 1.1 briggs NIC_PUT(sc, AE_P0_CR, AE_CR_PAGE_1|AE_CR_RD2|AE_CR_STA);
929 1.1 briggs
930 1.1 briggs /*
931 1.1 briggs * 'sc->next_packet' is the logical beginning of the ring-buffer - i.e.
932 1.1 briggs * it points to where new data has been buffered. The 'CURR'
933 1.1 briggs * (current) register points to the logical end of the ring-buffer
934 1.1 briggs * - i.e. it points to where additional new data will be added.
935 1.1 briggs * We loop here until the logical beginning equals the logical
936 1.1 briggs * end (or in other words, until the ring-buffer is empty).
937 1.1 briggs */
938 1.1 briggs while (sc->next_packet != NIC_GET(sc, AE_P1_CURR)) {
939 1.1 briggs
940 1.1 briggs /* get pointer to this buffer header structure */
941 1.1 briggs packet_ptr = (struct ae_ring *)(sc->smem_ring +
942 1.1 briggs (sc->next_packet - sc->rec_page_start) * AE_PAGE_SIZE);
943 1.1 briggs
944 1.1 briggs /*
945 1.1 briggs * The byte count includes the FCS - Frame Check Sequence (a
946 1.1 briggs * 32 bit CRC).
947 1.1 briggs */
948 1.1 briggs len = packet_ptr->count[0] | (packet_ptr->count[1] << 8);
949 1.1 briggs if ((len >= ETHER_MIN_LEN) && (len <= ETHER_MAX_LEN)) {
950 1.1 briggs /*
951 1.1 briggs * Go get packet. len - 4 removes CRC from length.
952 1.15 briggs * (packet_ptr + 1) points to data just after the
953 1.15 briggs * packet ring header (+4 bytes)
954 1.1 briggs */
955 1.1 briggs ae_get_packet(sc, (caddr_t)(packet_ptr + 1), len - 4);
956 1.1 briggs ++sc->arpcom.ac_if.if_ipackets;
957 1.1 briggs } else {
958 1.1 briggs /*
959 1.15 briggs * Really BAD...probably indicates that the ring
960 1.15 briggs * pointers are corrupted. Also seen on early rev
961 1.15 briggs * chips under high load - the byte order of the
962 1.15 briggs * length gets switched.
963 1.1 briggs */
964 1.1 briggs log(LOG_ERR,
965 1.1 briggs "ae%d: shared memory corrupt - invalid packet length %d\n",
966 1.1 briggs unit, len);
967 1.15 briggs ae_reset(sc);
968 1.1 briggs return;
969 1.1 briggs }
970 1.1 briggs
971 1.1 briggs /*
972 1.1 briggs * Update next packet pointer
973 1.1 briggs */
974 1.1 briggs sc->next_packet = packet_ptr->next_packet;
975 1.1 briggs
976 1.1 briggs /*
977 1.1 briggs * Update NIC boundry pointer - being careful to keep it
978 1.1 briggs * one buffer behind. (as recommended by NS databook)
979 1.1 briggs */
980 1.1 briggs boundry = sc->next_packet - 1;
981 1.1 briggs if (boundry < sc->rec_page_start)
982 1.1 briggs boundry = sc->rec_page_stop - 1;
983 1.1 briggs
984 1.1 briggs /*
985 1.1 briggs * Set NIC to page 0 registers to update boundry register
986 1.1 briggs */
987 1.1 briggs NIC_PUT(sc, AE_P0_CR, AE_CR_RD2|AE_CR_STA);
988 1.1 briggs
989 1.1 briggs NIC_PUT(sc, AE_P0_BNRY, boundry);
990 1.1 briggs
991 1.1 briggs /*
992 1.15 briggs * Set NIC to page 1 registers before looping to top
993 1.15 briggs * (prepare to get 'CURR' current pointer)
994 1.1 briggs */
995 1.1 briggs NIC_PUT(sc, AE_P0_CR, AE_CR_PAGE_1|AE_CR_RD2|AE_CR_STA);
996 1.1 briggs }
997 1.1 briggs }
998 1.1 briggs
999 1.1 briggs /*
1000 1.1 briggs * Ethernet interface interrupt processor
1001 1.1 briggs */
1002 1.18 briggs int
1003 1.1 briggs aeintr(unit)
1004 1.1 briggs int unit;
1005 1.1 briggs {
1006 1.1 briggs struct ae_softc *sc = &ae_softc[unit];
1007 1.1 briggs u_char isr;
1008 1.1 briggs
1009 1.18 briggs aeintr_ctr++;
1010 1.1 briggs /*
1011 1.1 briggs * Set NIC to page 0 registers
1012 1.1 briggs */
1013 1.1 briggs NIC_PUT(sc, AE_P0_CR, AE_CR_RD2|AE_CR_STA);
1014 1.1 briggs
1015 1.1 briggs /*
1016 1.1 briggs * loop until there are no more new interrupts
1017 1.1 briggs */
1018 1.1 briggs while (isr = NIC_GET(sc, AE_P0_ISR)) {
1019 1.1 briggs
1020 1.1 briggs /*
1021 1.1 briggs * reset all the bits that we are 'acknowledging'
1022 1.1 briggs * by writing a '1' to each bit position that was set
1023 1.1 briggs * (writing a '1' *clears* the bit)
1024 1.1 briggs */
1025 1.1 briggs NIC_PUT(sc, AE_P0_ISR, isr);
1026 1.1 briggs
1027 1.1 briggs /*
1028 1.1 briggs * Handle transmitter interrupts. Handle these first
1029 1.1 briggs * because the receiver will reset the board under
1030 1.1 briggs * some conditions.
1031 1.1 briggs */
1032 1.1 briggs if (isr & (AE_ISR_PTX|AE_ISR_TXE)) {
1033 1.1 briggs u_char collisions = NIC_GET(sc, AE_P0_NCR);
1034 1.1 briggs
1035 1.1 briggs /*
1036 1.1 briggs * Check for transmit error. If a TX completed with an
1037 1.1 briggs * error, we end up throwing the packet away. Really
1038 1.1 briggs * the only error that is possible is excessive
1039 1.1 briggs * collisions, and in this case it is best to allow the
1040 1.1 briggs * automatic mechanisms of TCP to backoff the flow. Of
1041 1.1 briggs * course, with UDP we're screwed, but this is expected
1042 1.1 briggs * when a network is heavily loaded.
1043 1.1 briggs */
1044 1.1 briggs if (isr & AE_ISR_TXE) {
1045 1.1 briggs
1046 1.1 briggs /*
1047 1.1 briggs * Excessive collisions (16)
1048 1.1 briggs */
1049 1.1 briggs if ((NIC_GET(sc, AE_P0_TSR) & AE_TSR_ABT)
1050 1.1 briggs && (collisions == 0)) {
1051 1.1 briggs /*
1052 1.1 briggs * When collisions total 16, the
1053 1.1 briggs * P0_NCR will indicate 0, and the
1054 1.1 briggs * TSR_ABT is set.
1055 1.1 briggs */
1056 1.1 briggs collisions = 16;
1057 1.1 briggs }
1058 1.1 briggs
1059 1.1 briggs /*
1060 1.1 briggs * update output errors counter
1061 1.1 briggs */
1062 1.1 briggs ++sc->arpcom.ac_if.if_oerrors;
1063 1.1 briggs } else {
1064 1.1 briggs /*
1065 1.1 briggs * Update total number of successfully
1066 1.1 briggs * transmitted packets.
1067 1.1 briggs */
1068 1.1 briggs ++sc->arpcom.ac_if.if_opackets;
1069 1.1 briggs }
1070 1.1 briggs
1071 1.1 briggs /*
1072 1.1 briggs * reset tx busy and output active flags
1073 1.1 briggs */
1074 1.1 briggs sc->xmit_busy = 0;
1075 1.1 briggs sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
1076 1.1 briggs
1077 1.1 briggs /*
1078 1.1 briggs * clear watchdog timer
1079 1.1 briggs */
1080 1.1 briggs sc->arpcom.ac_if.if_timer = 0;
1081 1.1 briggs
1082 1.1 briggs /*
1083 1.1 briggs * Add in total number of collisions on last
1084 1.1 briggs * transmission.
1085 1.1 briggs */
1086 1.1 briggs sc->arpcom.ac_if.if_collisions += collisions;
1087 1.1 briggs
1088 1.1 briggs /*
1089 1.1 briggs * If data is ready to transmit, start it transmitting,
1090 1.1 briggs * otherwise defer until after handling receiver
1091 1.1 briggs */
1092 1.1 briggs if (sc->data_buffered)
1093 1.1 briggs ae_xmit(&sc->arpcom.ac_if);
1094 1.1 briggs }
1095 1.1 briggs
1096 1.1 briggs /*
1097 1.1 briggs * Handle receiver interrupts
1098 1.1 briggs */
1099 1.1 briggs if (isr & (AE_ISR_PRX|AE_ISR_RXE|AE_ISR_OVW)) {
1100 1.1 briggs /*
1101 1.1 briggs * Overwrite warning. In order to make sure that a lockup
1102 1.1 briggs * of the local DMA hasn't occurred, we reset and
1103 1.1 briggs * re-init the NIC. The NSC manual suggests only a
1104 1.1 briggs * partial reset/re-init is necessary - but some
1105 1.1 briggs * chips seem to want more. The DMA lockup has been
1106 1.1 briggs * seen only with early rev chips - Methinks this
1107 1.1 briggs * bug was fixed in later revs. -DG
1108 1.1 briggs */
1109 1.1 briggs if (isr & AE_ISR_OVW) {
1110 1.1 briggs ++sc->arpcom.ac_if.if_ierrors;
1111 1.1 briggs log(LOG_WARNING,
1112 1.1 briggs "ae%d: warning - receiver ring buffer overrun\n",
1113 1.1 briggs unit);
1114 1.1 briggs /*
1115 1.1 briggs * Stop/reset/re-init NIC
1116 1.1 briggs */
1117 1.15 briggs ae_reset(sc);
1118 1.1 briggs } else {
1119 1.1 briggs
1120 1.1 briggs /*
1121 1.1 briggs * Receiver Error. One or more of: CRC error, frame
1122 1.1 briggs * alignment error FIFO overrun, or missed packet.
1123 1.1 briggs */
1124 1.1 briggs if (isr & AE_ISR_RXE) {
1125 1.1 briggs ++sc->arpcom.ac_if.if_ierrors;
1126 1.1 briggs #ifdef AE_DEBUG
1127 1.1 briggs printf("ae%d: receive error %x\n", unit,
1128 1.1 briggs NIC_GET(sc, AE_P0_RSR));
1129 1.1 briggs #endif
1130 1.1 briggs }
1131 1.1 briggs
1132 1.1 briggs /*
1133 1.1 briggs * Go get the packet(s)
1134 1.1 briggs * XXX - Doing this on an error is dubious
1135 1.1 briggs * because there shouldn't be any data to
1136 1.1 briggs * get (we've configured the interface to
1137 1.1 briggs * not accept packets with errors).
1138 1.1 briggs */
1139 1.1 briggs ae_rint (unit);
1140 1.1 briggs }
1141 1.1 briggs }
1142 1.1 briggs
1143 1.1 briggs /*
1144 1.1 briggs * If it looks like the transmitter can take more data,
1145 1.1 briggs * attempt to start output on the interface.
1146 1.1 briggs * This is done after handling the receiver to
1147 1.1 briggs * give the receiver priority.
1148 1.1 briggs */
1149 1.1 briggs if ((sc->arpcom.ac_if.if_flags & IFF_OACTIVE) == 0)
1150 1.1 briggs ae_start(&sc->arpcom.ac_if);
1151 1.1 briggs
1152 1.1 briggs /*
1153 1.1 briggs * return NIC CR to standard state: page 0, remote DMA complete,
1154 1.1 briggs * start (toggling the TXP bit off, even if was just set
1155 1.1 briggs * in the transmit routine, is *okay* - it is 'edge'
1156 1.1 briggs * triggered from low to high)
1157 1.1 briggs */
1158 1.1 briggs NIC_PUT(sc, AE_P0_CR, AE_CR_RD2|AE_CR_STA);
1159 1.1 briggs
1160 1.1 briggs /*
1161 1.1 briggs * If the Network Talley Counters overflow, read them to
1162 1.1 briggs * reset them. It appears that old 8390's won't
1163 1.1 briggs * clear the ISR flag otherwise - resulting in an
1164 1.1 briggs * infinite loop.
1165 1.1 briggs */
1166 1.1 briggs if (isr & AE_ISR_CNT) {
1167 1.1 briggs (void) NIC_GET(sc, AE_P0_CNTR0);
1168 1.1 briggs (void) NIC_GET(sc, AE_P0_CNTR1);
1169 1.1 briggs (void) NIC_GET(sc, AE_P0_CNTR2);
1170 1.1 briggs }
1171 1.1 briggs }
1172 1.18 briggs return 0;
1173 1.1 briggs }
1174 1.1 briggs
1175 1.1 briggs /*
1176 1.1 briggs * Process an ioctl request. This code needs some work - it looks
1177 1.1 briggs * pretty ugly.
1178 1.1 briggs */
1179 1.1 briggs int
1180 1.1 briggs ae_ioctl(ifp, command, data)
1181 1.1 briggs register struct ifnet *ifp;
1182 1.1 briggs int command;
1183 1.1 briggs caddr_t data;
1184 1.1 briggs {
1185 1.1 briggs register struct ifaddr *ifa = (struct ifaddr *)data;
1186 1.1 briggs struct ae_softc *sc = &ae_softc[ifp->if_unit];
1187 1.1 briggs struct ifreq *ifr = (struct ifreq *)data;
1188 1.1 briggs int s, error = 0;
1189 1.1 briggs
1190 1.1 briggs s = splnet();
1191 1.1 briggs
1192 1.1 briggs switch (command) {
1193 1.1 briggs
1194 1.1 briggs case SIOCSIFADDR:
1195 1.1 briggs ifp->if_flags |= IFF_UP;
1196 1.1 briggs
1197 1.1 briggs switch (ifa->ifa_addr->sa_family) {
1198 1.1 briggs #ifdef INET
1199 1.1 briggs case AF_INET:
1200 1.11 briggs ae_init(sc); /* before arpwhohas */
1201 1.1 briggs /*
1202 1.1 briggs * See if another station has *our* IP address.
1203 1.1 briggs * i.e.: There is an address conflict! If a
1204 1.1 briggs * conflict exists, a message is sent to the
1205 1.1 briggs * console.
1206 1.1 briggs */
1207 1.1 briggs ((struct arpcom *)ifp)->ac_ipaddr =
1208 1.1 briggs IA_SIN(ifa)->sin_addr;
1209 1.1 briggs arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
1210 1.1 briggs break;
1211 1.1 briggs #endif
1212 1.1 briggs #ifdef NS
1213 1.1 briggs /*
1214 1.1 briggs * XXX - This code is probably wrong
1215 1.1 briggs */
1216 1.1 briggs case AF_NS:
1217 1.1 briggs {
1218 1.1 briggs register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
1219 1.1 briggs
1220 1.1 briggs if (ns_nullhost(*ina))
1221 1.1 briggs ina->x_host =
1222 1.1 briggs *(union ns_host *)(sc->arpcom.ac_enaddr);
1223 1.1 briggs else {
1224 1.1 briggs /*
1225 1.1 briggs *
1226 1.1 briggs */
1227 1.12 lkestel bbcopy((caddr_t)ina->x_host.c_host,
1228 1.1 briggs (caddr_t)sc->arpcom.ac_enaddr,
1229 1.1 briggs sizeof(sc->arpcom.ac_enaddr));
1230 1.1 briggs }
1231 1.1 briggs /*
1232 1.1 briggs * Set new address
1233 1.1 briggs */
1234 1.11 briggs ae_init(sc);
1235 1.1 briggs break;
1236 1.1 briggs }
1237 1.1 briggs #endif
1238 1.1 briggs default:
1239 1.11 briggs ae_init(sc);
1240 1.1 briggs break;
1241 1.1 briggs }
1242 1.1 briggs break;
1243 1.1 briggs
1244 1.1 briggs case SIOCSIFFLAGS:
1245 1.1 briggs /*
1246 1.1 briggs * If interface is marked down and it is running, then stop it
1247 1.1 briggs */
1248 1.1 briggs if (((ifp->if_flags & IFF_UP) == 0) &&
1249 1.1 briggs (ifp->if_flags & IFF_RUNNING)) {
1250 1.15 briggs ae_stop(sc);
1251 1.1 briggs ifp->if_flags &= ~IFF_RUNNING;
1252 1.1 briggs } else {
1253 1.1 briggs /*
1254 1.1 briggs * If interface is marked up and it is stopped, then start it
1255 1.1 briggs */
1256 1.1 briggs if ((ifp->if_flags & IFF_UP) &&
1257 1.1 briggs ((ifp->if_flags & IFF_RUNNING) == 0))
1258 1.11 briggs ae_init(sc);
1259 1.1 briggs }
1260 1.1 briggs #if NBPFILTER > 0
1261 1.1 briggs if (ifp->if_flags & IFF_PROMISC) {
1262 1.1 briggs /*
1263 1.1 briggs * Set promiscuous mode on interface.
1264 1.1 briggs * XXX - for multicasts to work, we would need to
1265 1.1 briggs * write 1's in all bits of multicast
1266 1.1 briggs * hashing array. For now we assume that
1267 1.1 briggs * this was done in ae_init().
1268 1.1 briggs */
1269 1.1 briggs NIC_PUT(sc, AE_P0_RCR,
1270 1.1 briggs AE_RCR_PRO|AE_RCR_AM|AE_RCR_AB);
1271 1.1 briggs } else {
1272 1.1 briggs /*
1273 1.1 briggs * XXX - for multicasts to work, we would need to
1274 1.1 briggs * rewrite the multicast hashing array with the
1275 1.1 briggs * proper hash (would have been destroyed above).
1276 1.1 briggs */
1277 1.1 briggs NIC_PUT(sc, AE_P0_RCR, AE_RCR_AB);
1278 1.1 briggs }
1279 1.1 briggs #endif
1280 1.1 briggs break;
1281 1.1 briggs
1282 1.1 briggs default:
1283 1.1 briggs error = EINVAL;
1284 1.1 briggs }
1285 1.1 briggs (void) splx(s);
1286 1.1 briggs return (error);
1287 1.1 briggs }
1288 1.1 briggs
1289 1.1 briggs /*
1290 1.1 briggs * Macro to calculate a new address within shared memory when given an offset
1291 1.1 briggs * from an address, taking into account ring-wrap.
1292 1.1 briggs */
1293 1.1 briggs #define ringoffset(sc, start, off, type) \
1294 1.1 briggs ((type)( ((caddr_t)(start)+(off) >= (sc)->smem_end) ? \
1295 1.1 briggs (((caddr_t)(start)+(off))) - (sc)->smem_end \
1296 1.1 briggs + (sc)->smem_ring: \
1297 1.1 briggs ((caddr_t)(start)+(off)) ))
1298 1.1 briggs
1299 1.1 briggs /*
1300 1.1 briggs * Retreive packet from shared memory and send to the next level up via
1301 1.1 briggs * ether_input(). If there is a BPF listener, give a copy to BPF, too.
1302 1.1 briggs */
1303 1.1 briggs ae_get_packet(sc, buf, len)
1304 1.1 briggs struct ae_softc *sc;
1305 1.1 briggs char *buf;
1306 1.1 briggs u_short len;
1307 1.1 briggs {
1308 1.1 briggs struct ether_header *eh;
1309 1.1 briggs struct mbuf *m, *head, *ae_ring_to_mbuf();
1310 1.1 briggs u_short off;
1311 1.1 briggs int resid;
1312 1.1 briggs u_short etype;
1313 1.1 briggs struct trailer_header {
1314 1.1 briggs u_short trail_type;
1315 1.1 briggs u_short trail_residual;
1316 1.1 briggs } trailer_header;
1317 1.1 briggs
1318 1.1 briggs /* Allocate a header mbuf */
1319 1.1 briggs MGETHDR(m, M_DONTWAIT, MT_DATA);
1320 1.1 briggs if (m == 0)
1321 1.1 briggs goto bad;
1322 1.1 briggs m->m_pkthdr.rcvif = &sc->arpcom.ac_if;
1323 1.1 briggs m->m_pkthdr.len = len;
1324 1.1 briggs m->m_len = 0;
1325 1.1 briggs head = m;
1326 1.1 briggs
1327 1.1 briggs eh = (struct ether_header *)buf;
1328 1.1 briggs
1329 1.1 briggs /* The following sillines is to make NFS happy */
1330 1.1 briggs #define EROUND ((sizeof(struct ether_header) + 3) & ~3)
1331 1.1 briggs #define EOFF (EROUND - sizeof(struct ether_header))
1332 1.1 briggs
1333 1.1 briggs /*
1334 1.1 briggs * The following assumes there is room for
1335 1.1 briggs * the ether header in the header mbuf
1336 1.1 briggs */
1337 1.1 briggs head->m_data += EOFF;
1338 1.12 lkestel bbcopy(buf, mtod(head, caddr_t), sizeof(struct ether_header));
1339 1.1 briggs buf += sizeof(struct ether_header);
1340 1.1 briggs head->m_len += sizeof(struct ether_header);
1341 1.1 briggs len -= sizeof(struct ether_header);
1342 1.1 briggs
1343 1.1 briggs etype = ntohs((u_short)eh->ether_type);
1344 1.1 briggs
1345 1.1 briggs /*
1346 1.1 briggs * Deal with trailer protocol:
1347 1.1 briggs * If trailer protocol, calculate the datasize as 'off',
1348 1.1 briggs * which is also the offset to the trailer header.
1349 1.1 briggs * Set resid to the amount of packet data following the
1350 1.1 briggs * trailer header.
1351 1.1 briggs * Finally, copy residual data into mbuf chain.
1352 1.1 briggs */
1353 1.1 briggs if (etype >= ETHERTYPE_TRAIL &&
1354 1.1 briggs etype < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
1355 1.1 briggs
1356 1.1 briggs off = (etype - ETHERTYPE_TRAIL) << 9;
1357 1.1 briggs if ((off + sizeof(struct trailer_header)) > len)
1358 1.1 briggs goto bad; /* insanity */
1359 1.1 briggs
1360 1.1 briggs eh->ether_type = *ringoffset(sc, buf, off, u_short *);
1361 1.1 briggs resid = ntohs(*ringoffset(sc, buf, off+2, u_short *));
1362 1.1 briggs
1363 1.1 briggs if ((off + resid) > len) goto bad; /* insanity */
1364 1.1 briggs
1365 1.1 briggs resid -= sizeof(struct trailer_header);
1366 1.1 briggs if (resid < 0) goto bad; /* insanity */
1367 1.1 briggs
1368 1.15 briggs m = ae_ring_to_mbuf(sc, ringoffset(sc, buf, off+4, char *),
1369 1.15 briggs head, resid);
1370 1.1 briggs if (m == 0) goto bad;
1371 1.1 briggs
1372 1.1 briggs len = off;
1373 1.1 briggs head->m_pkthdr.len -= 4; /* subtract trailer header */
1374 1.1 briggs }
1375 1.1 briggs
1376 1.1 briggs /*
1377 1.1 briggs * Pull packet off interface. Or if this was a trailer packet,
1378 1.1 briggs * the data portion is appended.
1379 1.1 briggs */
1380 1.1 briggs m = ae_ring_to_mbuf(sc, buf, m, len);
1381 1.1 briggs if (m == 0) goto bad;
1382 1.1 briggs
1383 1.1 briggs #if NBPFILTER > 0
1384 1.1 briggs /*
1385 1.1 briggs * Check if there's a BPF listener on this interface.
1386 1.1 briggs * If so, hand off the raw packet to bpf.
1387 1.1 briggs */
1388 1.1 briggs if (sc->bpf) {
1389 1.1 briggs bpf_mtap(sc->bpf, head);
1390 1.1 briggs
1391 1.1 briggs /*
1392 1.1 briggs * Note that the interface cannot be in promiscuous mode if
1393 1.1 briggs * there are no BPF listeners. And if we are in promiscuous
1394 1.1 briggs * mode, we have to check if this packet is really ours.
1395 1.1 briggs *
1396 1.1 briggs * XXX This test does not support multicasts.
1397 1.1 briggs */
1398 1.1 briggs if ((sc->arpcom.ac_if.if_flags & IFF_PROMISC) &&
1399 1.1 briggs bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr,
1400 1.1 briggs sizeof(eh->ether_dhost)) != 0 &&
1401 1.1 briggs bcmp(eh->ether_dhost, etherbroadcastaddr,
1402 1.1 briggs sizeof(eh->ether_dhost)) != 0) {
1403 1.1 briggs
1404 1.1 briggs m_freem(head);
1405 1.1 briggs return;
1406 1.1 briggs }
1407 1.1 briggs }
1408 1.1 briggs #endif
1409 1.1 briggs
1410 1.1 briggs /*
1411 1.1 briggs * Fix up data start offset in mbuf to point past ether header
1412 1.1 briggs */
1413 1.1 briggs m_adj(head, sizeof(struct ether_header));
1414 1.1 briggs
1415 1.1 briggs ether_input(&sc->arpcom.ac_if, eh, head);
1416 1.1 briggs return;
1417 1.1 briggs
1418 1.1 briggs bad: if (head)
1419 1.1 briggs m_freem(head);
1420 1.1 briggs return;
1421 1.1 briggs }
1422 1.1 briggs
1423 1.1 briggs /*
1424 1.1 briggs * Supporting routines
1425 1.1 briggs */
1426 1.1 briggs
1427 1.1 briggs /*
1428 1.1 briggs * Given a source and destination address, copy 'amount' of a packet from
1429 1.1 briggs * the ring buffer into a linear destination buffer. Takes into account
1430 1.1 briggs * ring-wrap.
1431 1.1 briggs */
1432 1.1 briggs static inline char *
1433 1.1 briggs ae_ring_copy(sc,src,dst,amount)
1434 1.1 briggs struct ae_softc *sc;
1435 1.1 briggs char *src;
1436 1.1 briggs char *dst;
1437 1.1 briggs u_short amount;
1438 1.1 briggs {
1439 1.1 briggs u_short tmp_amount;
1440 1.1 briggs
1441 1.1 briggs /* does copy wrap to lower addr in ring buffer? */
1442 1.1 briggs if (src + amount > sc->smem_end) {
1443 1.1 briggs tmp_amount = sc->smem_end - src;
1444 1.15 briggs /* copy amount up to end of smem */
1445 1.15 briggs bbcopy(src, dst, tmp_amount);
1446 1.1 briggs amount -= tmp_amount;
1447 1.1 briggs src = sc->smem_ring;
1448 1.1 briggs dst += tmp_amount;
1449 1.1 briggs }
1450 1.1 briggs
1451 1.12 lkestel bbcopy(src, dst, amount);
1452 1.1 briggs
1453 1.1 briggs return(src + amount);
1454 1.1 briggs }
1455 1.1 briggs
1456 1.1 briggs /*
1457 1.1 briggs * Copy data from receive buffer to end of mbuf chain
1458 1.1 briggs * allocate additional mbufs as needed. return pointer
1459 1.1 briggs * to last mbuf in chain.
1460 1.1 briggs * sc = ed info (softc)
1461 1.1 briggs * src = pointer in ed ring buffer
1462 1.1 briggs * dst = pointer to last mbuf in mbuf chain to copy to
1463 1.1 briggs * amount = amount of data to copy
1464 1.1 briggs */
1465 1.1 briggs struct mbuf *
1466 1.1 briggs ae_ring_to_mbuf(sc,src,dst,total_len)
1467 1.1 briggs struct ae_softc *sc;
1468 1.1 briggs char *src;
1469 1.1 briggs struct mbuf *dst;
1470 1.1 briggs u_short total_len;
1471 1.1 briggs {
1472 1.1 briggs register struct mbuf *m = dst;
1473 1.1 briggs
1474 1.1 briggs while (total_len) {
1475 1.1 briggs register u_short amount = min(total_len, M_TRAILINGSPACE(m));
1476 1.1 briggs
1477 1.15 briggs if (amount == 0) {
1478 1.15 briggs /* no more data in this mbuf, alloc another */
1479 1.1 briggs /*
1480 1.1 briggs * If there is enough data for an mbuf cluster, attempt
1481 1.1 briggs * to allocate one of those, otherwise, a regular
1482 1.1 briggs * mbuf will do.
1483 1.1 briggs * Note that a regular mbuf is always required, even if
1484 1.1 briggs * we get a cluster - getting a cluster does not
1485 1.1 briggs * allocate any mbufs, and one is needed to assign
1486 1.1 briggs * the cluster to. The mbuf that has a cluster
1487 1.15 briggs * extension can not be used to contain data -
1488 1.15 briggs * only the cluster can contain data.
1489 1.1 briggs */
1490 1.1 briggs dst = m;
1491 1.1 briggs MGET(m, M_DONTWAIT, MT_DATA);
1492 1.1 briggs if (m == 0)
1493 1.1 briggs return (0);
1494 1.1 briggs
1495 1.1 briggs if (total_len >= MINCLSIZE)
1496 1.1 briggs MCLGET(m, M_DONTWAIT);
1497 1.1 briggs
1498 1.1 briggs m->m_len = 0;
1499 1.1 briggs dst->m_next = m;
1500 1.1 briggs amount = min(total_len, M_TRAILINGSPACE(m));
1501 1.1 briggs }
1502 1.1 briggs
1503 1.15 briggs src = ae_ring_copy(sc, src, mtod(m, caddr_t) + m->m_len,
1504 1.15 briggs amount);
1505 1.1 briggs
1506 1.1 briggs m->m_len += amount;
1507 1.1 briggs total_len -= amount;
1508 1.1 briggs
1509 1.1 briggs }
1510 1.1 briggs return (m);
1511 1.1 briggs }
1512