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