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