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