Remove PC98 fdisk(8).
[dragonfly.git] / sys / dev / netif / de / if_de.c
CommitLineData
984263bc
MD
1/* $NetBSD: if_de.c,v 1.86 1999/06/01 19:17:59 thorpej Exp $ */
2
3/* $FreeBSD: src/sys/pci/if_de.c,v 1.123.2.4 2000/08/04 23:25:09 peter Exp $ */
cdfcdfb0 4/* $DragonFly: src/sys/dev/netif/de/if_de.c,v 1.28 2005/02/21 05:25:49 joerg Exp $ */
984263bc
MD
5
6/*-
7 * Copyright (c) 1994-1997 Matt Thomas (matt@3am-software.com)
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. The name of the author may not be used to endorse or promote products
16 * derived from this software withough specific prior written permission
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Id: if_de.c,v 1.94 1997/07/03 16:55:07 thomas Exp
30 *
31 */
32
33/*
34 * DEC 21040 PCI Ethernet Controller
35 *
36 * Written by Matt Thomas
37 * BPF support code stolen directly from if_ec.c
38 *
39 * This driver supports the DEC DE435 or any other PCI
40 * board which support 21040, 21041, or 21140 (mostly).
41 */
984263bc
MD
42
43#include <sys/param.h>
44#include <sys/systm.h>
45#include <sys/mbuf.h>
46#include <sys/socket.h>
47#include <sys/sockio.h>
48#include <sys/malloc.h>
49#include <sys/kernel.h>
50#include <sys/eventhandler.h>
51#include <machine/clock.h>
52#include <machine/bus.h>
53#include <machine/resource.h>
54#include <sys/bus.h>
55#include <sys/rman.h>
56
57#include "opt_inet.h"
58#include "opt_ipx.h"
59
60#include <net/if.h>
61#include <net/if_media.h>
62#include <net/if_dl.h>
984263bc
MD
63
64#include <net/bpf.h>
65
66#ifdef INET
67#include <netinet/in.h>
68#include <netinet/if_ether.h>
69#endif
70
71#ifdef IPX
d2438d69
MD
72#include <netproto/ipx/ipx.h>
73#include <netproto/ipx/ipx_if.h>
984263bc
MD
74#endif
75
76#ifdef NS
d2438d69
MD
77#include <netproto/ns/ns.h>
78#include <netproto/ns/ns_if.h>
984263bc
MD
79#endif
80
81#include <vm/vm.h>
82
83#include <net/if_var.h>
84#include <vm/pmap.h>
1f2de5d4
MD
85#include <bus/pci/pcivar.h>
86#include <bus/pci/pcireg.h>
87#include <bus/pci/dc21040reg.h>
984263bc
MD
88
89/*
90 * Intel CPUs should use I/O mapped access.
91 */
92#if defined(__i386__)
93#define TULIP_IOMAPPED
94#endif
95
984263bc
MD
96#define TULIP_HZ 10
97
1f2de5d4 98#include "if_devar.h"
984263bc 99
cdfcdfb0
JS
100static tulip_softc_t *tulips[TULIP_MAX_DEVICES];
101
984263bc
MD
102/*
103 * This module supports
104 * the DEC 21040 PCI Ethernet Controller.
105 * the DEC 21041 PCI Ethernet Controller.
106 * the DEC 21140 PCI Fast Ethernet Controller.
107 */
108static void tulip_mii_autonegotiate(tulip_softc_t * const sc, const unsigned phyaddr);
109static void tulip_intr_shared(void *arg);
110static void tulip_intr_normal(void *arg);
111static void tulip_init(tulip_softc_t * const sc);
112static void tulip_reset(tulip_softc_t * const sc);
984263bc
MD
113static void tulip_ifstart(struct ifnet *ifp);
114static struct mbuf *tulip_txput(tulip_softc_t * const sc, struct mbuf *m);
115static void tulip_txput_setup(tulip_softc_t * const sc);
116static void tulip_rx_intr(tulip_softc_t * const sc);
117static void tulip_addr_filter(tulip_softc_t * const sc);
118static unsigned tulip_mii_readreg(tulip_softc_t * const sc, unsigned devaddr, unsigned regno);
119static void tulip_mii_writereg(tulip_softc_t * const sc, unsigned devaddr, unsigned regno, unsigned data);
120static int tulip_mii_map_abilities(tulip_softc_t * const sc, unsigned abilities);
121static tulip_media_t tulip_mii_phy_readspecific(tulip_softc_t * const sc);
122static int tulip_srom_decode(tulip_softc_t * const sc);
123static int tulip_ifmedia_change(struct ifnet * const ifp);
124static void tulip_ifmedia_status(struct ifnet * const ifp, struct ifmediareq *req);
125/* static void tulip_21140_map_media(tulip_softc_t *sc); */
126\f
127static void
128tulip_timeout_callback(
129 void *arg)
130{
131 tulip_softc_t * const sc = arg;
132 int s = splimp();
133
984263bc
MD
134 sc->tulip_flags &= ~TULIP_TIMEOUTPENDING;
135 sc->tulip_probe_timeout -= 1000 / TULIP_HZ;
136 (sc->tulip_boardsw->bd_media_poll)(sc, TULIP_MEDIAPOLL_TIMER);
984263bc
MD
137 splx(s);
138}
139
140static void
141tulip_timeout(
142 tulip_softc_t * const sc)
143{
144 if (sc->tulip_flags & TULIP_TIMEOUTPENDING)
145 return;
146 sc->tulip_flags |= TULIP_TIMEOUTPENDING;
88fcae56
JS
147 callout_reset(&sc->tulip_timer, (hz + TULIP_HZ / 2) / TULIP_HZ,
148 tulip_timeout_callback, sc);
984263bc
MD
149}
150
984263bc
MD
151static int
152tulip_txprobe(
153 tulip_softc_t * const sc)
154{
155 struct mbuf *m;
156 /*
157 * Before we are sure this is the right media we need
158 * to send a small packet to make sure there's carrier.
159 * Strangely, BNC and AUI will "see" receive data if
160 * either is connected so the transmit is the only way
161 * to verify the connectivity.
162 */
74f1caca 163 MGETHDR(m, MB_DONTWAIT, MT_DATA);
984263bc
MD
164 if (m == NULL)
165 return 0;
166 /*
167 * Construct a LLC TEST message which will point to ourselves.
168 */
169 bcopy(sc->tulip_enaddr, mtod(m, struct ether_header *)->ether_dhost, 6);
170 bcopy(sc->tulip_enaddr, mtod(m, struct ether_header *)->ether_shost, 6);
171 mtod(m, struct ether_header *)->ether_type = htons(3);
172 mtod(m, unsigned char *)[14] = 0;
173 mtod(m, unsigned char *)[15] = 0;
174 mtod(m, unsigned char *)[16] = 0xE3; /* LLC Class1 TEST (no poll) */
175 m->m_len = m->m_pkthdr.len = sizeof(struct ether_header) + 3;
176 /*
177 * send it!
178 */
179 sc->tulip_cmdmode |= TULIP_CMD_TXRUN;
180 sc->tulip_intrmask |= TULIP_STS_TXINTR;
181 sc->tulip_flags |= TULIP_TXPROBE_ACTIVE;
182 TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode);
183 TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask);
184 if ((m = tulip_txput(sc, m)) != NULL)
185 m_freem(m);
186 sc->tulip_probe.probe_txprobes++;
187 return 1;
188}
189\f
190#ifdef BIG_PACKET
191#define TULIP_SIAGEN_WATCHDOG (sc->tulip_if.if_mtu > ETHERMTU ? TULIP_WATCHDOG_RXDISABLE|TULIP_WATCHDOG_TXDISABLE : 0)
192#else
193#define TULIP_SIAGEN_WATCHDOG 0
194#endif
195
196static void
197tulip_media_set(
198 tulip_softc_t * const sc,
199 tulip_media_t media)
200{
201 const tulip_media_info_t *mi = sc->tulip_mediums[media];
202
203 if (mi == NULL)
204 return;
205
206 /*
207 * If we are switching media, make sure we don't think there's
208 * any stale RX activity
209 */
210 sc->tulip_flags &= ~TULIP_RXACT;
211 if (mi->mi_type == TULIP_MEDIAINFO_SIA) {
212 TULIP_CSR_WRITE(sc, csr_sia_connectivity, TULIP_SIACONN_RESET);
213 TULIP_CSR_WRITE(sc, csr_sia_tx_rx, mi->mi_sia_tx_rx);
214 if (sc->tulip_features & TULIP_HAVE_SIAGP) {
215 TULIP_CSR_WRITE(sc, csr_sia_general, mi->mi_sia_gp_control|mi->mi_sia_general|TULIP_SIAGEN_WATCHDOG);
216 DELAY(50);
217 TULIP_CSR_WRITE(sc, csr_sia_general, mi->mi_sia_gp_data|mi->mi_sia_general|TULIP_SIAGEN_WATCHDOG);
218 } else {
219 TULIP_CSR_WRITE(sc, csr_sia_general, mi->mi_sia_general|TULIP_SIAGEN_WATCHDOG);
220 }
221 TULIP_CSR_WRITE(sc, csr_sia_connectivity, mi->mi_sia_connectivity);
222 } else if (mi->mi_type == TULIP_MEDIAINFO_GPR) {
223#define TULIP_GPR_CMDBITS (TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER|TULIP_CMD_TXTHRSHLDCTL)
224 /*
225 * If the cmdmode bits don't match the currently operating mode,
226 * set the cmdmode appropriately and reset the chip.
227 */
228 if (((mi->mi_cmdmode ^ TULIP_CSR_READ(sc, csr_command)) & TULIP_GPR_CMDBITS) != 0) {
229 sc->tulip_cmdmode &= ~TULIP_GPR_CMDBITS;
230 sc->tulip_cmdmode |= mi->mi_cmdmode;
231 tulip_reset(sc);
232 }
233 TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_PINSET|sc->tulip_gpinit);
234 DELAY(10);
235 TULIP_CSR_WRITE(sc, csr_gp, (u_int8_t) mi->mi_gpdata);
236 } else if (mi->mi_type == TULIP_MEDIAINFO_SYM) {
237 /*
238 * If the cmdmode bits don't match the currently operating mode,
239 * set the cmdmode appropriately and reset the chip.
240 */
241 if (((mi->mi_cmdmode ^ TULIP_CSR_READ(sc, csr_command)) & TULIP_GPR_CMDBITS) != 0) {
242 sc->tulip_cmdmode &= ~TULIP_GPR_CMDBITS;
243 sc->tulip_cmdmode |= mi->mi_cmdmode;
244 tulip_reset(sc);
245 }
246 TULIP_CSR_WRITE(sc, csr_sia_general, mi->mi_gpcontrol);
247 TULIP_CSR_WRITE(sc, csr_sia_general, mi->mi_gpdata);
248 } else if (mi->mi_type == TULIP_MEDIAINFO_MII
249 && sc->tulip_probe_state != TULIP_PROBE_INACTIVE) {
250 int idx;
251 if (sc->tulip_features & TULIP_HAVE_SIAGP) {
252 const u_int8_t *dp;
253 dp = &sc->tulip_rombuf[mi->mi_reset_offset];
254 for (idx = 0; idx < mi->mi_reset_length; idx++, dp += 2) {
255 DELAY(10);
256 TULIP_CSR_WRITE(sc, csr_sia_general, (dp[0] + 256 * dp[1]) << 16);
257 }
258 sc->tulip_phyaddr = mi->mi_phyaddr;
259 dp = &sc->tulip_rombuf[mi->mi_gpr_offset];
260 for (idx = 0; idx < mi->mi_gpr_length; idx++, dp += 2) {
261 DELAY(10);
262 TULIP_CSR_WRITE(sc, csr_sia_general, (dp[0] + 256 * dp[1]) << 16);
263 }
264 } else {
265 for (idx = 0; idx < mi->mi_reset_length; idx++) {
266 DELAY(10);
267 TULIP_CSR_WRITE(sc, csr_gp, sc->tulip_rombuf[mi->mi_reset_offset + idx]);
268 }
269 sc->tulip_phyaddr = mi->mi_phyaddr;
270 for (idx = 0; idx < mi->mi_gpr_length; idx++) {
271 DELAY(10);
272 TULIP_CSR_WRITE(sc, csr_gp, sc->tulip_rombuf[mi->mi_gpr_offset + idx]);
273 }
274 }
275 if (sc->tulip_flags & TULIP_TRYNWAY) {
276 tulip_mii_autonegotiate(sc, sc->tulip_phyaddr);
277 } else if ((sc->tulip_flags & TULIP_DIDNWAY) == 0) {
278 u_int32_t data = tulip_mii_readreg(sc, sc->tulip_phyaddr, PHYREG_CONTROL);
279 data &= ~(PHYCTL_SELECT_100MB|PHYCTL_FULL_DUPLEX|PHYCTL_AUTONEG_ENABLE);
280 sc->tulip_flags &= ~TULIP_DIDNWAY;
281 if (TULIP_IS_MEDIA_FD(media))
282 data |= PHYCTL_FULL_DUPLEX;
283 if (TULIP_IS_MEDIA_100MB(media))
284 data |= PHYCTL_SELECT_100MB;
285 tulip_mii_writereg(sc, sc->tulip_phyaddr, PHYREG_CONTROL, data);
286 }
287 }
288}
289\f
290static void
291tulip_linkup(
292 tulip_softc_t * const sc,
293 tulip_media_t media)
294{
295 if ((sc->tulip_flags & TULIP_LINKUP) == 0)
296 sc->tulip_flags |= TULIP_PRINTLINKUP;
297 sc->tulip_flags |= TULIP_LINKUP;
298 sc->tulip_if.if_flags &= ~IFF_OACTIVE;
299#if 0 /* XXX how does with work with ifmedia? */
300 if ((sc->tulip_flags & TULIP_DIDNWAY) == 0) {
301 if (sc->tulip_if.if_flags & IFF_FULLDUPLEX) {
302 if (TULIP_CAN_MEDIA_FD(media)
303 && sc->tulip_mediums[TULIP_FD_MEDIA_OF(media)] != NULL)
304 media = TULIP_FD_MEDIA_OF(media);
305 } else {
306 if (TULIP_IS_MEDIA_FD(media)
307 && sc->tulip_mediums[TULIP_HD_MEDIA_OF(media)] != NULL)
308 media = TULIP_HD_MEDIA_OF(media);
309 }
310 }
311#endif
312 if (sc->tulip_media != media) {
984263bc
MD
313 sc->tulip_media = media;
314 sc->tulip_flags |= TULIP_PRINTMEDIA;
315 if (TULIP_IS_MEDIA_FD(sc->tulip_media)) {
316 sc->tulip_cmdmode |= TULIP_CMD_FULLDUPLEX;
317 } else if (sc->tulip_chipid != TULIP_21041 || (sc->tulip_flags & TULIP_DIDNWAY) == 0) {
318 sc->tulip_cmdmode &= ~TULIP_CMD_FULLDUPLEX;
319 }
320 }
321 /*
322 * We could set probe_timeout to 0 but setting to 3000 puts this
323 * in one central place and the only matters is tulip_link is
324 * followed by a tulip_timeout. Therefore setting it should not
325 * result in aberrant behavour.
326 */
327 sc->tulip_probe_timeout = 3000;
328 sc->tulip_probe_state = TULIP_PROBE_INACTIVE;
329 sc->tulip_flags &= ~(TULIP_TXPROBE_ACTIVE|TULIP_TRYNWAY);
330 if (sc->tulip_flags & TULIP_INRESET) {
331 tulip_media_set(sc, sc->tulip_media);
332 } else if (sc->tulip_probe_media != sc->tulip_media) {
333 /*
334 * No reason to change media if we have the right media.
335 */
336 tulip_reset(sc);
337 }
338 tulip_init(sc);
339}
340\f
341static void
342tulip_media_print(
343 tulip_softc_t * const sc)
344{
345 if ((sc->tulip_flags & TULIP_LINKUP) == 0)
346 return;
347 if (sc->tulip_flags & TULIP_PRINTMEDIA) {
348 printf("%s%d: enabling %s port\n",
349 sc->tulip_name, sc->tulip_unit,
350 tulip_mediums[sc->tulip_media]);
351 sc->tulip_flags &= ~(TULIP_PRINTMEDIA|TULIP_PRINTLINKUP);
352 } else if (sc->tulip_flags & TULIP_PRINTLINKUP) {
353 printf("%s%d: link up\n", sc->tulip_name, sc->tulip_unit);
354 sc->tulip_flags &= ~TULIP_PRINTLINKUP;
355 }
356}
357\f
358#if defined(TULIP_DO_GPR_SENSE)
359static tulip_media_t
360tulip_21140_gpr_media_sense(
361 tulip_softc_t * const sc)
362{
363 tulip_media_t maybe_media = TULIP_MEDIA_UNKNOWN;
364 tulip_media_t last_media = TULIP_MEDIA_UNKNOWN;
365 tulip_media_t media;
366
367 /*
368 * If one of the media blocks contained a default media flag,
369 * use that.
370 */
371 for (media = TULIP_MEDIA_UNKNOWN; media < TULIP_MEDIA_MAX; media++) {
372 const tulip_media_info_t *mi;
373 /*
374 * Media is not supported (or is full-duplex).
375 */
376 if ((mi = sc->tulip_mediums[media]) == NULL || TULIP_IS_MEDIA_FD(media))
377 continue;
378 if (mi->mi_type != TULIP_MEDIAINFO_GPR)
379 continue;
380
381 /*
382 * Remember the media is this is the "default" media.
383 */
384 if (mi->mi_default && maybe_media == TULIP_MEDIA_UNKNOWN)
385 maybe_media = media;
386
387 /*
388 * No activity mask? Can't see if it is active if there's no mask.
389 */
390 if (mi->mi_actmask == 0)
391 continue;
392
393 /*
394 * Does the activity data match?
395 */
396 if ((TULIP_CSR_READ(sc, csr_gp) & mi->mi_actmask) != mi->mi_actdata)
397 continue;
398
984263bc
MD
399 /*
400 * It does! If this is the first media we detected, then
401 * remember this media. If isn't the first, then there were
402 * multiple matches which we equate to no match (since we don't
403 * which to select (if any).
404 */
405 if (last_media == TULIP_MEDIA_UNKNOWN) {
406 last_media = media;
407 } else if (last_media != media) {
408 last_media = TULIP_MEDIA_UNKNOWN;
409 }
410 }
411 return (last_media != TULIP_MEDIA_UNKNOWN) ? last_media : maybe_media;
412}
413#endif /* TULIP_DO_GPR_SENSE */
414\f
415static tulip_link_status_t
416tulip_media_link_monitor(
417 tulip_softc_t * const sc)
418{
419 const tulip_media_info_t * const mi = sc->tulip_mediums[sc->tulip_media];
420 tulip_link_status_t linkup = TULIP_LINK_DOWN;
421
422 if (mi == NULL) {
46a77a85 423#if defined(DIAGNOSTIC)
984263bc
MD
424 panic("tulip_media_link_monitor: %s: botch at line %d\n",
425 tulip_mediums[sc->tulip_media],__LINE__);
426#endif
427 return TULIP_LINK_UNKNOWN;
428 }
429
430
431 /*
432 * Have we seen some packets? If so, the link must be good.
433 */
434 if ((sc->tulip_flags & (TULIP_RXACT|TULIP_LINKUP)) == (TULIP_RXACT|TULIP_LINKUP)) {
435 sc->tulip_flags &= ~TULIP_RXACT;
436 sc->tulip_probe_timeout = 3000;
437 return TULIP_LINK_UP;
438 }
439
440 sc->tulip_flags &= ~TULIP_RXACT;
441 if (mi->mi_type == TULIP_MEDIAINFO_MII) {
442 u_int32_t status;
443 /*
444 * Read the PHY status register.
445 */
446 status = tulip_mii_readreg(sc, sc->tulip_phyaddr, PHYREG_STATUS);
447 if (status & PHYSTS_AUTONEG_DONE) {
448 /*
449 * If the PHY has completed autonegotiation, see the if the
450 * remote systems abilities have changed. If so, upgrade or
451 * downgrade as appropriate.
452 */
453 u_int32_t abilities = tulip_mii_readreg(sc, sc->tulip_phyaddr, PHYREG_AUTONEG_ABILITIES);
454 abilities = (abilities << 6) & status;
455 if (abilities != sc->tulip_abilities) {
984263bc
MD
456 if (tulip_mii_map_abilities(sc, abilities)) {
457 tulip_linkup(sc, sc->tulip_probe_media);
458 return TULIP_LINK_UP;
459 }
460 /*
461 * if we had selected media because of autonegotiation,
462 * we need to probe for the new media.
463 */
464 sc->tulip_probe_state = TULIP_PROBE_INACTIVE;
465 if (sc->tulip_flags & TULIP_DIDNWAY)
466 return TULIP_LINK_DOWN;
467 }
468 }
469 /*
470 * The link is now up. If was down, say its back up.
471 */
472 if ((status & (PHYSTS_LINK_UP|PHYSTS_REMOTE_FAULT)) == PHYSTS_LINK_UP)
473 linkup = TULIP_LINK_UP;
474 } else if (mi->mi_type == TULIP_MEDIAINFO_GPR) {
475 /*
476 * No activity sensor? Assume all's well.
477 */
478 if (mi->mi_actmask == 0)
479 return TULIP_LINK_UNKNOWN;
480 /*
481 * Does the activity data match?
482 */
483 if ((TULIP_CSR_READ(sc, csr_gp) & mi->mi_actmask) == mi->mi_actdata)
484 linkup = TULIP_LINK_UP;
485 } else if (mi->mi_type == TULIP_MEDIAINFO_SIA) {
486 /*
487 * Assume non TP ok for now.
488 */
489 if (!TULIP_IS_MEDIA_TP(sc->tulip_media))
490 return TULIP_LINK_UNKNOWN;
491 if ((TULIP_CSR_READ(sc, csr_sia_status) & TULIP_SIASTS_LINKFAIL) == 0)
492 linkup = TULIP_LINK_UP;
984263bc
MD
493 } else if (mi->mi_type == TULIP_MEDIAINFO_SYM) {
494 return TULIP_LINK_UNKNOWN;
495 }
496 /*
497 * We will wait for 3 seconds until the link goes into suspect mode.
498 */
499 if (sc->tulip_flags & TULIP_LINKUP) {
500 if (linkup == TULIP_LINK_UP)
501 sc->tulip_probe_timeout = 3000;
502 if (sc->tulip_probe_timeout > 0)
503 return TULIP_LINK_UP;
504
505 sc->tulip_flags &= ~TULIP_LINKUP;
506 printf("%s%d: link down: cable problem?\n", sc->tulip_name, sc->tulip_unit);
507 }
984263bc
MD
508 return TULIP_LINK_DOWN;
509}
510\f
511static void
512tulip_media_poll(
513 tulip_softc_t * const sc,
514 tulip_mediapoll_event_t event)
515{
984263bc
MD
516 if (sc->tulip_probe_state == TULIP_PROBE_INACTIVE
517 && event == TULIP_MEDIAPOLL_TIMER) {
518 switch (tulip_media_link_monitor(sc)) {
519 case TULIP_LINK_DOWN: {
520 /*
521 * Link Monitor failed. Probe for new media.
522 */
523 event = TULIP_MEDIAPOLL_LINKFAIL;
524 break;
525 }
526 case TULIP_LINK_UP: {
527 /*
528 * Check again soon.
529 */
530 tulip_timeout(sc);
531 return;
532 }
533 case TULIP_LINK_UNKNOWN: {
534 /*
535 * We can't tell so don't bother.
536 */
537 return;
538 }
539 }
540 }
541
542 if (event == TULIP_MEDIAPOLL_LINKFAIL) {
543 if (sc->tulip_probe_state == TULIP_PROBE_INACTIVE) {
544 if (TULIP_DO_AUTOSENSE(sc)) {
984263bc
MD
545 sc->tulip_media = TULIP_MEDIA_UNKNOWN;
546 if (sc->tulip_if.if_flags & IFF_UP)
547 tulip_reset(sc); /* restart probe */
548 }
549 return;
550 }
984263bc
MD
551 }
552
553 if (event == TULIP_MEDIAPOLL_START) {
554 sc->tulip_if.if_flags |= IFF_OACTIVE;
555 if (sc->tulip_probe_state != TULIP_PROBE_INACTIVE)
556 return;
557 sc->tulip_probe_mediamask = 0;
558 sc->tulip_probe_passes = 0;
984263bc
MD
559 /*
560 * If the SROM contained an explicit media to use, use it.
561 */
562 sc->tulip_cmdmode &= ~(TULIP_CMD_RXRUN|TULIP_CMD_FULLDUPLEX);
563 sc->tulip_flags |= TULIP_TRYNWAY|TULIP_PROBE1STPASS;
564 sc->tulip_flags &= ~(TULIP_DIDNWAY|TULIP_PRINTMEDIA|TULIP_PRINTLINKUP);
565 /*
566 * connidx is defaulted to a media_unknown type.
567 */
568 sc->tulip_probe_media = tulip_srom_conninfo[sc->tulip_connidx].sc_media;
569 if (sc->tulip_probe_media != TULIP_MEDIA_UNKNOWN) {
570 tulip_linkup(sc, sc->tulip_probe_media);
571 tulip_timeout(sc);
572 return;
573 }
574
575 if (sc->tulip_features & TULIP_HAVE_GPR) {
576 sc->tulip_probe_state = TULIP_PROBE_GPRTEST;
577 sc->tulip_probe_timeout = 2000;
578 } else {
579 sc->tulip_probe_media = TULIP_MEDIA_MAX;
580 sc->tulip_probe_timeout = 0;
581 sc->tulip_probe_state = TULIP_PROBE_MEDIATEST;
582 }
583 }
584
585 /*
586 * Ignore txprobe failures or spurious callbacks.
587 */
588 if (event == TULIP_MEDIAPOLL_TXPROBE_FAILED
589 && sc->tulip_probe_state != TULIP_PROBE_MEDIATEST) {
590 sc->tulip_flags &= ~TULIP_TXPROBE_ACTIVE;
591 return;
592 }
593
594 /*
595 * If we really transmitted a packet, then that's the media we'll use.
596 */
597 if (event == TULIP_MEDIAPOLL_TXPROBE_OK || event == TULIP_MEDIAPOLL_LINKPASS) {
598 if (event == TULIP_MEDIAPOLL_LINKPASS) {
599 /* XXX Check media status just to be sure */
600 sc->tulip_probe_media = TULIP_MEDIA_10BASET;
984263bc
MD
601 }
602 tulip_linkup(sc, sc->tulip_probe_media);
603 tulip_timeout(sc);
604 return;
605 }
606
607 if (sc->tulip_probe_state == TULIP_PROBE_GPRTEST) {
608#if defined(TULIP_DO_GPR_SENSE)
609 /*
610 * Check for media via the general purpose register.
611 *
612 * Try to sense the media via the GPR. If the same value
613 * occurs 3 times in a row then just use that.
614 */
615 if (sc->tulip_probe_timeout > 0) {
616 tulip_media_t new_probe_media = tulip_21140_gpr_media_sense(sc);
984263bc
MD
617 if (new_probe_media != TULIP_MEDIA_UNKNOWN) {
618 if (new_probe_media == sc->tulip_probe_media) {
619 if (--sc->tulip_probe_count == 0)
620 tulip_linkup(sc, sc->tulip_probe_media);
621 } else {
622 sc->tulip_probe_count = 10;
623 }
624 }
625 sc->tulip_probe_media = new_probe_media;
626 tulip_timeout(sc);
627 return;
628 }
629#endif /* TULIP_DO_GPR_SENSE */
630 /*
631 * Brute force. We cycle through each of the media types
632 * and try to transmit a packet.
633 */
634 sc->tulip_probe_state = TULIP_PROBE_MEDIATEST;
635 sc->tulip_probe_media = TULIP_MEDIA_MAX;
636 sc->tulip_probe_timeout = 0;
637 tulip_timeout(sc);
638 return;
639 }
640
641 if (sc->tulip_probe_state != TULIP_PROBE_MEDIATEST
642 && (sc->tulip_features & TULIP_HAVE_MII)) {
643 tulip_media_t old_media = sc->tulip_probe_media;
644 tulip_mii_autonegotiate(sc, sc->tulip_phyaddr);
645 switch (sc->tulip_probe_state) {
646 case TULIP_PROBE_FAILED:
647 case TULIP_PROBE_MEDIATEST: {
648 /*
649 * Try the next media.
650 */
651 sc->tulip_probe_mediamask |= sc->tulip_mediums[sc->tulip_probe_media]->mi_mediamask;
652 sc->tulip_probe_timeout = 0;
653#ifdef notyet
654 if (sc->tulip_probe_state == TULIP_PROBE_FAILED)
655 break;
656 if (sc->tulip_probe_media != tulip_mii_phy_readspecific(sc))
657 break;
658 sc->tulip_probe_timeout = TULIP_IS_MEDIA_TP(sc->tulip_probe_media) ? 2500 : 300;
659#endif
660 break;
661 }
662 case TULIP_PROBE_PHYAUTONEG: {
663 return;
664 }
665 case TULIP_PROBE_INACTIVE: {
666 /*
667 * Only probe if we autonegotiated a media that hasn't failed.
668 */
669 sc->tulip_probe_timeout = 0;
670 if (sc->tulip_probe_mediamask & TULIP_BIT(sc->tulip_probe_media)) {
671 sc->tulip_probe_media = old_media;
672 break;
673 }
674 tulip_linkup(sc, sc->tulip_probe_media);
675 tulip_timeout(sc);
676 return;
677 }
678 default: {
46a77a85 679#if defined(DIAGNOSTIC)
984263bc
MD
680 panic("tulip_media_poll: botch at line %d\n", __LINE__);
681#endif
682 break;
683 }
684 }
685 }
686
687 if (event == TULIP_MEDIAPOLL_TXPROBE_FAILED) {
984263bc
MD
688 sc->tulip_flags &= ~TULIP_TXPROBE_ACTIVE;
689 return;
690 }
691
692 /*
693 * switch to another media if we tried this one enough.
694 */
695 if (/* event == TULIP_MEDIAPOLL_TXPROBE_FAILED || */ sc->tulip_probe_timeout <= 0) {
984263bc
MD
696 /*
697 * Find the next media type to check for. Full Duplex
698 * types are not allowed.
699 */
700 do {
701 sc->tulip_probe_media -= 1;
702 if (sc->tulip_probe_media == TULIP_MEDIA_UNKNOWN) {
703 if (++sc->tulip_probe_passes == 3) {
704 printf("%s%d: autosense failed: cable problem?\n",
705 sc->tulip_name, sc->tulip_unit);
706 if ((sc->tulip_if.if_flags & IFF_UP) == 0) {
707 sc->tulip_if.if_flags &= ~IFF_RUNNING;
708 sc->tulip_probe_state = TULIP_PROBE_INACTIVE;
709 return;
710 }
711 }
712 sc->tulip_flags ^= TULIP_TRYNWAY; /* XXX */
713 sc->tulip_probe_mediamask = 0;
714 sc->tulip_probe_media = TULIP_MEDIA_MAX - 1;
715 }
716 } while (sc->tulip_mediums[sc->tulip_probe_media] == NULL
717 || (sc->tulip_probe_mediamask & TULIP_BIT(sc->tulip_probe_media))
718 || TULIP_IS_MEDIA_FD(sc->tulip_probe_media));
719
984263bc
MD
720 sc->tulip_probe_timeout = TULIP_IS_MEDIA_TP(sc->tulip_probe_media) ? 2500 : 1000;
721 sc->tulip_probe_state = TULIP_PROBE_MEDIATEST;
722 sc->tulip_probe.probe_txprobes = 0;
723 tulip_reset(sc);
724 tulip_media_set(sc, sc->tulip_probe_media);
725 sc->tulip_flags &= ~TULIP_TXPROBE_ACTIVE;
726 }
727 tulip_timeout(sc);
728
729 /*
730 * If this is hanging off a phy, we know are doing NWAY and we have
731 * forced the phy to a specific speed. Wait for link up before
732 * before sending a packet.
733 */
734 switch (sc->tulip_mediums[sc->tulip_probe_media]->mi_type) {
735 case TULIP_MEDIAINFO_MII: {
736 if (sc->tulip_probe_media != tulip_mii_phy_readspecific(sc))
737 return;
738 break;
739 }
740 case TULIP_MEDIAINFO_SIA: {
741 if (TULIP_IS_MEDIA_TP(sc->tulip_probe_media)) {
742 if (TULIP_CSR_READ(sc, csr_sia_status) & TULIP_SIASTS_LINKFAIL)
743 return;
744 tulip_linkup(sc, sc->tulip_probe_media);
745#ifdef notyet
746 if (sc->tulip_features & TULIP_HAVE_MII)
747 tulip_timeout(sc);
748#endif
749 return;
750 }
751 break;
752 }
753 case TULIP_MEDIAINFO_RESET:
754 case TULIP_MEDIAINFO_SYM:
755 case TULIP_MEDIAINFO_NONE:
756 case TULIP_MEDIAINFO_GPR: {
757 break;
758 }
759 }
760 /*
761 * Try to send a packet.
762 */
763 tulip_txprobe(sc);
764}
765\f
766static void
767tulip_media_select(
768 tulip_softc_t * const sc)
769{
770 if (sc->tulip_features & TULIP_HAVE_GPR) {
771 TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_PINSET|sc->tulip_gpinit);
772 DELAY(10);
773 TULIP_CSR_WRITE(sc, csr_gp, sc->tulip_gpdata);
774 }
775 /*
776 * If this board has no media, just return
777 */
778 if (sc->tulip_features & TULIP_HAVE_NOMEDIA)
779 return;
780
781 if (sc->tulip_media == TULIP_MEDIA_UNKNOWN) {
782 TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask);
783 (*sc->tulip_boardsw->bd_media_poll)(sc, TULIP_MEDIAPOLL_START);
784 } else {
785 tulip_media_set(sc, sc->tulip_media);
786 }
787}
788\f
789static void
790tulip_21040_mediainfo_init(
791 tulip_softc_t * const sc,
792 tulip_media_t media)
793{
794 sc->tulip_cmdmode |= TULIP_CMD_CAPTREFFCT|TULIP_CMD_THRSHLD160
795 |TULIP_CMD_BACKOFFCTR;
796 sc->tulip_if.if_baudrate = 10000000;
797
798 if (media == TULIP_MEDIA_10BASET || media == TULIP_MEDIA_UNKNOWN) {
799 TULIP_MEDIAINFO_SIA_INIT(sc, &sc->tulip_mediainfo[0], 21040, 10BASET);
800 TULIP_MEDIAINFO_SIA_INIT(sc, &sc->tulip_mediainfo[1], 21040, 10BASET_FD);
801 sc->tulip_intrmask |= TULIP_STS_LINKPASS|TULIP_STS_LINKFAIL;
802 }
803
804 if (media == TULIP_MEDIA_AUIBNC || media == TULIP_MEDIA_UNKNOWN) {
805 TULIP_MEDIAINFO_SIA_INIT(sc, &sc->tulip_mediainfo[2], 21040, AUIBNC);
806 }
807
808 if (media == TULIP_MEDIA_UNKNOWN) {
809 TULIP_MEDIAINFO_SIA_INIT(sc, &sc->tulip_mediainfo[3], 21040, EXTSIA);
810 }
811}
812
813static void
814tulip_21040_media_probe(
815 tulip_softc_t * const sc)
816{
817 tulip_21040_mediainfo_init(sc, TULIP_MEDIA_UNKNOWN);
818 return;
819}
820
821static void
822tulip_21040_10baset_only_media_probe(
823 tulip_softc_t * const sc)
824{
825 tulip_21040_mediainfo_init(sc, TULIP_MEDIA_10BASET);
826 tulip_media_set(sc, TULIP_MEDIA_10BASET);
827 sc->tulip_media = TULIP_MEDIA_10BASET;
828}
829
830static void
831tulip_21040_10baset_only_media_select(
832 tulip_softc_t * const sc)
833{
834 sc->tulip_flags |= TULIP_LINKUP;
835 if (sc->tulip_media == TULIP_MEDIA_10BASET_FD) {
836 sc->tulip_cmdmode |= TULIP_CMD_FULLDUPLEX;
837 sc->tulip_flags &= ~TULIP_SQETEST;
838 } else {
839 sc->tulip_cmdmode &= ~TULIP_CMD_FULLDUPLEX;
840 sc->tulip_flags |= TULIP_SQETEST;
841 }
842 tulip_media_set(sc, sc->tulip_media);
843}
844
845static void
846tulip_21040_auibnc_only_media_probe(
847 tulip_softc_t * const sc)
848{
849 tulip_21040_mediainfo_init(sc, TULIP_MEDIA_AUIBNC);
850 sc->tulip_flags |= TULIP_SQETEST|TULIP_LINKUP;
851 tulip_media_set(sc, TULIP_MEDIA_AUIBNC);
852 sc->tulip_media = TULIP_MEDIA_AUIBNC;
853}
854
855static void
856tulip_21040_auibnc_only_media_select(
857 tulip_softc_t * const sc)
858{
859 tulip_media_set(sc, TULIP_MEDIA_AUIBNC);
860 sc->tulip_cmdmode &= ~TULIP_CMD_FULLDUPLEX;
861}
862
863static const tulip_boardsw_t tulip_21040_boardsw = {
864 TULIP_21040_GENERIC,
865 tulip_21040_media_probe,
866 tulip_media_select,
867 tulip_media_poll,
868};
869
870static const tulip_boardsw_t tulip_21040_10baset_only_boardsw = {
871 TULIP_21040_GENERIC,
872 tulip_21040_10baset_only_media_probe,
873 tulip_21040_10baset_only_media_select,
874 NULL,
875};
876
877static const tulip_boardsw_t tulip_21040_auibnc_only_boardsw = {
878 TULIP_21040_GENERIC,
879 tulip_21040_auibnc_only_media_probe,
880 tulip_21040_auibnc_only_media_select,
881 NULL,
882};
883\f
884static void
885tulip_21041_mediainfo_init(
886 tulip_softc_t * const sc)
887{
888 tulip_media_info_t * const mi = sc->tulip_mediainfo;
889
890#ifdef notyet
891 if (sc->tulip_revinfo >= 0x20) {
892 TULIP_MEDIAINFO_SIA_INIT(sc, &mi[0], 21041P2, 10BASET);
893 TULIP_MEDIAINFO_SIA_INIT(sc, &mi[1], 21041P2, 10BASET_FD);
894 TULIP_MEDIAINFO_SIA_INIT(sc, &mi[0], 21041P2, AUI);
895 TULIP_MEDIAINFO_SIA_INIT(sc, &mi[1], 21041P2, BNC);
896 return;
897 }
898#endif
899 TULIP_MEDIAINFO_SIA_INIT(sc, &mi[0], 21041, 10BASET);
900 TULIP_MEDIAINFO_SIA_INIT(sc, &mi[1], 21041, 10BASET_FD);
901 TULIP_MEDIAINFO_SIA_INIT(sc, &mi[2], 21041, AUI);
902 TULIP_MEDIAINFO_SIA_INIT(sc, &mi[3], 21041, BNC);
903}
904\f
905static void
906tulip_21041_media_probe(
907 tulip_softc_t * const sc)
908{
909 sc->tulip_if.if_baudrate = 10000000;
910 sc->tulip_cmdmode |= TULIP_CMD_CAPTREFFCT|TULIP_CMD_ENHCAPTEFFCT
911 |TULIP_CMD_THRSHLD160|TULIP_CMD_BACKOFFCTR;
912 sc->tulip_intrmask |= TULIP_STS_LINKPASS|TULIP_STS_LINKFAIL;
913 tulip_21041_mediainfo_init(sc);
914}
915
916static void
917tulip_21041_media_poll(
918 tulip_softc_t * const sc,
919 const tulip_mediapoll_event_t event)
920{
921 u_int32_t sia_status;
922
984263bc
MD
923 if (event == TULIP_MEDIAPOLL_LINKFAIL) {
924 if (sc->tulip_probe_state != TULIP_PROBE_INACTIVE
925 || !TULIP_DO_AUTOSENSE(sc))
926 return;
927 sc->tulip_media = TULIP_MEDIA_UNKNOWN;
928 tulip_reset(sc); /* start probe */
929 return;
930 }
931
932 /*
933 * If we've been been asked to start a poll or link change interrupt
934 * restart the probe (and reset the tulip to a known state).
935 */
936 if (event == TULIP_MEDIAPOLL_START) {
937 sc->tulip_if.if_flags |= IFF_OACTIVE;
938 sc->tulip_cmdmode &= ~(TULIP_CMD_FULLDUPLEX|TULIP_CMD_RXRUN);
939#ifdef notyet
940 if (sc->tulip_revinfo >= 0x20) {
941 sc->tulip_cmdmode |= TULIP_CMD_FULLDUPLEX;
942 sc->tulip_flags |= TULIP_DIDNWAY;
943 }
944#endif
945 TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode);
946 sc->tulip_probe_state = TULIP_PROBE_MEDIATEST;
947 sc->tulip_probe_media = TULIP_MEDIA_10BASET;
948 sc->tulip_probe_timeout = TULIP_21041_PROBE_10BASET_TIMEOUT;
949 tulip_media_set(sc, TULIP_MEDIA_10BASET);
950 tulip_timeout(sc);
951 return;
952 }
953
954 if (sc->tulip_probe_state == TULIP_PROBE_INACTIVE)
955 return;
956
957 if (event == TULIP_MEDIAPOLL_TXPROBE_OK) {
984263bc
MD
958 tulip_linkup(sc, sc->tulip_probe_media);
959 return;
960 }
961
962 sia_status = TULIP_CSR_READ(sc, csr_sia_status);
963 TULIP_CSR_WRITE(sc, csr_sia_status, sia_status);
964 if ((sia_status & TULIP_SIASTS_LINKFAIL) == 0) {
965 if (sc->tulip_revinfo >= 0x20) {
966 if (sia_status & (PHYSTS_10BASET_FD << (16 - 6)))
967 sc->tulip_probe_media = TULIP_MEDIA_10BASET_FD;
968 }
969 /*
970 * If the link has passed LinkPass, 10baseT is the
971 * proper media to use.
972 */
973 tulip_linkup(sc, sc->tulip_probe_media);
974 return;
975 }
976
977 /*
978 * wait for up to 2.4 seconds for the link to reach pass state.
979 * Only then start scanning the other media for activity.
980 * choose media with receive activity over those without.
981 */
982 if (sc->tulip_probe_media == TULIP_MEDIA_10BASET) {
983 if (event != TULIP_MEDIAPOLL_TIMER)
984 return;
985 if (sc->tulip_probe_timeout > 0
986 && (sia_status & TULIP_SIASTS_OTHERRXACTIVITY) == 0) {
987 tulip_timeout(sc);
988 return;
989 }
990 sc->tulip_probe_timeout = TULIP_21041_PROBE_AUIBNC_TIMEOUT;
991 sc->tulip_flags |= TULIP_WANTRXACT;
992 if (sia_status & TULIP_SIASTS_OTHERRXACTIVITY) {
993 sc->tulip_probe_media = TULIP_MEDIA_BNC;
994 } else {
995 sc->tulip_probe_media = TULIP_MEDIA_AUI;
996 }
997 tulip_media_set(sc, sc->tulip_probe_media);
998 tulip_timeout(sc);
999 return;
1000 }
1001
1002 /*
1003 * If we failed, clear the txprobe active flag.
1004 */
1005 if (event == TULIP_MEDIAPOLL_TXPROBE_FAILED)
1006 sc->tulip_flags &= ~TULIP_TXPROBE_ACTIVE;
1007
1008
1009 if (event == TULIP_MEDIAPOLL_TIMER) {
1010 /*
1011 * If we've received something, then that's our link!
1012 */
1013 if (sc->tulip_flags & TULIP_RXACT) {
1014 tulip_linkup(sc, sc->tulip_probe_media);
1015 return;
1016 }
1017 /*
1018 * if no txprobe active
1019 */
1020 if ((sc->tulip_flags & TULIP_TXPROBE_ACTIVE) == 0
1021 && ((sc->tulip_flags & TULIP_WANTRXACT) == 0
1022 || (sia_status & TULIP_SIASTS_RXACTIVITY))) {
1023 sc->tulip_probe_timeout = TULIP_21041_PROBE_AUIBNC_TIMEOUT;
1024 tulip_txprobe(sc);
1025 tulip_timeout(sc);
1026 return;
1027 }
1028 /*
1029 * Take 2 passes through before deciding to not
1030 * wait for receive activity. Then take another
1031 * two passes before spitting out a warning.
1032 */
1033 if (sc->tulip_probe_timeout <= 0) {
1034 if (sc->tulip_flags & TULIP_WANTRXACT) {
1035 sc->tulip_flags &= ~TULIP_WANTRXACT;
1036 sc->tulip_probe_timeout = TULIP_21041_PROBE_AUIBNC_TIMEOUT;
1037 } else {
1038 printf("%s%d: autosense failed: cable problem?\n",
1039 sc->tulip_name, sc->tulip_unit);
1040 if ((sc->tulip_if.if_flags & IFF_UP) == 0) {
1041 sc->tulip_if.if_flags &= ~IFF_RUNNING;
1042 sc->tulip_probe_state = TULIP_PROBE_INACTIVE;
1043 return;
1044 }
1045 }
1046 }
1047 }
1048
1049 /*
1050 * Since this media failed to probe, try the other one.
1051 */
1052 sc->tulip_probe_timeout = TULIP_21041_PROBE_AUIBNC_TIMEOUT;
1053 if (sc->tulip_probe_media == TULIP_MEDIA_AUI) {
1054 sc->tulip_probe_media = TULIP_MEDIA_BNC;
1055 } else {
1056 sc->tulip_probe_media = TULIP_MEDIA_AUI;
1057 }
1058 tulip_media_set(sc, sc->tulip_probe_media);
1059 sc->tulip_flags &= ~TULIP_TXPROBE_ACTIVE;
1060 tulip_timeout(sc);
1061}
1062
1063static const tulip_boardsw_t tulip_21041_boardsw = {
1064 TULIP_21041_GENERIC,
1065 tulip_21041_media_probe,
1066 tulip_media_select,
1067 tulip_21041_media_poll
1068};
1069\f
1070static const tulip_phy_attr_t tulip_mii_phy_attrlist[] = {
1071 { 0x20005c00, 0, /* 08-00-17 */
1072 {
1073 { 0x19, 0x0040, 0x0040 }, /* 10TX */
1074 { 0x19, 0x0040, 0x0000 }, /* 100TX */
1075 },
984263bc
MD
1076 },
1077 { 0x0281F400, 0, /* 00-A0-7D */
1078 {
1079 { 0x12, 0x0010, 0x0000 }, /* 10T */
1080 { }, /* 100TX */
1081 { 0x12, 0x0010, 0x0010 }, /* 100T4 */
1082 { 0x12, 0x0008, 0x0008 }, /* FULL_DUPLEX */
1083 },
984263bc
MD
1084 },
1085#if 0
1086 { 0x0015F420, 0, /* 00-A0-7D */
1087 {
1088 { 0x12, 0x0010, 0x0000 }, /* 10T */
1089 { }, /* 100TX */
1090 { 0x12, 0x0010, 0x0010 }, /* 100T4 */
1091 { 0x12, 0x0008, 0x0008 }, /* FULL_DUPLEX */
1092 },
984263bc
MD
1093 },
1094#endif
1095 { 0x0281F400, 0, /* 00-A0-BE */
1096 {
1097 { 0x11, 0x8000, 0x0000 }, /* 10T */
1098 { 0x11, 0x8000, 0x8000 }, /* 100TX */
1099 { }, /* 100T4 */
1100 { 0x11, 0x4000, 0x4000 }, /* FULL_DUPLEX */
1101 },
984263bc
MD
1102 },
1103 { 0 }
1104};
1105\f
1106static tulip_media_t
1107tulip_mii_phy_readspecific(
1108 tulip_softc_t * const sc)
1109{
1110 const tulip_phy_attr_t *attr;
1111 u_int16_t data;
1112 u_int32_t id;
1113 unsigned idx = 0;
1114 static const tulip_media_t table[] = {
1115 TULIP_MEDIA_UNKNOWN,
1116 TULIP_MEDIA_10BASET,
1117 TULIP_MEDIA_100BASETX,
1118 TULIP_MEDIA_100BASET4,
1119 TULIP_MEDIA_UNKNOWN,
1120 TULIP_MEDIA_10BASET_FD,
1121 TULIP_MEDIA_100BASETX_FD,
1122 TULIP_MEDIA_UNKNOWN
1123 };
1124
1125 /*
1126 * Don't read phy specific registers if link is not up.
1127 */
1128 data = tulip_mii_readreg(sc, sc->tulip_phyaddr, PHYREG_STATUS);
1129 if ((data & (PHYSTS_LINK_UP|PHYSTS_EXTENDED_REGS)) != (PHYSTS_LINK_UP|PHYSTS_EXTENDED_REGS))
1130 return TULIP_MEDIA_UNKNOWN;
1131
1132 id = (tulip_mii_readreg(sc, sc->tulip_phyaddr, PHYREG_IDLOW) << 16) |
1133 tulip_mii_readreg(sc, sc->tulip_phyaddr, PHYREG_IDHIGH);
1134 for (attr = tulip_mii_phy_attrlist;; attr++) {
1135 if (attr->attr_id == 0)
1136 return TULIP_MEDIA_UNKNOWN;
1137 if ((id & ~0x0F) == attr->attr_id)
1138 break;
1139 }
1140
1141 if (attr->attr_modes[PHY_MODE_100TX].pm_regno) {
1142 const tulip_phy_modedata_t * const pm = &attr->attr_modes[PHY_MODE_100TX];
1143 data = tulip_mii_readreg(sc, sc->tulip_phyaddr, pm->pm_regno);
1144 if ((data & pm->pm_mask) == pm->pm_value)
1145 idx = 2;
1146 }
1147 if (idx == 0 && attr->attr_modes[PHY_MODE_100T4].pm_regno) {
1148 const tulip_phy_modedata_t * const pm = &attr->attr_modes[PHY_MODE_100T4];
1149 data = tulip_mii_readreg(sc, sc->tulip_phyaddr, pm->pm_regno);
1150 if ((data & pm->pm_mask) == pm->pm_value)
1151 idx = 3;
1152 }
1153 if (idx == 0 && attr->attr_modes[PHY_MODE_10T].pm_regno) {
1154 const tulip_phy_modedata_t * const pm = &attr->attr_modes[PHY_MODE_10T];
1155 data = tulip_mii_readreg(sc, sc->tulip_phyaddr, pm->pm_regno);
1156 if ((data & pm->pm_mask) == pm->pm_value)
1157 idx = 1;
1158 }
1159 if (idx != 0 && attr->attr_modes[PHY_MODE_FULLDUPLEX].pm_regno) {
1160 const tulip_phy_modedata_t * const pm = &attr->attr_modes[PHY_MODE_FULLDUPLEX];
1161 data = tulip_mii_readreg(sc, sc->tulip_phyaddr, pm->pm_regno);
1162 idx += ((data & pm->pm_mask) == pm->pm_value ? 4 : 0);
1163 }
1164 return table[idx];
1165}
1166\f
1167static unsigned
1168tulip_mii_get_phyaddr(
1169 tulip_softc_t * const sc,
1170 unsigned offset)
1171{
1172 unsigned phyaddr;
1173
1174 for (phyaddr = 1; phyaddr < 32; phyaddr++) {
1175 unsigned status = tulip_mii_readreg(sc, phyaddr, PHYREG_STATUS);
1176 if (status == 0 || status == 0xFFFF || status < PHYSTS_10BASET)
1177 continue;
1178 if (offset == 0)
1179 return phyaddr;
1180 offset--;
1181 }
1182 if (offset == 0) {
1183 unsigned status = tulip_mii_readreg(sc, 0, PHYREG_STATUS);
1184 if (status == 0 || status == 0xFFFF || status < PHYSTS_10BASET)
1185 return TULIP_MII_NOPHY;
1186 return 0;
1187 }
1188 return TULIP_MII_NOPHY;
1189}
1190\f
1191static int
1192tulip_mii_map_abilities(
1193 tulip_softc_t * const sc,
1194 unsigned abilities)
1195{
1196 sc->tulip_abilities = abilities;
1197 if (abilities & PHYSTS_100BASETX_FD) {
1198 sc->tulip_probe_media = TULIP_MEDIA_100BASETX_FD;
1199 } else if (abilities & PHYSTS_100BASET4) {
1200 sc->tulip_probe_media = TULIP_MEDIA_100BASET4;
1201 } else if (abilities & PHYSTS_100BASETX) {
1202 sc->tulip_probe_media = TULIP_MEDIA_100BASETX;
1203 } else if (abilities & PHYSTS_10BASET_FD) {
1204 sc->tulip_probe_media = TULIP_MEDIA_10BASET_FD;
1205 } else if (abilities & PHYSTS_10BASET) {
1206 sc->tulip_probe_media = TULIP_MEDIA_10BASET;
1207 } else {
1208 sc->tulip_probe_state = TULIP_PROBE_MEDIATEST;
1209 return 0;
1210 }
1211 sc->tulip_probe_state = TULIP_PROBE_INACTIVE;
1212 return 1;
1213}
1214
1215static void
1216tulip_mii_autonegotiate(
1217 tulip_softc_t * const sc,
1218 const unsigned phyaddr)
1219{
1220 switch (sc->tulip_probe_state) {
1221 case TULIP_PROBE_MEDIATEST:
1222 case TULIP_PROBE_INACTIVE: {
1223 sc->tulip_flags |= TULIP_DIDNWAY;
1224 tulip_mii_writereg(sc, phyaddr, PHYREG_CONTROL, PHYCTL_RESET);
1225 sc->tulip_probe_timeout = 3000;
1226 sc->tulip_intrmask |= TULIP_STS_ABNRMLINTR|TULIP_STS_NORMALINTR;
1227 sc->tulip_probe_state = TULIP_PROBE_PHYRESET;
1228 /* FALL THROUGH */
1229 }
1230 case TULIP_PROBE_PHYRESET: {
1231 u_int32_t status;
1232 u_int32_t data = tulip_mii_readreg(sc, phyaddr, PHYREG_CONTROL);
1233 if (data & PHYCTL_RESET) {
1234 if (sc->tulip_probe_timeout > 0) {
1235 tulip_timeout(sc);
1236 return;
1237 }
1238 printf("%s%d(phy%d): error: reset of PHY never completed!\n",
1239 sc->tulip_name, sc->tulip_unit, phyaddr);
1240 sc->tulip_flags &= ~TULIP_TXPROBE_ACTIVE;
1241 sc->tulip_probe_state = TULIP_PROBE_FAILED;
1242 sc->tulip_if.if_flags &= ~(IFF_UP|IFF_RUNNING);
1243 return;
1244 }
1245 status = tulip_mii_readreg(sc, phyaddr, PHYREG_STATUS);
1246 if ((status & PHYSTS_CAN_AUTONEG) == 0) {
984263bc
MD
1247 sc->tulip_flags &= ~TULIP_DIDNWAY;
1248 sc->tulip_probe_state = TULIP_PROBE_MEDIATEST;
1249 return;
1250 }
1251 if (tulip_mii_readreg(sc, phyaddr, PHYREG_AUTONEG_ADVERTISEMENT) != ((status >> 6) | 0x01))
1252 tulip_mii_writereg(sc, phyaddr, PHYREG_AUTONEG_ADVERTISEMENT, (status >> 6) | 0x01);
1253 tulip_mii_writereg(sc, phyaddr, PHYREG_CONTROL, data|PHYCTL_AUTONEG_RESTART|PHYCTL_AUTONEG_ENABLE);
1254 data = tulip_mii_readreg(sc, phyaddr, PHYREG_CONTROL);
984263bc
MD
1255 sc->tulip_probe_state = TULIP_PROBE_PHYAUTONEG;
1256 sc->tulip_probe_timeout = 3000;
1257 /* FALL THROUGH */
1258 }
1259 case TULIP_PROBE_PHYAUTONEG: {
1260 u_int32_t status = tulip_mii_readreg(sc, phyaddr, PHYREG_STATUS);
1261 u_int32_t data;
1262 if ((status & PHYSTS_AUTONEG_DONE) == 0) {
1263 if (sc->tulip_probe_timeout > 0) {
1264 tulip_timeout(sc);
1265 return;
1266 }
984263bc
MD
1267 sc->tulip_flags &= ~TULIP_DIDNWAY;
1268 sc->tulip_probe_state = TULIP_PROBE_MEDIATEST;
1269 return;
1270 }
1271 data = tulip_mii_readreg(sc, phyaddr, PHYREG_AUTONEG_ABILITIES);
984263bc
MD
1272 data = (data << 6) & status;
1273 if (!tulip_mii_map_abilities(sc, data))
1274 sc->tulip_flags &= ~TULIP_DIDNWAY;
1275 return;
1276 }
1277 default: {
1278#if defined(DIAGNOSTIC)
1279 panic("tulip_media_poll: botch at line %d\n", __LINE__);
1280#endif
1281 break;
1282 }
1283 }
984263bc
MD
1284}
1285\f
1286static void
1287tulip_2114x_media_preset(
1288 tulip_softc_t * const sc)
1289{
1290 const tulip_media_info_t *mi = NULL;
1291 tulip_media_t media = sc->tulip_media;
1292
1293 if (sc->tulip_probe_state == TULIP_PROBE_INACTIVE)
1294 media = sc->tulip_media;
1295 else
1296 media = sc->tulip_probe_media;
1297
1298 sc->tulip_cmdmode &= ~TULIP_CMD_PORTSELECT;
1299 sc->tulip_flags &= ~TULIP_SQETEST;
1300 if (media != TULIP_MEDIA_UNKNOWN && media != TULIP_MEDIA_MAX) {
984263bc
MD
1301 mi = sc->tulip_mediums[media];
1302 if (mi->mi_type == TULIP_MEDIAINFO_MII) {
1303 sc->tulip_cmdmode |= TULIP_CMD_PORTSELECT;
1304 } else if (mi->mi_type == TULIP_MEDIAINFO_GPR
1305 || mi->mi_type == TULIP_MEDIAINFO_SYM) {
1306 sc->tulip_cmdmode &= ~TULIP_GPR_CMDBITS;
1307 sc->tulip_cmdmode |= mi->mi_cmdmode;
1308 } else if (mi->mi_type == TULIP_MEDIAINFO_SIA) {
1309 TULIP_CSR_WRITE(sc, csr_sia_connectivity, TULIP_SIACONN_RESET);
1310 }
984263bc
MD
1311 }
1312 switch (media) {
1313 case TULIP_MEDIA_BNC:
1314 case TULIP_MEDIA_AUI:
1315 case TULIP_MEDIA_10BASET: {
1316 sc->tulip_cmdmode &= ~TULIP_CMD_FULLDUPLEX;
1317 sc->tulip_cmdmode |= TULIP_CMD_TXTHRSHLDCTL;
1318 sc->tulip_if.if_baudrate = 10000000;
1319 sc->tulip_flags |= TULIP_SQETEST;
1320 break;
1321 }
1322 case TULIP_MEDIA_10BASET_FD: {
1323 sc->tulip_cmdmode |= TULIP_CMD_FULLDUPLEX|TULIP_CMD_TXTHRSHLDCTL;
1324 sc->tulip_if.if_baudrate = 10000000;
1325 break;
1326 }
1327 case TULIP_MEDIA_100BASEFX:
1328 case TULIP_MEDIA_100BASET4:
1329 case TULIP_MEDIA_100BASETX: {
1330 sc->tulip_cmdmode &= ~(TULIP_CMD_FULLDUPLEX|TULIP_CMD_TXTHRSHLDCTL);
1331 sc->tulip_cmdmode |= TULIP_CMD_PORTSELECT;
1332 sc->tulip_if.if_baudrate = 100000000;
1333 break;
1334 }
1335 case TULIP_MEDIA_100BASEFX_FD:
1336 case TULIP_MEDIA_100BASETX_FD: {
1337 sc->tulip_cmdmode |= TULIP_CMD_FULLDUPLEX|TULIP_CMD_PORTSELECT;
1338 sc->tulip_cmdmode &= ~TULIP_CMD_TXTHRSHLDCTL;
1339 sc->tulip_if.if_baudrate = 100000000;
1340 break;
1341 }
1342 default: {
1343 break;
1344 }
1345 }
1346 TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode);
1347}
1348\f
1349/*
1350 ********************************************************************
1351 * Start of 21140/21140A support which does not use the MII interface
1352 */
1353\f
1354static void
1355tulip_null_media_poll(
1356 tulip_softc_t * const sc,
1357 tulip_mediapoll_event_t event)
1358{
984263bc
MD
1359#if defined(DIAGNOSTIC)
1360 printf("%s%d: botch(media_poll) at line %d\n",
1361 sc->tulip_name, sc->tulip_unit, __LINE__);
1362#endif
1363}
1364
1365__inline__ static void
1366tulip_21140_mediainit(
1367 tulip_softc_t * const sc,
1368 tulip_media_info_t * const mip,
1369 tulip_media_t const media,
1370 unsigned gpdata,
1371 unsigned cmdmode)
1372{
1373 sc->tulip_mediums[media] = mip;
1374 mip->mi_type = TULIP_MEDIAINFO_GPR;
1375 mip->mi_cmdmode = cmdmode;
1376 mip->mi_gpdata = gpdata;
1377}
1378\f
1379static void
1380tulip_21140_evalboard_media_probe(
1381 tulip_softc_t * const sc)
1382{
1383 tulip_media_info_t *mip = sc->tulip_mediainfo;
1384
1385 sc->tulip_gpinit = TULIP_GP_EB_PINS;
1386 sc->tulip_gpdata = TULIP_GP_EB_INIT;
1387 TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_EB_PINS);
1388 TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_EB_INIT);
1389 TULIP_CSR_WRITE(sc, csr_command,
1390 TULIP_CSR_READ(sc, csr_command) | TULIP_CMD_PORTSELECT |
1391 TULIP_CMD_PCSFUNCTION | TULIP_CMD_SCRAMBLER | TULIP_CMD_MUSTBEONE);
1392 TULIP_CSR_WRITE(sc, csr_command,
1393 TULIP_CSR_READ(sc, csr_command) & ~TULIP_CMD_TXTHRSHLDCTL);
1394 DELAY(1000000);
1395 if ((TULIP_CSR_READ(sc, csr_gp) & TULIP_GP_EB_OK100) != 0) {
1396 sc->tulip_media = TULIP_MEDIA_10BASET;
1397 } else {
1398 sc->tulip_media = TULIP_MEDIA_100BASETX;
1399 }
1400 tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_10BASET,
1401 TULIP_GP_EB_INIT,
1402 TULIP_CMD_TXTHRSHLDCTL);
1403 tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_10BASET_FD,
1404 TULIP_GP_EB_INIT,
1405 TULIP_CMD_TXTHRSHLDCTL|TULIP_CMD_FULLDUPLEX);
1406 tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX,
1407 TULIP_GP_EB_INIT,
1408 TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
1409 |TULIP_CMD_SCRAMBLER);
1410 tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX_FD,
1411 TULIP_GP_EB_INIT,
1412 TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
1413 |TULIP_CMD_SCRAMBLER|TULIP_CMD_FULLDUPLEX);
1414}
1415
1416static const tulip_boardsw_t tulip_21140_eb_boardsw = {
1417 TULIP_21140_DEC_EB,
1418 tulip_21140_evalboard_media_probe,
1419 tulip_media_select,
1420 tulip_null_media_poll,
1421 tulip_2114x_media_preset,
1422};
1423\f
1424static void
1425tulip_21140_accton_media_probe(
1426 tulip_softc_t * const sc)
1427{
1428 tulip_media_info_t *mip = sc->tulip_mediainfo;
1429 unsigned gpdata;
1430
1431 sc->tulip_gpinit = TULIP_GP_EB_PINS;
1432 sc->tulip_gpdata = TULIP_GP_EB_INIT;
1433 TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_EB_PINS);
1434 TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_EB_INIT);
1435 TULIP_CSR_WRITE(sc, csr_command,
1436 TULIP_CSR_READ(sc, csr_command) | TULIP_CMD_PORTSELECT |
1437 TULIP_CMD_PCSFUNCTION | TULIP_CMD_SCRAMBLER | TULIP_CMD_MUSTBEONE);
1438 TULIP_CSR_WRITE(sc, csr_command,
1439 TULIP_CSR_READ(sc, csr_command) & ~TULIP_CMD_TXTHRSHLDCTL);
1440 DELAY(1000000);
1441 gpdata = TULIP_CSR_READ(sc, csr_gp);
1442 if ((gpdata & TULIP_GP_EN1207_UTP_INIT) == 0) {
1443 sc->tulip_media = TULIP_MEDIA_10BASET;
1444 } else {
1445 if ((gpdata & TULIP_GP_EN1207_BNC_INIT) == 0) {
1446 sc->tulip_media = TULIP_MEDIA_BNC;
1447 } else {
1448 sc->tulip_media = TULIP_MEDIA_100BASETX;
1449 }
1450 }
1451 tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_BNC,
1452 TULIP_GP_EN1207_BNC_INIT,
1453 TULIP_CMD_TXTHRSHLDCTL);
1454 tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_10BASET,
1455 TULIP_GP_EN1207_UTP_INIT,
1456 TULIP_CMD_TXTHRSHLDCTL);
1457 tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_10BASET_FD,
1458 TULIP_GP_EN1207_UTP_INIT,
1459 TULIP_CMD_TXTHRSHLDCTL|TULIP_CMD_FULLDUPLEX);
1460 tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX,
1461 TULIP_GP_EN1207_100_INIT,
1462 TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
1463 |TULIP_CMD_SCRAMBLER);
1464 tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX_FD,
1465 TULIP_GP_EN1207_100_INIT,
1466 TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
1467 |TULIP_CMD_SCRAMBLER|TULIP_CMD_FULLDUPLEX);
1468}
1469
1470static const tulip_boardsw_t tulip_21140_accton_boardsw = {
1471 TULIP_21140_EN1207,
1472 tulip_21140_accton_media_probe,
1473 tulip_media_select,
1474 tulip_null_media_poll,
1475 tulip_2114x_media_preset,
1476};
1477\f
1478static void
1479tulip_21140_smc9332_media_probe(
1480 tulip_softc_t * const sc)
1481{
1482 tulip_media_info_t *mip = sc->tulip_mediainfo;
1483 int idx, cnt = 0;
1484
1485 TULIP_CSR_WRITE(sc, csr_command, TULIP_CMD_PORTSELECT|TULIP_CMD_MUSTBEONE);
1486 TULIP_CSR_WRITE(sc, csr_busmode, TULIP_BUSMODE_SWRESET);
1487 DELAY(10); /* Wait 10 microseconds (actually 50 PCI cycles but at
1488 33MHz that comes to two microseconds but wait a
1489 bit longer anyways) */
1490 TULIP_CSR_WRITE(sc, csr_command, TULIP_CMD_PORTSELECT |
1491 TULIP_CMD_PCSFUNCTION | TULIP_CMD_SCRAMBLER | TULIP_CMD_MUSTBEONE);
1492 sc->tulip_gpinit = TULIP_GP_SMC_9332_PINS;
1493 sc->tulip_gpdata = TULIP_GP_SMC_9332_INIT;
1494 TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_SMC_9332_PINS|TULIP_GP_PINSET);
1495 TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_SMC_9332_INIT);
1496 DELAY(200000);
1497 for (idx = 1000; idx > 0; idx--) {
1498 u_int32_t csr = TULIP_CSR_READ(sc, csr_gp);
1499 if ((csr & (TULIP_GP_SMC_9332_OK10|TULIP_GP_SMC_9332_OK100)) == (TULIP_GP_SMC_9332_OK10|TULIP_GP_SMC_9332_OK100)) {
1500 if (++cnt > 100)
1501 break;
1502 } else if ((csr & TULIP_GP_SMC_9332_OK10) == 0) {
1503 break;
1504 } else {
1505 cnt = 0;
1506 }
1507 DELAY(1000);
1508 }
1509 sc->tulip_media = cnt > 100 ? TULIP_MEDIA_100BASETX : TULIP_MEDIA_10BASET;
1510 tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX,
1511 TULIP_GP_SMC_9332_INIT,
1512 TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
1513 |TULIP_CMD_SCRAMBLER);
1514 tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX_FD,
1515 TULIP_GP_SMC_9332_INIT,
1516 TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
1517 |TULIP_CMD_SCRAMBLER|TULIP_CMD_FULLDUPLEX);
1518 tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_10BASET,
1519 TULIP_GP_SMC_9332_INIT,
1520 TULIP_CMD_TXTHRSHLDCTL);
1521 tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_10BASET_FD,
1522 TULIP_GP_SMC_9332_INIT,
1523 TULIP_CMD_TXTHRSHLDCTL|TULIP_CMD_FULLDUPLEX);
1524}
1525
1526static const tulip_boardsw_t tulip_21140_smc9332_boardsw = {
1527 TULIP_21140_SMC_9332,
1528 tulip_21140_smc9332_media_probe,
1529 tulip_media_select,
1530 tulip_null_media_poll,
1531 tulip_2114x_media_preset,
1532};
1533\f
1534static void
1535tulip_21140_cogent_em100_media_probe(
1536 tulip_softc_t * const sc)
1537{
1538 tulip_media_info_t *mip = sc->tulip_mediainfo;
1539 u_int32_t cmdmode = TULIP_CSR_READ(sc, csr_command);
1540
1541 sc->tulip_gpinit = TULIP_GP_EM100_PINS;
1542 sc->tulip_gpdata = TULIP_GP_EM100_INIT;
1543 TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_EM100_PINS);
1544 TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_EM100_INIT);
1545
1546 cmdmode = TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION|TULIP_CMD_MUSTBEONE;
1547 cmdmode &= ~(TULIP_CMD_TXTHRSHLDCTL|TULIP_CMD_SCRAMBLER);
1548 if (sc->tulip_rombuf[32] == TULIP_COGENT_EM100FX_ID) {
1549 TULIP_CSR_WRITE(sc, csr_command, cmdmode);
1550 sc->tulip_media = TULIP_MEDIA_100BASEFX;
1551
1552 tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASEFX,
1553 TULIP_GP_EM100_INIT,
1554 TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION);
1555 tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASEFX_FD,
1556 TULIP_GP_EM100_INIT,
1557 TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
1558 |TULIP_CMD_FULLDUPLEX);
1559 } else {
1560 TULIP_CSR_WRITE(sc, csr_command, cmdmode|TULIP_CMD_SCRAMBLER);
1561 sc->tulip_media = TULIP_MEDIA_100BASETX;
1562 tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX,
1563 TULIP_GP_EM100_INIT,
1564 TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
1565 |TULIP_CMD_SCRAMBLER);
1566 tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX_FD,
1567 TULIP_GP_EM100_INIT,
1568 TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
1569 |TULIP_CMD_SCRAMBLER|TULIP_CMD_FULLDUPLEX);
1570 }
1571}
1572
1573static const tulip_boardsw_t tulip_21140_cogent_em100_boardsw = {
1574 TULIP_21140_COGENT_EM100,
1575 tulip_21140_cogent_em100_media_probe,
1576 tulip_media_select,
1577 tulip_null_media_poll,
1578 tulip_2114x_media_preset
1579};
1580\f
1581static void
1582tulip_21140_znyx_zx34x_media_probe(
1583 tulip_softc_t * const sc)
1584{
1585 tulip_media_info_t *mip = sc->tulip_mediainfo;
1586 int cnt10 = 0, cnt100 = 0, idx;
1587
1588 sc->tulip_gpinit = TULIP_GP_ZX34X_PINS;
1589 sc->tulip_gpdata = TULIP_GP_ZX34X_INIT;
1590 TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_ZX34X_PINS);
1591 TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_ZX34X_INIT);
1592 TULIP_CSR_WRITE(sc, csr_command,
1593 TULIP_CSR_READ(sc, csr_command) | TULIP_CMD_PORTSELECT |
1594 TULIP_CMD_PCSFUNCTION | TULIP_CMD_SCRAMBLER | TULIP_CMD_MUSTBEONE);
1595 TULIP_CSR_WRITE(sc, csr_command,
1596 TULIP_CSR_READ(sc, csr_command) & ~TULIP_CMD_TXTHRSHLDCTL);
1597
1598 DELAY(200000);
1599 for (idx = 1000; idx > 0; idx--) {
1600 u_int32_t csr = TULIP_CSR_READ(sc, csr_gp);
1601 if ((csr & (TULIP_GP_ZX34X_LNKFAIL|TULIP_GP_ZX34X_SYMDET|TULIP_GP_ZX34X_SIGDET)) == (TULIP_GP_ZX34X_LNKFAIL|TULIP_GP_ZX34X_SYMDET|TULIP_GP_ZX34X_SIGDET)) {
1602 if (++cnt100 > 100)
1603 break;
1604 } else if ((csr & TULIP_GP_ZX34X_LNKFAIL) == 0) {
1605 if (++cnt10 > 100)
1606 break;
1607 } else {
1608 cnt10 = 0;
1609 cnt100 = 0;
1610 }
1611 DELAY(1000);
1612 }
1613 sc->tulip_media = cnt100 > 100 ? TULIP_MEDIA_100BASETX : TULIP_MEDIA_10BASET;
1614 tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_10BASET,
1615 TULIP_GP_ZX34X_INIT,
1616 TULIP_CMD_TXTHRSHLDCTL);
1617 tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_10BASET_FD,
1618 TULIP_GP_ZX34X_INIT,
1619 TULIP_CMD_TXTHRSHLDCTL|TULIP_CMD_FULLDUPLEX);
1620 tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX,
1621 TULIP_GP_ZX34X_INIT,
1622 TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
1623 |TULIP_CMD_SCRAMBLER);
1624 tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX_FD,
1625 TULIP_GP_ZX34X_INIT,
1626 TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
1627 |TULIP_CMD_SCRAMBLER|TULIP_CMD_FULLDUPLEX);
1628}
1629
1630static const tulip_boardsw_t tulip_21140_znyx_zx34x_boardsw = {
1631 TULIP_21140_ZNYX_ZX34X,
1632 tulip_21140_znyx_zx34x_media_probe,
1633 tulip_media_select,
1634 tulip_null_media_poll,
1635 tulip_2114x_media_preset,
1636};
1637\f
1638static void
1639tulip_2114x_media_probe(
1640 tulip_softc_t * const sc)
1641{
1642 sc->tulip_cmdmode |= TULIP_CMD_MUSTBEONE
1643 |TULIP_CMD_BACKOFFCTR|TULIP_CMD_THRSHLD72;
1644}
1645
1646static const tulip_boardsw_t tulip_2114x_isv_boardsw = {
1647 TULIP_21140_ISV,
1648 tulip_2114x_media_probe,
1649 tulip_media_select,
1650 tulip_media_poll,
1651 tulip_2114x_media_preset,
1652};
1653\f
1654/*
1655 * ******** END of chip-specific handlers. ***********
1656 */
1657\f
1658/*
1659 * Code the read the SROM and MII bit streams (I2C)
1660 */
1661#define EMIT do { TULIP_CSR_WRITE(sc, csr_srom_mii, csr); DELAY(1); } while (0)
1662
1663static void
1664tulip_srom_idle(
1665 tulip_softc_t * const sc)
1666{
1667 unsigned bit, csr;
1668
1669 csr = SROMSEL ; EMIT;
1670 csr = SROMSEL | SROMRD; EMIT;
1671 csr ^= SROMCS; EMIT;
1672 csr ^= SROMCLKON; EMIT;
1673
1674 /*
1675 * Write 25 cycles of 0 which will force the SROM to be idle.
1676 */
1677 for (bit = 3 + SROM_BITWIDTH + 16; bit > 0; bit--) {
1678 csr ^= SROMCLKOFF; EMIT; /* clock low; data not valid */
1679 csr ^= SROMCLKON; EMIT; /* clock high; data valid */
1680 }
1681 csr ^= SROMCLKOFF; EMIT;
1682 csr ^= SROMCS; EMIT;
1683 csr = 0; EMIT;
1684}
1685
1686
1687static void
1688tulip_srom_read(
1689 tulip_softc_t * const sc)
1690{
1691 unsigned idx;
1692 const unsigned bitwidth = SROM_BITWIDTH;
1693 const unsigned cmdmask = (SROMCMD_RD << bitwidth);
1694 const unsigned msb = 1 << (bitwidth + 3 - 1);
1695 unsigned lastidx = (1 << bitwidth) - 1;
1696
1697 tulip_srom_idle(sc);
1698
1699 for (idx = 0; idx <= lastidx; idx++) {
1700 unsigned lastbit, data, bits, bit, csr;
1701 csr = SROMSEL ; EMIT;
1702 csr = SROMSEL | SROMRD; EMIT;
1703 csr ^= SROMCSON; EMIT;
1704 csr ^= SROMCLKON; EMIT;
1705
1706 lastbit = 0;
1707 for (bits = idx|cmdmask, bit = bitwidth + 3; bit > 0; bit--, bits <<= 1) {
1708 const unsigned thisbit = bits & msb;
1709 csr ^= SROMCLKOFF; EMIT; /* clock low; data not valid */
1710 if (thisbit != lastbit) {
1711 csr ^= SROMDOUT; EMIT; /* clock low; invert data */
1712 } else {
1713 EMIT;
1714 }
1715 csr ^= SROMCLKON; EMIT; /* clock high; data valid */
1716 lastbit = thisbit;
1717 }
1718 csr ^= SROMCLKOFF; EMIT;
1719
1720 for (data = 0, bits = 0; bits < 16; bits++) {
1721 data <<= 1;
1722 csr ^= SROMCLKON; EMIT; /* clock high; data valid */
1723 data |= TULIP_CSR_READ(sc, csr_srom_mii) & SROMDIN ? 1 : 0;
1724 csr ^= SROMCLKOFF; EMIT; /* clock low; data not valid */
1725 }
1726 sc->tulip_rombuf[idx*2] = data & 0xFF;
1727 sc->tulip_rombuf[idx*2+1] = data >> 8;
1728 csr = SROMSEL | SROMRD; EMIT;
1729 csr = 0; EMIT;
1730 }
1731 tulip_srom_idle(sc);
1732}
1733\f
1734#define MII_EMIT do { TULIP_CSR_WRITE(sc, csr_srom_mii, csr); DELAY(1); } while (0)
1735
1736static void
1737tulip_mii_writebits(
1738 tulip_softc_t * const sc,
1739 unsigned data,
1740 unsigned bits)
1741{
1742 unsigned msb = 1 << (bits - 1);
1743 unsigned csr = TULIP_CSR_READ(sc, csr_srom_mii) & (MII_RD|MII_DOUT|MII_CLK);
1744 unsigned lastbit = (csr & MII_DOUT) ? msb : 0;
1745
1746 csr |= MII_WR; MII_EMIT; /* clock low; assert write */
1747
1748 for (; bits > 0; bits--, data <<= 1) {
1749 const unsigned thisbit = data & msb;
1750 if (thisbit != lastbit) {
1751 csr ^= MII_DOUT; MII_EMIT; /* clock low; invert data */
1752 }
1753 csr ^= MII_CLKON; MII_EMIT; /* clock high; data valid */
1754 lastbit = thisbit;
1755 csr ^= MII_CLKOFF; MII_EMIT; /* clock low; data not valid */
1756 }
1757}
1758
1759static void
1760tulip_mii_turnaround(
1761 tulip_softc_t * const sc,
1762 unsigned cmd)
1763{
1764 unsigned csr = TULIP_CSR_READ(sc, csr_srom_mii) & (MII_RD|MII_DOUT|MII_CLK);
1765
1766 if (cmd == MII_WRCMD) {
1767 csr |= MII_DOUT; MII_EMIT; /* clock low; change data */
1768 csr ^= MII_CLKON; MII_EMIT; /* clock high; data valid */
1769 csr ^= MII_CLKOFF; MII_EMIT; /* clock low; data not valid */
1770 csr ^= MII_DOUT; MII_EMIT; /* clock low; change data */
1771 } else {
1772 csr |= MII_RD; MII_EMIT; /* clock low; switch to read */
1773 }
1774 csr ^= MII_CLKON; MII_EMIT; /* clock high; data valid */
1775 csr ^= MII_CLKOFF; MII_EMIT; /* clock low; data not valid */
1776}
1777
1778static unsigned
1779tulip_mii_readbits(
1780 tulip_softc_t * const sc)
1781{
1782 unsigned data;
1783 unsigned csr = TULIP_CSR_READ(sc, csr_srom_mii) & (MII_RD|MII_DOUT|MII_CLK);
1784 int idx;
1785
1786 for (idx = 0, data = 0; idx < 16; idx++) {
1787 data <<= 1; /* this is NOOP on the first pass through */
1788 csr ^= MII_CLKON; MII_EMIT; /* clock high; data valid */
1789 if (TULIP_CSR_READ(sc, csr_srom_mii) & MII_DIN)
1790 data |= 1;
1791 csr ^= MII_CLKOFF; MII_EMIT; /* clock low; data not valid */
1792 }
1793 csr ^= MII_RD; MII_EMIT; /* clock low; turn off read */
1794
1795 return data;
1796}
1797
1798static unsigned
1799tulip_mii_readreg(
1800 tulip_softc_t * const sc,
1801 unsigned devaddr,
1802 unsigned regno)
1803{
1804 unsigned csr = TULIP_CSR_READ(sc, csr_srom_mii) & (MII_RD|MII_DOUT|MII_CLK);
1805 unsigned data;
1806
1807 csr &= ~(MII_RD|MII_CLK); MII_EMIT;
1808 tulip_mii_writebits(sc, MII_PREAMBLE, 32);
1809 tulip_mii_writebits(sc, MII_RDCMD, 8);
1810 tulip_mii_writebits(sc, devaddr, 5);
1811 tulip_mii_writebits(sc, regno, 5);
1812 tulip_mii_turnaround(sc, MII_RDCMD);
1813
1814 data = tulip_mii_readbits(sc);
984263bc
MD
1815 return data;
1816}
1817
1818static void
1819tulip_mii_writereg(
1820 tulip_softc_t * const sc,
1821 unsigned devaddr,
1822 unsigned regno,
1823 unsigned data)
1824{
1825 unsigned csr = TULIP_CSR_READ(sc, csr_srom_mii) & (MII_RD|MII_DOUT|MII_CLK);
1826 csr &= ~(MII_RD|MII_CLK); MII_EMIT;
1827 tulip_mii_writebits(sc, MII_PREAMBLE, 32);
1828 tulip_mii_writebits(sc, MII_WRCMD, 8);
1829 tulip_mii_writebits(sc, devaddr, 5);
1830 tulip_mii_writebits(sc, regno, 5);
1831 tulip_mii_turnaround(sc, MII_WRCMD);
1832 tulip_mii_writebits(sc, data, 16);
984263bc
MD
1833}
1834\f
18261b0d 1835#define tulip_mchash(mca) (ether_crc32_le(mca, 6) & 0x1FF)
984263bc 1836#define tulip_srom_crcok(databuf) ( \
18261b0d 1837 ((ether_crc32_le(databuf, 126) & 0xFFFFU) ^ 0xFFFFU) == \
984263bc 1838 ((databuf)[126] | ((databuf)[127] << 8)))
984263bc
MD
1839\f
1840static void
1841tulip_identify_dec_nic(
1842 tulip_softc_t * const sc)
1843{
1844 strcpy(sc->tulip_boardid, "DEC ");
1845#define D0 4
1846 if (sc->tulip_chipid <= TULIP_21040)
1847 return;
1848 if (bcmp(sc->tulip_rombuf + 29, "DE500", 5) == 0
1849 || bcmp(sc->tulip_rombuf + 29, "DE450", 5) == 0) {
1850 bcopy(sc->tulip_rombuf + 29, &sc->tulip_boardid[D0], 8);
1851 sc->tulip_boardid[D0+8] = ' ';
1852 }
1853#undef D0
1854}
1855\f
1856static void
1857tulip_identify_znyx_nic(
1858 tulip_softc_t * const sc)
1859{
1860 unsigned id = 0;
1861 strcpy(sc->tulip_boardid, "ZNYX ZX3XX ");
1862 if (sc->tulip_chipid == TULIP_21140 || sc->tulip_chipid == TULIP_21140A) {
1863 unsigned znyx_ptr;
1864 sc->tulip_boardid[8] = '4';
1865 znyx_ptr = sc->tulip_rombuf[124] + 256 * sc->tulip_rombuf[125];
1866 if (znyx_ptr < 26 || znyx_ptr > 116) {
1867 sc->tulip_boardsw = &tulip_21140_znyx_zx34x_boardsw;
1868 return;
1869 }
1870 /* ZX344 = 0010 .. 0013FF
1871 */
1872 if (sc->tulip_rombuf[znyx_ptr] == 0x4A
1873 && sc->tulip_rombuf[znyx_ptr + 1] == 0x52
1874 && sc->tulip_rombuf[znyx_ptr + 2] == 0x01) {
1875 id = sc->tulip_rombuf[znyx_ptr + 5] + 256 * sc->tulip_rombuf[znyx_ptr + 4];
1876 if ((id >> 8) == (TULIP_ZNYX_ID_ZX342 >> 8)) {
1877 sc->tulip_boardid[9] = '2';
1878 if (id == TULIP_ZNYX_ID_ZX342B) {
1879 sc->tulip_boardid[10] = 'B';
1880 sc->tulip_boardid[11] = ' ';
1881 }
1882 sc->tulip_boardsw = &tulip_21140_znyx_zx34x_boardsw;
1883 } else if (id == TULIP_ZNYX_ID_ZX344) {
1884 sc->tulip_boardid[10] = '4';
1885 sc->tulip_boardsw = &tulip_21140_znyx_zx34x_boardsw;
1886 } else if (id == TULIP_ZNYX_ID_ZX345) {
1887 sc->tulip_boardid[9] = (sc->tulip_rombuf[19] > 1) ? '8' : '5';
1888 } else if (id == TULIP_ZNYX_ID_ZX346) {
1889 sc->tulip_boardid[9] = '6';
1890 } else if (id == TULIP_ZNYX_ID_ZX351) {
1891 sc->tulip_boardid[8] = '5';
1892 sc->tulip_boardid[9] = '1';
1893 }
1894 }
1895 if (id == 0) {
1896 /*
1897 * Assume it's a ZX342...
1898 */
1899 sc->tulip_boardsw = &tulip_21140_znyx_zx34x_boardsw;
1900 }
1901 return;
1902 }
1903 sc->tulip_boardid[8] = '1';
1904 if (sc->tulip_chipid == TULIP_21041) {
1905 sc->tulip_boardid[10] = '1';
1906 return;
1907 }
1908 if (sc->tulip_rombuf[32] == 0x4A && sc->tulip_rombuf[33] == 0x52) {
1909 id = sc->tulip_rombuf[37] + 256 * sc->tulip_rombuf[36];
1910 if (id == TULIP_ZNYX_ID_ZX312T) {
1911 sc->tulip_boardid[9] = '2';
1912 sc->tulip_boardid[10] = 'T';
1913 sc->tulip_boardid[11] = ' ';
1914 sc->tulip_boardsw = &tulip_21040_10baset_only_boardsw;
1915 } else if (id == TULIP_ZNYX_ID_ZX314_INTA) {
1916 sc->tulip_boardid[9] = '4';
1917 sc->tulip_boardsw = &tulip_21040_10baset_only_boardsw;
1918 sc->tulip_features |= TULIP_HAVE_SHAREDINTR|TULIP_HAVE_BASEROM;
1919 } else if (id == TULIP_ZNYX_ID_ZX314) {
1920 sc->tulip_boardid[9] = '4';
1921 sc->tulip_boardsw = &tulip_21040_10baset_only_boardsw;
1922 sc->tulip_features |= TULIP_HAVE_BASEROM;
1923 } else if (id == TULIP_ZNYX_ID_ZX315_INTA) {
1924 sc->tulip_boardid[9] = '5';
1925 sc->tulip_features |= TULIP_HAVE_SHAREDINTR|TULIP_HAVE_BASEROM;
1926 } else if (id == TULIP_ZNYX_ID_ZX315) {
1927 sc->tulip_boardid[9] = '5';
1928 sc->tulip_features |= TULIP_HAVE_BASEROM;
1929 } else {
1930 id = 0;
1931 }
1932 }
1933 if (id == 0) {
1934 if ((sc->tulip_enaddr[3] & ~3) == 0xF0 && (sc->tulip_enaddr[5] & 2) == 0) {
1935 sc->tulip_boardid[9] = '4';
1936 sc->tulip_boardsw = &tulip_21040_10baset_only_boardsw;
1937 sc->tulip_features |= TULIP_HAVE_SHAREDINTR|TULIP_HAVE_BASEROM;
1938 } else if ((sc->tulip_enaddr[3] & ~3) == 0xF4 && (sc->tulip_enaddr[5] & 1) == 0) {
1939 sc->tulip_boardid[9] = '5';
1940 sc->tulip_boardsw = &tulip_21040_boardsw;
1941 sc->tulip_features |= TULIP_HAVE_SHAREDINTR|TULIP_HAVE_BASEROM;
1942 } else if ((sc->tulip_enaddr[3] & ~3) == 0xEC) {
1943 sc->tulip_boardid[9] = '2';
1944 sc->tulip_boardsw = &tulip_21040_boardsw;
1945 }
1946 }
1947}
1948\f
1949static void
1950tulip_identify_smc_nic(
1951 tulip_softc_t * const sc)
1952{
1953 u_int32_t id1, id2, ei;
1954 int auibnc = 0, utp = 0;
1955 char *cp;
1956
1957 strcpy(sc->tulip_boardid, "SMC ");
1958 if (sc->tulip_chipid == TULIP_21041)
1959 return;
1960 if (sc->tulip_chipid != TULIP_21040) {
1961 if (sc->tulip_boardsw != &tulip_2114x_isv_boardsw) {
1962 strcpy(&sc->tulip_boardid[4], "9332DST ");
1963 sc->tulip_boardsw = &tulip_21140_smc9332_boardsw;
1964 } else if (sc->tulip_features & (TULIP_HAVE_BASEROM|TULIP_HAVE_SLAVEDROM)) {
1965 strcpy(&sc->tulip_boardid[4], "9334BDT ");
1966 } else {
1967 strcpy(&sc->tulip_boardid[4], "9332BDT ");
1968 }
1969 return;
1970 }
1971 id1 = sc->tulip_rombuf[0x60] | (sc->tulip_rombuf[0x61] << 8);
1972 id2 = sc->tulip_rombuf[0x62] | (sc->tulip_rombuf[0x63] << 8);
1973 ei = sc->tulip_rombuf[0x66] | (sc->tulip_rombuf[0x67] << 8);
1974
1975 strcpy(&sc->tulip_boardid[4], "8432");
1976 cp = &sc->tulip_boardid[8];
1977 if ((id1 & 1) == 0)
1978 *cp++ = 'B', auibnc = 1;
1979 if ((id1 & 0xFF) > 0x32)
1980 *cp++ = 'T', utp = 1;
1981 if ((id1 & 0x4000) == 0)
1982 *cp++ = 'A', auibnc = 1;
1983 if (id2 == 0x15) {
1984 sc->tulip_boardid[7] = '4';
1985 *cp++ = '-';
1986 *cp++ = 'C';
1987 *cp++ = 'H';
1988 *cp++ = (ei ? '2' : '1');
1989 }
1990 *cp++ = ' ';
1991 *cp = '\0';
1992 if (utp && !auibnc)
1993 sc->tulip_boardsw = &tulip_21040_10baset_only_boardsw;
1994 else if (!utp && auibnc)
1995 sc->tulip_boardsw = &tulip_21040_auibnc_only_boardsw;
1996}
1997\f
1998static void
1999tulip_identify_cogent_nic(
2000 tulip_softc_t * const sc)
2001{
2002 strcpy(sc->tulip_boardid, "Cogent ");
2003 if (sc->tulip_chipid == TULIP_21140 || sc->tulip_chipid == TULIP_21140A) {
2004 if (sc->tulip_rombuf[32] == TULIP_COGENT_EM100TX_ID) {
2005 strcat(sc->tulip_boardid, "EM100TX ");
2006 sc->tulip_boardsw = &tulip_21140_cogent_em100_boardsw;
2007#if defined(TULIP_COGENT_EM110TX_ID)
2008 } else if (sc->tulip_rombuf[32] == TULIP_COGENT_EM110TX_ID) {
2009 strcat(sc->tulip_boardid, "EM110TX ");
2010 sc->tulip_boardsw = &tulip_21140_cogent_em100_boardsw;
2011#endif
2012 } else if (sc->tulip_rombuf[32] == TULIP_COGENT_EM100FX_ID) {
2013 strcat(sc->tulip_boardid, "EM100FX ");
2014 sc->tulip_boardsw = &tulip_21140_cogent_em100_boardsw;
2015 }
2016 /*
2017 * Magic number (0x24001109U) is the SubVendor (0x2400) and
2018 * SubDevId (0x1109) for the ANA6944TX (EM440TX).
2019 */
2020 if (*(u_int32_t *) sc->tulip_rombuf == 0x24001109U
2021 && (sc->tulip_features & TULIP_HAVE_BASEROM)) {
2022 /*
2023 * Cogent (Adaptec) is still mapping all INTs to INTA of
2024 * first 21140. Dumb! Dumb!
2025 */
2026 strcat(sc->tulip_boardid, "EM440TX ");
2027 sc->tulip_features |= TULIP_HAVE_SHAREDINTR;
2028 }
2029 } else if (sc->tulip_chipid == TULIP_21040) {
2030 sc->tulip_features |= TULIP_HAVE_SHAREDINTR|TULIP_HAVE_BASEROM;
2031 }
2032}
2033\f
2034static void
2035tulip_identify_accton_nic(
2036 tulip_softc_t * const sc)
2037{
2038 strcpy(sc->tulip_boardid, "ACCTON ");
2039 switch (sc->tulip_chipid) {
2040 case TULIP_21140A:
2041 strcat(sc->tulip_boardid, "EN1207 ");
2042 if (sc->tulip_boardsw != &tulip_2114x_isv_boardsw)
2043 sc->tulip_boardsw = &tulip_21140_accton_boardsw;
2044 break;
2045 case TULIP_21140:
2046 strcat(sc->tulip_boardid, "EN1207TX ");
2047 if (sc->tulip_boardsw != &tulip_2114x_isv_boardsw)
2048 sc->tulip_boardsw = &tulip_21140_eb_boardsw;
2049 break;
2050 case TULIP_21040:
2051 strcat(sc->tulip_boardid, "EN1203 ");
2052 sc->tulip_boardsw = &tulip_21040_boardsw;
2053 break;
2054 case TULIP_21041:
2055 strcat(sc->tulip_boardid, "EN1203 ");
2056 sc->tulip_boardsw = &tulip_21041_boardsw;
2057 break;
2058 default:
2059 sc->tulip_boardsw = &tulip_2114x_isv_boardsw;
2060 break;
2061 }
2062}
2063\f
2064static void
2065tulip_identify_asante_nic(
2066 tulip_softc_t * const sc)
2067{
2068 strcpy(sc->tulip_boardid, "Asante ");
2069 if ((sc->tulip_chipid == TULIP_21140 || sc->tulip_chipid == TULIP_21140A)
2070 && sc->tulip_boardsw != &tulip_2114x_isv_boardsw) {
2071 tulip_media_info_t *mi = sc->tulip_mediainfo;
2072 int idx;
2073 /*
2074 * The Asante Fast Ethernet doesn't always ship with a valid
2075 * new format SROM. So if isn't in the new format, we cheat
2076 * set it up as if we had.
2077 */
2078
2079 sc->tulip_gpinit = TULIP_GP_ASANTE_PINS;
2080 sc->tulip_gpdata = 0;
2081
2082 TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_ASANTE_PINS|TULIP_GP_PINSET);
2083 TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_ASANTE_PHYRESET);
2084 DELAY(100);
2085 TULIP_CSR_WRITE(sc, csr_gp, 0);
2086
2087 mi->mi_type = TULIP_MEDIAINFO_MII;
2088 mi->mi_gpr_length = 0;
2089 mi->mi_gpr_offset = 0;
2090 mi->mi_reset_length = 0;
2091 mi->mi_reset_offset = 0;;
2092
2093 mi->mi_phyaddr = TULIP_MII_NOPHY;
2094 for (idx = 20; idx > 0 && mi->mi_phyaddr == TULIP_MII_NOPHY; idx--) {
2095 DELAY(10000);
2096 mi->mi_phyaddr = tulip_mii_get_phyaddr(sc, 0);
2097 }
2098 if (mi->mi_phyaddr == TULIP_MII_NOPHY) {
2099 printf("%s%d: can't find phy 0\n", sc->tulip_name, sc->tulip_unit);
2100 return;
2101 }
2102
2103 sc->tulip_features |= TULIP_HAVE_MII;
2104 mi->mi_capabilities = PHYSTS_10BASET|PHYSTS_10BASET_FD|PHYSTS_100BASETX|PHYSTS_100BASETX_FD;
2105 mi->mi_advertisement = PHYSTS_10BASET|PHYSTS_10BASET_FD|PHYSTS_100BASETX|PHYSTS_100BASETX_FD;
2106 mi->mi_full_duplex = PHYSTS_10BASET_FD|PHYSTS_100BASETX_FD;
2107 mi->mi_tx_threshold = PHYSTS_10BASET|PHYSTS_10BASET_FD;
2108 TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASETX_FD);
2109 TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASETX);
2110 TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASET4);
2111 TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 10BASET_FD);
2112 TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 10BASET);
2113 mi->mi_phyid = (tulip_mii_readreg(sc, mi->mi_phyaddr, PHYREG_IDLOW) << 16) |
2114 tulip_mii_readreg(sc, mi->mi_phyaddr, PHYREG_IDHIGH);
2115
2116 sc->tulip_boardsw = &tulip_2114x_isv_boardsw;
2117 }
2118}
2119\f
2120static void
2121tulip_identify_compex_nic(
2122 tulip_softc_t * const sc)
2123{
2124 strcpy(sc->tulip_boardid, "COMPEX ");
2125 if (sc->tulip_chipid == TULIP_21140A) {
2126 int root_unit;
2127 tulip_softc_t *root_sc = NULL;
2128
2129 strcat(sc->tulip_boardid, "400TX/PCI ");
2130 /*
2131 * All 4 chips on these boards share an interrupt. This code
2132 * copied from tulip_read_macaddr.
2133 */
2134 sc->tulip_features |= TULIP_HAVE_SHAREDINTR;
2135 for (root_unit = sc->tulip_unit - 1; root_unit >= 0; root_unit--) {
2136 root_sc = tulips[root_unit];
2137 if (root_sc == NULL
2138 || !(root_sc->tulip_features & TULIP_HAVE_SLAVEDINTR))
2139 break;
2140 root_sc = NULL;
2141 }
2142 if (root_sc != NULL
2143 && root_sc->tulip_chipid == sc->tulip_chipid
2144 && root_sc->tulip_pci_busno == sc->tulip_pci_busno) {
2145 sc->tulip_features |= TULIP_HAVE_SLAVEDINTR;
2146 sc->tulip_slaves = root_sc->tulip_slaves;
2147 root_sc->tulip_slaves = sc;
2148 } else if(sc->tulip_features & TULIP_HAVE_SLAVEDINTR) {
2149 printf("\nCannot find master device for de%d interrupts",
2150 sc->tulip_unit);
2151 }
2152 } else {
2153 strcat(sc->tulip_boardid, "unknown ");
2154 }
2155 /* sc->tulip_boardsw = &tulip_21140_eb_boardsw; */
2156 return;
2157}
2158\f
2159static int
2160tulip_srom_decode(
2161 tulip_softc_t * const sc)
2162{
2163 unsigned idx1, idx2, idx3;
2164
2165 const tulip_srom_header_t *shp = (const tulip_srom_header_t *) &sc->tulip_rombuf[0];
2166 const tulip_srom_adapter_info_t *saip = (const tulip_srom_adapter_info_t *) (shp + 1);
2167 tulip_srom_media_t srom_media;
2168 tulip_media_info_t *mi = sc->tulip_mediainfo;
2169 const u_int8_t *dp;
2170 u_int32_t leaf_offset, blocks, data;
2171
2172 for (idx1 = 0; idx1 < shp->sh_adapter_count; idx1++, saip++) {
2173 if (shp->sh_adapter_count == 1)
2174 break;
2175 if (saip->sai_device == sc->tulip_pci_devno)
2176 break;
2177 }
2178 /*
2179 * Didn't find the right media block for this card.
2180 */
2181 if (idx1 == shp->sh_adapter_count)
2182 return 0;
2183
2184 /*
2185 * Save the hardware address.
2186 */
2187 bcopy(shp->sh_ieee802_address, sc->tulip_enaddr, 6);
2188 /*
2189 * If this is a multiple port card, add the adapter index to the last
2190 * byte of the hardware address. (if it isn't multiport, adding 0
2191 * won't hurt.
2192 */
2193 sc->tulip_enaddr[5] += idx1;
2194
2195 leaf_offset = saip->sai_leaf_offset_lowbyte
2196 + saip->sai_leaf_offset_highbyte * 256;
2197 dp = sc->tulip_rombuf + leaf_offset;
2198
2199 sc->tulip_conntype = (tulip_srom_connection_t) (dp[0] + dp[1] * 256); dp += 2;
2200
2201 for (idx2 = 0;; idx2++) {
2202 if (tulip_srom_conninfo[idx2].sc_type == sc->tulip_conntype
2203 || tulip_srom_conninfo[idx2].sc_type == TULIP_SROM_CONNTYPE_NOT_USED)
2204 break;
2205 }
2206 sc->tulip_connidx = idx2;
2207
2208 if (sc->tulip_chipid == TULIP_21041) {
2209 blocks = *dp++;
2210 for (idx2 = 0; idx2 < blocks; idx2++) {
2211 tulip_media_t media;
2212 data = *dp++;
2213 srom_media = (tulip_srom_media_t) (data & 0x3F);
2214 for (idx3 = 0; tulip_srom_mediums[idx3].sm_type != TULIP_MEDIA_UNKNOWN; idx3++) {
2215 if (tulip_srom_mediums[idx3].sm_srom_type == srom_media)
2216 break;
2217 }
2218 media = tulip_srom_mediums[idx3].sm_type;
2219 if (media != TULIP_MEDIA_UNKNOWN) {
2220 if (data & TULIP_SROM_21041_EXTENDED) {
2221 mi->mi_type = TULIP_MEDIAINFO_SIA;
2222 sc->tulip_mediums[media] = mi;
2223 mi->mi_sia_connectivity = dp[0] + dp[1] * 256;
2224 mi->mi_sia_tx_rx = dp[2] + dp[3] * 256;
2225 mi->mi_sia_general = dp[4] + dp[5] * 256;
2226 mi++;
2227 } else {
2228 switch (media) {
2229 case TULIP_MEDIA_BNC: {
2230 TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21041, BNC);
2231 mi++;
2232 break;
2233 }
2234 case TULIP_MEDIA_AUI: {
2235 TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21041, AUI);
2236 mi++;
2237 break;
2238 }
2239 case TULIP_MEDIA_10BASET: {
2240 TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21041, 10BASET);
2241 mi++;
2242 break;
2243 }
2244 case TULIP_MEDIA_10BASET_FD: {
2245 TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21041, 10BASET_FD);
2246 mi++;
2247 break;
2248 }
2249 default: {
2250 break;
2251 }
2252 }
2253 }
2254 }
2255 if (data & TULIP_SROM_21041_EXTENDED)
2256 dp += 6;
2257 }
2258#ifdef notdef
2259 if (blocks == 0) {
2260 TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21041, BNC); mi++;
2261 TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21041, AUI); mi++;
2262 TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21041, 10BASET); mi++;
2263 TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21041, 10BASET_FD); mi++;
2264 }
2265#endif
2266 } else {
2267 unsigned length, type;
2268 tulip_media_t gp_media = TULIP_MEDIA_UNKNOWN;
2269 if (sc->tulip_features & TULIP_HAVE_GPR)
2270 sc->tulip_gpinit = *dp++;
2271 blocks = *dp++;
2272 for (idx2 = 0; idx2 < blocks; idx2++) {
2273 const u_int8_t *ep;
2274 if ((*dp & 0x80) == 0) {
2275 length = 4;
2276 type = 0;
2277 } else {
2278 length = (*dp++ & 0x7f) - 1;
2279 type = *dp++ & 0x3f;
2280 }
2281 ep = dp + length;
2282 switch (type & 0x3f) {
2283 case 0: { /* 21140[A] GPR block */
2284 tulip_media_t media;
2285 srom_media = (tulip_srom_media_t)(dp[0] & 0x3f);
2286 for (idx3 = 0; tulip_srom_mediums[idx3].sm_type != TULIP_MEDIA_UNKNOWN; idx3++) {
2287 if (tulip_srom_mediums[idx3].sm_srom_type == srom_media)
2288 break;
2289 }
2290 media = tulip_srom_mediums[idx3].sm_type;
2291 if (media == TULIP_MEDIA_UNKNOWN)
2292 break;
2293 mi->mi_type = TULIP_MEDIAINFO_GPR;
2294 sc->tulip_mediums[media] = mi;
2295 mi->mi_gpdata = dp[1];
2296 if (media > gp_media && !TULIP_IS_MEDIA_FD(media)) {
2297 sc->tulip_gpdata = mi->mi_gpdata;
2298 gp_media = media;
2299 }
2300 data = dp[2] + dp[3] * 256;
2301 mi->mi_cmdmode = TULIP_SROM_2114X_CMDBITS(data);
2302 if (data & TULIP_SROM_2114X_NOINDICATOR) {
2303 mi->mi_actmask = 0;
2304 } else {
2305#if 0
2306 mi->mi_default = (data & TULIP_SROM_2114X_DEFAULT) != 0;
2307#endif
2308 mi->mi_actmask = TULIP_SROM_2114X_BITPOS(data);
2309 mi->mi_actdata = (data & TULIP_SROM_2114X_POLARITY) ? 0 : mi->mi_actmask;
2310 }
2311 mi++;
2312 break;
2313 }
2314 case 1: { /* 21140[A] MII block */
2315 const unsigned phyno = *dp++;
2316 mi->mi_type = TULIP_MEDIAINFO_MII;
2317 mi->mi_gpr_length = *dp++;
2318 mi->mi_gpr_offset = dp - sc->tulip_rombuf;
2319 dp += mi->mi_gpr_length;
2320 mi->mi_reset_length = *dp++;
2321 mi->mi_reset_offset = dp - sc->tulip_rombuf;
2322 dp += mi->mi_reset_length;
2323
2324 /*
2325 * Before we probe for a PHY, use the GPR information
2326 * to select it. If we don't, it may be inaccessible.
2327 */
2328 TULIP_CSR_WRITE(sc, csr_gp, sc->tulip_gpinit|TULIP_GP_PINSET);
2329 for (idx3 = 0; idx3 < mi->mi_reset_length; idx3++) {
2330 DELAY(10);
2331 TULIP_CSR_WRITE(sc, csr_gp, sc->tulip_rombuf[mi->mi_reset_offset + idx3]);
2332 }
2333 sc->tulip_phyaddr = mi->mi_phyaddr;
2334 for (idx3 = 0; idx3 < mi->mi_gpr_length; idx3++) {
2335 DELAY(10);
2336 TULIP_CSR_WRITE(sc, csr_gp, sc->tulip_rombuf[mi->mi_gpr_offset + idx3]);
2337 }
2338
2339 /*
2340 * At least write something!
2341 */
2342 if (mi->mi_reset_length == 0 && mi->mi_gpr_length == 0)
2343 TULIP_CSR_WRITE(sc, csr_gp, 0);
2344
2345 mi->mi_phyaddr = TULIP_MII_NOPHY;
2346 for (idx3 = 20; idx3 > 0 && mi->mi_phyaddr == TULIP_MII_NOPHY; idx3--) {
2347 DELAY(10000);
2348 mi->mi_phyaddr = tulip_mii_get_phyaddr(sc, phyno);
2349 }
46a77a85 2350 if (mi->mi_phyaddr == TULIP_MII_NOPHY)
984263bc 2351 break;
984263bc
MD
2352 sc->tulip_features |= TULIP_HAVE_MII;
2353 mi->mi_capabilities = dp[0] + dp[1] * 256; dp += 2;
2354 mi->mi_advertisement = dp[0] + dp[1] * 256; dp += 2;
2355 mi->mi_full_duplex = dp[0] + dp[1] * 256; dp += 2;
2356 mi->mi_tx_threshold = dp[0] + dp[1] * 256; dp += 2;
2357 TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASETX_FD);
2358 TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASETX);
2359 TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASET4);
2360 TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 10BASET_FD);
2361 TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 10BASET);
2362 mi->mi_phyid = (tulip_mii_readreg(sc, mi->mi_phyaddr, PHYREG_IDLOW) << 16) |
2363 tulip_mii_readreg(sc, mi->mi_phyaddr, PHYREG_IDHIGH);
2364 mi++;
2365 break;
2366 }
2367 case 2: { /* 2114[23] SIA block */
2368 tulip_media_t media;
2369 srom_media = (tulip_srom_media_t)(dp[0] & 0x3f);
2370 for (idx3 = 0; tulip_srom_mediums[idx3].sm_type != TULIP_MEDIA_UNKNOWN; idx3++) {
2371 if (tulip_srom_mediums[idx3].sm_srom_type == srom_media)
2372 break;
2373 }
2374 media = tulip_srom_mediums[idx3].sm_type;
2375 if (media == TULIP_MEDIA_UNKNOWN)
2376 break;
2377 mi->mi_type = TULIP_MEDIAINFO_SIA;
2378 sc->tulip_mediums[media] = mi;
2379 if (dp[0] & 0x40) {
2380 mi->mi_sia_connectivity = dp[1] + dp[2] * 256;
2381 mi->mi_sia_tx_rx = dp[3] + dp[4] * 256;
2382 mi->mi_sia_general = dp[5] + dp[6] * 256;
2383 dp += 6;
2384 } else {
2385 switch (media) {
2386 case TULIP_MEDIA_BNC: {
2387 TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21142, BNC);
2388 break;
2389 }
2390 case TULIP_MEDIA_AUI: {
2391 TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21142, AUI);
2392 break;
2393 }
2394 case TULIP_MEDIA_10BASET: {
2395 TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21142, 10BASET);
2396 sc->tulip_intrmask |= TULIP_STS_LINKPASS|TULIP_STS_LINKFAIL;
2397 break;
2398 }
2399 case TULIP_MEDIA_10BASET_FD: {
2400 TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21142, 10BASET_FD);
2401 sc->tulip_intrmask |= TULIP_STS_LINKPASS|TULIP_STS_LINKFAIL;
2402 break;
2403 }
2404 default: {
2405 goto bad_media;
2406 }
2407 }
2408 }
2409 mi->mi_sia_gp_control = (dp[1] + dp[2] * 256) << 16;
2410 mi->mi_sia_gp_data = (dp[3] + dp[4] * 256) << 16;
2411 mi++;
2412 bad_media:
2413 break;
2414 }
2415 case 3: { /* 2114[23] MII PHY block */
2416 const unsigned phyno = *dp++;
2417 const u_int8_t *dp0;
2418 mi->mi_type = TULIP_MEDIAINFO_MII;
2419 mi->mi_gpr_length = *dp++;
2420 mi->mi_gpr_offset = dp - sc->tulip_rombuf;
2421 dp += 2 * mi->mi_gpr_length;
2422 mi->mi_reset_length = *dp++;
2423 mi->mi_reset_offset = dp - sc->tulip_rombuf;
2424 dp += 2 * mi->mi_reset_length;
2425
2426 dp0 = &sc->tulip_rombuf[mi->mi_reset_offset];
2427 for (idx3 = 0; idx3 < mi->mi_reset_length; idx3++, dp0 += 2) {
2428 DELAY(10);
2429 TULIP_CSR_WRITE(sc, csr_sia_general, (dp0[0] + 256 * dp0[1]) << 16);
2430 }
2431 sc->tulip_phyaddr = mi->mi_phyaddr;
2432 dp0 = &sc->tulip_rombuf[mi->mi_gpr_offset];
2433 for (idx3 = 0; idx3 < mi->mi_gpr_length; idx3++, dp0 += 2) {
2434 DELAY(10);
2435 TULIP_CSR_WRITE(sc, csr_sia_general, (dp0[0] + 256 * dp0[1]) << 16);
2436 }
2437
2438 if (mi->mi_reset_length == 0 && mi->mi_gpr_length == 0)
2439 TULIP_CSR_WRITE(sc, csr_sia_general, 0);
2440
2441 mi->mi_phyaddr = TULIP_MII_NOPHY;
2442 for (idx3 = 20; idx3 > 0 && mi->mi_phyaddr == TULIP_MII_NOPHY; idx3--) {
2443 DELAY(10000);
2444 mi->mi_phyaddr = tulip_mii_get_phyaddr(sc, phyno);
2445 }
46a77a85 2446 if (mi->mi_phyaddr == TULIP_MII_NOPHY)
984263bc 2447 break;
984263bc
MD
2448 sc->tulip_features |= TULIP_HAVE_MII;
2449 mi->mi_capabilities = dp[0] + dp[1] * 256; dp += 2;
2450 mi->mi_advertisement = dp[0] + dp[1] * 256; dp += 2;
2451 mi->mi_full_duplex = dp[0] + dp[1] * 256; dp += 2;
2452 mi->mi_tx_threshold = dp[0] + dp[1] * 256; dp += 2;
2453 mi->mi_mii_interrupt = dp[0] + dp[1] * 256; dp += 2;
2454 TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASETX_FD);
2455 TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASETX);
2456 TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASET4);
2457 TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 10BASET_FD);
2458 TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 10BASET);
2459 mi->mi_phyid = (tulip_mii_readreg(sc, mi->mi_phyaddr, PHYREG_IDLOW) << 16) |
2460 tulip_mii_readreg(sc, mi->mi_phyaddr, PHYREG_IDHIGH);
2461 mi++;
2462 break;
2463 }
2464 case 4: { /* 21143 SYM block */
2465 tulip_media_t media;
2466 srom_media = (tulip_srom_media_t) dp[0];
2467 for (idx3 = 0; tulip_srom_mediums[idx3].sm_type != TULIP_MEDIA_UNKNOWN; idx3++) {
2468 if (tulip_srom_mediums[idx3].sm_srom_type == srom_media)
2469 break;
2470 }
2471 media = tulip_srom_mediums[idx3].sm_type;
2472 if (media == TULIP_MEDIA_UNKNOWN)
2473 break;
2474 mi->mi_type = TULIP_MEDIAINFO_SYM;
2475 sc->tulip_mediums[media] = mi;
2476 mi->mi_gpcontrol = (dp[1] + dp[2] * 256) << 16;
2477 mi->mi_gpdata = (dp[3] + dp[4] * 256) << 16;
2478 data = dp[5] + dp[6] * 256;
2479 mi->mi_cmdmode = TULIP_SROM_2114X_CMDBITS(data);
2480 if (data & TULIP_SROM_2114X_NOINDICATOR) {
2481 mi->mi_actmask = 0;
2482 } else {
2483 mi->mi_default = (data & TULIP_SROM_2114X_DEFAULT) != 0;
2484 mi->mi_actmask = TULIP_SROM_2114X_BITPOS(data);
2485 mi->mi_actdata = (data & TULIP_SROM_2114X_POLARITY) ? 0 : mi->mi_actmask;
2486 }
2487 if (TULIP_IS_MEDIA_TP(media))
2488 sc->tulip_intrmask |= TULIP_STS_LINKPASS|TULIP_STS_LINKFAIL;
2489 mi++;
2490 break;
2491 }
2492#if 0
2493 case 5: { /* 21143 Reset block */
2494 mi->mi_type = TULIP_MEDIAINFO_RESET;
2495 mi->mi_reset_length = *dp++;
2496 mi->mi_reset_offset = dp - sc->tulip_rombuf;
2497 dp += 2 * mi->mi_reset_length;
2498 mi++;
2499 break;
2500 }
2501#endif
2502 default: {
2503 }
2504 }
2505 dp = ep;
2506 }
2507 }
2508 return mi - sc->tulip_mediainfo;
2509}
2510\f
2511static const struct {
2512 void (*vendor_identify_nic)(tulip_softc_t * const sc);
2513 unsigned char vendor_oui[3];
2514} tulip_vendors[] = {
2515 { tulip_identify_dec_nic, { 0x08, 0x00, 0x2B } },
2516 { tulip_identify_dec_nic, { 0x00, 0x00, 0xF8 } },
2517 { tulip_identify_smc_nic, { 0x00, 0x00, 0xC0 } },
2518 { tulip_identify_smc_nic, { 0x00, 0xE0, 0x29 } },
2519 { tulip_identify_znyx_nic, { 0x00, 0xC0, 0x95 } },
2520 { tulip_identify_cogent_nic, { 0x00, 0x00, 0x92 } },
2521 { tulip_identify_asante_nic, { 0x00, 0x00, 0x94 } },
2522 { tulip_identify_cogent_nic, { 0x00, 0x00, 0xD1 } },
2523 { tulip_identify_accton_nic, { 0x00, 0x00, 0xE8 } },
2524 { tulip_identify_compex_nic, { 0x00, 0x80, 0x48 } },
2525 { NULL }
2526};
2527
2528/*
2529 * This deals with the vagaries of the address roms and the
2530 * brain-deadness that various vendors commit in using them.
2531 */
2532static int
2533tulip_read_macaddr(
2534 tulip_softc_t * const sc)
2535{
2536 unsigned cksum, rom_cksum, idx;
2537 u_int32_t csr;
2538 unsigned char tmpbuf[8];
2539 static const u_char testpat[] = { 0xFF, 0, 0x55, 0xAA, 0xFF, 0, 0x55, 0xAA };
2540
2541 sc->tulip_connidx = TULIP_SROM_LASTCONNIDX;
2542
2543 if (sc->tulip_chipid == TULIP_21040) {
2544 TULIP_CSR_WRITE(sc, csr_enetrom, 1);
2545 for (idx = 0; idx < sizeof(sc->tulip_rombuf); idx++) {
2546 int cnt = 0;
2547 while (((csr = TULIP_CSR_READ(sc, csr_enetrom)) & 0x80000000L) && cnt < 10000)
2548 cnt++;
2549 sc->tulip_rombuf[idx] = csr & 0xFF;
2550 }
2551 sc->tulip_boardsw = &tulip_21040_boardsw;
2552 } else {
2553 if (sc->tulip_chipid == TULIP_21041) {
2554 /*
2555 * Thankfully all 21041's act the same.
2556 */
2557 sc->tulip_boardsw = &tulip_21041_boardsw;
2558 } else {
2559 /*
2560 * Assume all 21140 board are compatible with the
2561 * DEC 10/100 evaluation board. Not really valid but
2562 * it's the best we can do until every one switches to
2563 * the new SROM format.
2564 */
2565
2566 sc->tulip_boardsw = &tulip_21140_eb_boardsw;
2567 }
2568 tulip_srom_read(sc);
2569 if (tulip_srom_crcok(sc->tulip_rombuf)) {
2570 /*
2571 * SROM CRC is valid therefore it must be in the
2572 * new format.
2573 */
2574 sc->tulip_features |= TULIP_HAVE_ISVSROM|TULIP_HAVE_OKSROM;
2575 } else if (sc->tulip_rombuf[126] == 0xff && sc->tulip_rombuf[127] == 0xFF) {
2576 /*
2577 * No checksum is present. See if the SROM id checks out;
2578 * the first 18 bytes should be 0 followed by a 1 followed
2579 * by the number of adapters (which we don't deal with yet).
2580 */
2581 for (idx = 0; idx < 18; idx++) {
2582 if (sc->tulip_rombuf[idx] != 0)
2583 break;
2584 }
2585 if (idx == 18 && sc->tulip_rombuf[18] == 1 && sc->tulip_rombuf[19] != 0)
2586 sc->tulip_features |= TULIP_HAVE_ISVSROM;
2587 } else if (sc->tulip_chipid >= TULIP_21142) {
2588 sc->tulip_features |= TULIP_HAVE_ISVSROM;
2589 sc->tulip_boardsw = &tulip_2114x_isv_boardsw;
2590 }
2591 if ((sc->tulip_features & TULIP_HAVE_ISVSROM) && tulip_srom_decode(sc)) {
2592 if (sc->tulip_chipid != TULIP_21041)
2593 sc->tulip_boardsw = &tulip_2114x_isv_boardsw;
2594
2595 /*
2596 * If the SROM specifies more than one adapter, tag this as a
2597 * BASE rom.
2598 */
2599 if (sc->tulip_rombuf[19] > 1)
2600 sc->tulip_features |= TULIP_HAVE_BASEROM;
2601 if (sc->tulip_boardsw == NULL)
2602 return -6;
2603 goto check_oui;
2604 }
2605 }
2606
2607
2608 if (bcmp(&sc->tulip_rombuf[0], &sc->tulip_rombuf[16], 8) != 0) {
2609 /*
2610 * Some folks don't use the standard ethernet rom format
2611 * but instead just put the address in the first 6 bytes
2612 * of the rom and let the rest be all 0xffs. (Can we say
2613 * ZNYX?) (well sometimes they put in a checksum so we'll
2614 * start at 8).
2615 */
2616 for (idx = 8; idx < 32; idx++) {
2617 if (sc->tulip_rombuf[idx] != 0xFF)
2618 return -4;
2619 }
2620 /*
2621 * Make sure the address is not multicast or locally assigned
2622 * that the OUI is not 00-00-00.
2623 */
2624 if ((sc->tulip_rombuf[0] & 3) != 0)
2625 return -4;
2626 if (sc->tulip_rombuf[0] == 0 && sc->tulip_rombuf[1] == 0
2627 && sc->tulip_rombuf[2] == 0)
2628 return -4;
2629 bcopy(sc->tulip_rombuf, sc->tulip_enaddr, 6);
2630 sc->tulip_features |= TULIP_HAVE_OKROM;
2631 goto check_oui;
2632 } else {
2633 /*
2634 * A number of makers of multiport boards (ZNYX and Cogent)
2635 * only put on one address ROM on their 21040 boards. So
2636 * if the ROM is all zeros (or all 0xFFs), look at the
2637 * previous configured boards (as long as they are on the same
2638 * PCI bus and the bus number is non-zero) until we find the
2639 * master board with address ROM. We then use its address ROM
2640 * as the base for this board. (we add our relative board
2641 * to the last byte of its address).
2642 */
2643 for (idx = 0; idx < sizeof(sc->tulip_rombuf); idx++) {
2644 if (sc->tulip_rombuf[idx] != 0 && sc->tulip_rombuf[idx] != 0xFF)
2645 break;
2646 }
2647 if (idx == sizeof(sc->tulip_rombuf)) {
2648 int root_unit;
2649 tulip_softc_t *root_sc = NULL;
2650 for (root_unit = sc->tulip_unit - 1; root_unit >= 0; root_unit--) {
2651 root_sc = tulips[root_unit];
2652 if (root_sc == NULL || (root_sc->tulip_features & (TULIP_HAVE_OKROM|TULIP_HAVE_SLAVEDROM)) == TULIP_HAVE_OKROM)
2653 break;
2654 root_sc = NULL;
2655 }
2656 if (root_sc != NULL && (root_sc->tulip_features & TULIP_HAVE_BASEROM)
2657 && root_sc->tulip_chipid == sc->tulip_chipid
2658 && root_sc->tulip_pci_busno == sc->tulip_pci_busno) {
2659 sc->tulip_features |= TULIP_HAVE_SLAVEDROM;
2660 sc->tulip_boardsw = root_sc->tulip_boardsw;
2661 strcpy(sc->tulip_boardid, root_sc->tulip_boardid);
2662 if (sc->tulip_boardsw->bd_type == TULIP_21140_ISV) {
2663 bcopy(root_sc->tulip_rombuf, sc->tulip_rombuf,
2664 sizeof(sc->tulip_rombuf));
2665 if (!tulip_srom_decode(sc))
2666 return -5;
2667 } else {
2668 bcopy(root_sc->tulip_enaddr, sc->tulip_enaddr, 6);
2669 sc->tulip_enaddr[5] += sc->tulip_unit - root_sc->tulip_unit;
2670 }
2671 /*
2672 * Now for a truly disgusting kludge: all 4 21040s on
2673 * the ZX314 share the same INTA line so the mapping
2674 * setup by the BIOS on the PCI bridge is worthless.
2675 * Rather than reprogramming the value in the config
2676 * register, we will handle this internally.
2677 */
2678 if (root_sc->tulip_features & TULIP_HAVE_SHAREDINTR) {
2679 sc->tulip_slaves = root_sc->tulip_slaves;
2680 root_sc->tulip_slaves = sc;
2681 sc->tulip_features |= TULIP_HAVE_SLAVEDINTR;
2682 }
2683 return 0;
2684 }
2685 }
2686 }
2687
2688 /*
2689 * This is the standard DEC address ROM test.
2690 */
2691
2692 if (bcmp(&sc->tulip_rombuf[24], testpat, 8) != 0)
2693 return -3;
2694
2695 tmpbuf[0] = sc->tulip_rombuf[15]; tmpbuf[1] = sc->tulip_rombuf[14];
2696 tmpbuf[2] = sc->tulip_rombuf[13]; tmpbuf[3] = sc->tulip_rombuf[12];
2697 tmpbuf[4] = sc->tulip_rombuf[11]; tmpbuf[5] = sc->tulip_rombuf[10];
2698 tmpbuf[6] = sc->tulip_rombuf[9]; tmpbuf[7] = sc->tulip_rombuf[8];
2699 if (bcmp(&sc->tulip_rombuf[0], tmpbuf, 8) != 0)
2700 return -2;
2701
2702 bcopy(sc->tulip_rombuf, sc->tulip_enaddr, 6);
2703
2704 cksum = *(u_int16_t *) &sc->tulip_enaddr[0];
2705 cksum *= 2;
2706 if (cksum > 65535) cksum -= 65535;
2707 cksum += *(u_int16_t *) &sc->tulip_enaddr[2];
2708 if (cksum > 65535) cksum -= 65535;
2709 cksum *= 2;
2710 if (cksum > 65535) cksum -= 65535;
2711 cksum += *(u_int16_t *) &sc->tulip_enaddr[4];
2712 if (cksum >= 65535) cksum -= 65535;
2713
2714 rom_cksum = *(u_int16_t *) &sc->tulip_rombuf[6];
2715
2716 if (cksum != rom_cksum)
2717 return -1;
2718
2719 check_oui:
2720 /*
2721 * Check for various boards based on OUI. Did I say braindead?
2722 */
2723 for (idx = 0; tulip_vendors[idx].vendor_identify_nic != NULL; idx++) {
2724 if (bcmp(sc->tulip_enaddr, tulip_vendors[idx].vendor_oui, 3) == 0) {
2725 (*tulip_vendors[idx].vendor_identify_nic)(sc);
2726 break;
2727 }
2728 }
2729
2730 sc->tulip_features |= TULIP_HAVE_OKROM;
2731 return 0;
2732}
2733\f
2734static void
2735tulip_ifmedia_add(
2736 tulip_softc_t * const sc)
2737{
2738 tulip_media_t media;
2739 int medias = 0;
2740
2741 for (media = TULIP_MEDIA_UNKNOWN; media < TULIP_MEDIA_MAX; media++) {
2742 if (sc->tulip_mediums[media] != NULL) {
2743 ifmedia_add(&sc->tulip_ifmedia, tulip_media_to_ifmedia[media],
2744 0, 0);
2745 medias++;
2746 }
2747 }
2748 if (medias == 0) {
2749 sc->tulip_features |= TULIP_HAVE_NOMEDIA;
2750 ifmedia_add(&sc->tulip_ifmedia, IFM_ETHER | IFM_NONE, 0, 0);
2751 ifmedia_set(&sc->tulip_ifmedia, IFM_ETHER | IFM_NONE);
2752 } else if (sc->tulip_media == TULIP_MEDIA_UNKNOWN) {
2753 ifmedia_add(&sc->tulip_ifmedia, IFM_ETHER | IFM_AUTO, 0, 0);
2754 ifmedia_set(&sc->tulip_ifmedia, IFM_ETHER | IFM_AUTO);
2755 } else {
2756 ifmedia_set(&sc->tulip_ifmedia, tulip_media_to_ifmedia[sc->tulip_media]);
2757 sc->tulip_flags |= TULIP_PRINTMEDIA;
2758 tulip_linkup(sc, sc->tulip_media);
2759 }
2760}
2761
2762static int
2763tulip_ifmedia_change(
2764 struct ifnet * const ifp)
2765{
2766 tulip_softc_t * const sc = (tulip_softc_t *)ifp->if_softc;
2767
2768 sc->tulip_flags |= TULIP_NEEDRESET;
2769 sc->tulip_probe_state = TULIP_PROBE_INACTIVE;
2770 sc->tulip_media = TULIP_MEDIA_UNKNOWN;
2771 if (IFM_SUBTYPE(sc->tulip_ifmedia.ifm_media) != IFM_AUTO) {
2772 tulip_media_t media;
2773 for (media = TULIP_MEDIA_UNKNOWN; media < TULIP_MEDIA_MAX; media++) {
2774 if (sc->tulip_mediums[media] != NULL
2775 && sc->tulip_ifmedia.ifm_media == tulip_media_to_ifmedia[media]) {
2776 sc->tulip_flags |= TULIP_PRINTMEDIA;
2777 sc->tulip_flags &= ~TULIP_DIDNWAY;
2778 tulip_linkup(sc, media);
2779 return 0;
2780 }
2781 }
2782 }
2783 sc->tulip_flags &= ~(TULIP_TXPROBE_ACTIVE|TULIP_WANTRXACT);
2784 tulip_reset(sc);
2785 tulip_init(sc);
2786 return 0;
2787}
2788\f
2789/*
2790 * Media status callback
2791 */
2792static void
2793tulip_ifmedia_status(
2794 struct ifnet * const ifp,
2795 struct ifmediareq *req)
2796{
2797 tulip_softc_t *sc = (tulip_softc_t *)ifp->if_softc;
2798
2799 if (sc->tulip_media == TULIP_MEDIA_UNKNOWN)
2800 return;
2801
2802 req->ifm_status = IFM_AVALID;
2803 if (sc->tulip_flags & TULIP_LINKUP)
2804 req->ifm_status |= IFM_ACTIVE;
2805
2806 req->ifm_active = tulip_media_to_ifmedia[sc->tulip_media];
2807}
2808\f
2809static void
2810tulip_addr_filter(
2811 tulip_softc_t * const sc)
2812{
2813 struct ifmultiaddr *ifma;
2814 u_char *addrp;
2815 int multicnt;
2816
2817 sc->tulip_flags &= ~(TULIP_WANTHASHPERFECT|TULIP_WANTHASHONLY|TULIP_ALLMULTI);
2818 sc->tulip_flags |= TULIP_WANTSETUP|TULIP_WANTTXSTART;
2819 sc->tulip_cmdmode &= ~TULIP_CMD_RXRUN;
2820 sc->tulip_intrmask &= ~TULIP_STS_RXSTOPPED;
2821#if defined(IFF_ALLMULTI)
2822 if (sc->tulip_if.if_flags & IFF_ALLMULTI)
2823 sc->tulip_flags |= TULIP_ALLMULTI ;
2824#endif
2825
2826 multicnt = 0;
2827 for (ifma = sc->tulip_if.if_multiaddrs.lh_first; ifma != NULL;
2828 ifma = ifma->ifma_link.le_next) {
2829
2830 if (ifma->ifma_addr->sa_family == AF_LINK)
2831 multicnt++;
2832 }
2833
2834 sc->tulip_if.if_start = tulip_ifstart; /* so the setup packet gets queued */
2835 if (multicnt > 14) {
2836 u_int32_t *sp = sc->tulip_setupdata;
2837 unsigned hash;
2838 /*
2839 * Some early passes of the 21140 have broken implementations of
2840 * hash-perfect mode. When we get too many multicasts for perfect
2841 * filtering with these chips, we need to switch into hash-only
2842 * mode (this is better than all-multicast on network with lots
2843 * of multicast traffic).
2844 */
2845 if (sc->tulip_features & TULIP_HAVE_BROKEN_HASH)
2846 sc->tulip_flags |= TULIP_WANTHASHONLY;
2847 else
2848 sc->tulip_flags |= TULIP_WANTHASHPERFECT;
2849 /*
2850 * If we have more than 14 multicasts, we have
2851 * go into hash perfect mode (512 bit multicast
2852 * hash and one perfect hardware).
2853 */
2854 bzero(sc->tulip_setupdata, sizeof(sc->tulip_setupdata));
2855
2856 for (ifma = sc->tulip_if.if_multiaddrs.lh_first; ifma != NULL;
2857 ifma = ifma->ifma_link.le_next) {
2858
2859 if (ifma->ifma_addr->sa_family != AF_LINK)
2860 continue;
2861
2862 hash = tulip_mchash(LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
2863#if BYTE_ORDER == BIG_ENDIAN
2864 sp[hash >> 4] |= bswap32(1 << (hash & 0xF));
2865#else
2866 sp[hash >> 4] |= 1 << (hash & 0xF);
2867#endif
2868 }
2869 /*
2870 * No reason to use a hash if we are going to be
2871 * receiving every multicast.
2872 */
2873 if ((sc->tulip_flags & TULIP_ALLMULTI) == 0) {
c401f0fd 2874 hash = tulip_mchash(sc->tulip_if.if_broadcastaddr);
984263bc
MD
2875#if BYTE_ORDER == BIG_ENDIAN
2876 sp[hash >> 4] |= bswap32(1 << (hash & 0xF));
2877#else
2878 sp[hash >> 4] |= 1 << (hash & 0xF);
2879#endif
2880 if (sc->tulip_flags & TULIP_WANTHASHONLY) {
2881 hash = tulip_mchash(sc->tulip_enaddr);
2882#if BYTE_ORDER == BIG_ENDIAN
2883 sp[hash >> 4] |= bswap32(1 << (hash & 0xF));
2884#else
2885 sp[hash >> 4] |= 1 << (hash & 0xF);
2886#endif
2887 } else {
2888#if BYTE_ORDER == BIG_ENDIAN
2889 sp[39] = ((u_int16_t *) sc->tulip_enaddr)[0] << 16;
2890 sp[40] = ((u_int16_t *) sc->tulip_enaddr)[1] << 16;
2891 sp[41] = ((u_int16_t *) sc->tulip_enaddr)[2] << 16;
2892#else
2893 sp[39] = ((u_int16_t *) sc->tulip_enaddr)[0];
2894 sp[40] = ((u_int16_t *) sc->tulip_enaddr)[1];
2895 sp[41] = ((u_int16_t *) sc->tulip_enaddr)[2];
2896#endif
2897 }
2898 }
2899 }
2900 if ((sc->tulip_flags & (TULIP_WANTHASHPERFECT|TULIP_WANTHASHONLY)) == 0) {
2901 u_int32_t *sp = sc->tulip_setupdata;
2902 int idx = 0;
2903 if ((sc->tulip_flags & TULIP_ALLMULTI) == 0) {
2904 /*
2905 * Else can get perfect filtering for 16 addresses.
2906 */
2907 for (ifma = sc->tulip_if.if_multiaddrs.lh_first; ifma != NULL;
2908 ifma = ifma->ifma_link.le_next) {
2909 if (ifma->ifma_addr->sa_family != AF_LINK)
2910 continue;
2911 addrp = LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
2912#if BYTE_ORDER == BIG_ENDIAN
2913 *sp++ = ((u_int16_t *) addrp)[0] << 16;
2914 *sp++ = ((u_int16_t *) addrp)[1] << 16;
2915 *sp++ = ((u_int16_t *) addrp)[2] << 16;
2916#else
2917 *sp++ = ((u_int16_t *) addrp)[0];
2918 *sp++ = ((u_int16_t *) addrp)[1];
2919 *sp++ = ((u_int16_t *) addrp)[2];
2920#endif
2921 idx++;
2922 }
2923 /*
2924 * Add the broadcast address.
2925 */
2926 idx++;
2927#if BYTE_ORDER == BIG_ENDIAN
2928 *sp++ = 0xFFFF << 16;
2929 *sp++ = 0xFFFF << 16;
2930 *sp++ = 0xFFFF << 16;
2931#else
2932 *sp++ = 0xFFFF;
2933 *sp++ = 0xFFFF;
2934 *sp++ = 0xFFFF;
2935#endif
2936 }
2937 /*
2938 * Pad the rest with our hardware address
2939 */
2940 for (; idx < 16; idx++) {
2941#if BYTE_ORDER == BIG_ENDIAN
2942 *sp++ = ((u_int16_t *) sc->tulip_enaddr)[0] << 16;
2943 *sp++ = ((u_int16_t *) sc->tulip_enaddr)[1] << 16;
2944 *sp++ = ((u_int16_t *) sc->tulip_enaddr)[2] << 16;
2945#else
2946 *sp++ = ((u_int16_t *) sc->tulip_enaddr)[0];
2947 *sp++ = ((u_int16_t *) sc->tulip_enaddr)[1];
2948 *sp++ = ((u_int16_t *) sc->tulip_enaddr)[2];
2949#endif
2950 }
2951 }
2952#if defined(IFF_ALLMULTI)
2953 if (sc->tulip_flags & TULIP_ALLMULTI)
2954 sc->tulip_if.if_flags |= IFF_ALLMULTI;
2955#endif
2956}
2957\f
2958static void
2959tulip_reset(
2960 tulip_softc_t * const sc)
2961{
2962 tulip_ringinfo_t *ri;
2963 tulip_desc_t *di;
2964 u_int32_t inreset = (sc->tulip_flags & TULIP_INRESET);
2965
2966 /*
2967 * Brilliant. Simply brilliant. When switching modes/speeds
2968 * on a 2114*, you need to set the appriopriate MII/PCS/SCL/PS
2969 * bits in CSR6 and then do a software reset to get the 21140
2970 * to properly reset its internal pathways to the right places.
2971 * Grrrr.
2972 */
2973 if ((sc->tulip_flags & TULIP_DEVICEPROBE) == 0
2974 && sc->tulip_boardsw->bd_media_preset != NULL)
2975 (*sc->tulip_boardsw->bd_media_preset)(sc);
2976
2977 TULIP_CSR_WRITE(sc, csr_busmode, TULIP_BUSMODE_SWRESET);
2978 DELAY(10); /* Wait 10 microseconds (actually 50 PCI cycles but at
2979 33MHz that comes to two microseconds but wait a
2980 bit longer anyways) */
2981
2982 if (!inreset) {
2983 sc->tulip_flags |= TULIP_INRESET;
2984 sc->tulip_flags &= ~(TULIP_NEEDRESET|TULIP_RXBUFSLOW);
2985 sc->tulip_if.if_flags &= ~IFF_OACTIVE;
2986 sc->tulip_if.if_start = tulip_ifstart;
2987 }
2988
984263bc 2989 TULIP_CSR_WRITE(sc, csr_txlist, TULIP_KVATOPHYS(sc, &sc->tulip_txinfo.ri_first[0]));
984263bc 2990 TULIP_CSR_WRITE(sc, csr_rxlist, TULIP_KVATOPHYS(sc, &sc->tulip_rxinfo.ri_first[0]));
984263bc
MD
2991 TULIP_CSR_WRITE(sc, csr_busmode,
2992 (1 << (3 /*pci_max_burst_len*/ + 8))
2993 |TULIP_BUSMODE_CACHE_ALIGN8
2994 |TULIP_BUSMODE_READMULTIPLE
2995 |(BYTE_ORDER != LITTLE_ENDIAN ?
2996 TULIP_BUSMODE_DESC_BIGENDIAN : 0));
2997
2998 sc->tulip_txtimer = 0;
2999 sc->tulip_txq.ifq_maxlen = TULIP_TXDESCS;
3000 /*
3001 * Free all the mbufs that were on the transmit ring.
3002 */
3003 for (;;) {
984263bc
MD
3004 struct mbuf *m;
3005 IF_DEQUEUE(&sc->tulip_txq, m);
3006 if (m == NULL)
3007 break;
984263bc
MD
3008 m_freem(m);
3009 }
3010
3011 ri = &sc->tulip_txinfo;
3012 ri->ri_nextin = ri->ri_nextout = ri->ri_first;
3013 ri->ri_free = ri->ri_max;
3014 for (di = ri->ri_first; di < ri->ri_last; di++)
3015 di->d_status = 0;
984263bc
MD
3016
3017 /*
3018 * We need to collect all the mbufs were on the
3019 * receive ring before we reinit it either to put
3020 * them back on or to know if we have to allocate
3021 * more.
3022 */
3023 ri = &sc->tulip_rxinfo;
3024 ri->ri_nextin = ri->ri_nextout = ri->ri_first;
3025 ri->ri_free = ri->ri_max;
3026 for (di = ri->ri_first; di < ri->ri_last; di++) {
3027 di->d_status = 0;
3028 di->d_length1 = 0; di->d_addr1 = 0;
3029 di->d_length2 = 0; di->d_addr2 = 0;
3030 }
984263bc 3031 for (;;) {
984263bc
MD
3032 struct mbuf *m;
3033 IF_DEQUEUE(&sc->tulip_rxq, m);
3034 if (m == NULL)
3035 break;
984263bc
MD
3036 m_freem(m);
3037 }
3038
3039 /*
3040 * If tulip_reset is being called recurisvely, exit quickly knowing
3041 * that when the outer tulip_reset returns all the right stuff will
3042 * have happened.
3043 */
3044 if (inreset)
3045 return;
3046
3047 sc->tulip_intrmask |= TULIP_STS_NORMALINTR|TULIP_STS_RXINTR|TULIP_STS_TXINTR
3048 |TULIP_STS_ABNRMLINTR|TULIP_STS_SYSERROR|TULIP_STS_TXSTOPPED
3049 |TULIP_STS_TXUNDERFLOW|TULIP_STS_TXBABBLE
3050 |TULIP_STS_RXSTOPPED;
3051
3052 if ((sc->tulip_flags & TULIP_DEVICEPROBE) == 0)
3053 (*sc->tulip_boardsw->bd_media_select)(sc);
984263bc
MD
3054 tulip_media_print(sc);
3055 if (sc->tulip_features & TULIP_HAVE_DUALSENSE)
3056 TULIP_CSR_WRITE(sc, csr_sia_status, TULIP_CSR_READ(sc, csr_sia_status));
3057
3058 sc->tulip_flags &= ~(TULIP_DOINGSETUP|TULIP_WANTSETUP|TULIP_INRESET
3059 |TULIP_RXACT);
3060 tulip_addr_filter(sc);
3061}
3062\f
3063static void
3064tulip_init(
3065 tulip_softc_t * const sc)
3066{
3067 if (sc->tulip_if.if_flags & IFF_UP) {
3068 if ((sc->tulip_if.if_flags & IFF_RUNNING) == 0) {
3069 /* initialize the media */
3070 tulip_reset(sc);
3071 }
3072 sc->tulip_if.if_flags |= IFF_RUNNING;
3073 if (sc->tulip_if.if_flags & IFF_PROMISC) {
3074 sc->tulip_flags |= TULIP_PROMISC;
3075 sc->tulip_cmdmode |= TULIP_CMD_PROMISCUOUS;
3076 sc->tulip_intrmask |= TULIP_STS_TXINTR;
3077 } else {
3078 sc->tulip_flags &= ~TULIP_PROMISC;
3079 sc->tulip_cmdmode &= ~TULIP_CMD_PROMISCUOUS;
3080 if (sc->tulip_flags & TULIP_ALLMULTI) {
3081 sc->tulip_cmdmode |= TULIP_CMD_ALLMULTI;
3082 } else {
3083 sc->tulip_cmdmode &= ~TULIP_CMD_ALLMULTI;
3084 }
3085 }
3086 sc->tulip_cmdmode |= TULIP_CMD_TXRUN;
3087 if ((sc->tulip_flags & (TULIP_TXPROBE_ACTIVE|TULIP_WANTSETUP)) == 0) {
3088 tulip_rx_intr(sc);
3089 sc->tulip_cmdmode |= TULIP_CMD_RXRUN;
3090 sc->tulip_intrmask |= TULIP_STS_RXSTOPPED;
3091 } else {
3092 sc->tulip_if.if_flags |= IFF_OACTIVE;
3093 sc->tulip_cmdmode &= ~TULIP_CMD_RXRUN;
3094 sc->tulip_intrmask &= ~TULIP_STS_RXSTOPPED;
3095 }
3096 TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask);
3097 TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode);
3098 if ((sc->tulip_flags & (TULIP_WANTSETUP|TULIP_TXPROBE_ACTIVE)) == TULIP_WANTSETUP)
3099 tulip_txput_setup(sc);
3100 } else {
3101 sc->tulip_if.if_flags &= ~IFF_RUNNING;
3102 tulip_reset(sc);
3103 }
3104}
3105\f
3106static void
3107tulip_rx_intr(
3108 tulip_softc_t * const sc)
3109{
984263bc
MD
3110 tulip_ringinfo_t * const ri = &sc->tulip_rxinfo;
3111 struct ifnet * const ifp = &sc->tulip_if;
3112 int fillok = 1;
984263bc
MD
3113
3114 for (;;) {
984263bc
MD
3115 struct ether_header eh;
3116 tulip_desc_t *eop = ri->ri_nextin;
3117 int total_len = 0, last_offset = 0;
3118 struct mbuf *ms = NULL, *me = NULL;
3119 int accept = 0;
984263bc
MD
3120
3121 if (fillok && sc->tulip_rxq.ifq_len < TULIP_RXQ_TARGET)
3122 goto queue_mbuf;
3123
984263bc
MD
3124 /*
3125 * If the TULIP has no descriptors, there can't be any receive
3126 * descriptors to process.
3127 */
3128 if (eop == ri->ri_nextout)
3129 break;
3130
3131 /*
3132 * 90% of the packets will fit in one descriptor. So we optimize
3133 * for that case.
3134 */
3135 TULIP_RXDESC_POSTSYNC(sc, eop, sizeof(*eop));
3136 if ((((volatile tulip_desc_t *) eop)->d_status & (TULIP_DSTS_OWNER|TULIP_DSTS_RxFIRSTDESC|TULIP_DSTS_RxLASTDESC)) == (TULIP_DSTS_RxFIRSTDESC|TULIP_DSTS_RxLASTDESC)) {
3137 IF_DEQUEUE(&sc->tulip_rxq, ms);
3138 me = ms;
3139 } else {
3140 /*
3141 * If still owned by the TULIP, don't touch it.
3142 */
3143 if (((volatile tulip_desc_t *) eop)->d_status & TULIP_DSTS_OWNER)
3144 break;
3145
3146 /*
3147 * It is possible (though improbable unless the BIG_PACKET support
3148 * is enabled or MCLBYTES < 1518) for a received packet to cross
3149 * more than one receive descriptor.
3150 */
3151 while ((((volatile tulip_desc_t *) eop)->d_status & TULIP_DSTS_RxLASTDESC) == 0) {
3152 if (++eop == ri->ri_last)
3153 eop = ri->ri_first;
3154 TULIP_RXDESC_POSTSYNC(sc, eop, sizeof(*eop));
3155 if (eop == ri->ri_nextout || ((((volatile tulip_desc_t *) eop)->d_status & TULIP_DSTS_OWNER))) {
984263bc
MD
3156 return;
3157 }
3158 total_len++;
3159 }
3160
3161 /*
3162 * Dequeue the first buffer for the start of the packet. Hopefully
3163 * this will be the only one we need to dequeue. However, if the
3164 * packet consumed multiple descriptors, then we need to dequeue
3165 * those buffers and chain to the starting mbuf. All buffers but
3166 * the last buffer have the same length so we can set that now.
3167 * (we add to last_offset instead of multiplying since we normally
3168 * won't go into the loop and thereby saving a ourselves from
3169 * doing a multiplication by 0 in the normal case).
3170 */
3171 IF_DEQUEUE(&sc->tulip_rxq, ms);
3172 for (me = ms; total_len > 0; total_len--) {
984263bc
MD
3173 me->m_len = TULIP_RX_BUFLEN;
3174 last_offset += TULIP_RX_BUFLEN;
3175 IF_DEQUEUE(&sc->tulip_rxq, me->m_next);
3176 me = me->m_next;
3177 }
3178 }
3179
3180 /*
3181 * Now get the size of received packet (minus the CRC).
3182 */
3183 total_len = ((eop->d_status >> 16) & 0x7FFF) - 4;
3184 if ((sc->tulip_flags & TULIP_RXIGNORE) == 0
3185 && ((eop->d_status & TULIP_DSTS_ERRSUM) == 0
3186#ifdef BIG_PACKET
3187 || (total_len <= sc->tulip_if.if_mtu + sizeof(struct ether_header) &&
3188 (eop->d_status & (TULIP_DSTS_RxBADLENGTH|TULIP_DSTS_RxRUNT|
3189 TULIP_DSTS_RxCOLLSEEN|TULIP_DSTS_RxBADCRC|
3190 TULIP_DSTS_RxOVERFLOW)) == 0)
3191#endif
3192 )) {
3193 me->m_len = total_len - last_offset;
3194
984263bc 3195 eh = *mtod(ms, struct ether_header *);
984263bc
MD
3196 sc->tulip_flags |= TULIP_RXACT;
3197 accept = 1;
3198 } else {
3199 ifp->if_ierrors++;
3200 if (eop->d_status & (TULIP_DSTS_RxBADLENGTH|TULIP_DSTS_RxOVERFLOW|TULIP_DSTS_RxWATCHDOG)) {
3201 sc->tulip_dot3stats.dot3StatsInternalMacReceiveErrors++;
3202 } else {
984263bc
MD
3203 if (eop->d_status & TULIP_DSTS_RxTOOLONG) {
3204 sc->tulip_dot3stats.dot3StatsFrameTooLongs++;
984263bc
MD
3205 }
3206 if (eop->d_status & TULIP_DSTS_RxBADCRC) {
3207 if (eop->d_status & TULIP_DSTS_RxDRBBLBIT) {
3208 sc->tulip_dot3stats.dot3StatsAlignmentErrors++;
984263bc
MD
3209 } else {
3210 sc->tulip_dot3stats.dot3StatsFCSErrors++;
984263bc
MD
3211 }
3212 }
984263bc 3213 }
984263bc 3214 }
984263bc
MD
3215 ifp->if_ipackets++;
3216 if (++eop == ri->ri_last)
3217 eop = ri->ri_first;
3218 ri->ri_nextin = eop;
3219 queue_mbuf:
3220 /*
3221 * Either we are priming the TULIP with mbufs (m == NULL)
3222 * or we are about to accept an mbuf for the upper layers
3223 * so we need to allocate an mbuf to replace it. If we
3224 * can't replace it, send up it anyways. This may cause
3225 * us to drop packets in the future but that's better than
3226 * being caught in livelock.
3227 *
3228 * Note that if this packet crossed multiple descriptors
3229 * we don't even try to reallocate all the mbufs here.
3230 * Instead we rely on the test of the beginning of
3231 * the loop to refill for the extra consumed mbufs.
3232 */
3233 if (accept || ms == NULL) {
3234 struct mbuf *m0;
74f1caca 3235 MGETHDR(m0, MB_DONTWAIT, MT_DATA);
984263bc
MD
3236 if (m0 != NULL) {
3237#if defined(TULIP_COPY_RXDATA)
3238 if (!accept || total_len >= (MHLEN - 2)) {
3239#endif
74f1caca 3240 MCLGET(m0, MB_DONTWAIT);
984263bc
MD
3241 if ((m0->m_flags & M_EXT) == 0) {
3242 m_freem(m0);
3243 m0 = NULL;
3244 }
3245#if defined(TULIP_COPY_RXDATA)
3246 }
3247#endif
3248 }
3249 if (accept
3250#if defined(TULIP_COPY_RXDATA)
3251 && m0 != NULL
3252#endif
3253 ) {
3254#if !defined(TULIP_COPY_RXDATA)
3255 ms->m_pkthdr.len = total_len;
3256 ms->m_pkthdr.rcvif = ifp;
3257 m_adj(ms, sizeof(struct ether_header));
3258 ether_input(ifp, &eh, ms);
3259#else
3260#ifdef BIG_PACKET
3261#error BIG_PACKET is incompatible with TULIP_COPY_RXDATA
3262#endif
3263 m0->m_data += 2; /* align data after header */
3264 m_copydata(ms, 0, total_len, mtod(m0, caddr_t));
3265 m0->m_len = m0->m_pkthdr.len = total_len;
3266 m0->m_pkthdr.rcvif = ifp;
3267 m_adj(m0, sizeof(struct ether_header));
3268 ether_input(ifp, &eh, m0);
3269 m0 = ms;
3270#endif /* ! TULIP_COPY_RXDATA */
3271 }
3272 ms = m0;
3273 }
3274 if (ms == NULL) {
3275 /*
3276 * Couldn't allocate a new buffer. Don't bother
3277 * trying to replenish the receive queue.
3278 */
3279 fillok = 0;
3280 sc->tulip_flags |= TULIP_RXBUFSLOW;
984263bc
MD
3281 continue;
3282 }
3283 /*
3284 * Now give the buffer(s) to the TULIP and save in our
3285 * receive queue.
3286 */
3287 do {
3288 tulip_desc_t * const nextout = ri->ri_nextout;
984263bc
MD
3289 nextout->d_addr1 = TULIP_KVATOPHYS(sc, mtod(ms, caddr_t));
3290 nextout->d_length1 = TULIP_RX_BUFLEN;
984263bc
MD
3291 nextout->d_status = TULIP_DSTS_OWNER;
3292 TULIP_RXDESC_POSTSYNC(sc, nextout, sizeof(u_int32_t));
3293 if (++ri->ri_nextout == ri->ri_last)
3294 ri->ri_nextout = ri->ri_first;
3295 me = ms->m_next;
3296 ms->m_next = NULL;
3297 IF_ENQUEUE(&sc->tulip_rxq, ms);
3298 } while ((ms = me) != NULL);
3299
3300 if (sc->tulip_rxq.ifq_len >= TULIP_RXQ_TARGET)
3301 sc->tulip_flags &= ~TULIP_RXBUFSLOW;
984263bc 3302 }
984263bc
MD
3303}
3304\f
3305static int
3306tulip_tx_intr(
3307 tulip_softc_t * const sc)
3308{
984263bc
MD
3309 tulip_ringinfo_t * const ri = &sc->tulip_txinfo;
3310 struct mbuf *m;
3311 int xmits = 0;
3312 int descs = 0;
3313
3314 while (ri->ri_free < ri->ri_max) {
3315 u_int32_t d_flag;
3316
3317 TULIP_TXDESC_POSTSYNC(sc, ri->ri_nextin, sizeof(*ri->ri_nextin));
3318 if (((volatile tulip_desc_t *) ri->ri_nextin)->d_status & TULIP_DSTS_OWNER)
3319 break;
3320
3321 ri->ri_free++;
3322 descs++;
3323 d_flag = ri->ri_nextin->d_flag;
3324 if (d_flag & TULIP_DFLAG_TxLASTSEG) {
3325 if (d_flag & TULIP_DFLAG_TxSETUPPKT) {
3326 /*
3327 * We've just finished processing a setup packet.
3328 * Mark that we finished it. If there's not
3329 * another pending, startup the TULIP receiver.
3330 * Make sure we ack the RXSTOPPED so we won't get
3331 * an abormal interrupt indication.
3332 */
3333 TULIP_TXMAP_POSTSYNC(sc, sc->tulip_setupmap);
3334 sc->tulip_flags &= ~(TULIP_DOINGSETUP|TULIP_HASHONLY);
3335 if (ri->ri_nextin->d_flag & TULIP_DFLAG_TxINVRSFILT)
3336 sc->tulip_flags |= TULIP_HASHONLY;
3337 if ((sc->tulip_flags & (TULIP_WANTSETUP|TULIP_TXPROBE_ACTIVE)) == 0) {
3338 tulip_rx_intr(sc);
3339 sc->tulip_cmdmode |= TULIP_CMD_RXRUN;
3340 sc->tulip_intrmask |= TULIP_STS_RXSTOPPED;
3341 TULIP_CSR_WRITE(sc, csr_status, TULIP_STS_RXSTOPPED);
3342 TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask);
3343 TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode);
3344 }
3345 } else {
3346 const u_int32_t d_status = ri->ri_nextin->d_status;
3347 IF_DEQUEUE(&sc->tulip_txq, m);
3348 if (m != NULL) {
984263bc 3349 m_freem(m);
984263bc
MD
3350 }
3351 if (sc->tulip_flags & TULIP_TXPROBE_ACTIVE) {
3352 tulip_mediapoll_event_t event = TULIP_MEDIAPOLL_TXPROBE_OK;
3353 if (d_status & (TULIP_DSTS_TxNOCARR|TULIP_DSTS_TxEXCCOLL)) {
984263bc
MD
3354 event = TULIP_MEDIAPOLL_TXPROBE_FAILED;
3355 }
3356 (*sc->tulip_boardsw->bd_media_poll)(sc, event);
3357 /*
3358 * Escape from the loop before media poll has reset the TULIP!
3359 */
3360 break;
3361 } else {
3362 xmits++;
3363 if (d_status & TULIP_DSTS_ERRSUM) {
3364 sc->tulip_if.if_oerrors++;
3365 if (d_status & TULIP_DSTS_TxEXCCOLL)
3366 sc->tulip_dot3stats.dot3StatsExcessiveCollisions++;
3367 if (d_status & TULIP_DSTS_TxLATECOLL)
3368 sc->tulip_dot3stats.dot3StatsLateCollisions++;
3369 if (d_status & (TULIP_DSTS_TxNOCARR|TULIP_DSTS_TxCARRLOSS))
3370 sc->tulip_dot3stats.dot3StatsCarrierSenseErrors++;
3371 if (d_status & (TULIP_DSTS_TxUNDERFLOW|TULIP_DSTS_TxBABBLE))
3372 sc->tulip_dot3stats.dot3StatsInternalMacTransmitErrors++;
3373 if (d_status & TULIP_DSTS_TxUNDERFLOW)
3374 sc->tulip_dot3stats.dot3StatsInternalTransmitUnderflows++;
3375 if (d_status & TULIP_DSTS_TxBABBLE)
3376 sc->tulip_dot3stats.dot3StatsInternalTransmitBabbles++;
3377 } else {
3378 u_int32_t collisions =
3379 (d_status & TULIP_DSTS_TxCOLLMASK)
3380 >> TULIP_DSTS_V_TxCOLLCNT;
3381 sc->tulip_if.if_collisions += collisions;
3382 if (collisions == 1)
3383 sc->tulip_dot3stats.dot3StatsSingleCollisionFrames++;
3384 else if (collisions > 1)
3385 sc->tulip_dot3stats.dot3StatsMultipleCollisionFrames++;
3386 else if (d_status & TULIP_DSTS_TxDEFERRED)
3387 sc->tulip_dot3stats.dot3StatsDeferredTransmissions++;
3388 /*
3389 * SQE is only valid for 10baseT/BNC/AUI when not
3390 * running in full-duplex. In order to speed up the
3391 * test, the corresponding bit in tulip_flags needs to
3392 * set as well to get us to count SQE Test Errors.
3393 */
3394 if (d_status & TULIP_DSTS_TxNOHRTBT & sc->tulip_flags)
3395 sc->tulip_dot3stats.dot3StatsSQETestErrors++;
3396 }
3397 }
3398 }
3399 }
3400
3401 if (++ri->ri_nextin == ri->ri_last)
3402 ri->ri_nextin = ri->ri_first;
3403
3404 if ((sc->tulip_flags & TULIP_TXPROBE_ACTIVE) == 0)
3405 sc->tulip_if.if_flags &= ~IFF_OACTIVE;
3406 }
3407 /*
3408 * If nothing left to transmit, disable the timer.
3409 * Else if progress, reset the timer back to 2 ticks.
3410 */
3411 if (ri->ri_free == ri->ri_max || (sc->tulip_flags & TULIP_TXPROBE_ACTIVE))
3412 sc->tulip_txtimer = 0;
3413 else if (xmits > 0)
3414 sc->tulip_txtimer = TULIP_TXTIMER;
3415 sc->tulip_if.if_opackets += xmits;
984263bc
MD
3416 return descs;
3417}
3418\f
3419static void
3420tulip_print_abnormal_interrupt(
3421 tulip_softc_t * const sc,
3422 u_int32_t csr)
3423{
3424 const char * const *msgp = tulip_status_bits;
3425 const char *sep;
3426 u_int32_t mask;
3427 const char thrsh[] = "72|128\0\0\0" "96|256\0\0\0" "128|512\0\0" "160|1024";
3428
3429 csr &= (1 << (sizeof(tulip_status_bits)/sizeof(tulip_status_bits[0]))) - 1;
3430 printf("%s%d: abnormal interrupt:", sc->tulip_name, sc->tulip_unit);
3431 for (sep = " ", mask = 1; mask <= csr; mask <<= 1, msgp++) {
3432 if ((csr & mask) && *msgp != NULL) {
3433 printf("%s%s", sep, *msgp);
3434 if (mask == TULIP_STS_TXUNDERFLOW && (sc->tulip_flags & TULIP_NEWTXTHRESH)) {
3435 sc->tulip_flags &= ~TULIP_NEWTXTHRESH;
3436 if (sc->tulip_cmdmode & TULIP_CMD_STOREFWD) {
3437 printf(" (switching to store-and-forward mode)");
3438 } else {
3439 printf(" (raising TX threshold to %s)",
3440 &thrsh[9 * ((sc->tulip_cmdmode & TULIP_CMD_THRESHOLDCTL) >> 14)]);
3441 }
3442 }
3443 sep = ", ";
3444 }
3445 }
3446 printf("\n");
3447}
3448
3449static void
3450tulip_intr_handler(
3451 tulip_softc_t * const sc,
3452 int *progress_p)
3453{
984263bc
MD
3454 u_int32_t csr;
3455
3456 while ((csr = TULIP_CSR_READ(sc, csr_status)) & sc->tulip_intrmask) {
3457 *progress_p = 1;
3458 TULIP_CSR_WRITE(sc, csr_status, csr);
3459
3460 if (csr & TULIP_STS_SYSERROR) {
3461 sc->tulip_last_system_error = (csr & TULIP_STS_ERRORMASK) >> TULIP_STS_ERR_SHIFT;
3462 if (sc->tulip_flags & TULIP_NOMESSAGES) {
3463 sc->tulip_flags |= TULIP_SYSTEMERROR;
3464 } else {
3465 printf("%s%d: system error: %s\n",
3466 sc->tulip_name, sc->tulip_unit,
3467 tulip_system_errors[sc->tulip_last_system_error]);
3468 }
3469 sc->tulip_flags |= TULIP_NEEDRESET;
3470 sc->tulip_system_errors++;
3471 break;
3472 }
3473 if (csr & (TULIP_STS_LINKPASS|TULIP_STS_LINKFAIL) & sc->tulip_intrmask) {
984263bc
MD
3474 if (sc->tulip_boardsw->bd_media_poll != NULL) {
3475 (*sc->tulip_boardsw->bd_media_poll)(sc, csr & TULIP_STS_LINKFAIL
3476 ? TULIP_MEDIAPOLL_LINKFAIL
3477 : TULIP_MEDIAPOLL_LINKPASS);
3478 csr &= ~TULIP_STS_ABNRMLINTR;
3479 }
3480 tulip_media_print(sc);
3481 }
3482 if (csr & (TULIP_STS_RXINTR|TULIP_STS_RXNOBUF)) {
3483 u_int32_t misses = TULIP_CSR_READ(sc, csr_missed_frames);
3484 if (csr & TULIP_STS_RXNOBUF)
3485 sc->tulip_dot3stats.dot3StatsMissedFrames += misses & 0xFFFF;
3486 /*
3487 * Pass 2.[012] of the 21140A-A[CDE] may hang and/or corrupt data
3488 * on receive overflows.
3489 */
3490 if ((misses & 0x0FFE0000) && (sc->tulip_features & TULIP_HAVE_RXBADOVRFLW)) {
3491 sc->tulip_dot3stats.dot3StatsInternalMacReceiveErrors++;
3492 /*
3493 * Stop the receiver process and spin until it's stopped.
3494 * Tell rx_intr to drop the packets it dequeues.
3495 */
3496 TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode & ~TULIP_CMD_RXRUN);
3497 while ((TULIP_CSR_READ(sc, csr_status) & TULIP_STS_RXSTOPPED) == 0)
3498 ;
3499 TULIP_CSR_WRITE(sc, csr_status, TULIP_STS_RXSTOPPED);
3500 sc->tulip_flags |= TULIP_RXIGNORE;
3501 }
3502 tulip_rx_intr(sc);
3503 if (sc->tulip_flags & TULIP_RXIGNORE) {
3504 /*
3505 * Restart the receiver.
3506 */
3507 sc->tulip_flags &= ~TULIP_RXIGNORE;
3508 TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode);
3509 }
3510 }
3511 if (csr & TULIP_STS_ABNRMLINTR) {
3512 u_int32_t tmp = csr & sc->tulip_intrmask
3513 & ~(TULIP_STS_NORMALINTR|TULIP_STS_ABNRMLINTR);
3514 if (csr & TULIP_STS_TXUNDERFLOW) {
3515 if ((sc->tulip_cmdmode & TULIP_CMD_THRESHOLDCTL) != TULIP_CMD_THRSHLD160) {
3516 sc->tulip_cmdmode += TULIP_CMD_THRSHLD96;
3517 sc->tulip_flags |= TULIP_NEWTXTHRESH;
3518 } else if (sc->tulip_features & TULIP_HAVE_STOREFWD) {
3519 sc->tulip_cmdmode |= TULIP_CMD_STOREFWD;
3520 sc->tulip_flags |= TULIP_NEWTXTHRESH;
3521 }
3522 }
3523 if (sc->tulip_flags & TULIP_NOMESSAGES) {
3524 sc->tulip_statusbits |= tmp;
3525 } else {
3526 tulip_print_abnormal_interrupt(sc, tmp);
3527 sc->tulip_flags |= TULIP_NOMESSAGES;
3528 }
3529 TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode);
3530 }
3531 if (sc->tulip_flags & (TULIP_WANTTXSTART|TULIP_TXPROBE_ACTIVE|TULIP_DOINGSETUP|TULIP_PROMISC)) {
3532 tulip_tx_intr(sc);
3533 if ((sc->tulip_flags & TULIP_TXPROBE_ACTIVE) == 0)
3534 tulip_ifstart(&sc->tulip_if);
3535 }
3536 }
3537 if (sc->tulip_flags & TULIP_NEEDRESET) {
3538 tulip_reset(sc);
3539 tulip_init(sc);
3540 }
984263bc
MD
3541}
3542
984263bc
MD
3543static void
3544tulip_intr_shared(
3545 void *arg)
3546{
3547 tulip_softc_t * sc = arg;
3548 int progress = 0;
3549
3550 for (; sc != NULL; sc = sc->tulip_slaves) {
984263bc 3551 tulip_intr_handler(sc, &progress);
984263bc 3552 }
984263bc
MD
3553}
3554
3555static void
3556tulip_intr_normal(
3557 void *arg)
3558{
3559 tulip_softc_t * sc = (tulip_softc_t *) arg;
3560 int progress = 0;
3561
984263bc 3562 tulip_intr_handler(sc, &progress);
984263bc
MD
3563}
3564\f
3565static struct mbuf *
3566tulip_mbuf_compress(
3567 struct mbuf *m)
3568{
3569 struct mbuf *m0;
3570#if MCLBYTES >= ETHERMTU + 18 && !defined(BIG_PACKET)
74f1caca 3571 MGETHDR(m0, MB_DONTWAIT, MT_DATA);
984263bc
MD
3572 if (m0 != NULL) {
3573 if (m->m_pkthdr.len > MHLEN) {
74f1caca 3574 MCLGET(m0, MB_DONTWAIT);
984263bc
MD
3575 if ((m0->m_flags & M_EXT) == 0) {
3576 m_freem(m);
3577 m_freem(m0);
3578 return NULL;
3579 }
3580 }
3581 m_copydata(m, 0, m->m_pkthdr.len, mtod(m0, caddr_t));
3582 m0->m_pkthdr.len = m0->m_len = m->m_pkthdr.len;
3583 }
3584#else
3585 int mlen = MHLEN;
3586 int len = m->m_pkthdr.len;
3587 struct mbuf **mp = &m0;
3588
3589 while (len > 0) {
3590 if (mlen == MHLEN) {
74f1caca 3591 MGETHDR(*mp, MB_DONTWAIT, MT_DATA);
984263bc 3592 } else {
74f1caca 3593 MGET(*mp, MB_DONTWAIT, MT_DATA);
984263bc
MD
3594 }
3595 if (*mp == NULL) {
3596 m_freem(m0);
3597 m0 = NULL;
3598 break;
3599 }
3600 if (len > MLEN) {
74f1caca 3601 MCLGET(*mp, MB_DONTWAIT);
984263bc
MD
3602 if (((*mp)->m_flags & M_EXT) == 0) {
3603 m_freem(m0);
3604 m0 = NULL;
3605 break;
3606 }
3607 (*mp)->m_len = len <= MCLBYTES ? len : MCLBYTES;
3608 } else {
3609 (*mp)->m_len = len <= mlen ? len : mlen;
3610 }
3611 m_copydata(m, m->m_pkthdr.len - len,
3612 (*mp)->m_len, mtod((*mp), caddr_t));
3613 len -= (*mp)->m_len;
3614 mp = &(*mp)->m_next;
3615 mlen = MLEN;
3616 }
3617#endif
3618 m_freem(m);
3619 return m0;
3620}
3621\f
3622static struct mbuf *
3623tulip_txput(
3624 tulip_softc_t * const sc,
3625 struct mbuf *m)
3626{
984263bc
MD
3627 tulip_ringinfo_t * const ri = &sc->tulip_txinfo;
3628 tulip_desc_t *eop, *nextout;
3629 int segcnt, free;
3630 u_int32_t d_status;
984263bc 3631 struct mbuf *m0;
984263bc 3632
984263bc
MD
3633 /*
3634 * Now we try to fill in our transmit descriptors. This is
3635 * a bit reminiscent of going on the Ark two by two
3636 * since each descriptor for the TULIP can describe
3637 * two buffers. So we advance through packet filling
3638 * each of the two entries at a time to to fill each
3639 * descriptor. Clear the first and last segment bits
3640 * in each descriptor (actually just clear everything
3641 * but the end-of-ring or chain bits) to make sure
3642 * we don't get messed up by previously sent packets.
3643 *
3644 * We may fail to put the entire packet on the ring if
3645 * there is either not enough ring entries free or if the
3646 * packet has more than MAX_TXSEG segments. In the former
3647 * case we will just wait for the ring to empty. In the
3648 * latter case we have to recopy.
3649 */
984263bc
MD
3650 again:
3651 m0 = m;
984263bc
MD
3652 d_status = 0;
3653 eop = nextout = ri->ri_nextout;
3654 segcnt = 0;
3655 free = ri->ri_free;
3656
984263bc
MD
3657 do {
3658 int len = m0->m_len;
3659 caddr_t addr = mtod(m0, caddr_t);
3660 unsigned clsize = PAGE_SIZE - (((uintptr_t) addr) & (PAGE_SIZE-1));
3661
3662 while (len > 0) {
3663 unsigned slen = min(len, clsize);
3664#ifdef BIG_PACKET
3665 int partial = 0;
3666 if (slen >= 2048)
3667 slen = 2040, partial = 1;
3668#endif
3669 segcnt++;
3670 if (segcnt > TULIP_MAX_TXSEG) {
3671 /*
3672 * The packet exceeds the number of transmit buffer
3673 * entries that we can use for one packet, so we have
3674 * recopy it into one mbuf and then try again.
3675 */
3676 m = tulip_mbuf_compress(m);
3677 if (m == NULL)
3678 goto finish;
3679 goto again;
3680 }
3681 if (segcnt & 1) {
3682 if (--free == 0) {
3683 /*
3684 * See if there's any unclaimed space in the
3685 * transmit ring.
3686 */
3687 if ((free += tulip_tx_intr(sc)) == 0) {
3688 /*
3689 * There's no more room but since nothing
3690 * has been committed at this point, just
3691 * show output is active, put back the
3692 * mbuf and return.
3693 */
3694 sc->tulip_flags |= TULIP_WANTTXSTART;
984263bc
MD
3695 goto finish;
3696 }
3697 }
3698 eop = nextout;
3699 if (++nextout == ri->ri_last)
3700 nextout = ri->ri_first;
3701 eop->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN;
3702 eop->d_status = d_status;
3703 eop->d_addr1 = TULIP_KVATOPHYS(sc, addr);
3704 eop->d_length1 = slen;
3705 } else {
3706 /*
3707 * Fill in second half of descriptor
3708 */
3709 eop->d_addr2 = TULIP_KVATOPHYS(sc, addr);
3710 eop->d_length2 = slen;
3711 }
3712 d_status = TULIP_DSTS_OWNER;
3713 len -= slen;
3714 addr += slen;
3715#ifdef BIG_PACKET
3716 if (partial)
3717 continue;
3718#endif
3719 clsize = PAGE_SIZE;
3720 }
3721 } while ((m0 = m0->m_next) != NULL);
984263bc 3722
7600679e 3723 BPF_MTAP(&sc->tulip_if, m);
984263bc
MD
3724
3725 /*
3726 * The descriptors have been filled in. Now get ready
3727 * to transmit.
3728 */
3729 IF_ENQUEUE(&sc->tulip_txq, m);
3730 m = NULL;
3731
3732 /*
3733 * Make sure the next descriptor after this packet is owned
3734 * by us since it may have been set up above if we ran out
3735 * of room in the ring.
3736 */
3737 nextout->d_status = 0;
3738 TULIP_TXDESC_PRESYNC(sc, nextout, sizeof(u_int32_t));
3739
984263bc
MD
3740 /*
3741 * If we only used the first segment of the last descriptor,
3742 * make sure the second segment will not be used.
3743 */
3744 if (segcnt & 1) {
3745 eop->d_addr2 = 0;
3746 eop->d_length2 = 0;
3747 }
984263bc
MD
3748
3749 /*
3750 * Mark the last and first segments, indicate we want a transmit
3751 * complete interrupt, and tell it to transmit!
3752 */
3753 eop->d_flag |= TULIP_DFLAG_TxLASTSEG|TULIP_DFLAG_TxWANTINTR;
3754
3755 /*
3756 * Note that ri->ri_nextout is still the start of the packet
3757 * and until we set the OWNER bit, we can still back out of
3758 * everything we have done.
3759 */
3760 ri->ri_nextout->d_flag |= TULIP_DFLAG_TxFIRSTSEG;
984263bc
MD
3761 ri->ri_nextout->d_status = TULIP_DSTS_OWNER;
3762 TULIP_TXDESC_PRESYNC(sc, ri->ri_nextout, sizeof(u_int32_t));
3763
3764 /*
3765 * This advances the ring for us.
3766 */
3767 ri->ri_nextout = nextout;
3768 ri->ri_free = free;
3769
984263bc
MD
3770 if (sc->tulip_flags & TULIP_TXPROBE_ACTIVE) {
3771 TULIP_CSR_WRITE(sc, csr_txpoll, 1);
3772 sc->tulip_if.if_flags |= IFF_OACTIVE;
3773 sc->tulip_if.if_start = tulip_ifstart;
984263bc
MD
3774 return NULL;
3775 }
3776
3777 /*
3778 * switch back to the single queueing ifstart.
3779 */
3780 sc->tulip_flags &= ~TULIP_WANTTXSTART;
3781 if (sc->tulip_txtimer == 0)
3782 sc->tulip_txtimer = TULIP_TXTIMER;
984263bc
MD
3783
3784 /*
3785 * If we want a txstart, there must be not enough space in the
3786 * transmit ring. So we want to enable transmit done interrupts
3787 * so we can immediately reclaim some space. When the transmit
3788 * interrupt is posted, the interrupt handler will call tx_intr
3789 * to reclaim space and then txstart (since WANTTXSTART is set).
3790 * txstart will move the packet into the transmit ring and clear
3791 * WANTTXSTART thereby causing TXINTR to be cleared.
3792 */
3793 finish:
984263bc
MD
3794 if (sc->tulip_flags & (TULIP_WANTTXSTART|TULIP_DOINGSETUP)) {
3795 sc->tulip_if.if_flags |= IFF_OACTIVE;
3796 sc->tulip_if.if_start = tulip_ifstart;
3797 if ((sc->tulip_intrmask & TULIP_STS_TXINTR) == 0) {
3798 sc->tulip_intrmask |= TULIP_STS_TXINTR;
3799 TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask);
3800 }
3801 } else if ((sc->tulip_flags & TULIP_PROMISC) == 0) {
3802 if (sc->tulip_intrmask & TULIP_STS_TXINTR) {
3803 sc->tulip_intrmask &= ~TULIP_STS_TXINTR;
3804 TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask);
3805 }
3806 }
3807 TULIP_CSR_WRITE(sc, csr_txpoll, 1);
984263bc
MD
3808 return m;
3809}
3810\f
3811static void
3812tulip_txput_setup(
3813 tulip_softc_t * const sc)
3814{
3815 tulip_ringinfo_t * const ri = &sc->tulip_txinfo;
3816 tulip_desc_t *nextout;
3817
3818 /*
3819 * We will transmit, at most, one setup packet per call to ifstart.
3820 */
3821
984263bc
MD
3822 /*
3823 * Try to reclaim some free descriptors..
3824 */
3825 if (ri->ri_free < 2)
3826 tulip_tx_intr(sc);
3827 if ((sc->tulip_flags & TULIP_DOINGSETUP) || ri->ri_free == 1) {
3828 sc->tulip_flags |= TULIP_WANTTXSTART;
3829 sc->tulip_if.if_start = tulip_ifstart;
3830 return;
3831 }
3832 bcopy(sc->tulip_setupdata, sc->tulip_setupbuf,
3833 sizeof(sc->tulip_setupbuf));
3834 /*
3835 * Clear WANTSETUP and set DOINGSETUP. Set know that WANTSETUP is
3836 * set and DOINGSETUP is clear doing an XOR of the two will DTRT.
3837 */
3838 sc->tulip_flags ^= TULIP_WANTSETUP|TULIP_DOINGSETUP;
3839 ri->ri_free--;
3840 nextout = ri->ri_nextout;
3841 nextout->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN;
3842 nextout->d_flag |= TULIP_DFLAG_TxFIRSTSEG|TULIP_DFLAG_TxLASTSEG
3843 |TULIP_DFLAG_TxSETUPPKT|TULIP_DFLAG_TxWANTINTR;
3844 if (sc->tulip_flags & TULIP_WANTHASHPERFECT)
3845 nextout->d_flag |= TULIP_DFLAG_TxHASHFILT;
3846 else if (sc->tulip_flags & TULIP_WANTHASHONLY)
3847 nextout->d_flag |= TULIP_DFLAG_TxHASHFILT|TULIP_DFLAG_TxINVRSFILT;
3848
3849 nextout->d_length2 = 0;
3850 nextout->d_addr2 = 0;
984263bc
MD
3851 nextout->d_length1 = sizeof(sc->tulip_setupbuf);
3852 nextout->d_addr1 = TULIP_KVATOPHYS(sc, sc->tulip_setupbuf);
984263bc
MD
3853
3854 /*
3855 * Advance the ring for the next transmit packet.
3856 */
3857 if (++ri->ri_nextout == ri->ri_last)
3858 ri->ri_nextout = ri->ri_first;
3859
3860 /*
3861 * Make sure the next descriptor is owned by us since it
3862 * may have been set up above if we ran out of room in the
3863 * ring.
3864 */
3865 ri->ri_nextout->d_status = 0;
3866 TULIP_TXDESC_PRESYNC(sc, ri->ri_nextout, sizeof(u_int32_t));
3867 nextout->d_status = TULIP_DSTS_OWNER;
3868 /*
3869 * Flush the ownwership of the current descriptor
3870 */
3871 TULIP_TXDESC_PRESYNC(sc, nextout, sizeof(u_int32_t));
3872 TULIP_CSR_WRITE(sc, csr_txpoll, 1);
3873 if ((sc->tulip_intrmask & TULIP_STS_TXINTR) == 0) {
3874 sc->tulip_intrmask |= TULIP_STS_TXINTR;
3875 TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask);
3876 }
3877}
3878
3879\f
984263bc
MD
3880static int
3881tulip_ifioctl(
3882 struct ifnet * ifp,
3883 u_long cmd,
bd4539cc
JH
3884 caddr_t data,
3885 struct ucred * cr)
984263bc 3886{