elink3.c revision 1.15 1 1.15 jonathan /* $NetBSD: elink3.c,v 1.15 1996/12/29 13:32:46 jonathan Exp $ */
2 1.1 thorpej
3 1.1 thorpej /*
4 1.6 thorpej * Copyright (c) 1994 Herb Peyerl <hpeyerl (at) beer.org>
5 1.1 thorpej * All rights reserved.
6 1.1 thorpej *
7 1.1 thorpej * Redistribution and use in source and binary forms, with or without
8 1.1 thorpej * modification, are permitted provided that the following conditions
9 1.1 thorpej * are met:
10 1.1 thorpej * 1. Redistributions of source code must retain the above copyright
11 1.1 thorpej * notice, this list of conditions and the following disclaimer.
12 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 thorpej * notice, this list of conditions and the following disclaimer in the
14 1.1 thorpej * documentation and/or other materials provided with the distribution.
15 1.1 thorpej * 3. All advertising materials mentioning features or use of this software
16 1.1 thorpej * must display the following acknowledgement:
17 1.1 thorpej * This product includes software developed by Herb Peyerl.
18 1.1 thorpej * 4. The name of Herb Peyerl may not be used to endorse or promote products
19 1.1 thorpej * derived from this software without specific prior written permission.
20 1.1 thorpej *
21 1.1 thorpej * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 1.1 thorpej * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 1.1 thorpej * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 1.1 thorpej * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 1.1 thorpej * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 1.1 thorpej * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 1.1 thorpej * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 1.1 thorpej * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 1.1 thorpej * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 1.1 thorpej * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 1.1 thorpej */
32 1.1 thorpej
33 1.1 thorpej #include "bpfilter.h"
34 1.1 thorpej
35 1.1 thorpej #include <sys/param.h>
36 1.3 christos #include <sys/systm.h>
37 1.1 thorpej #include <sys/mbuf.h>
38 1.1 thorpej #include <sys/socket.h>
39 1.1 thorpej #include <sys/ioctl.h>
40 1.1 thorpej #include <sys/errno.h>
41 1.1 thorpej #include <sys/syslog.h>
42 1.1 thorpej #include <sys/select.h>
43 1.1 thorpej #include <sys/device.h>
44 1.1 thorpej
45 1.1 thorpej #include <net/if.h>
46 1.1 thorpej #include <net/netisr.h>
47 1.1 thorpej #include <net/if_dl.h>
48 1.1 thorpej #include <net/if_types.h>
49 1.1 thorpej #include <net/netisr.h>
50 1.1 thorpej
51 1.1 thorpej #ifdef INET
52 1.1 thorpej #include <netinet/in.h>
53 1.1 thorpej #include <netinet/in_systm.h>
54 1.1 thorpej #include <netinet/in_var.h>
55 1.1 thorpej #include <netinet/ip.h>
56 1.1 thorpej #include <netinet/if_ether.h>
57 1.1 thorpej #endif
58 1.1 thorpej
59 1.1 thorpej #ifdef NS
60 1.1 thorpej #include <netns/ns.h>
61 1.1 thorpej #include <netns/ns_if.h>
62 1.1 thorpej #endif
63 1.1 thorpej
64 1.1 thorpej #if NBPFILTER > 0
65 1.1 thorpej #include <net/bpf.h>
66 1.1 thorpej #include <net/bpfdesc.h>
67 1.1 thorpej #endif
68 1.1 thorpej
69 1.1 thorpej #include <machine/cpu.h>
70 1.2 thorpej #include <machine/bus.h>
71 1.7 thorpej #include <machine/intr.h>
72 1.1 thorpej
73 1.1 thorpej #include <dev/ic/elink3var.h>
74 1.1 thorpej #include <dev/ic/elink3reg.h>
75 1.1 thorpej
76 1.1 thorpej #define ETHER_MIN_LEN 64
77 1.1 thorpej #define ETHER_MAX_LEN 1518
78 1.1 thorpej #define ETHER_ADDR_LEN 6
79 1.1 thorpej
80 1.1 thorpej struct cfdriver ep_cd = {
81 1.1 thorpej NULL, "ep", DV_IFNET
82 1.1 thorpej };
83 1.1 thorpej
84 1.15 jonathan void ep_internalconfig __P((struct ep_softc *sc));
85 1.15 jonathan void ep_vortex_internalconfig __P((struct ep_softc *sc));
86 1.3 christos static void eptxstat __P((struct ep_softc *));
87 1.1 thorpej static int epstatus __P((struct ep_softc *));
88 1.1 thorpej void epinit __P((struct ep_softc *));
89 1.1 thorpej int epioctl __P((struct ifnet *, u_long, caddr_t));
90 1.1 thorpej void epstart __P((struct ifnet *));
91 1.5 thorpej void epwatchdog __P((struct ifnet *));
92 1.1 thorpej void epreset __P((struct ep_softc *));
93 1.1 thorpej void epread __P((struct ep_softc *));
94 1.1 thorpej struct mbuf *epget __P((struct ep_softc *, int));
95 1.3 christos void epmbuffill __P((void *));
96 1.1 thorpej void epmbufempty __P((struct ep_softc *));
97 1.1 thorpej void epsetfilter __P((struct ep_softc *));
98 1.1 thorpej void epsetlink __P((struct ep_softc *));
99 1.1 thorpej
100 1.1 thorpej static int epbusyeeprom __P((struct ep_softc *));
101 1.1 thorpej
102 1.15 jonathan
103 1.1 thorpej void
104 1.1 thorpej epconfig(sc, conn)
105 1.1 thorpej struct ep_softc *sc;
106 1.7 thorpej u_int16_t conn;
107 1.1 thorpej {
108 1.5 thorpej struct ifnet *ifp = &sc->sc_arpcom.ac_if;
109 1.11 thorpej bus_space_tag_t iot = sc->sc_iot;
110 1.11 thorpej bus_space_handle_t ioh = sc->sc_ioh;
111 1.7 thorpej u_int16_t i;
112 1.1 thorpej
113 1.14 cjs printf("%s: ", sc->sc_dev.dv_xname);
114 1.14 cjs
115 1.15 jonathan
116 1.14 cjs /* print RAM size */
117 1.15 jonathan ep_internalconfig(sc);
118 1.14 cjs GO_WINDOW(0);
119 1.14 cjs
120 1.14 cjs /* determine connectors available */
121 1.1 thorpej sc->ep_connectors = 0;
122 1.1 thorpej if (conn & IS_AUI) {
123 1.10 christos printf("aui");
124 1.1 thorpej sc->ep_connectors |= AUI;
125 1.1 thorpej }
126 1.1 thorpej if (conn & IS_BNC) {
127 1.1 thorpej if (sc->ep_connectors)
128 1.10 christos printf("/");
129 1.10 christos printf("bnc");
130 1.1 thorpej sc->ep_connectors |= BNC;
131 1.1 thorpej }
132 1.1 thorpej if (conn & IS_UTP) {
133 1.1 thorpej if (sc->ep_connectors)
134 1.10 christos printf("/");
135 1.15 jonathan printf("10baseT");
136 1.1 thorpej sc->ep_connectors |= UTP;
137 1.1 thorpej }
138 1.15 jonathan if (conn & IS_100BASE_TX) {
139 1.15 jonathan if (sc->ep_connectors)
140 1.15 jonathan printf("/");
141 1.15 jonathan printf("100base-TX");
142 1.15 jonathan sc->ep_connectors |= TX;
143 1.15 jonathan }
144 1.15 jonathan if (conn & IS_100BASE_T4) {
145 1.15 jonathan if (sc->ep_connectors)
146 1.15 jonathan printf("/");
147 1.15 jonathan printf("100base-T4");
148 1.15 jonathan sc->ep_connectors |= T4;
149 1.15 jonathan }
150 1.15 jonathan if (conn & IS_100BASE_FX) {
151 1.15 jonathan if (sc->ep_connectors)
152 1.15 jonathan printf("/");
153 1.15 jonathan printf("100base-FX");
154 1.15 jonathan sc->ep_connectors |= FX;
155 1.15 jonathan }
156 1.15 jonathan if (conn & IS_100BASE_MII) {
157 1.15 jonathan if (sc->ep_connectors)
158 1.15 jonathan printf("/");
159 1.15 jonathan printf("MII");
160 1.15 jonathan sc->ep_connectors |= MII;
161 1.15 jonathan }
162 1.15 jonathan
163 1.1 thorpej if (!sc->ep_connectors)
164 1.10 christos printf("no connectors!");
165 1.15 jonathan printf("\n");
166 1.1 thorpej
167 1.1 thorpej /*
168 1.1 thorpej * Read the station address from the eeprom
169 1.1 thorpej */
170 1.1 thorpej for (i = 0; i < 3; i++) {
171 1.7 thorpej u_int16_t x;
172 1.1 thorpej if (epbusyeeprom(sc))
173 1.1 thorpej return;
174 1.11 thorpej bus_space_write_2(iot, ioh, EP_W0_EEPROM_COMMAND,
175 1.11 thorpej READ_EEPROM | i);
176 1.1 thorpej if (epbusyeeprom(sc))
177 1.1 thorpej return;
178 1.11 thorpej x = bus_space_read_2(iot, ioh, EP_W0_EEPROM_DATA);
179 1.1 thorpej sc->sc_arpcom.ac_enaddr[(i << 1)] = x >> 8;
180 1.1 thorpej sc->sc_arpcom.ac_enaddr[(i << 1) + 1] = x;
181 1.1 thorpej }
182 1.1 thorpej
183 1.15 jonathan printf("%s: , address %s\n", sc->sc_dev.dv_xname,
184 1.15 jonathan ether_sprintf(sc->sc_arpcom.ac_enaddr));
185 1.1 thorpej
186 1.12 jonathan /*
187 1.12 jonathan * Vortex-based (3c59x, eisa)? and Boomerang (3c900)cards allow
188 1.12 jonathan * FDDI-sized (4500) byte packets. Commands only take an 11-bit
189 1.12 jonathan * parameter, and 11 bits isn't enough to hold a full-size pkt length.
190 1.12 jonathan * Commands to these cards implicitly upshift a packet size
191 1.12 jonathan * or threshold by 2 bits.
192 1.12 jonathan * To detect cards with large-packet support, we probe by setting
193 1.12 jonathan * the transmit threshold register, then change windows and
194 1.12 jonathan * read back the threshold register directly, and see if the
195 1.12 jonathan * threshold value was shifted or not.
196 1.12 jonathan */
197 1.12 jonathan bus_space_write_2(iot, ioh, EP_COMMAND,
198 1.13 jonathan SET_TX_AVAIL_THRESH | EP_LARGEWIN_PROBE );
199 1.12 jonathan GO_WINDOW(5);
200 1.12 jonathan i = bus_space_read_2(iot, ioh, EP_W5_TX_AVAIL_THRESH);
201 1.12 jonathan GO_WINDOW(1);
202 1.12 jonathan switch (i) {
203 1.13 jonathan case EP_LARGEWIN_PROBE:
204 1.13 jonathan case (EP_LARGEWIN_PROBE & EP_LARGEWIN_MASK):
205 1.12 jonathan sc->ep_pktlenshift = 0;
206 1.12 jonathan break;
207 1.12 jonathan
208 1.13 jonathan case (EP_LARGEWIN_PROBE << 2):
209 1.12 jonathan sc->ep_pktlenshift = 2;
210 1.15 jonathan ep_vortex_internalconfig(sc);
211 1.12 jonathan break;
212 1.12 jonathan
213 1.12 jonathan default:
214 1.14 cjs printf("%s: wrote %d to TX_AVAIL_THRESH, read back %d. "
215 1.14 cjs "Interface disabled\n",
216 1.12 jonathan sc->sc_dev.dv_xname, EP_THRESH_DISABLE, (int) i);
217 1.12 jonathan return;
218 1.12 jonathan }
219 1.12 jonathan /*
220 1.12 jonathan * Ensure Tx-available interrupts are enabled for
221 1.12 jonathan * start the interface.
222 1.12 jonathan * XXX should be in epinit().
223 1.12 jonathan */
224 1.12 jonathan bus_space_write_2(iot, ioh, EP_COMMAND,
225 1.12 jonathan SET_TX_AVAIL_THRESH | (1600 >> sc->ep_pktlenshift));
226 1.12 jonathan
227 1.5 thorpej bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
228 1.5 thorpej ifp->if_softc = sc;
229 1.1 thorpej ifp->if_start = epstart;
230 1.1 thorpej ifp->if_ioctl = epioctl;
231 1.1 thorpej ifp->if_watchdog = epwatchdog;
232 1.1 thorpej ifp->if_flags =
233 1.1 thorpej IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
234 1.1 thorpej
235 1.1 thorpej if_attach(ifp);
236 1.1 thorpej ether_ifattach(ifp);
237 1.1 thorpej
238 1.1 thorpej #if NBPFILTER > 0
239 1.1 thorpej bpfattach(&sc->sc_arpcom.ac_if.if_bpf, ifp, DLT_EN10MB,
240 1.1 thorpej sizeof(struct ether_header));
241 1.1 thorpej #endif
242 1.1 thorpej
243 1.1 thorpej sc->tx_start_thresh = 20; /* probably a good starting point. */
244 1.12 jonathan
245 1.12 jonathan #if 0
246 1.12 jonathan /* XXX */
247 1.12 jonathan bus_space_write_2(iot, ioh, EP_COMMAND, RX_RESET);
248 1.12 jonathan bus_space_write_2(iot, ioh, EP_COMMAND, TX_RESET);
249 1.12 jonathan #else
250 1.12 jonathan
251 1.12 jonathan epinit(sc); /*XXX fix up after probe */
252 1.12 jonathan DELAY(20000);
253 1.12 jonathan epstop(sc); /*XXX reset after probe, stop interface. */
254 1.12 jonathan DELAY(20000);
255 1.12 jonathan #endif
256 1.1 thorpej }
257 1.1 thorpej
258 1.1 thorpej /*
259 1.15 jonathan * Show interface-model-independent info from window 3
260 1.15 jonathan * internal-configuration register.
261 1.15 jonathan */
262 1.15 jonathan void
263 1.15 jonathan ep_internalconfig(sc)
264 1.15 jonathan struct ep_softc *sc;
265 1.15 jonathan {
266 1.15 jonathan bus_space_tag_t iot = sc->sc_iot;
267 1.15 jonathan bus_space_handle_t ioh = sc->sc_ioh;
268 1.15 jonathan
269 1.15 jonathan u_int config0;
270 1.15 jonathan u_int config1;
271 1.15 jonathan
272 1.15 jonathan int ram_size, ram_width, ram_speed, rom_size, ram_split;
273 1.15 jonathan /*
274 1.15 jonathan * NVRAM buffer Rx:Tx config names for busmastering cards
275 1.15 jonathan * (Demon, Vortex, and later).
276 1.15 jonathan */
277 1.15 jonathan const char *onboard_ram_config[] = {
278 1.15 jonathan "5:3", "3:1", "1:1", "(undefined)" };
279 1.15 jonathan
280 1.15 jonathan GO_WINDOW(3);
281 1.15 jonathan config0 = (u_int)bus_space_read_2(iot, ioh, EP_W3_INTERNAL_CONFIG);
282 1.15 jonathan config1 = (u_int)bus_space_read_2(iot, ioh, EP_W3_INTERNAL_CONFIG+2);
283 1.15 jonathan GO_WINDOW(0);
284 1.15 jonathan
285 1.15 jonathan ram_size = (config0 & CONFIG_RAMSIZE) >> CONFIG_RAMSIZE_SHIFT;
286 1.15 jonathan ram_width = (config0 & CONFIG_RAMWIDTH) >> CONFIG_RAMWIDTH_SHIFT;
287 1.15 jonathan ram_speed = (config0 & CONFIG_RAMSPEED) >> CONFIG_RAMSPEED_SHIFT;
288 1.15 jonathan rom_size = (config0 & CONFIG_ROMSIZE) >> CONFIG_ROMSIZE_SHIFT;
289 1.15 jonathan
290 1.15 jonathan ram_split = (config1 & CONFIG_RAMSPLIT) >> CONFIG_RAMSPLIT_SHIFT;
291 1.15 jonathan
292 1.15 jonathan printf("%dKB %s-wide FIFO, %s Rx:Tx split, ",
293 1.15 jonathan 8 << ram_size,
294 1.15 jonathan (ram_width) ? "word" : "byte",
295 1.15 jonathan onboard_ram_config[ram_split]);
296 1.15 jonathan }
297 1.15 jonathan
298 1.15 jonathan
299 1.15 jonathan /*
300 1.15 jonathan * Show onboard configuration of large-packet-capable elink3 devices (Demon,
301 1.15 jonathan * Vortex, Boomerang), using media and card-version info in window 3.
302 1.15 jonathan *
303 1.15 jonathan * XXX how much of this works with 3c515, pcmcia 10/100? With 3c509, 3c589?
304 1.15 jonathan */
305 1.15 jonathan void
306 1.15 jonathan ep_vortex_internalconfig(sc)
307 1.15 jonathan struct ep_softc *sc;
308 1.15 jonathan {
309 1.15 jonathan bus_space_tag_t iot = sc->sc_iot;
310 1.15 jonathan bus_space_handle_t ioh = sc->sc_ioh;
311 1.15 jonathan u_int config0;
312 1.15 jonathan u_int config1;
313 1.15 jonathan int reset_options;
314 1.15 jonathan
315 1.15 jonathan int media_mask, autoselect;
316 1.15 jonathan /* Names for media in the media bitmask field. */
317 1.15 jonathan const char *medium_name;
318 1.15 jonathan const char *media_names[8] ={
319 1.15 jonathan "10baseT",
320 1.15 jonathan "10base AUI",
321 1.15 jonathan "undefined",
322 1.15 jonathan "10base2",
323 1.15 jonathan "100baseTX",
324 1.15 jonathan "100baseFX",
325 1.15 jonathan "MII",
326 1.15 jonathan "100baseT4"};
327 1.15 jonathan
328 1.15 jonathan GO_WINDOW(3);
329 1.15 jonathan config0 = (u_int)bus_space_read_2(iot, ioh, EP_W3_INTERNAL_CONFIG);
330 1.15 jonathan config1 = (u_int)bus_space_read_2(iot, ioh, EP_W3_INTERNAL_CONFIG+2);
331 1.15 jonathan reset_options = (int)bus_space_read_1(iot, ioh, EP_W3_RESET_OPTIONS);
332 1.15 jonathan GO_WINDOW(0);
333 1.15 jonathan
334 1.15 jonathan media_mask = (config1 & CONFIG_MEDIAMASK) >> CONFIG_MEDIAMASK_SHIFT;
335 1.15 jonathan autoselect = (config1 & CONFIG_AUTOSELECT) >> CONFIG_AUTOSELECT_SHIFT;
336 1.15 jonathan
337 1.15 jonathan medium_name = (media_mask > 8) ? "(unknown/impossible media)"
338 1.15 jonathan : media_names[media_mask];
339 1.15 jonathan
340 1.15 jonathan media_mask = (config1 & CONFIG_MEDIAMASK) >> CONFIG_MEDIAMASK_SHIFT;
341 1.15 jonathan autoselect = (config1 & CONFIG_AUTOSELECT) >> CONFIG_AUTOSELECT_SHIFT;
342 1.15 jonathan
343 1.15 jonathan
344 1.15 jonathan printf("%s: default medium %s, autoselect %s\n",
345 1.15 jonathan sc->sc_dev.dv_xname,
346 1.15 jonathan medium_name, (autoselect)? "on" : "off" );
347 1.15 jonathan }
348 1.15 jonathan
349 1.15 jonathan /*
350 1.1 thorpej * The order in here seems important. Otherwise we may not receive
351 1.1 thorpej * interrupts. ?!
352 1.1 thorpej */
353 1.1 thorpej void
354 1.1 thorpej epinit(sc)
355 1.1 thorpej register struct ep_softc *sc;
356 1.1 thorpej {
357 1.1 thorpej register struct ifnet *ifp = &sc->sc_arpcom.ac_if;
358 1.11 thorpej bus_space_tag_t iot = sc->sc_iot;
359 1.11 thorpej bus_space_handle_t ioh = sc->sc_ioh;
360 1.1 thorpej int i;
361 1.1 thorpej
362 1.11 thorpej while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
363 1.1 thorpej ;
364 1.1 thorpej
365 1.1 thorpej if (sc->bustype != EP_BUS_PCI) {
366 1.1 thorpej GO_WINDOW(0);
367 1.11 thorpej bus_space_write_2(iot, ioh, EP_W0_CONFIG_CTRL, 0);
368 1.11 thorpej bus_space_write_2(iot, ioh, EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ);
369 1.1 thorpej }
370 1.1 thorpej
371 1.1 thorpej if (sc->bustype == EP_BUS_PCMCIA) {
372 1.1 thorpej #ifdef EP_COAX_DEFAULT
373 1.11 thorpej bus_space_write_2(iot, ioh, EP_W0_ADDRESS_CFG,3<<14);
374 1.1 thorpej #else
375 1.11 thorpej bus_space_write_2(iot, ioh, EP_W0_ADDRESS_CFG,0<<14);
376 1.1 thorpej #endif
377 1.11 thorpej bus_space_write_2(iot, ioh, EP_W0_RESOURCE_CFG, 0x3f00);
378 1.1 thorpej }
379 1.1 thorpej
380 1.1 thorpej GO_WINDOW(2);
381 1.1 thorpej for (i = 0; i < 6; i++) /* Reload the ether_addr. */
382 1.11 thorpej bus_space_write_1(iot, ioh, EP_W2_ADDR_0 + i,
383 1.2 thorpej sc->sc_arpcom.ac_enaddr[i]);
384 1.8 christos
385 1.12 jonathan /*
386 1.12 jonathan * Reset the station-address receive filter.
387 1.12 jonathan * A bug workaround for busmastering (Vortex, Demon) cards.
388 1.12 jonathan */
389 1.12 jonathan for (i = 0; i < 6; i++)
390 1.12 jonathan bus_space_write_1(iot, ioh, EP_W2_RECVMASK_0 + i, 0);
391 1.1 thorpej
392 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND, RX_RESET);
393 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND, TX_RESET);
394 1.1 thorpej
395 1.1 thorpej GO_WINDOW(1); /* Window 1 is operating window */
396 1.1 thorpej for (i = 0; i < 31; i++)
397 1.11 thorpej bus_space_read_1(iot, ioh, EP_W1_TX_STATUS);
398 1.1 thorpej
399 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND, SET_RD_0_MASK | S_CARD_FAILURE |
400 1.1 thorpej S_RX_COMPLETE | S_TX_COMPLETE | S_TX_AVAIL);
401 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND, SET_INTR_MASK | S_CARD_FAILURE |
402 1.1 thorpej S_RX_COMPLETE | S_TX_COMPLETE | S_TX_AVAIL);
403 1.1 thorpej
404 1.1 thorpej /*
405 1.1 thorpej * Attempt to get rid of any stray interrupts that occured during
406 1.1 thorpej * configuration. On the i386 this isn't possible because one may
407 1.1 thorpej * already be queued. However, a single stray interrupt is
408 1.1 thorpej * unimportant.
409 1.1 thorpej */
410 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND, ACK_INTR | 0xff);
411 1.1 thorpej
412 1.1 thorpej epsetfilter(sc);
413 1.1 thorpej epsetlink(sc);
414 1.1 thorpej
415 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND, RX_ENABLE);
416 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND, TX_ENABLE);
417 1.1 thorpej
418 1.1 thorpej epmbuffill(sc);
419 1.1 thorpej
420 1.1 thorpej /* Interface is now `running', with no output active. */
421 1.1 thorpej ifp->if_flags |= IFF_RUNNING;
422 1.1 thorpej ifp->if_flags &= ~IFF_OACTIVE;
423 1.1 thorpej
424 1.1 thorpej /* Attempt to start output, if any. */
425 1.1 thorpej epstart(ifp);
426 1.1 thorpej }
427 1.1 thorpej
428 1.1 thorpej void
429 1.1 thorpej epsetfilter(sc)
430 1.1 thorpej register struct ep_softc *sc;
431 1.1 thorpej {
432 1.1 thorpej register struct ifnet *ifp = &sc->sc_arpcom.ac_if;
433 1.1 thorpej
434 1.1 thorpej GO_WINDOW(1); /* Window 1 is operating window */
435 1.11 thorpej bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_COMMAND, SET_RX_FILTER |
436 1.1 thorpej FIL_INDIVIDUAL | FIL_BRDCST |
437 1.1 thorpej ((ifp->if_flags & IFF_MULTICAST) ? FIL_MULTICAST : 0 ) |
438 1.1 thorpej ((ifp->if_flags & IFF_PROMISC) ? FIL_PROMISC : 0 ));
439 1.1 thorpej }
440 1.1 thorpej
441 1.15 jonathan /*
442 1.15 jonathan * select media based on link{0,1,2} switches.
443 1.15 jonathan * Assumes 10Mbit interface, totatlly broken for 10/100 adaptors.
444 1.15 jonathan */
445 1.1 thorpej void
446 1.1 thorpej epsetlink(sc)
447 1.1 thorpej register struct ep_softc *sc;
448 1.1 thorpej {
449 1.1 thorpej register struct ifnet *ifp = &sc->sc_arpcom.ac_if;
450 1.11 thorpej bus_space_tag_t iot = sc->sc_iot;
451 1.11 thorpej bus_space_handle_t ioh = sc->sc_ioh;
452 1.1 thorpej
453 1.1 thorpej /*
454 1.1 thorpej * you can `ifconfig (link0|-link0) ep0' to get the following
455 1.1 thorpej * behaviour:
456 1.1 thorpej * -link0 disable AUI/UTP. enable BNC.
457 1.1 thorpej * link0 disable BNC. enable AUI.
458 1.1 thorpej * link1 if the card has a UTP connector, and link0 is
459 1.1 thorpej * set too, then you get the UTP port.
460 1.1 thorpej */
461 1.1 thorpej GO_WINDOW(4);
462 1.11 thorpej bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE, DISABLE_UTP);
463 1.1 thorpej if (!(ifp->if_flags & IFF_LINK0) && (sc->ep_connectors & BNC)) {
464 1.1 thorpej if (sc->bustype == EP_BUS_PCMCIA) {
465 1.1 thorpej GO_WINDOW(0);
466 1.11 thorpej bus_space_write_2(iot, ioh, EP_W0_ADDRESS_CFG,3<<14);
467 1.1 thorpej GO_WINDOW(1);
468 1.1 thorpej }
469 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND, START_TRANSCEIVER);
470 1.1 thorpej delay(1000);
471 1.1 thorpej }
472 1.1 thorpej if (ifp->if_flags & IFF_LINK0) {
473 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND, STOP_TRANSCEIVER);
474 1.1 thorpej delay(1000);
475 1.1 thorpej if ((ifp->if_flags & IFF_LINK1) && (sc->ep_connectors & UTP)) {
476 1.1 thorpej if (sc->bustype == EP_BUS_PCMCIA) {
477 1.1 thorpej GO_WINDOW(0);
478 1.11 thorpej bus_space_write_2(iot, ioh,
479 1.2 thorpej EP_W0_ADDRESS_CFG,0<<14);
480 1.1 thorpej GO_WINDOW(4);
481 1.1 thorpej }
482 1.11 thorpej bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE, ENABLE_UTP);
483 1.1 thorpej }
484 1.1 thorpej }
485 1.1 thorpej GO_WINDOW(1);
486 1.1 thorpej }
487 1.1 thorpej
488 1.1 thorpej /*
489 1.1 thorpej * Start outputting on the interface.
490 1.1 thorpej * Always called as splnet().
491 1.1 thorpej */
492 1.1 thorpej void
493 1.1 thorpej epstart(ifp)
494 1.1 thorpej struct ifnet *ifp;
495 1.1 thorpej {
496 1.5 thorpej register struct ep_softc *sc = ifp->if_softc;
497 1.11 thorpej bus_space_tag_t iot = sc->sc_iot;
498 1.11 thorpej bus_space_handle_t ioh = sc->sc_ioh;
499 1.1 thorpej struct mbuf *m, *m0;
500 1.1 thorpej int sh, len, pad;
501 1.1 thorpej
502 1.1 thorpej /* Don't transmit if interface is busy or not running */
503 1.1 thorpej if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
504 1.1 thorpej return;
505 1.1 thorpej
506 1.1 thorpej startagain:
507 1.1 thorpej /* Sneak a peek at the next packet */
508 1.1 thorpej m0 = ifp->if_snd.ifq_head;
509 1.1 thorpej if (m0 == 0)
510 1.1 thorpej return;
511 1.1 thorpej
512 1.1 thorpej /* We need to use m->m_pkthdr.len, so require the header */
513 1.1 thorpej if ((m0->m_flags & M_PKTHDR) == 0)
514 1.1 thorpej panic("epstart: no header mbuf");
515 1.1 thorpej len = m0->m_pkthdr.len;
516 1.1 thorpej
517 1.1 thorpej pad = (4 - len) & 3;
518 1.1 thorpej
519 1.1 thorpej /*
520 1.1 thorpej * The 3c509 automatically pads short packets to minimum ethernet
521 1.1 thorpej * length, but we drop packets that are too large. Perhaps we should
522 1.1 thorpej * truncate them instead?
523 1.1 thorpej */
524 1.1 thorpej if (len + pad > ETHER_MAX_LEN) {
525 1.1 thorpej /* packet is obviously too large: toss it */
526 1.1 thorpej ++ifp->if_oerrors;
527 1.1 thorpej IF_DEQUEUE(&ifp->if_snd, m0);
528 1.1 thorpej m_freem(m0);
529 1.1 thorpej goto readcheck;
530 1.1 thorpej }
531 1.1 thorpej
532 1.11 thorpej if (bus_space_read_2(iot, ioh, EP_W1_FREE_TX) < len + pad + 4) {
533 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND,
534 1.12 jonathan SET_TX_AVAIL_THRESH |
535 1.12 jonathan ((len + pad + 4) >> sc->ep_pktlenshift));
536 1.1 thorpej /* not enough room in FIFO */
537 1.1 thorpej ifp->if_flags |= IFF_OACTIVE;
538 1.1 thorpej return;
539 1.1 thorpej } else {
540 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND,
541 1.12 jonathan SET_TX_AVAIL_THRESH | EP_THRESH_DISABLE );
542 1.1 thorpej }
543 1.1 thorpej
544 1.1 thorpej IF_DEQUEUE(&ifp->if_snd, m0);
545 1.1 thorpej if (m0 == 0) /* not really needed */
546 1.1 thorpej return;
547 1.1 thorpej
548 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND, SET_TX_START_THRESH |
549 1.12 jonathan ((len / 4 + sc->tx_start_thresh) /* >> sc->ep_pktlenshift*/) );
550 1.1 thorpej
551 1.1 thorpej #if NBPFILTER > 0
552 1.1 thorpej if (ifp->if_bpf)
553 1.1 thorpej bpf_mtap(ifp->if_bpf, m0);
554 1.1 thorpej #endif
555 1.1 thorpej
556 1.1 thorpej /*
557 1.1 thorpej * Do the output at splhigh() so that an interrupt from another device
558 1.1 thorpej * won't cause a FIFO underrun.
559 1.1 thorpej */
560 1.1 thorpej sh = splhigh();
561 1.1 thorpej
562 1.11 thorpej bus_space_write_2(iot, ioh, EP_W1_TX_PIO_WR_1, len);
563 1.11 thorpej bus_space_write_2(iot, ioh, EP_W1_TX_PIO_WR_1,
564 1.2 thorpej 0xffff); /* Second dword meaningless */
565 1.1 thorpej if (EP_IS_BUS_32(sc->bustype)) {
566 1.1 thorpej for (m = m0; m; ) {
567 1.14 cjs if (m->m_len > 3) {
568 1.14 cjs /* align our reads from core */
569 1.14 cjs if (mtod(m, u_long) & 3) {
570 1.14 cjs u_long count =
571 1.14 cjs 4 - (mtod(m, u_long) & 3);
572 1.14 cjs bus_space_write_multi_1(iot, ioh,
573 1.14 cjs EP_W1_TX_PIO_WR_1,
574 1.14 cjs mtod(m, u_int8_t *), count);
575 1.14 cjs m->m_data =
576 1.14 cjs (void *)(mtod(m, u_long) + count);
577 1.14 cjs m->m_len -= count;
578 1.14 cjs }
579 1.11 thorpej bus_space_write_multi_4(iot, ioh,
580 1.14 cjs EP_W1_TX_PIO_WR_1,
581 1.14 cjs mtod(m, u_int32_t *), m->m_len >> 2);
582 1.14 cjs m->m_data = (void *)(mtod(m, u_long) +
583 1.14 cjs (u_long)(m->m_len & ~3));
584 1.14 cjs m->m_len -= m->m_len & ~3;
585 1.14 cjs }
586 1.14 cjs if (m->m_len) {
587 1.11 thorpej bus_space_write_multi_1(iot, ioh,
588 1.2 thorpej EP_W1_TX_PIO_WR_1,
589 1.14 cjs mtod(m, u_int8_t *), m->m_len);
590 1.14 cjs }
591 1.1 thorpej MFREE(m, m0);
592 1.1 thorpej m = m0;
593 1.1 thorpej }
594 1.1 thorpej } else {
595 1.1 thorpej for (m = m0; m; ) {
596 1.14 cjs if (m->m_len > 1) {
597 1.14 cjs if (mtod(m, u_long) & 1) {
598 1.14 cjs bus_space_write_1(iot, ioh,
599 1.14 cjs EP_W1_TX_PIO_WR_1,
600 1.14 cjs *(mtod(m, u_int8_t *)));
601 1.14 cjs m->m_data =
602 1.14 cjs (void *)(mtod(m, u_long) + 1);
603 1.14 cjs m->m_len -= 1;
604 1.14 cjs }
605 1.11 thorpej bus_space_write_multi_2(iot, ioh,
606 1.2 thorpej EP_W1_TX_PIO_WR_1, mtod(m, u_int16_t *),
607 1.14 cjs m->m_len >> 1);
608 1.14 cjs }
609 1.14 cjs if (m->m_len & 1) {
610 1.11 thorpej bus_space_write_1(iot, ioh, EP_W1_TX_PIO_WR_1,
611 1.2 thorpej *(mtod(m, u_int8_t *) + m->m_len - 1));
612 1.14 cjs }
613 1.1 thorpej MFREE(m, m0);
614 1.1 thorpej m = m0;
615 1.1 thorpej }
616 1.1 thorpej }
617 1.1 thorpej while (pad--)
618 1.11 thorpej bus_space_write_1(iot, ioh, EP_W1_TX_PIO_WR_1, 0);
619 1.1 thorpej
620 1.1 thorpej splx(sh);
621 1.1 thorpej
622 1.1 thorpej ++ifp->if_opackets;
623 1.1 thorpej
624 1.1 thorpej readcheck:
625 1.11 thorpej if ((bus_space_read_2(iot, ioh, EP_W1_RX_STATUS) & ERR_INCOMPLETE) == 0) {
626 1.1 thorpej /* We received a complete packet. */
627 1.11 thorpej u_int16_t status = bus_space_read_2(iot, ioh, EP_STATUS);
628 1.1 thorpej
629 1.1 thorpej if ((status & S_INTR_LATCH) == 0) {
630 1.1 thorpej /*
631 1.1 thorpej * No interrupt, read the packet and continue
632 1.1 thorpej * Is this supposed to happen? Is my motherboard
633 1.1 thorpej * completely busted?
634 1.1 thorpej */
635 1.1 thorpej epread(sc);
636 1.1 thorpej }
637 1.1 thorpej else
638 1.1 thorpej /* Got an interrupt, return so that it gets serviced. */
639 1.1 thorpej return;
640 1.1 thorpej }
641 1.1 thorpej else {
642 1.1 thorpej /* Check if we are stuck and reset [see XXX comment] */
643 1.1 thorpej if (epstatus(sc)) {
644 1.1 thorpej if (ifp->if_flags & IFF_DEBUG)
645 1.10 christos printf("%s: adapter reset\n",
646 1.9 christos sc->sc_dev.dv_xname);
647 1.1 thorpej epreset(sc);
648 1.1 thorpej }
649 1.1 thorpej }
650 1.1 thorpej
651 1.1 thorpej goto startagain;
652 1.1 thorpej }
653 1.1 thorpej
654 1.1 thorpej
655 1.1 thorpej /*
656 1.1 thorpej * XXX: The 3c509 card can get in a mode where both the fifo status bit
657 1.1 thorpej * FIFOS_RX_OVERRUN and the status bit ERR_INCOMPLETE are set
658 1.1 thorpej * We detect this situation and we reset the adapter.
659 1.1 thorpej * It happens at times when there is a lot of broadcast traffic
660 1.1 thorpej * on the cable (once in a blue moon).
661 1.1 thorpej */
662 1.1 thorpej static int
663 1.1 thorpej epstatus(sc)
664 1.1 thorpej register struct ep_softc *sc;
665 1.1 thorpej {
666 1.11 thorpej bus_space_tag_t iot = sc->sc_iot;
667 1.11 thorpej bus_space_handle_t ioh = sc->sc_ioh;
668 1.7 thorpej u_int16_t fifost;
669 1.1 thorpej
670 1.1 thorpej /*
671 1.1 thorpej * Check the FIFO status and act accordingly
672 1.1 thorpej */
673 1.1 thorpej GO_WINDOW(4);
674 1.11 thorpej fifost = bus_space_read_2(iot, ioh, EP_W4_FIFO_DIAG);
675 1.1 thorpej GO_WINDOW(1);
676 1.1 thorpej
677 1.1 thorpej if (fifost & FIFOS_RX_UNDERRUN) {
678 1.1 thorpej if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
679 1.10 christos printf("%s: RX underrun\n", sc->sc_dev.dv_xname);
680 1.1 thorpej epreset(sc);
681 1.1 thorpej return 0;
682 1.1 thorpej }
683 1.1 thorpej
684 1.1 thorpej if (fifost & FIFOS_RX_STATUS_OVERRUN) {
685 1.1 thorpej if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
686 1.10 christos printf("%s: RX Status overrun\n", sc->sc_dev.dv_xname);
687 1.1 thorpej return 1;
688 1.1 thorpej }
689 1.1 thorpej
690 1.1 thorpej if (fifost & FIFOS_RX_OVERRUN) {
691 1.1 thorpej if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
692 1.10 christos printf("%s: RX overrun\n", sc->sc_dev.dv_xname);
693 1.1 thorpej return 1;
694 1.1 thorpej }
695 1.1 thorpej
696 1.1 thorpej if (fifost & FIFOS_TX_OVERRUN) {
697 1.1 thorpej if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
698 1.10 christos printf("%s: TX overrun\n", sc->sc_dev.dv_xname);
699 1.1 thorpej epreset(sc);
700 1.1 thorpej return 0;
701 1.1 thorpej }
702 1.1 thorpej
703 1.1 thorpej return 0;
704 1.1 thorpej }
705 1.1 thorpej
706 1.1 thorpej
707 1.1 thorpej static void
708 1.1 thorpej eptxstat(sc)
709 1.1 thorpej register struct ep_softc *sc;
710 1.1 thorpej {
711 1.11 thorpej bus_space_tag_t iot = sc->sc_iot;
712 1.11 thorpej bus_space_handle_t ioh = sc->sc_ioh;
713 1.1 thorpej int i;
714 1.1 thorpej
715 1.1 thorpej /*
716 1.1 thorpej * We need to read+write TX_STATUS until we get a 0 status
717 1.1 thorpej * in order to turn off the interrupt flag.
718 1.1 thorpej */
719 1.11 thorpej while ((i = bus_space_read_1(iot, ioh, EP_W1_TX_STATUS)) & TXS_COMPLETE) {
720 1.11 thorpej bus_space_write_1(iot, ioh, EP_W1_TX_STATUS, 0x0);
721 1.1 thorpej
722 1.1 thorpej if (i & TXS_JABBER) {
723 1.1 thorpej ++sc->sc_arpcom.ac_if.if_oerrors;
724 1.1 thorpej if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
725 1.10 christos printf("%s: jabber (%x)\n",
726 1.1 thorpej sc->sc_dev.dv_xname, i);
727 1.1 thorpej epreset(sc);
728 1.1 thorpej } else if (i & TXS_UNDERRUN) {
729 1.1 thorpej ++sc->sc_arpcom.ac_if.if_oerrors;
730 1.1 thorpej if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
731 1.10 christos printf("%s: fifo underrun (%x) @%d\n",
732 1.1 thorpej sc->sc_dev.dv_xname, i,
733 1.1 thorpej sc->tx_start_thresh);
734 1.1 thorpej if (sc->tx_succ_ok < 100)
735 1.1 thorpej sc->tx_start_thresh = min(ETHER_MAX_LEN,
736 1.1 thorpej sc->tx_start_thresh + 20);
737 1.1 thorpej sc->tx_succ_ok = 0;
738 1.1 thorpej epreset(sc);
739 1.1 thorpej } else if (i & TXS_MAX_COLLISION) {
740 1.1 thorpej ++sc->sc_arpcom.ac_if.if_collisions;
741 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND, TX_ENABLE);
742 1.1 thorpej sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
743 1.1 thorpej } else
744 1.1 thorpej sc->tx_succ_ok = (sc->tx_succ_ok+1) & 127;
745 1.1 thorpej }
746 1.1 thorpej }
747 1.1 thorpej
748 1.1 thorpej int
749 1.1 thorpej epintr(arg)
750 1.1 thorpej void *arg;
751 1.1 thorpej {
752 1.1 thorpej register struct ep_softc *sc = arg;
753 1.11 thorpej bus_space_tag_t iot = sc->sc_iot;
754 1.11 thorpej bus_space_handle_t ioh = sc->sc_ioh;
755 1.1 thorpej struct ifnet *ifp = &sc->sc_arpcom.ac_if;
756 1.7 thorpej u_int16_t status;
757 1.1 thorpej int ret = 0;
758 1.1 thorpej
759 1.1 thorpej for (;;) {
760 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND, C_INTR_LATCH);
761 1.1 thorpej
762 1.11 thorpej status = bus_space_read_2(iot, ioh, EP_STATUS);
763 1.1 thorpej
764 1.1 thorpej if ((status & (S_TX_COMPLETE | S_TX_AVAIL |
765 1.1 thorpej S_RX_COMPLETE | S_CARD_FAILURE)) == 0)
766 1.1 thorpej break;
767 1.1 thorpej
768 1.1 thorpej ret = 1;
769 1.1 thorpej
770 1.1 thorpej /*
771 1.1 thorpej * Acknowledge any interrupts. It's important that we do this
772 1.1 thorpej * first, since there would otherwise be a race condition.
773 1.1 thorpej * Due to the i386 interrupt queueing, we may get spurious
774 1.1 thorpej * interrupts occasionally.
775 1.1 thorpej */
776 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND, ACK_INTR | status);
777 1.1 thorpej
778 1.1 thorpej if (status & S_RX_COMPLETE)
779 1.1 thorpej epread(sc);
780 1.1 thorpej if (status & S_TX_AVAIL) {
781 1.1 thorpej sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
782 1.1 thorpej epstart(&sc->sc_arpcom.ac_if);
783 1.1 thorpej }
784 1.1 thorpej if (status & S_CARD_FAILURE) {
785 1.10 christos printf("%s: adapter failure (%x)\n",
786 1.9 christos sc->sc_dev.dv_xname, status);
787 1.1 thorpej epreset(sc);
788 1.1 thorpej return (1);
789 1.1 thorpej }
790 1.1 thorpej if (status & S_TX_COMPLETE) {
791 1.1 thorpej eptxstat(sc);
792 1.1 thorpej epstart(ifp);
793 1.1 thorpej }
794 1.1 thorpej }
795 1.1 thorpej
796 1.1 thorpej /* no more interrupts */
797 1.1 thorpej return (ret);
798 1.1 thorpej }
799 1.1 thorpej
800 1.1 thorpej void
801 1.1 thorpej epread(sc)
802 1.1 thorpej register struct ep_softc *sc;
803 1.1 thorpej {
804 1.11 thorpej bus_space_tag_t iot = sc->sc_iot;
805 1.11 thorpej bus_space_handle_t ioh = sc->sc_ioh;
806 1.1 thorpej struct ifnet *ifp = &sc->sc_arpcom.ac_if;
807 1.1 thorpej struct mbuf *m;
808 1.1 thorpej struct ether_header *eh;
809 1.1 thorpej int len;
810 1.1 thorpej
811 1.11 thorpej len = bus_space_read_2(iot, ioh, EP_W1_RX_STATUS);
812 1.1 thorpej
813 1.1 thorpej again:
814 1.1 thorpej if (ifp->if_flags & IFF_DEBUG) {
815 1.1 thorpej int err = len & ERR_MASK;
816 1.1 thorpej char *s = NULL;
817 1.1 thorpej
818 1.1 thorpej if (len & ERR_INCOMPLETE)
819 1.1 thorpej s = "incomplete packet";
820 1.1 thorpej else if (err == ERR_OVERRUN)
821 1.1 thorpej s = "packet overrun";
822 1.1 thorpej else if (err == ERR_RUNT)
823 1.1 thorpej s = "runt packet";
824 1.1 thorpej else if (err == ERR_ALIGNMENT)
825 1.1 thorpej s = "bad alignment";
826 1.1 thorpej else if (err == ERR_CRC)
827 1.1 thorpej s = "bad crc";
828 1.1 thorpej else if (err == ERR_OVERSIZE)
829 1.1 thorpej s = "oversized packet";
830 1.1 thorpej else if (err == ERR_DRIBBLE)
831 1.1 thorpej s = "dribble bits";
832 1.1 thorpej
833 1.1 thorpej if (s)
834 1.10 christos printf("%s: %s\n", sc->sc_dev.dv_xname, s);
835 1.1 thorpej }
836 1.1 thorpej
837 1.1 thorpej if (len & ERR_INCOMPLETE)
838 1.1 thorpej return;
839 1.1 thorpej
840 1.1 thorpej if (len & ERR_RX) {
841 1.1 thorpej ++ifp->if_ierrors;
842 1.1 thorpej goto abort;
843 1.1 thorpej }
844 1.1 thorpej
845 1.1 thorpej len &= RX_BYTES_MASK; /* Lower 11 bits = RX bytes. */
846 1.1 thorpej
847 1.1 thorpej /* Pull packet off interface. */
848 1.1 thorpej m = epget(sc, len);
849 1.1 thorpej if (m == 0) {
850 1.1 thorpej ifp->if_ierrors++;
851 1.1 thorpej goto abort;
852 1.1 thorpej }
853 1.1 thorpej
854 1.1 thorpej ++ifp->if_ipackets;
855 1.1 thorpej
856 1.1 thorpej /* We assume the header fit entirely in one mbuf. */
857 1.1 thorpej eh = mtod(m, struct ether_header *);
858 1.1 thorpej
859 1.1 thorpej #if NBPFILTER > 0
860 1.1 thorpej /*
861 1.1 thorpej * Check if there's a BPF listener on this interface.
862 1.1 thorpej * If so, hand off the raw packet to BPF.
863 1.1 thorpej */
864 1.1 thorpej if (ifp->if_bpf) {
865 1.1 thorpej bpf_mtap(ifp->if_bpf, m);
866 1.1 thorpej
867 1.1 thorpej /*
868 1.1 thorpej * Note that the interface cannot be in promiscuous mode if
869 1.1 thorpej * there are no BPF listeners. And if we are in promiscuous
870 1.1 thorpej * mode, we have to check if this packet is really ours.
871 1.1 thorpej */
872 1.1 thorpej if ((ifp->if_flags & IFF_PROMISC) &&
873 1.1 thorpej (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
874 1.1 thorpej bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr,
875 1.1 thorpej sizeof(eh->ether_dhost)) != 0) {
876 1.1 thorpej m_freem(m);
877 1.1 thorpej return;
878 1.1 thorpej }
879 1.1 thorpej }
880 1.1 thorpej #endif
881 1.1 thorpej
882 1.1 thorpej /* We assume the header fit entirely in one mbuf. */
883 1.1 thorpej m_adj(m, sizeof(struct ether_header));
884 1.1 thorpej ether_input(ifp, eh, m);
885 1.1 thorpej
886 1.1 thorpej /*
887 1.1 thorpej * In periods of high traffic we can actually receive enough
888 1.1 thorpej * packets so that the fifo overrun bit will be set at this point,
889 1.1 thorpej * even though we just read a packet. In this case we
890 1.1 thorpej * are not going to receive any more interrupts. We check for
891 1.1 thorpej * this condition and read again until the fifo is not full.
892 1.1 thorpej * We could simplify this test by not using epstatus(), but
893 1.1 thorpej * rechecking the RX_STATUS register directly. This test could
894 1.1 thorpej * result in unnecessary looping in cases where there is a new
895 1.1 thorpej * packet but the fifo is not full, but it will not fix the
896 1.1 thorpej * stuck behavior.
897 1.1 thorpej *
898 1.1 thorpej * Even with this improvement, we still get packet overrun errors
899 1.1 thorpej * which are hurting performance. Maybe when I get some more time
900 1.1 thorpej * I'll modify epread() so that it can handle RX_EARLY interrupts.
901 1.1 thorpej */
902 1.1 thorpej if (epstatus(sc)) {
903 1.11 thorpej len = bus_space_read_2(iot, ioh, EP_W1_RX_STATUS);
904 1.1 thorpej /* Check if we are stuck and reset [see XXX comment] */
905 1.1 thorpej if (len & ERR_INCOMPLETE) {
906 1.1 thorpej if (ifp->if_flags & IFF_DEBUG)
907 1.10 christos printf("%s: adapter reset\n",
908 1.9 christos sc->sc_dev.dv_xname);
909 1.1 thorpej epreset(sc);
910 1.1 thorpej return;
911 1.1 thorpej }
912 1.1 thorpej goto again;
913 1.1 thorpej }
914 1.1 thorpej
915 1.1 thorpej return;
916 1.1 thorpej
917 1.1 thorpej abort:
918 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISCARD_TOP_PACK);
919 1.11 thorpej while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
920 1.1 thorpej ;
921 1.1 thorpej }
922 1.1 thorpej
923 1.1 thorpej struct mbuf *
924 1.1 thorpej epget(sc, totlen)
925 1.1 thorpej struct ep_softc *sc;
926 1.1 thorpej int totlen;
927 1.1 thorpej {
928 1.11 thorpej bus_space_tag_t iot = sc->sc_iot;
929 1.11 thorpej bus_space_handle_t ioh = sc->sc_ioh;
930 1.1 thorpej struct ifnet *ifp = &sc->sc_arpcom.ac_if;
931 1.1 thorpej struct mbuf *top, **mp, *m;
932 1.14 cjs int len, remaining;
933 1.1 thorpej int sh;
934 1.1 thorpej
935 1.1 thorpej m = sc->mb[sc->next_mb];
936 1.1 thorpej sc->mb[sc->next_mb] = 0;
937 1.1 thorpej if (m == 0) {
938 1.1 thorpej MGETHDR(m, M_DONTWAIT, MT_DATA);
939 1.1 thorpej if (m == 0)
940 1.1 thorpej return 0;
941 1.1 thorpej } else {
942 1.1 thorpej /* If the queue is no longer full, refill. */
943 1.1 thorpej if (sc->last_mb == sc->next_mb)
944 1.1 thorpej timeout(epmbuffill, sc, 1);
945 1.1 thorpej /* Convert one of our saved mbuf's. */
946 1.1 thorpej sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
947 1.1 thorpej m->m_data = m->m_pktdat;
948 1.1 thorpej m->m_flags = M_PKTHDR;
949 1.1 thorpej }
950 1.1 thorpej m->m_pkthdr.rcvif = ifp;
951 1.1 thorpej m->m_pkthdr.len = totlen;
952 1.1 thorpej len = MHLEN;
953 1.1 thorpej top = 0;
954 1.1 thorpej mp = ⊤
955 1.1 thorpej
956 1.1 thorpej /*
957 1.1 thorpej * We read the packet at splhigh() so that an interrupt from another
958 1.1 thorpej * device doesn't cause the card's buffer to overflow while we're
959 1.1 thorpej * reading it. We may still lose packets at other times.
960 1.1 thorpej */
961 1.1 thorpej sh = splhigh();
962 1.1 thorpej
963 1.1 thorpej while (totlen > 0) {
964 1.1 thorpej if (top) {
965 1.1 thorpej m = sc->mb[sc->next_mb];
966 1.1 thorpej sc->mb[sc->next_mb] = 0;
967 1.1 thorpej if (m == 0) {
968 1.1 thorpej MGET(m, M_DONTWAIT, MT_DATA);
969 1.1 thorpej if (m == 0) {
970 1.1 thorpej splx(sh);
971 1.1 thorpej m_freem(top);
972 1.1 thorpej return 0;
973 1.1 thorpej }
974 1.1 thorpej } else {
975 1.1 thorpej sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
976 1.1 thorpej }
977 1.1 thorpej len = MLEN;
978 1.1 thorpej }
979 1.1 thorpej if (totlen >= MINCLSIZE) {
980 1.1 thorpej MCLGET(m, M_DONTWAIT);
981 1.1 thorpej if (m->m_flags & M_EXT)
982 1.1 thorpej len = MCLBYTES;
983 1.1 thorpej }
984 1.14 cjs if (EP_IS_BUS_32(sc->bustype) ) {
985 1.14 cjs u_long pad;
986 1.14 cjs if (top == 0) {
987 1.14 cjs /* align the struct ip header */
988 1.14 cjs pad = ALIGN(sizeof(struct ether_header))
989 1.14 cjs - sizeof(struct ether_header);
990 1.14 cjs } else {
991 1.14 cjs /* XXX do we really need this? */
992 1.14 cjs pad = ALIGN(m->m_data) - (u_long) m->m_data;
993 1.14 cjs }
994 1.14 cjs m->m_data += pad;
995 1.14 cjs len -= pad;
996 1.14 cjs }
997 1.14 cjs remaining = len = min(totlen, len);
998 1.1 thorpej if (EP_IS_BUS_32(sc->bustype)) {
999 1.14 cjs u_long offset = mtod(m, u_long);
1000 1.14 cjs /*
1001 1.14 cjs * Read bytes up to the point where we are aligned.
1002 1.14 cjs * (We can align to 4 bytes, rather than ALIGNBYTES,
1003 1.14 cjs * here because we're later reading 4-byte chunks.)
1004 1.14 cjs */
1005 1.14 cjs if ((remaining > 3) && (offset & 3)) {
1006 1.14 cjs int count = (4 - (offset & 3));
1007 1.14 cjs bus_space_read_multi_1(iot, ioh,
1008 1.14 cjs EP_W1_RX_PIO_RD_1,
1009 1.14 cjs (u_int8_t *) offset, count);
1010 1.14 cjs offset += count;
1011 1.14 cjs remaining -= count;
1012 1.14 cjs }
1013 1.14 cjs if (remaining > 3) {
1014 1.11 thorpej bus_space_read_multi_4(iot, ioh,
1015 1.14 cjs EP_W1_RX_PIO_RD_1,
1016 1.14 cjs (u_int32_t *) offset, remaining >> 2);
1017 1.14 cjs offset += remaining & ~3;
1018 1.14 cjs remaining &= 3;
1019 1.14 cjs }
1020 1.14 cjs if (remaining) {
1021 1.11 thorpej bus_space_read_multi_1(iot, ioh,
1022 1.14 cjs EP_W1_RX_PIO_RD_1,
1023 1.14 cjs (u_int8_t *) offset, remaining);
1024 1.14 cjs }
1025 1.1 thorpej } else {
1026 1.14 cjs u_long offset = mtod(m, u_long);
1027 1.14 cjs if ((remaining > 1) && (offset & 1)) {
1028 1.14 cjs bus_space_read_multi_1(iot, ioh,
1029 1.14 cjs EP_W1_RX_PIO_RD_1,
1030 1.14 cjs (u_int8_t *) offset, 1);
1031 1.14 cjs remaining -= 1;
1032 1.14 cjs offset += 1;
1033 1.14 cjs }
1034 1.14 cjs if (remaining > 1) {
1035 1.11 thorpej bus_space_read_multi_2(iot, ioh,
1036 1.14 cjs EP_W1_RX_PIO_RD_1,
1037 1.14 cjs (u_int16_t *) offset, remaining >> 1);
1038 1.14 cjs offset += remaining & ~1;
1039 1.14 cjs }
1040 1.14 cjs if (remaining & 1) {
1041 1.14 cjs bus_space_read_multi_1(iot, ioh,
1042 1.14 cjs EP_W1_RX_PIO_RD_1,
1043 1.14 cjs (u_int8_t *) offset, remaining & 1);
1044 1.14 cjs }
1045 1.1 thorpej }
1046 1.1 thorpej m->m_len = len;
1047 1.1 thorpej totlen -= len;
1048 1.1 thorpej *mp = m;
1049 1.1 thorpej mp = &m->m_next;
1050 1.1 thorpej }
1051 1.1 thorpej
1052 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISCARD_TOP_PACK);
1053 1.11 thorpej while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
1054 1.1 thorpej ;
1055 1.1 thorpej
1056 1.1 thorpej splx(sh);
1057 1.1 thorpej
1058 1.1 thorpej return top;
1059 1.1 thorpej }
1060 1.1 thorpej
1061 1.1 thorpej int
1062 1.1 thorpej epioctl(ifp, cmd, data)
1063 1.1 thorpej register struct ifnet *ifp;
1064 1.1 thorpej u_long cmd;
1065 1.1 thorpej caddr_t data;
1066 1.1 thorpej {
1067 1.5 thorpej struct ep_softc *sc = ifp->if_softc;
1068 1.1 thorpej struct ifaddr *ifa = (struct ifaddr *)data;
1069 1.1 thorpej struct ifreq *ifr = (struct ifreq *)data;
1070 1.1 thorpej int s, error = 0;
1071 1.1 thorpej
1072 1.1 thorpej s = splnet();
1073 1.1 thorpej
1074 1.1 thorpej switch (cmd) {
1075 1.1 thorpej
1076 1.1 thorpej case SIOCSIFADDR:
1077 1.1 thorpej ifp->if_flags |= IFF_UP;
1078 1.1 thorpej
1079 1.1 thorpej switch (ifa->ifa_addr->sa_family) {
1080 1.1 thorpej #ifdef INET
1081 1.1 thorpej case AF_INET:
1082 1.1 thorpej epinit(sc);
1083 1.1 thorpej arp_ifinit(&sc->sc_arpcom, ifa);
1084 1.1 thorpej break;
1085 1.1 thorpej #endif
1086 1.1 thorpej #ifdef NS
1087 1.1 thorpej case AF_NS:
1088 1.1 thorpej {
1089 1.1 thorpej register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
1090 1.1 thorpej
1091 1.1 thorpej if (ns_nullhost(*ina))
1092 1.1 thorpej ina->x_host =
1093 1.1 thorpej *(union ns_host *)(sc->sc_arpcom.ac_enaddr);
1094 1.1 thorpej else
1095 1.1 thorpej bcopy(ina->x_host.c_host,
1096 1.1 thorpej sc->sc_arpcom.ac_enaddr,
1097 1.1 thorpej sizeof(sc->sc_arpcom.ac_enaddr));
1098 1.1 thorpej /* Set new address. */
1099 1.1 thorpej epinit(sc);
1100 1.1 thorpej break;
1101 1.1 thorpej }
1102 1.1 thorpej #endif
1103 1.1 thorpej default:
1104 1.1 thorpej epinit(sc);
1105 1.1 thorpej break;
1106 1.1 thorpej }
1107 1.1 thorpej break;
1108 1.1 thorpej
1109 1.1 thorpej case SIOCSIFFLAGS:
1110 1.1 thorpej if ((ifp->if_flags & IFF_UP) == 0 &&
1111 1.1 thorpej (ifp->if_flags & IFF_RUNNING) != 0) {
1112 1.1 thorpej /*
1113 1.1 thorpej * If interface is marked down and it is running, then
1114 1.1 thorpej * stop it.
1115 1.1 thorpej */
1116 1.1 thorpej epstop(sc);
1117 1.1 thorpej ifp->if_flags &= ~IFF_RUNNING;
1118 1.1 thorpej } else if ((ifp->if_flags & IFF_UP) != 0 &&
1119 1.1 thorpej (ifp->if_flags & IFF_RUNNING) == 0) {
1120 1.1 thorpej /*
1121 1.1 thorpej * If interface is marked up and it is stopped, then
1122 1.1 thorpej * start it.
1123 1.1 thorpej */
1124 1.1 thorpej epinit(sc);
1125 1.1 thorpej } else {
1126 1.1 thorpej /*
1127 1.1 thorpej * deal with flags changes:
1128 1.1 thorpej * IFF_MULTICAST, IFF_PROMISC,
1129 1.1 thorpej * IFF_LINK0, IFF_LINK1,
1130 1.1 thorpej */
1131 1.1 thorpej epsetfilter(sc);
1132 1.1 thorpej epsetlink(sc);
1133 1.1 thorpej }
1134 1.1 thorpej break;
1135 1.1 thorpej
1136 1.1 thorpej case SIOCADDMULTI:
1137 1.1 thorpej case SIOCDELMULTI:
1138 1.1 thorpej error = (cmd == SIOCADDMULTI) ?
1139 1.1 thorpej ether_addmulti(ifr, &sc->sc_arpcom) :
1140 1.1 thorpej ether_delmulti(ifr, &sc->sc_arpcom);
1141 1.1 thorpej
1142 1.1 thorpej if (error == ENETRESET) {
1143 1.1 thorpej /*
1144 1.1 thorpej * Multicast list has changed; set the hardware filter
1145 1.1 thorpej * accordingly.
1146 1.1 thorpej */
1147 1.1 thorpej epreset(sc);
1148 1.1 thorpej error = 0;
1149 1.1 thorpej }
1150 1.1 thorpej break;
1151 1.1 thorpej
1152 1.1 thorpej default:
1153 1.1 thorpej error = EINVAL;
1154 1.1 thorpej break;
1155 1.1 thorpej }
1156 1.1 thorpej
1157 1.1 thorpej splx(s);
1158 1.1 thorpej return (error);
1159 1.1 thorpej }
1160 1.1 thorpej
1161 1.1 thorpej void
1162 1.1 thorpej epreset(sc)
1163 1.1 thorpej struct ep_softc *sc;
1164 1.1 thorpej {
1165 1.1 thorpej int s;
1166 1.1 thorpej
1167 1.1 thorpej s = splnet();
1168 1.1 thorpej epstop(sc);
1169 1.1 thorpej epinit(sc);
1170 1.1 thorpej splx(s);
1171 1.1 thorpej }
1172 1.1 thorpej
1173 1.1 thorpej void
1174 1.5 thorpej epwatchdog(ifp)
1175 1.5 thorpej struct ifnet *ifp;
1176 1.1 thorpej {
1177 1.5 thorpej struct ep_softc *sc = ifp->if_softc;
1178 1.1 thorpej
1179 1.1 thorpej log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
1180 1.1 thorpej ++sc->sc_arpcom.ac_if.if_oerrors;
1181 1.1 thorpej
1182 1.1 thorpej epreset(sc);
1183 1.1 thorpej }
1184 1.1 thorpej
1185 1.1 thorpej void
1186 1.1 thorpej epstop(sc)
1187 1.1 thorpej register struct ep_softc *sc;
1188 1.1 thorpej {
1189 1.11 thorpej bus_space_tag_t iot = sc->sc_iot;
1190 1.11 thorpej bus_space_handle_t ioh = sc->sc_ioh;
1191 1.1 thorpej
1192 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISABLE);
1193 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISCARD_TOP_PACK);
1194 1.11 thorpej while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
1195 1.1 thorpej ;
1196 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND, TX_DISABLE);
1197 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND, STOP_TRANSCEIVER);
1198 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND, RX_RESET);
1199 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND, TX_RESET);
1200 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND, C_INTR_LATCH);
1201 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND, SET_RD_0_MASK);
1202 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND, SET_INTR_MASK);
1203 1.11 thorpej bus_space_write_2(iot, ioh, EP_COMMAND, SET_RX_FILTER);
1204 1.1 thorpej
1205 1.1 thorpej epmbufempty(sc);
1206 1.1 thorpej }
1207 1.1 thorpej
1208 1.1 thorpej /*
1209 1.1 thorpej * We get eeprom data from the id_port given an offset into the
1210 1.1 thorpej * eeprom. Basically; after the ID_sequence is sent to all of
1211 1.1 thorpej * the cards; they enter the ID_CMD state where they will accept
1212 1.1 thorpej * command requests. 0x80-0xbf loads the eeprom data. We then
1213 1.1 thorpej * read the port 16 times and with every read; the cards check
1214 1.1 thorpej * for contention (ie: if one card writes a 0 bit and another
1215 1.1 thorpej * writes a 1 bit then the host sees a 0. At the end of the cycle;
1216 1.1 thorpej * each card compares the data on the bus; if there is a difference
1217 1.1 thorpej * then that card goes into ID_WAIT state again). In the meantime;
1218 1.1 thorpej * one bit of data is returned in the AX register which is conveniently
1219 1.11 thorpej * returned to us by bus_space_read_1(). Hence; we read 16 times getting one
1220 1.1 thorpej * bit of data with each read.
1221 1.2 thorpej *
1222 1.2 thorpej * NOTE: the caller must provide an i/o handle for ELINK_ID_PORT!
1223 1.1 thorpej */
1224 1.2 thorpej u_int16_t
1225 1.11 thorpej epreadeeprom(iot, ioh, offset)
1226 1.11 thorpej bus_space_tag_t iot;
1227 1.11 thorpej bus_space_handle_t ioh;
1228 1.2 thorpej int offset;
1229 1.1 thorpej {
1230 1.2 thorpej u_int16_t data = 0;
1231 1.2 thorpej int i;
1232 1.1 thorpej
1233 1.11 thorpej bus_space_write_1(iot, ioh, 0, 0x80 + offset);
1234 1.1 thorpej delay(1000);
1235 1.1 thorpej for (i = 0; i < 16; i++)
1236 1.11 thorpej data = (data << 1) | (bus_space_read_2(iot, ioh, 0) & 1);
1237 1.1 thorpej return (data);
1238 1.1 thorpej }
1239 1.1 thorpej
1240 1.1 thorpej static int
1241 1.1 thorpej epbusyeeprom(sc)
1242 1.1 thorpej struct ep_softc *sc;
1243 1.1 thorpej {
1244 1.11 thorpej bus_space_tag_t iot = sc->sc_iot;
1245 1.11 thorpej bus_space_handle_t ioh = sc->sc_ioh;
1246 1.1 thorpej int i = 100, j;
1247 1.1 thorpej
1248 1.1 thorpej if (sc->bustype == EP_BUS_PCMCIA) {
1249 1.1 thorpej delay(1000);
1250 1.1 thorpej return 0;
1251 1.1 thorpej }
1252 1.1 thorpej
1253 1.1 thorpej while (i--) {
1254 1.11 thorpej j = bus_space_read_2(iot, ioh, EP_W0_EEPROM_COMMAND);
1255 1.1 thorpej if (j & EEPROM_BUSY)
1256 1.1 thorpej delay(100);
1257 1.1 thorpej else
1258 1.1 thorpej break;
1259 1.1 thorpej }
1260 1.1 thorpej if (!i) {
1261 1.10 christos printf("\n%s: eeprom failed to come ready\n",
1262 1.1 thorpej sc->sc_dev.dv_xname);
1263 1.1 thorpej return (1);
1264 1.1 thorpej }
1265 1.1 thorpej if (j & EEPROM_TST_MODE) {
1266 1.10 christos printf("\n%s: erase pencil mark, or disable plug-n-play mode!\n",
1267 1.1 thorpej sc->sc_dev.dv_xname);
1268 1.1 thorpej return (1);
1269 1.1 thorpej }
1270 1.1 thorpej return (0);
1271 1.1 thorpej }
1272 1.1 thorpej
1273 1.1 thorpej void
1274 1.3 christos epmbuffill(v)
1275 1.3 christos void *v;
1276 1.1 thorpej {
1277 1.3 christos struct ep_softc *sc = v;
1278 1.1 thorpej int s, i;
1279 1.1 thorpej
1280 1.1 thorpej s = splnet();
1281 1.1 thorpej i = sc->last_mb;
1282 1.1 thorpej do {
1283 1.1 thorpej if (sc->mb[i] == NULL)
1284 1.1 thorpej MGET(sc->mb[i], M_DONTWAIT, MT_DATA);
1285 1.1 thorpej if (sc->mb[i] == NULL)
1286 1.1 thorpej break;
1287 1.1 thorpej i = (i + 1) % MAX_MBS;
1288 1.1 thorpej } while (i != sc->next_mb);
1289 1.1 thorpej sc->last_mb = i;
1290 1.1 thorpej /* If the queue was not filled, try again. */
1291 1.1 thorpej if (sc->last_mb != sc->next_mb)
1292 1.1 thorpej timeout(epmbuffill, sc, 1);
1293 1.1 thorpej splx(s);
1294 1.1 thorpej }
1295 1.1 thorpej
1296 1.1 thorpej void
1297 1.1 thorpej epmbufempty(sc)
1298 1.1 thorpej struct ep_softc *sc;
1299 1.1 thorpej {
1300 1.1 thorpej int s, i;
1301 1.1 thorpej
1302 1.1 thorpej s = splnet();
1303 1.1 thorpej for (i = 0; i<MAX_MBS; i++) {
1304 1.1 thorpej if (sc->mb[i]) {
1305 1.1 thorpej m_freem(sc->mb[i]);
1306 1.1 thorpej sc->mb[i] = NULL;
1307 1.1 thorpej }
1308 1.1 thorpej }
1309 1.1 thorpej sc->last_mb = sc->next_mb = 0;
1310 1.1 thorpej untimeout(epmbuffill, sc);
1311 1.1 thorpej splx(s);
1312 1.1 thorpej }
1313