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