Annotation of sys/dev/pci/if_de.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_de.c,v 1.97 2007/02/14 00:53:48 jsg Exp $ */
2: /* $NetBSD: if_de.c,v 1.58 1998/01/12 09:39:58 thorpej Exp $ */
3:
4: /*-
5: * Copyright (c) 1994-1997 Matt Thomas (matt@3am-software.com)
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. The name of the author may not be used to endorse or promote products
14: * derived from this software without specific prior written permission
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26: *
27: * Id: if_de.c,v 1.89 1997/06/03 19:19:55 thomas Exp
28: *
29: */
30:
31: /*
32: * DEC 21040 PCI Ethernet Controller
33: *
34: * Written by Matt Thomas
35: * BPF support code stolen directly from if_ec.c
36: *
37: * This driver supports the DEC DE435 or any other PCI
38: * board which support 21040, 21041, or 21140 (mostly).
39: */
40:
41: #include <sys/param.h>
42: #include <sys/systm.h>
43: #include <sys/mbuf.h>
44: #include <sys/protosw.h>
45: #include <sys/socket.h>
46: #include <sys/ioctl.h>
47: #include <sys/errno.h>
48: #include <sys/malloc.h>
49: #include <sys/kernel.h>
50: #include <sys/proc.h> /* only for declaration of wakeup() used by vm.h */
51: #include <sys/device.h>
52: #include <sys/timeout.h>
53:
54: #include <net/if.h>
55: #include <net/if_media.h>
56: #include <net/if_types.h>
57: #include <net/if_dl.h>
58: #include <net/route.h>
59: #include <net/netisr.h>
60:
61: #include "bpfilter.h"
62: #if NBPFILTER > 0
63: #include <net/bpf.h>
64: #endif
65:
66: #ifdef INET
67: #include <netinet/in.h>
68: #include <netinet/in_systm.h>
69: #include <netinet/in_var.h>
70: #include <netinet/ip.h>
71: #endif
72:
73: #include <netinet/if_ether.h>
74:
75: #include <machine/bus.h>
76: #include <machine/intr.h>
77: #include <dev/pci/pcireg.h>
78: #include <dev/pci/pcivar.h>
79: #include <dev/pci/pcidevs.h>
80: #include <dev/ic/dc21040reg.h>
81:
82: /*
83: * Intel CPUs should use I/O mapped access.
84: */
85: #if defined(__i386__)
86: #define TULIP_IOMAPPED
87: #endif
88:
89: #define TULIP_HZ 10
90:
91: #define TULIP_SIAGEN_WATCHDOG 0
92:
93: #define TULIP_GPR_CMDBITS (TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER|TULIP_CMD_TXTHRSHLDCTL)
94:
95: #define EMIT do { TULIP_CSR_WRITE(sc, csr_srom_mii, csr); tulip_delay_300ns(sc); } while (0)
96: #define MII_EMIT do { TULIP_CSR_WRITE(sc, csr_srom_mii, csr); tulip_delay_300ns(sc); } while (0)
97:
98: #define tulip_mchash(mca) (ether_crc32_le(mca, 6) & 0x1FF)
99: #define tulip_srom_crcok(databuf) ( \
100: ((ether_crc32_le(databuf, 126) & 0xFFFFU) ^ 0xFFFFU) == \
101: ((databuf)[126] | ((databuf)[127] << 8)))
102:
103: /*
104: * This is the PCI configuration support. Since the 21040 is available
105: * on both EISA and PCI boards, one must be careful in how defines the
106: * 21040 in the config file.
107: */
108:
109: #define PCI_CFID 0x00 /* Configuration ID */
110: #define PCI_CFCS 0x04 /* Configurtion Command/Status */
111: #define PCI_CFRV 0x08 /* Configuration Revision */
112: #define PCI_CFLT 0x0c /* Configuration Latency Timer */
113: #define PCI_CBIO 0x10 /* Configuration Base IO Address */
114: #define PCI_CBMA 0x14 /* Configuration Base Memory Address */
115: #define PCI_CFIT 0x3c /* Configuration Interrupt */
116: #define PCI_CFDA 0x40 /* Configuration Driver Area */
117:
118: #define PCI_CONF_WRITE(r, v) pci_conf_write(pa->pa_pc, pa->pa_tag, (r), (v))
119: #define PCI_CONF_READ(r) pci_conf_read(pa->pa_pc, pa->pa_tag, (r))
120: #define PCI_GETBUSDEVINFO(sc) do { \
121: (sc)->tulip_pci_busno = parent; \
122: (sc)->tulip_pci_devno = pa->pa_device; \
123: } while (0)
124:
125: #include <dev/pci/if_devar.h>
126: /*
127: * This module supports
128: * the DEC 21040 PCI Ethernet Controller.
129: * the DEC 21041 PCI Ethernet Controller.
130: * the DEC 21140 PCI Fast Ethernet Controller.
131: */
132: int tulip_probe(struct device *parent, void *match, void *aux);
133: void tulip_attach(struct device * const parent, struct device * const self, void * const aux);
134:
135: struct cfattach de_ca = {
136: sizeof(tulip_softc_t), tulip_probe, tulip_attach
137: };
138:
139: struct cfdriver de_cd = {
140: 0, "de", DV_IFNET
141: };
142:
143: void tulip_timeout_callback(void *arg);
144: void tulip_timeout(tulip_softc_t * const sc);
145: int tulip_txprobe(tulip_softc_t * const sc);
146: void tulip_media_set(tulip_softc_t * const sc, tulip_media_t media);
147: void tulip_linkup(tulip_softc_t * const sc, tulip_media_t media);
148: void tulip_media_print(tulip_softc_t * const sc);
149: tulip_link_status_t tulip_media_link_monitor(tulip_softc_t * const sc);
150: void tulip_media_poll(tulip_softc_t * const sc, tulip_mediapoll_event_t event);
151: void tulip_media_select(tulip_softc_t * const sc);
152:
153: void tulip_21040_mediainfo_init(tulip_softc_t * const sc, tulip_media_t media);
154: void tulip_21040_media_probe(tulip_softc_t * const sc);
155: void tulip_21040_10baset_only_media_probe(tulip_softc_t * const sc);
156: void tulip_21040_10baset_only_media_select(tulip_softc_t * const sc);
157: void tulip_21040_auibnc_only_media_probe(tulip_softc_t * const sc);
158: void tulip_21040_auibnc_only_media_select(tulip_softc_t * const sc);
159:
160: void tulip_21041_mediainfo_init(tulip_softc_t * const sc);
161: void tulip_21041_media_noprobe(tulip_softc_t * const sc);
162: void tulip_21041_media_probe(tulip_softc_t * const sc);
163: void tulip_21041_media_poll(tulip_softc_t * const sc, const tulip_mediapoll_event_t event);
164:
165: tulip_media_t tulip_mii_phy_readspecific(tulip_softc_t * const sc);
166: unsigned tulip_mii_get_phyaddr(tulip_softc_t * const sc, unsigned offset);
167: int tulip_mii_map_abilities(tulip_softc_t * const sc, unsigned abilities);
168: void tulip_mii_autonegotiate(tulip_softc_t * const sc, const unsigned phyaddr);
169:
170: void tulip_2114x_media_preset(tulip_softc_t * const sc);
171:
172: void tulip_null_media_poll(tulip_softc_t * const sc, tulip_mediapoll_event_t event);
173:
174: void tulip_21140_mediainit(tulip_softc_t * const sc, tulip_media_info_t * const mip,
175: tulip_media_t const media, unsigned gpdata, unsigned cmdmode);
176: void tulip_21140_evalboard_media_probe(tulip_softc_t * const sc);
177: void tulip_21140_accton_media_probe(tulip_softc_t * const sc);
178: void tulip_21140_smc9332_media_probe(tulip_softc_t * const sc);
179: void tulip_21140_cogent_em100_media_probe(tulip_softc_t * const sc);
180: void tulip_21140_znyx_zx34x_media_probe(tulip_softc_t * const sc);
181:
182: void tulip_2114x_media_probe(tulip_softc_t * const sc);
183:
184: void tulip_delay_300ns(tulip_softc_t * const sc);
185: void tulip_srom_idle(tulip_softc_t * const sc);
186: void tulip_srom_read(tulip_softc_t * const sc);
187: void tulip_mii_writebits(tulip_softc_t * const sc, unsigned data, unsigned bits);
188: void tulip_mii_turnaround(tulip_softc_t * const sc, unsigned cmd);
189: unsigned tulip_mii_readbits(tulip_softc_t * const sc);
190: unsigned tulip_mii_readreg(tulip_softc_t * const sc, unsigned devaddr, unsigned regno);
191: void tulip_mii_writereg(tulip_softc_t * const sc, unsigned devaddr, unsigned regno,
192: unsigned data);
193:
194: void tulip_identify_dec_nic(tulip_softc_t * const sc);
195: void tulip_identify_znyx_nic(tulip_softc_t * const sc);
196: void tulip_identify_smc_nic(tulip_softc_t * const sc);
197: void tulip_identify_cogent_nic(tulip_softc_t * const sc);
198: void tulip_identify_accton_nic(tulip_softc_t * const sc);
199: void tulip_identify_asante_nic(tulip_softc_t * const sc);
200: void tulip_identify_compex_nic(tulip_softc_t * const sc);
201:
202: int tulip_srom_decode(tulip_softc_t * const sc);
203: int tulip_read_macaddr(tulip_softc_t * const sc);
204: void tulip_ifmedia_add(tulip_softc_t * const sc);
205: int tulip_ifmedia_change(struct ifnet * const ifp);
206: void tulip_ifmedia_status(struct ifnet * const ifp, struct ifmediareq *req);
207: void tulip_addr_filter(tulip_softc_t * const sc);
208: void tulip_reset(tulip_softc_t * const sc);
209: void tulip_init(tulip_softc_t * const sc);
210: void tulip_rx_intr(tulip_softc_t * const sc);
211: int tulip_tx_intr(tulip_softc_t * const sc);
212: void tulip_print_abnormal_interrupt(tulip_softc_t * const sc, u_int32_t csr);
213: void tulip_intr_handler(tulip_softc_t * const sc, int *progress_p);
214: int tulip_intr_shared(void *arg);
215: int tulip_intr_normal(void *arg);
216: struct mbuf *tulip_mbuf_compress(struct mbuf *m);
217: struct mbuf *tulip_txput(tulip_softc_t * const sc, struct mbuf *m);
218: void tulip_txput_setup(tulip_softc_t * const sc);
219: int tulip_ifioctl(struct ifnet * ifp, u_long cmd, caddr_t data);
220: void tulip_ifstart(struct ifnet *ifp);
221: void tulip_ifstart_one(struct ifnet *ifp);
222: void tulip_ifwatchdog(struct ifnet *ifp);
223: int tulip_busdma_allocmem(tulip_softc_t * const sc, size_t size,
224: bus_dmamap_t *map_p, tulip_desc_t **desc_p);
225: int tulip_busdma_init(tulip_softc_t * const sc);
226: void tulip_initcsrs(tulip_softc_t * const sc, bus_addr_t csr_base, size_t csr_size);
227: void tulip_initring(tulip_softc_t * const sc, tulip_ringinfo_t * const ri,
228: tulip_desc_t *descs, int ndescs);
229: void tulip_shutdown(void *arg);
230:
231:
232: void
233: tulip_timeout_callback(void *arg)
234: {
235: tulip_softc_t * const sc = arg;
236: int s;
237:
238: s = splnet();
239:
240: TULIP_PERFSTART(timeout)
241:
242: sc->tulip_flags &= ~TULIP_TIMEOUTPENDING;
243: sc->tulip_probe_timeout -= 1000 / TULIP_HZ;
244: (sc->tulip_boardsw->bd_media_poll)(sc, TULIP_MEDIAPOLL_TIMER);
245:
246: TULIP_PERFEND(timeout);
247: splx(s);
248: }
249:
250: void
251: tulip_timeout(tulip_softc_t * const sc)
252: {
253: if (sc->tulip_flags & TULIP_TIMEOUTPENDING)
254: return;
255: sc->tulip_flags |= TULIP_TIMEOUTPENDING;
256: timeout_add(&sc->tulip_stmo, (hz + TULIP_HZ / 2) / TULIP_HZ);
257: }
258:
259: int
260: tulip_txprobe(tulip_softc_t * const sc)
261: {
262: struct mbuf *m;
263:
264: /*
265: * Before we are sure this is the right media we need
266: * to send a small packet to make sure there's carrier.
267: * Strangely, BNC and AUI will "see" receive data if
268: * either is connected so the transmit is the only way
269: * to verify the connectivity.
270: */
271: MGETHDR(m, M_DONTWAIT, MT_DATA);
272: if (m == NULL)
273: return (0);
274: /*
275: * Construct a LLC TEST message which will point to ourselves.
276: */
277: bcopy(sc->tulip_enaddr, mtod(m, struct ether_header *)->ether_dhost,
278: ETHER_ADDR_LEN);
279: bcopy(sc->tulip_enaddr, mtod(m, struct ether_header *)->ether_shost,
280: ETHER_ADDR_LEN);
281: mtod(m, struct ether_header *)->ether_type = htons(3);
282: mtod(m, unsigned char *)[14] = 0;
283: mtod(m, unsigned char *)[15] = 0;
284: mtod(m, unsigned char *)[16] = 0xE3; /* LLC Class1 TEST (no poll) */
285: m->m_len = m->m_pkthdr.len = sizeof(struct ether_header) + 3;
286: /*
287: * send it!
288: */
289: sc->tulip_cmdmode |= TULIP_CMD_TXRUN;
290: sc->tulip_intrmask |= TULIP_STS_TXINTR;
291: sc->tulip_flags |= TULIP_TXPROBE_ACTIVE;
292: TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode);
293: TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask);
294: if ((m = tulip_txput(sc, m)) != NULL)
295: m_freem(m);
296: sc->tulip_probe.probe_txprobes++;
297: return (1);
298: }
299:
300: void
301: tulip_media_set(tulip_softc_t * const sc, tulip_media_t media)
302: {
303: const tulip_media_info_t *mi = sc->tulip_mediums[media];
304:
305: if (mi == NULL)
306: return;
307:
308: /* Reset the SIA first
309: */
310: if (mi->mi_type == TULIP_MEDIAINFO_SIA || (sc->tulip_features & TULIP_HAVE_SIANWAY))
311: TULIP_CSR_WRITE(sc, csr_sia_connectivity, TULIP_SIACONN_RESET);
312:
313: /* Next, set full duplex if needed.
314: */
315: if (sc->tulip_flags & TULIP_FULLDUPLEX) {
316: #ifdef TULIP_DEBUG
317: if (TULIP_CSR_READ(sc, csr_command) & (TULIP_CMD_RXRUN|TULIP_CMD_TXRUN))
318: printf(TULIP_PRINTF_FMT ": warning: board is running (FD).\n", TULIP_PRINTF_ARGS);
319: if ((TULIP_CSR_READ(sc, csr_command) & TULIP_CMD_FULLDUPLEX) == 0)
320: printf(TULIP_PRINTF_FMT ": setting full duplex.\n", TULIP_PRINTF_ARGS);
321: TULIP_PRINTF_ARGS);
322: #endif
323: sc->tulip_cmdmode |= TULIP_CMD_FULLDUPLEX;
324: TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode & ~(TULIP_CMD_RXRUN|TULIP_CMD_TXRUN));
325: }
326:
327: /* Now setup the media.
328: *
329: * If we are switching media, make sure we don't think there's
330: * any stale RX activity
331: */
332: sc->tulip_flags &= ~TULIP_RXACT;
333: if (mi->mi_type == TULIP_MEDIAINFO_SIA) {
334: TULIP_CSR_WRITE(sc, csr_sia_tx_rx, mi->mi_sia_tx_rx);
335: if (sc->tulip_features & TULIP_HAVE_SIAGP) {
336: TULIP_CSR_WRITE(sc, csr_sia_general, mi->mi_sia_gp_control|mi->mi_sia_general|TULIP_SIAGEN_WATCHDOG);
337: DELAY(50);
338: TULIP_CSR_WRITE(sc, csr_sia_general, mi->mi_sia_gp_data|mi->mi_sia_general|TULIP_SIAGEN_WATCHDOG);
339: } else
340: TULIP_CSR_WRITE(sc, csr_sia_general, mi->mi_sia_general|TULIP_SIAGEN_WATCHDOG);
341: TULIP_CSR_WRITE(sc, csr_sia_connectivity, mi->mi_sia_connectivity);
342: } else if (mi->mi_type == TULIP_MEDIAINFO_GPR) {
343: /*
344: * If the cmdmode bits don't match the currently operating mode,
345: * set the cmdmode appropriately and reset the chip.
346: */
347: if (((mi->mi_cmdmode ^ TULIP_CSR_READ(sc, csr_command)) & TULIP_GPR_CMDBITS) != 0) {
348: sc->tulip_cmdmode &= ~TULIP_GPR_CMDBITS;
349: sc->tulip_cmdmode |= mi->mi_cmdmode;
350: tulip_reset(sc);
351: }
352: TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_PINSET|sc->tulip_gpinit);
353: DELAY(10);
354: TULIP_CSR_WRITE(sc, csr_gp, (u_int8_t) mi->mi_gpdata);
355: } else if (mi->mi_type == TULIP_MEDIAINFO_SYM) {
356: /*
357: * If the cmdmode bits don't match the currently operating mode,
358: * set the cmdmode appropriately and reset the chip.
359: */
360: if (((mi->mi_cmdmode ^ TULIP_CSR_READ(sc, csr_command)) & TULIP_GPR_CMDBITS) != 0) {
361: sc->tulip_cmdmode &= ~TULIP_GPR_CMDBITS;
362: sc->tulip_cmdmode |= mi->mi_cmdmode;
363: tulip_reset(sc);
364: }
365: TULIP_CSR_WRITE(sc, csr_sia_general, mi->mi_gpcontrol);
366: TULIP_CSR_WRITE(sc, csr_sia_general, mi->mi_gpdata);
367: } else if (mi->mi_type == TULIP_MEDIAINFO_MII
368: && sc->tulip_probe_state != TULIP_PROBE_INACTIVE) {
369: int idx;
370: if (sc->tulip_features & TULIP_HAVE_SIAGP) {
371: const u_int8_t *dp;
372: dp = &sc->tulip_rombuf[mi->mi_reset_offset];
373: for (idx = 0; idx < mi->mi_reset_length; idx++, dp += 2) {
374: DELAY(10);
375: TULIP_CSR_WRITE(sc, csr_sia_general, (dp[0] + 256 * dp[1]) << 16);
376: }
377: sc->tulip_phyaddr = mi->mi_phyaddr;
378: dp = &sc->tulip_rombuf[mi->mi_gpr_offset];
379: for (idx = 0; idx < mi->mi_gpr_length; idx++, dp += 2) {
380: DELAY(10);
381: TULIP_CSR_WRITE(sc, csr_sia_general, (dp[0] + 256 * dp[1]) << 16);
382: }
383: } else {
384: for (idx = 0; idx < mi->mi_reset_length; idx++) {
385: DELAY(10);
386: TULIP_CSR_WRITE(sc, csr_gp, sc->tulip_rombuf[mi->mi_reset_offset + idx]);
387: }
388: sc->tulip_phyaddr = mi->mi_phyaddr;
389: for (idx = 0; idx < mi->mi_gpr_length; idx++) {
390: DELAY(10);
391: TULIP_CSR_WRITE(sc, csr_gp, sc->tulip_rombuf[mi->mi_gpr_offset + idx]);
392: }
393: }
394:
395: if (sc->tulip_features & TULIP_HAVE_SIANWAY) {
396: /* Set the SIA port into MII mode */
397: TULIP_CSR_WRITE(sc, csr_sia_general, 1);
398: TULIP_CSR_WRITE(sc, csr_sia_tx_rx, 0);
399: TULIP_CSR_WRITE(sc, csr_sia_status, 0);
400: }
401:
402: if (sc->tulip_flags & TULIP_TRYNWAY)
403: tulip_mii_autonegotiate(sc, sc->tulip_phyaddr);
404: else if ((sc->tulip_flags & TULIP_DIDNWAY) == 0) {
405: u_int32_t data = tulip_mii_readreg(sc, sc->tulip_phyaddr, PHYREG_CONTROL);
406: data &= ~(PHYCTL_SELECT_100MB|PHYCTL_FULL_DUPLEX|PHYCTL_AUTONEG_ENABLE);
407: sc->tulip_flags &= ~TULIP_DIDNWAY;
408: if (TULIP_IS_MEDIA_FD(media))
409: data |= PHYCTL_FULL_DUPLEX;
410: if (TULIP_IS_MEDIA_100MB(media))
411: data |= PHYCTL_SELECT_100MB;
412: tulip_mii_writereg(sc, sc->tulip_phyaddr, PHYREG_CONTROL, data);
413: }
414: }
415: }
416:
417: void
418: tulip_linkup(tulip_softc_t * const sc, tulip_media_t media)
419: {
420: if ((sc->tulip_flags & TULIP_LINKUP) == 0)
421: sc->tulip_flags |= TULIP_PRINTLINKUP;
422: sc->tulip_flags |= TULIP_LINKUP;
423: sc->tulip_if.if_flags &= ~IFF_OACTIVE;
424: if (sc->tulip_media != media) {
425: #ifdef TULIP_DEBUG
426: sc->tulip_dbg.dbg_last_media = sc->tulip_media;
427: #endif
428: sc->tulip_media = media;
429: sc->tulip_flags |= TULIP_PRINTMEDIA;
430: if (TULIP_IS_MEDIA_FD(sc->tulip_media))
431: sc->tulip_flags |= TULIP_FULLDUPLEX;
432: else if (sc->tulip_chipid != TULIP_21041 || (sc->tulip_flags & TULIP_DIDNWAY) == 0)
433: sc->tulip_flags &= ~TULIP_FULLDUPLEX;
434: }
435: /*
436: * We could set probe_timeout to 0 but setting to 3000 puts this
437: * in one central place and the only matters is tulip_link is
438: * followed by a tulip_timeout. Therefore setting it should not
439: * result in aberrant behavour.
440: */
441: sc->tulip_probe_timeout = 3000;
442: sc->tulip_probe_state = TULIP_PROBE_INACTIVE;
443: sc->tulip_flags &= ~(TULIP_TXPROBE_ACTIVE|TULIP_TRYNWAY);
444: if (sc->tulip_flags & TULIP_INRESET)
445: tulip_media_set(sc, sc->tulip_media);
446: else if (sc->tulip_probe_media != sc->tulip_media) {
447: /*
448: * No reason to change media if we have the right media.
449: */
450: tulip_reset(sc);
451: }
452: tulip_init(sc);
453: }
454:
455: void
456: tulip_media_print(tulip_softc_t * const sc)
457: {
458: if ((sc->tulip_flags & TULIP_LINKUP) == 0)
459: return;
460: if (sc->tulip_flags & TULIP_PRINTMEDIA) {
461: #ifdef TULIP_DEBUG
462: printf(TULIP_PRINTF_FMT ": enabling %s port\n",
463: TULIP_PRINTF_ARGS,
464: tulip_mediums[sc->tulip_media]);
465: #endif
466: sc->tulip_flags &= ~(TULIP_PRINTMEDIA|TULIP_PRINTLINKUP);
467: } else if (sc->tulip_flags & TULIP_PRINTLINKUP) {
468: #ifdef TULIP_DEBUG
469: printf(TULIP_PRINTF_FMT ": link up\n", TULIP_PRINTF_ARGS);
470: #endif
471: sc->tulip_flags &= ~TULIP_PRINTLINKUP;
472: }
473: }
474:
475: tulip_link_status_t
476: tulip_media_link_monitor(tulip_softc_t * const sc)
477: {
478: const tulip_media_info_t * const mi = sc->tulip_mediums[sc->tulip_media];
479: tulip_link_status_t linkup = TULIP_LINK_DOWN;
480:
481: if (mi == NULL) {
482: #if defined(TULIP_DEBUG)
483: printf("tulip_media_link_monitor: %s: botch at line %d\n",
484: tulip_mediums[sc->tulip_media],__LINE__);
485: #endif
486: return (TULIP_LINK_UNKNOWN);
487: }
488:
489:
490: /*
491: * Have we seen some packets? If so, the link must be good.
492: */
493: if ((sc->tulip_flags & (TULIP_RXACT|TULIP_LINKUP)) == (TULIP_RXACT|TULIP_LINKUP)) {
494: sc->tulip_flags &= ~TULIP_RXACT;
495: sc->tulip_probe_timeout = 3000;
496: return (TULIP_LINK_UP);
497: }
498:
499: sc->tulip_flags &= ~TULIP_RXACT;
500: if (mi->mi_type == TULIP_MEDIAINFO_MII) {
501: u_int32_t status;
502: /*
503: * Read the PHY status register.
504: */
505: status = tulip_mii_readreg(sc, sc->tulip_phyaddr, PHYREG_STATUS)
506: | tulip_mii_readreg(sc, sc->tulip_phyaddr, PHYREG_STATUS);
507: if (status & PHYSTS_AUTONEG_DONE) {
508: /*
509: * If the PHY has completed autonegotiation, see the if the
510: * remote systems abilities have changed. If so, upgrade or
511: * downgrade as appropriate.
512: */
513: u_int32_t abilities = tulip_mii_readreg(sc, sc->tulip_phyaddr, PHYREG_AUTONEG_ABILITIES);
514: abilities = (abilities << 6) & status;
515: if (abilities != sc->tulip_abilities) {
516: #if defined(TULIP_DEBUG)
517: printf(TULIP_PRINTF_FMT "(phy%d): autonegotiation changed: 0x%04x -> 0x%04x\n",
518: TULIP_PRINTF_ARGS, sc->tulip_phyaddr,
519: sc->tulip_abilities, abilities);
520: #endif
521: if (tulip_mii_map_abilities(sc, abilities)) {
522: tulip_linkup(sc, sc->tulip_probe_media);
523: return (TULIP_LINK_UP);
524: }
525: /*
526: * if we had selected media because of autonegotiation,
527: * we need to probe for the new media.
528: */
529: sc->tulip_probe_state = TULIP_PROBE_INACTIVE;
530: if (sc->tulip_flags & TULIP_DIDNWAY)
531: return (TULIP_LINK_DOWN);
532: }
533: }
534: /*
535: * The link is now up. If was down, say its back up.
536: */
537: if ((status & (PHYSTS_LINK_UP|PHYSTS_REMOTE_FAULT)) == PHYSTS_LINK_UP)
538: linkup = TULIP_LINK_UP;
539: } else if (mi->mi_type == TULIP_MEDIAINFO_GPR) {
540: /*
541: * No activity sensor? Assume all's well.
542: */
543: if (mi->mi_actmask == 0)
544: return (TULIP_LINK_UNKNOWN);
545: /*
546: * Does the activity data match?
547: */
548: if ((TULIP_CSR_READ(sc, csr_gp) & mi->mi_actmask) == mi->mi_actdata)
549: linkup = TULIP_LINK_UP;
550: } else if (mi->mi_type == TULIP_MEDIAINFO_SIA) {
551: /*
552: * Assume non TP ok for now.
553: */
554: if (!TULIP_IS_MEDIA_TP(sc->tulip_media))
555: return (TULIP_LINK_UNKNOWN);
556: if ((TULIP_CSR_READ(sc, csr_sia_status) & TULIP_SIASTS_LINKFAIL) == 0)
557: linkup = TULIP_LINK_UP;
558: #if defined(TULIP_DEBUG)
559: if (sc->tulip_probe_timeout <= 0)
560: printf(TULIP_PRINTF_FMT ": sia status = 0x%08x\n", TULIP_PRINTF_ARGS, TULIP_CSR_READ(sc, csr_sia_status));
561: #endif
562: } else if (mi->mi_type == TULIP_MEDIAINFO_SYM)
563: return (TULIP_LINK_UNKNOWN);
564: /*
565: * We will wait for 3 seconds until the link goes into suspect mode.
566: */
567: if (sc->tulip_flags & TULIP_LINKUP) {
568: if (linkup == TULIP_LINK_UP)
569: sc->tulip_probe_timeout = 3000;
570: if (sc->tulip_probe_timeout > 0)
571: return (TULIP_LINK_UP);
572:
573: sc->tulip_flags &= ~TULIP_LINKUP;
574: }
575: #if defined(TULIP_DEBUG)
576: sc->tulip_dbg.dbg_link_downed++;
577: #endif
578: return (TULIP_LINK_DOWN);
579: }
580:
581: void
582: tulip_media_poll(tulip_softc_t * const sc, tulip_mediapoll_event_t event)
583: {
584: #if defined(TULIP_DEBUG)
585: sc->tulip_dbg.dbg_events[event]++;
586: #endif
587: if (sc->tulip_probe_state == TULIP_PROBE_INACTIVE
588: && event == TULIP_MEDIAPOLL_TIMER) {
589: switch (tulip_media_link_monitor(sc)) {
590: case TULIP_LINK_DOWN: {
591: /*
592: * Link Monitor failed. Probe for new media.
593: */
594: event = TULIP_MEDIAPOLL_LINKFAIL;
595: break;
596: }
597: case TULIP_LINK_UP: {
598: /*
599: * Check again soon.
600: */
601: tulip_timeout(sc);
602: return;
603: }
604: case TULIP_LINK_UNKNOWN: {
605: /*
606: * We can't tell so don't bother.
607: */
608: return;
609: }
610: }
611: }
612:
613: if (event == TULIP_MEDIAPOLL_LINKFAIL) {
614: if (sc->tulip_probe_state == TULIP_PROBE_INACTIVE) {
615: if (TULIP_DO_AUTOSENSE(sc)) {
616: #if defined(TULIP_DEBUG)
617: sc->tulip_dbg.dbg_link_failures++;
618: #endif
619: sc->tulip_media = TULIP_MEDIA_UNKNOWN;
620: if (sc->tulip_if.if_flags & IFF_UP)
621: tulip_reset(sc); /* restart probe */
622: }
623: return;
624: }
625: #if defined(TULIP_DEBUG)
626: sc->tulip_dbg.dbg_link_pollintrs++;
627: #endif
628: }
629:
630: if (event == TULIP_MEDIAPOLL_START) {
631: sc->tulip_if.if_flags |= IFF_OACTIVE;
632: if (sc->tulip_probe_state != TULIP_PROBE_INACTIVE)
633: return;
634: sc->tulip_probe_mediamask = 0;
635: sc->tulip_probe_passes = 0;
636: #if defined(TULIP_DEBUG)
637: sc->tulip_dbg.dbg_media_probes++;
638: #endif
639: /*
640: * If the SROM contained an explicit media to use, use it.
641: */
642: sc->tulip_cmdmode &= ~(TULIP_CMD_RXRUN|TULIP_CMD_FULLDUPLEX);
643: sc->tulip_flags |= TULIP_TRYNWAY|TULIP_PROBE1STPASS;
644: sc->tulip_flags &= ~(TULIP_DIDNWAY|TULIP_PRINTMEDIA|TULIP_PRINTLINKUP);
645: /*
646: * connidx is defaulted to a media_unknown type.
647: */
648: sc->tulip_probe_media = tulip_srom_conninfo[sc->tulip_connidx].sc_media;
649: if (sc->tulip_probe_media != TULIP_MEDIA_UNKNOWN) {
650: tulip_linkup(sc, sc->tulip_probe_media);
651: tulip_timeout(sc);
652: return;
653: }
654:
655: if (sc->tulip_features & TULIP_HAVE_GPR) {
656: sc->tulip_probe_state = TULIP_PROBE_GPRTEST;
657: sc->tulip_probe_timeout = 2000;
658: } else {
659: sc->tulip_probe_media = TULIP_MEDIA_MAX;
660: sc->tulip_probe_timeout = 0;
661: sc->tulip_probe_state = TULIP_PROBE_MEDIATEST;
662: }
663: }
664:
665: /*
666: * Ignore txprobe failures or spurious callbacks.
667: */
668: if (event == TULIP_MEDIAPOLL_TXPROBE_FAILED
669: && sc->tulip_probe_state != TULIP_PROBE_MEDIATEST) {
670: sc->tulip_flags &= ~TULIP_TXPROBE_ACTIVE;
671: return;
672: }
673:
674: /*
675: * If we really transmitted a packet, then that's the media we'll use.
676: */
677: if (event == TULIP_MEDIAPOLL_TXPROBE_OK || event == TULIP_MEDIAPOLL_LINKPASS) {
678: if (event == TULIP_MEDIAPOLL_LINKPASS) {
679: /* XXX Check media status just to be sure */
680: sc->tulip_probe_media = TULIP_MEDIA_10BASET;
681: #if defined(TULIP_DEBUG)
682: } else {
683: sc->tulip_dbg.dbg_txprobes_ok[sc->tulip_probe_media]++;
684: #endif
685: }
686: tulip_linkup(sc, sc->tulip_probe_media);
687: tulip_timeout(sc);
688: return;
689: }
690:
691: if (sc->tulip_probe_state == TULIP_PROBE_GPRTEST) {
692: /*
693: * Brute force. We cycle through each of the media types
694: * and try to transmit a packet.
695: */
696: sc->tulip_probe_state = TULIP_PROBE_MEDIATEST;
697: sc->tulip_probe_media = TULIP_MEDIA_MAX;
698: sc->tulip_probe_timeout = 0;
699: tulip_timeout(sc);
700: return;
701: }
702:
703: if (sc->tulip_probe_state != TULIP_PROBE_MEDIATEST
704: && (sc->tulip_features & TULIP_HAVE_MII)) {
705: tulip_media_t old_media = sc->tulip_probe_media;
706: tulip_mii_autonegotiate(sc, sc->tulip_phyaddr);
707: switch (sc->tulip_probe_state) {
708: case TULIP_PROBE_FAILED:
709: case TULIP_PROBE_MEDIATEST: {
710: /*
711: * Try the next media.
712: */
713: sc->tulip_probe_mediamask |= sc->tulip_mediums[sc->tulip_probe_media]->mi_mediamask;
714: sc->tulip_probe_timeout = 0;
715: break;
716: }
717: case TULIP_PROBE_PHYAUTONEG: {
718: return;
719: }
720: case TULIP_PROBE_INACTIVE: {
721: /*
722: * Only probe if we autonegotiated a media that hasn't failed.
723: */
724: sc->tulip_probe_timeout = 0;
725: if (sc->tulip_probe_mediamask & TULIP_BIT(sc->tulip_probe_media)) {
726: sc->tulip_probe_media = old_media;
727: break;
728: }
729: tulip_linkup(sc, sc->tulip_probe_media);
730: tulip_timeout(sc);
731: return;
732: }
733: default: {
734: #if defined(DIAGNOSTIC) || defined(TULIP_DEBUG)
735: printf("tulip_media_poll: botch at line %d\n", __LINE__);
736: #endif
737: break;
738: }
739: }
740: }
741:
742: if (event == TULIP_MEDIAPOLL_TXPROBE_FAILED) {
743: #if defined(TULIP_DEBUG)
744: sc->tulip_dbg.dbg_txprobes_failed[sc->tulip_probe_media]++;
745: #endif
746: sc->tulip_flags &= ~TULIP_TXPROBE_ACTIVE;
747: return;
748: }
749:
750: /*
751: * Switch to another media if we tried this one enough.
752: */
753: if (/* event == TULIP_MEDIAPOLL_TXPROBE_FAILED || */ sc->tulip_probe_timeout <= 0) {
754: #if defined(TULIP_DEBUG)
755: if (sc->tulip_probe_media == TULIP_MEDIA_UNKNOWN) {
756: printf(TULIP_PRINTF_FMT ": poll media unknown!\n",
757: TULIP_PRINTF_ARGS);
758: sc->tulip_probe_media = TULIP_MEDIA_MAX;
759: }
760: #endif
761: /*
762: * Find the next media type to check for. Full Duplex
763: * types are not allowed.
764: */
765: do {
766: sc->tulip_probe_media -= 1;
767: if (sc->tulip_probe_media == TULIP_MEDIA_UNKNOWN) {
768: if (++sc->tulip_probe_passes == 3) {
769: if ((sc->tulip_if.if_flags & IFF_UP) == 0) {
770: sc->tulip_if.if_flags &= ~IFF_RUNNING;
771: sc->tulip_probe_state = TULIP_PROBE_INACTIVE;
772: return;
773: }
774: }
775: sc->tulip_flags ^= TULIP_TRYNWAY; /* XXX */
776: sc->tulip_probe_mediamask = 0;
777: sc->tulip_probe_media = TULIP_MEDIA_MAX - 1;
778: }
779: } while (sc->tulip_mediums[sc->tulip_probe_media] == NULL
780: || (sc->tulip_probe_mediamask & TULIP_BIT(sc->tulip_probe_media))
781: || TULIP_IS_MEDIA_FD(sc->tulip_probe_media));
782:
783: #if defined(TULIP_DEBUG)
784: printf(TULIP_PRINTF_FMT ": %s: probing %s\n", TULIP_PRINTF_ARGS,
785: event == TULIP_MEDIAPOLL_TXPROBE_FAILED ? "txprobe failed" : "timeout",
786: tulip_mediums[sc->tulip_probe_media]);
787: #endif
788: sc->tulip_probe_timeout = TULIP_IS_MEDIA_TP(sc->tulip_probe_media) ? 2500 : 1000;
789: sc->tulip_probe_state = TULIP_PROBE_MEDIATEST;
790: sc->tulip_probe.probe_txprobes = 0;
791: tulip_reset(sc);
792: tulip_media_set(sc, sc->tulip_probe_media);
793: sc->tulip_flags &= ~TULIP_TXPROBE_ACTIVE;
794: }
795: tulip_timeout(sc);
796:
797: /*
798: * If this is hanging off a phy, we know are doing NWAY and we have
799: * forced the phy to a specific speed. Wait for link up before
800: * before sending a packet.
801: */
802: switch (sc->tulip_mediums[sc->tulip_probe_media]->mi_type) {
803: case TULIP_MEDIAINFO_MII: {
804: if (sc->tulip_probe_media != tulip_mii_phy_readspecific(sc))
805: return;
806: break;
807: }
808: case TULIP_MEDIAINFO_SIA: {
809: if (TULIP_IS_MEDIA_TP(sc->tulip_probe_media)) {
810: if (TULIP_CSR_READ(sc, csr_sia_status) & TULIP_SIASTS_LINKFAIL)
811: return;
812: tulip_linkup(sc, sc->tulip_probe_media);
813: return;
814: }
815: break;
816: }
817: case TULIP_MEDIAINFO_RESET:
818: case TULIP_MEDIAINFO_SYM:
819: case TULIP_MEDIAINFO_NONE:
820: case TULIP_MEDIAINFO_GPR: {
821: break;
822: }
823: }
824: /*
825: * Try to send a packet.
826: */
827: tulip_txprobe(sc);
828: }
829:
830: void
831: tulip_media_select(tulip_softc_t * const sc)
832: {
833: if (sc->tulip_features & TULIP_HAVE_GPR) {
834: TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_PINSET|sc->tulip_gpinit);
835: DELAY(10);
836: TULIP_CSR_WRITE(sc, csr_gp, sc->tulip_gpdata);
837: }
838: /*
839: * If this board has no media, just return
840: */
841: if (sc->tulip_features & TULIP_HAVE_NOMEDIA)
842: return;
843:
844: if (sc->tulip_media == TULIP_MEDIA_UNKNOWN) {
845: TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask);
846: (*sc->tulip_boardsw->bd_media_poll)(sc, TULIP_MEDIAPOLL_START);
847: } else
848: tulip_media_set(sc, sc->tulip_media);
849: }
850:
851: void
852: tulip_21040_mediainfo_init(tulip_softc_t * const sc, tulip_media_t media)
853: {
854: sc->tulip_cmdmode |= TULIP_CMD_CAPTREFFCT|TULIP_CMD_THRSHLD160
855: |TULIP_CMD_BACKOFFCTR;
856: sc->tulip_if.if_baudrate = 10000000;
857:
858: if (media == TULIP_MEDIA_10BASET || media == TULIP_MEDIA_UNKNOWN) {
859: TULIP_MEDIAINFO_SIA_INIT(sc, &sc->tulip_mediainfo[0], 21040, 10BASET);
860: TULIP_MEDIAINFO_SIA_INIT(sc, &sc->tulip_mediainfo[1], 21040, 10BASET_FD);
861: sc->tulip_intrmask |= TULIP_STS_LINKPASS|TULIP_STS_LINKFAIL;
862: }
863:
864: if (media == TULIP_MEDIA_AUIBNC || media == TULIP_MEDIA_UNKNOWN)
865: TULIP_MEDIAINFO_SIA_INIT(sc, &sc->tulip_mediainfo[2], 21040, AUIBNC);
866:
867: if (media == TULIP_MEDIA_UNKNOWN)
868: TULIP_MEDIAINFO_SIA_INIT(sc, &sc->tulip_mediainfo[3], 21040, EXTSIA);
869: }
870:
871: void
872: tulip_21040_media_probe(tulip_softc_t * const sc)
873: {
874: tulip_21040_mediainfo_init(sc, TULIP_MEDIA_UNKNOWN);
875: }
876:
877: void
878: tulip_21040_10baset_only_media_probe(tulip_softc_t * const sc)
879: {
880: tulip_21040_mediainfo_init(sc, TULIP_MEDIA_10BASET);
881: tulip_media_set(sc, TULIP_MEDIA_10BASET);
882: sc->tulip_media = TULIP_MEDIA_10BASET;
883: }
884:
885: void
886: tulip_21040_10baset_only_media_select(tulip_softc_t * const sc)
887: {
888: sc->tulip_flags |= TULIP_LINKUP;
889: if (sc->tulip_media == TULIP_MEDIA_10BASET_FD) {
890: sc->tulip_cmdmode |= TULIP_CMD_FULLDUPLEX;
891: sc->tulip_flags &= ~TULIP_SQETEST;
892: } else {
893: sc->tulip_cmdmode &= ~TULIP_CMD_FULLDUPLEX;
894: sc->tulip_flags |= TULIP_SQETEST;
895: }
896: tulip_media_set(sc, sc->tulip_media);
897: }
898:
899: void
900: tulip_21040_auibnc_only_media_probe(tulip_softc_t * const sc)
901: {
902: tulip_21040_mediainfo_init(sc, TULIP_MEDIA_AUIBNC);
903: sc->tulip_flags |= TULIP_SQETEST|TULIP_LINKUP;
904: tulip_media_set(sc, TULIP_MEDIA_AUIBNC);
905: sc->tulip_media = TULIP_MEDIA_AUIBNC;
906: }
907:
908: void
909: tulip_21040_auibnc_only_media_select(tulip_softc_t * const sc)
910: {
911: tulip_media_set(sc, TULIP_MEDIA_AUIBNC);
912: sc->tulip_cmdmode &= ~TULIP_CMD_FULLDUPLEX;
913: }
914:
915: static const tulip_boardsw_t tulip_21040_boardsw = {
916: TULIP_21040_GENERIC,
917: tulip_21040_media_probe,
918: tulip_media_select,
919: tulip_media_poll,
920: };
921:
922: static const tulip_boardsw_t tulip_21040_10baset_only_boardsw = {
923: TULIP_21040_GENERIC,
924: tulip_21040_10baset_only_media_probe,
925: tulip_21040_10baset_only_media_select,
926: NULL,
927: };
928:
929: static const tulip_boardsw_t tulip_21040_auibnc_only_boardsw = {
930: TULIP_21040_GENERIC,
931: tulip_21040_auibnc_only_media_probe,
932: tulip_21040_auibnc_only_media_select,
933: NULL,
934: };
935:
936: void
937: tulip_21041_mediainfo_init(tulip_softc_t * const sc)
938: {
939: tulip_media_info_t * const mi = sc->tulip_mediainfo;
940:
941: TULIP_MEDIAINFO_SIA_INIT(sc, &mi[0], 21041, 10BASET);
942: TULIP_MEDIAINFO_SIA_INIT(sc, &mi[1], 21041, 10BASET_FD);
943: TULIP_MEDIAINFO_SIA_INIT(sc, &mi[2], 21041, AUI);
944: TULIP_MEDIAINFO_SIA_INIT(sc, &mi[3], 21041, BNC);
945: }
946:
947: void
948: tulip_21041_media_noprobe(tulip_softc_t * const sc)
949: {
950: sc->tulip_if.if_baudrate = 10000000;
951: sc->tulip_cmdmode |= TULIP_CMD_CAPTREFFCT|TULIP_CMD_ENHCAPTEFFCT
952: |TULIP_CMD_THRSHLD160|TULIP_CMD_BACKOFFCTR;
953: sc->tulip_intrmask |= TULIP_STS_LINKPASS|TULIP_STS_LINKFAIL;
954: }
955:
956: void
957: tulip_21041_media_probe(tulip_softc_t * const sc)
958: {
959: sc->tulip_if.if_baudrate = 10000000;
960: sc->tulip_cmdmode |= TULIP_CMD_CAPTREFFCT|TULIP_CMD_ENHCAPTEFFCT
961: |TULIP_CMD_THRSHLD160|TULIP_CMD_BACKOFFCTR;
962: sc->tulip_intrmask |= TULIP_STS_LINKPASS|TULIP_STS_LINKFAIL;
963: tulip_21041_mediainfo_init(sc);
964: }
965:
966: void
967: tulip_21041_media_poll(tulip_softc_t * const sc, const tulip_mediapoll_event_t event)
968: {
969: u_int32_t sia_status;
970:
971: #if defined(TULIP_DEBUG)
972: sc->tulip_dbg.dbg_events[event]++;
973: #endif
974:
975: if (event == TULIP_MEDIAPOLL_LINKFAIL) {
976: if (sc->tulip_probe_state != TULIP_PROBE_INACTIVE
977: || !TULIP_DO_AUTOSENSE(sc))
978: return;
979: sc->tulip_media = TULIP_MEDIA_UNKNOWN;
980: tulip_reset(sc); /* start probe */
981: return;
982: }
983:
984: /*
985: * If we've been been asked to start a poll or link change interrupt
986: * restart the probe (and reset the tulip to a known state).
987: */
988: if (event == TULIP_MEDIAPOLL_START) {
989: sc->tulip_if.if_flags |= IFF_OACTIVE;
990: sc->tulip_cmdmode &= ~(TULIP_CMD_FULLDUPLEX|TULIP_CMD_RXRUN);
991: TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode);
992: sc->tulip_probe_state = TULIP_PROBE_MEDIATEST;
993: sc->tulip_probe_media = TULIP_MEDIA_10BASET;
994: sc->tulip_probe_timeout = TULIP_21041_PROBE_10BASET_TIMEOUT;
995: tulip_media_set(sc, TULIP_MEDIA_10BASET);
996: tulip_timeout(sc);
997: return;
998: }
999:
1000: if (sc->tulip_probe_state == TULIP_PROBE_INACTIVE)
1001: return;
1002:
1003: if (event == TULIP_MEDIAPOLL_TXPROBE_OK) {
1004: #if defined(TULIP_DEBUG)
1005: sc->tulip_dbg.dbg_txprobes_ok[sc->tulip_probe_media]++;
1006: #endif
1007: tulip_linkup(sc, sc->tulip_probe_media);
1008: return;
1009: }
1010:
1011: sia_status = TULIP_CSR_READ(sc, csr_sia_status);
1012: TULIP_CSR_WRITE(sc, csr_sia_status, sia_status);
1013: if ((sia_status & TULIP_SIASTS_LINKFAIL) == 0) {
1014: if (sc->tulip_revinfo >= 0x20) {
1015: if (sia_status & (PHYSTS_10BASET_FD << (16 - 6)))
1016: sc->tulip_probe_media = TULIP_MEDIA_10BASET_FD;
1017: }
1018: /*
1019: * If the link has passed LinkPass, 10baseT is the
1020: * proper media to use.
1021: */
1022: tulip_linkup(sc, sc->tulip_probe_media);
1023: return;
1024: }
1025:
1026: /*
1027: * wait for up to 2.4 seconds for the link to reach pass state.
1028: * Only then start scanning the other media for activity.
1029: * choose media with receive activity over those without.
1030: */
1031: if (sc->tulip_probe_media == TULIP_MEDIA_10BASET) {
1032: if (event != TULIP_MEDIAPOLL_TIMER)
1033: return;
1034: if (sc->tulip_probe_timeout > 0
1035: && (sia_status & TULIP_SIASTS_OTHERRXACTIVITY) == 0) {
1036: tulip_timeout(sc);
1037: return;
1038: }
1039: sc->tulip_probe_timeout = TULIP_21041_PROBE_AUIBNC_TIMEOUT;
1040: sc->tulip_flags |= TULIP_WANTRXACT;
1041: if (sia_status & TULIP_SIASTS_OTHERRXACTIVITY)
1042: sc->tulip_probe_media = TULIP_MEDIA_BNC;
1043: else
1044: sc->tulip_probe_media = TULIP_MEDIA_AUI;
1045: tulip_media_set(sc, sc->tulip_probe_media);
1046: tulip_timeout(sc);
1047: return;
1048: }
1049:
1050: /*
1051: * If we failed, clear the txprobe active flag.
1052: */
1053: if (event == TULIP_MEDIAPOLL_TXPROBE_FAILED)
1054: sc->tulip_flags &= ~TULIP_TXPROBE_ACTIVE;
1055:
1056:
1057: if (event == TULIP_MEDIAPOLL_TIMER) {
1058: /*
1059: * If we've received something, then that's our link!
1060: */
1061: if (sc->tulip_flags & TULIP_RXACT) {
1062: tulip_linkup(sc, sc->tulip_probe_media);
1063: return;
1064: }
1065: /*
1066: * if no txprobe active
1067: */
1068: if ((sc->tulip_flags & TULIP_TXPROBE_ACTIVE) == 0
1069: && ((sc->tulip_flags & TULIP_WANTRXACT) == 0
1070: || (sia_status & TULIP_SIASTS_RXACTIVITY))) {
1071: sc->tulip_probe_timeout = TULIP_21041_PROBE_AUIBNC_TIMEOUT;
1072: tulip_txprobe(sc);
1073: tulip_timeout(sc);
1074: return;
1075: }
1076: /*
1077: * Take 2 passes through before deciding to not
1078: * wait for receive activity. Then take another
1079: * two passes before spitting out a warning.
1080: */
1081: if (sc->tulip_probe_timeout <= 0) {
1082: if (sc->tulip_flags & TULIP_WANTRXACT) {
1083: sc->tulip_flags &= ~TULIP_WANTRXACT;
1084: sc->tulip_probe_timeout = TULIP_21041_PROBE_AUIBNC_TIMEOUT;
1085: } else {
1086: if ((sc->tulip_if.if_flags & IFF_UP) == 0) {
1087: sc->tulip_if.if_flags &= ~IFF_RUNNING;
1088: sc->tulip_probe_state = TULIP_PROBE_INACTIVE;
1089: return;
1090: }
1091: }
1092: }
1093: }
1094:
1095: /*
1096: * Since this media failed to probe, try the other one.
1097: */
1098: sc->tulip_probe_timeout = TULIP_21041_PROBE_AUIBNC_TIMEOUT;
1099: if (sc->tulip_probe_media == TULIP_MEDIA_AUI)
1100: sc->tulip_probe_media = TULIP_MEDIA_BNC;
1101: else
1102: sc->tulip_probe_media = TULIP_MEDIA_AUI;
1103: tulip_media_set(sc, sc->tulip_probe_media);
1104: sc->tulip_flags &= ~TULIP_TXPROBE_ACTIVE;
1105: tulip_timeout(sc);
1106: }
1107:
1108: static const tulip_boardsw_t tulip_21041_boardsw = {
1109: TULIP_21041_GENERIC,
1110: tulip_21041_media_probe,
1111: tulip_media_select,
1112: tulip_21041_media_poll
1113: };
1114:
1115: static const tulip_boardsw_t tulip_21041np_boardsw = {
1116: TULIP_21041_GENERIC,
1117: tulip_21041_media_noprobe,
1118: tulip_media_select,
1119: tulip_21041_media_poll
1120: };
1121:
1122: static const tulip_phy_attr_t tulip_mii_phy_attrlist[] = {
1123: { 0x20005c00, 0, /* 08-00-17 */
1124: {
1125: { 0x19, 0x0040, 0x0040 }, /* 10TX */
1126: { 0x19, 0x0040, 0x0000 }, /* 100TX */
1127: },
1128: #if defined(TULIP_DEBUG)
1129: "NS DP83840",
1130: #endif
1131: },
1132: { 0x0281F400, 0, /* 00-A0-7D */
1133: {
1134: { 0x12, 0x0010, 0x0000 }, /* 10T */
1135: { 0 }, /* 100TX */
1136: { 0x12, 0x0010, 0x0010 }, /* 100T4 */
1137: { 0x12, 0x0008, 0x0008 }, /* FULL_DUPLEX */
1138: },
1139: #if defined(TULIP_DEBUG)
1140: "Seeq 80C240"
1141: #endif
1142: },
1143: { 0x0281F400, 3, /* 00-A0-7D */
1144: {
1145: { 0x12, 0x0080, 0x0000 }, /* 10T */
1146: { 0x12, 0x0080, 0x0080 }, /* 100TX */
1147: { 0 }, /* 100T4 */
1148: { 0x12, 0x0040, 0x0040 }, /* FULL_DUPLEX */
1149: },
1150: #if defined(TULIP_DEBUG)
1151: "Seeq 80225"
1152: #endif
1153: },
1154: { 0x0281F400, 0, /* 00-A0-BE */
1155: {
1156: { 0x11, 0x8000, 0x0000 }, /* 10T */
1157: { 0x11, 0x8000, 0x8000 }, /* 100TX */
1158: { 0 }, /* 100T4 */
1159: { 0x11, 0x4000, 0x4000 }, /* FULL_DUPLEX */
1160: },
1161: #if defined(TULIP_DEBUG)
1162: "ICS 1890"
1163: #endif
1164: },
1165: { 0x78100000, 0, /* 00-A0-CC */
1166: {
1167: { 0x14, 0x0800, 0x0000 }, /* 10TX */
1168: { 0x14, 0x0800, 0x0800 }, /* 100TX */
1169: { 0 }, /* 100T4 */
1170: { 0x14, 0x1000, 0x1000 }, /* FULL_DUPLEX */
1171: },
1172: #if defined(TULIP_DEBUG)
1173: "LEVEL1 LXT970"
1174: #endif
1175: },
1176: { 0 }
1177: };
1178:
1179: tulip_media_t
1180: tulip_mii_phy_readspecific(tulip_softc_t * const sc)
1181: {
1182: const tulip_phy_attr_t *attr;
1183: u_int16_t data;
1184: u_int32_t id;
1185: unsigned idx = 0;
1186: static const tulip_media_t table[] = {
1187: TULIP_MEDIA_UNKNOWN,
1188: TULIP_MEDIA_10BASET,
1189: TULIP_MEDIA_100BASETX,
1190: TULIP_MEDIA_100BASET4,
1191: TULIP_MEDIA_UNKNOWN,
1192: TULIP_MEDIA_10BASET_FD,
1193: TULIP_MEDIA_100BASETX_FD,
1194: TULIP_MEDIA_UNKNOWN
1195: };
1196:
1197: /*
1198: * Don't read phy specific registers if link is not up.
1199: */
1200: data = tulip_mii_readreg(sc, sc->tulip_phyaddr, PHYREG_STATUS)
1201: | tulip_mii_readreg(sc, sc->tulip_phyaddr, PHYREG_STATUS);
1202: if ((data & (PHYSTS_LINK_UP|PHYSTS_EXTENDED_REGS)) != (PHYSTS_LINK_UP|PHYSTS_EXTENDED_REGS))
1203: return (TULIP_MEDIA_UNKNOWN);
1204:
1205: id = (tulip_mii_readreg(sc, sc->tulip_phyaddr, PHYREG_IDLOW) << 16) |
1206: tulip_mii_readreg(sc, sc->tulip_phyaddr, PHYREG_IDHIGH);
1207: for (attr = tulip_mii_phy_attrlist;; attr++) {
1208: if (attr->attr_id == 0)
1209: return (TULIP_MEDIA_UNKNOWN);
1210: if ((id & ~0x0F) == attr->attr_id)
1211: break;
1212: }
1213:
1214: if (attr->attr_modes[PHY_MODE_100TX].pm_regno) {
1215: const tulip_phy_modedata_t * const pm = &attr->attr_modes[PHY_MODE_100TX];
1216: data = tulip_mii_readreg(sc, sc->tulip_phyaddr, pm->pm_regno);
1217: if ((data & pm->pm_mask) == pm->pm_value)
1218: idx = 2;
1219: }
1220: if (idx == 0 && attr->attr_modes[PHY_MODE_100T4].pm_regno) {
1221: const tulip_phy_modedata_t * const pm = &attr->attr_modes[PHY_MODE_100T4];
1222: data = tulip_mii_readreg(sc, sc->tulip_phyaddr, pm->pm_regno);
1223: if ((data & pm->pm_mask) == pm->pm_value)
1224: idx = 3;
1225: }
1226: if (idx == 0 && attr->attr_modes[PHY_MODE_10T].pm_regno) {
1227: const tulip_phy_modedata_t * const pm = &attr->attr_modes[PHY_MODE_10T];
1228: data = tulip_mii_readreg(sc, sc->tulip_phyaddr, pm->pm_regno);
1229: if ((data & pm->pm_mask) == pm->pm_value)
1230: idx = 1;
1231: }
1232: if (idx != 0 && attr->attr_modes[PHY_MODE_FULLDUPLEX].pm_regno) {
1233: const tulip_phy_modedata_t * const pm = &attr->attr_modes[PHY_MODE_FULLDUPLEX];
1234: data = tulip_mii_readreg(sc, sc->tulip_phyaddr, pm->pm_regno);
1235: idx += ((data & pm->pm_mask) == pm->pm_value ? 4 : 0);
1236: }
1237: return (table[idx]);
1238: }
1239:
1240: unsigned
1241: tulip_mii_get_phyaddr(tulip_softc_t * const sc, unsigned offset)
1242: {
1243: unsigned phyaddr;
1244:
1245: for (phyaddr = 1; phyaddr < 32; phyaddr++) {
1246: unsigned status = tulip_mii_readreg(sc, phyaddr, PHYREG_STATUS);
1247: if (status == 0 || status == 0xFFFF || status < PHYSTS_10BASET)
1248: continue;
1249: if (offset == 0)
1250: return (phyaddr);
1251: offset--;
1252: }
1253: if (offset == 0) {
1254: unsigned status = tulip_mii_readreg(sc, 0, PHYREG_STATUS);
1255: if (status == 0 || status == 0xFFFF || status < PHYSTS_10BASET)
1256: return (TULIP_MII_NOPHY);
1257: return (0);
1258: }
1259: return (TULIP_MII_NOPHY);
1260: }
1261:
1262: int
1263: tulip_mii_map_abilities(tulip_softc_t * const sc, unsigned abilities)
1264: {
1265: sc->tulip_abilities = abilities;
1266: if (abilities & PHYSTS_100BASETX_FD)
1267: sc->tulip_probe_media = TULIP_MEDIA_100BASETX_FD;
1268: else if (abilities & PHYSTS_100BASET4)
1269: sc->tulip_probe_media = TULIP_MEDIA_100BASET4;
1270: else if (abilities & PHYSTS_100BASETX)
1271: sc->tulip_probe_media = TULIP_MEDIA_100BASETX;
1272: else if (abilities & PHYSTS_10BASET_FD)
1273: sc->tulip_probe_media = TULIP_MEDIA_10BASET_FD;
1274: else if (abilities & PHYSTS_10BASET)
1275: sc->tulip_probe_media = TULIP_MEDIA_10BASET;
1276: else {
1277: sc->tulip_probe_state = TULIP_PROBE_MEDIATEST;
1278: return (0);
1279: }
1280: sc->tulip_probe_state = TULIP_PROBE_INACTIVE;
1281: return (1);
1282: }
1283:
1284: void
1285: tulip_mii_autonegotiate(tulip_softc_t * const sc, const unsigned phyaddr)
1286: {
1287: switch (sc->tulip_probe_state) {
1288: case TULIP_PROBE_MEDIATEST:
1289: case TULIP_PROBE_INACTIVE: {
1290: sc->tulip_flags |= TULIP_DIDNWAY;
1291: tulip_mii_writereg(sc, phyaddr, PHYREG_CONTROL, PHYCTL_RESET);
1292: sc->tulip_probe_timeout = 3000;
1293: sc->tulip_intrmask |= TULIP_STS_ABNRMLINTR|TULIP_STS_NORMALINTR;
1294: sc->tulip_probe_state = TULIP_PROBE_PHYRESET;
1295: /* FALLTHROUGH */
1296: }
1297: case TULIP_PROBE_PHYRESET: {
1298: u_int32_t status;
1299: u_int32_t data = tulip_mii_readreg(sc, phyaddr, PHYREG_CONTROL);
1300: if (data & PHYCTL_RESET) {
1301: if (sc->tulip_probe_timeout > 0) {
1302: tulip_timeout(sc);
1303: return;
1304: }
1305: #ifdef TULIP_DEBUG
1306: printf(TULIP_PRINTF_FMT "(phy%d): error: reset of PHY never completed!\n",
1307: TULIP_PRINTF_ARGS, phyaddr);
1308: #endif
1309: sc->tulip_flags &= ~TULIP_TXPROBE_ACTIVE;
1310: sc->tulip_probe_state = TULIP_PROBE_FAILED;
1311: sc->tulip_if.if_flags &= ~(IFF_UP|IFF_RUNNING);
1312: return;
1313: }
1314: status = tulip_mii_readreg(sc, phyaddr, PHYREG_STATUS)
1315: | tulip_mii_readreg(sc, phyaddr, PHYREG_STATUS);
1316: if ((status & PHYSTS_CAN_AUTONEG) == 0) {
1317: #if defined(TULIP_DEBUG)
1318: printf(TULIP_PRINTF_FMT "(phy%d): autonegotiation disabled\n",
1319: TULIP_PRINTF_ARGS, phyaddr);
1320: #endif
1321: sc->tulip_flags &= ~TULIP_DIDNWAY;
1322: sc->tulip_probe_state = TULIP_PROBE_MEDIATEST;
1323: return;
1324: }
1325: if (tulip_mii_readreg(sc, phyaddr, PHYREG_AUTONEG_ADVERTISEMENT) != ((status >> 6) | 0x01))
1326: tulip_mii_writereg(sc, phyaddr, PHYREG_AUTONEG_ADVERTISEMENT, (status >> 6) | 0x01);
1327: tulip_mii_writereg(sc, phyaddr, PHYREG_CONTROL, data|PHYCTL_AUTONEG_RESTART|PHYCTL_AUTONEG_ENABLE);
1328: data = tulip_mii_readreg(sc, phyaddr, PHYREG_CONTROL);
1329: #if defined(TULIP_DEBUG)
1330: if ((data & PHYCTL_AUTONEG_ENABLE) == 0)
1331: printf(TULIP_PRINTF_FMT "(phy%d): oops: enable autonegotiation failed: 0x%04x\n",
1332: TULIP_PRINTF_ARGS, phyaddr, data);
1333: else
1334: printf(TULIP_PRINTF_FMT "(phy%d): autonegotiation restarted: 0x%04x (ad=0x%04x)\n",
1335: TULIP_PRINTF_ARGS, phyaddr, data,
1336: tulip_mii_readreg(sc, phyaddr, PHYREG_AUTONEG_ADVERTISEMENT));
1337: sc->tulip_dbg.dbg_nway_starts++;
1338: #endif
1339: sc->tulip_probe_state = TULIP_PROBE_PHYAUTONEG;
1340: sc->tulip_probe_timeout = 3000;
1341: /* FALLTHROUGH */
1342: }
1343: case TULIP_PROBE_PHYAUTONEG: {
1344: u_int32_t status = tulip_mii_readreg(sc, phyaddr, PHYREG_STATUS)
1345: | tulip_mii_readreg(sc, phyaddr, PHYREG_STATUS);
1346: u_int32_t data;
1347: if ((status & PHYSTS_AUTONEG_DONE) == 0) {
1348: if (sc->tulip_probe_timeout > 0) {
1349: tulip_timeout(sc);
1350: return;
1351: }
1352: #if defined(TULIP_DEBUG)
1353: printf(TULIP_PRINTF_FMT "(phy%d): autonegotiation timeout: sts=0x%04x, ctl=0x%04x\n",
1354: TULIP_PRINTF_ARGS, phyaddr, status,
1355: tulip_mii_readreg(sc, phyaddr, PHYREG_CONTROL));
1356: #endif
1357: sc->tulip_flags &= ~TULIP_DIDNWAY;
1358: sc->tulip_probe_state = TULIP_PROBE_MEDIATEST;
1359: return;
1360: }
1361: data = tulip_mii_readreg(sc, phyaddr, PHYREG_AUTONEG_ABILITIES)
1362: | tulip_mii_readreg(sc, phyaddr, PHYREG_AUTONEG_ABILITIES);
1363: #if defined(TULIP_DEBUG)
1364: printf(TULIP_PRINTF_FMT "(phy%d): autonegotiation complete: 0x%04x (sts=0x%04x)\n",
1365: TULIP_PRINTF_ARGS, phyaddr, data, status);
1366: #endif
1367: data = (data << 6) & status;
1368: if (!tulip_mii_map_abilities(sc, data))
1369: sc->tulip_flags &= ~TULIP_DIDNWAY;
1370: return;
1371: }
1372: default: {
1373: #if defined(DIAGNOSTIC)
1374: printf("tulip_media_poll: botch at line %d\n", __LINE__);
1375: #endif
1376: break;
1377: }
1378: }
1379: #if defined(TULIP_DEBUG)
1380: printf(TULIP_PRINTF_FMT "(phy%d): autonegotiation failure: state = %d\n",
1381: TULIP_PRINTF_ARGS, phyaddr, sc->tulip_probe_state);
1382: sc->tulip_dbg.dbg_nway_failures++;
1383: #endif
1384: }
1385:
1386: void
1387: tulip_2114x_media_preset(tulip_softc_t * const sc)
1388: {
1389: const tulip_media_info_t *mi = NULL;
1390: tulip_media_t media = sc->tulip_media;
1391:
1392: if (sc->tulip_probe_state == TULIP_PROBE_INACTIVE)
1393: media = sc->tulip_media;
1394: else
1395: media = sc->tulip_probe_media;
1396:
1397: sc->tulip_cmdmode &= ~(TULIP_CMD_PORTSELECT|TULIP_CMD_NOHEARTBEAT
1398: |TULIP_CMD_FULLDUPLEX|TULIP_CMD_TXTHRSHLDCTL);
1399: sc->tulip_flags &= ~(TULIP_SQETEST|TULIP_FULLDUPLEX);
1400: if (media != TULIP_MEDIA_UNKNOWN && media != TULIP_MEDIA_MAX) {
1401: #if defined(TULIP_DEBUG)
1402: if (media < TULIP_MEDIA_MAX && sc->tulip_mediums[media] != NULL) {
1403: #endif
1404: mi = sc->tulip_mediums[media];
1405: if (mi->mi_type == TULIP_MEDIAINFO_MII)
1406: sc->tulip_cmdmode |= TULIP_CMD_PORTSELECT;
1407: else if (mi->mi_type == TULIP_MEDIAINFO_GPR
1408: || mi->mi_type == TULIP_MEDIAINFO_SYM) {
1409: sc->tulip_cmdmode &= ~TULIP_GPR_CMDBITS;
1410: sc->tulip_cmdmode |= mi->mi_cmdmode;
1411: } else if (mi->mi_type == TULIP_MEDIAINFO_SIA)
1412: TULIP_CSR_WRITE(sc, csr_sia_connectivity, TULIP_SIACONN_RESET);
1413: #if defined(TULIP_DEBUG)
1414: } else {
1415: printf(TULIP_PRINTF_FMT ": preset: bad media %d!\n",
1416: TULIP_PRINTF_ARGS, media);
1417: }
1418: #endif
1419: }
1420: switch (media) {
1421: case TULIP_MEDIA_BNC:
1422: case TULIP_MEDIA_AUI:
1423: case TULIP_MEDIA_10BASET: {
1424: sc->tulip_cmdmode |= TULIP_CMD_TXTHRSHLDCTL;
1425: sc->tulip_if.if_baudrate = 10000000;
1426: sc->tulip_flags |= TULIP_SQETEST;
1427: break;
1428: }
1429: case TULIP_MEDIA_10BASET_FD: {
1430: sc->tulip_flags |= TULIP_FULLDUPLEX;
1431: sc->tulip_cmdmode |= TULIP_CMD_TXTHRSHLDCTL|TULIP_CMD_FULLDUPLEX;
1432: sc->tulip_if.if_baudrate = 10000000;
1433: break;
1434: }
1435: case TULIP_MEDIA_100BASEFX:
1436: case TULIP_MEDIA_100BASET4:
1437: case TULIP_MEDIA_100BASETX: {
1438: sc->tulip_cmdmode |= TULIP_CMD_PORTSELECT;
1439: sc->tulip_if.if_baudrate = 100000000;
1440: if (mi->mi_type == TULIP_MEDIAINFO_SYM
1441: || mi->mi_type == TULIP_MEDIAINFO_MII) {
1442: sc->tulip_cmdmode |= TULIP_CMD_NOHEARTBEAT;
1443: }
1444: break;
1445: }
1446: case TULIP_MEDIA_100BASEFX_FD:
1447: case TULIP_MEDIA_100BASETX_FD: {
1448: sc->tulip_flags |= TULIP_FULLDUPLEX;
1449: sc->tulip_cmdmode |= TULIP_CMD_PORTSELECT|TULIP_CMD_FULLDUPLEX;
1450: sc->tulip_if.if_baudrate = 100000000;
1451: if (mi->mi_type == TULIP_MEDIAINFO_SYM
1452: || mi->mi_type == TULIP_MEDIAINFO_MII) {
1453: sc->tulip_cmdmode |= TULIP_CMD_NOHEARTBEAT;
1454: }
1455: break;
1456: }
1457: default: {
1458: break;
1459: }
1460: }
1461: TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode);
1462: }
1463:
1464: /*
1465: ********************************************************************
1466: * Start of 21140/21140A support which does not use the MII interface
1467: */
1468:
1469: void
1470: tulip_null_media_poll(tulip_softc_t * const sc, tulip_mediapoll_event_t event)
1471: {
1472: #if defined(TULIP_DEBUG)
1473: sc->tulip_dbg.dbg_events[event]++;
1474: #endif
1475: #if defined(DIAGNOSTIC)
1476: printf(TULIP_PRINTF_FMT ": botch(media_poll) at line %d\n",
1477: TULIP_PRINTF_ARGS, __LINE__);
1478: #endif
1479: }
1480:
1481: void
1482: tulip_21140_mediainit(tulip_softc_t * const sc, tulip_media_info_t * const mip,
1483: tulip_media_t const media, unsigned gpdata, unsigned cmdmode)
1484: {
1485: sc->tulip_mediums[media] = mip;
1486: mip->mi_type = TULIP_MEDIAINFO_GPR;
1487: mip->mi_cmdmode = cmdmode;
1488: mip->mi_gpdata = gpdata;
1489: }
1490:
1491: void
1492: tulip_21140_evalboard_media_probe(tulip_softc_t * const sc)
1493: {
1494: tulip_media_info_t *mip = sc->tulip_mediainfo;
1495:
1496: sc->tulip_gpinit = TULIP_GP_EB_PINS;
1497: sc->tulip_gpdata = TULIP_GP_EB_INIT;
1498: TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_EB_PINS);
1499: TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_EB_INIT);
1500: TULIP_CSR_WRITE(sc, csr_command,
1501: TULIP_CSR_READ(sc, csr_command) | TULIP_CMD_PORTSELECT |
1502: TULIP_CMD_PCSFUNCTION | TULIP_CMD_SCRAMBLER | TULIP_CMD_MUSTBEONE);
1503: TULIP_CSR_WRITE(sc, csr_command,
1504: TULIP_CSR_READ(sc, csr_command) & ~TULIP_CMD_TXTHRSHLDCTL);
1505: DELAY(1000000);
1506: if ((TULIP_CSR_READ(sc, csr_gp) & TULIP_GP_EB_OK100) != 0)
1507: sc->tulip_media = TULIP_MEDIA_10BASET;
1508: else
1509: sc->tulip_media = TULIP_MEDIA_100BASETX;
1510: tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_10BASET,
1511: TULIP_GP_EB_INIT,
1512: TULIP_CMD_TXTHRSHLDCTL);
1513: tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_10BASET_FD,
1514: TULIP_GP_EB_INIT,
1515: TULIP_CMD_TXTHRSHLDCTL|TULIP_CMD_FULLDUPLEX);
1516: tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX,
1517: TULIP_GP_EB_INIT,
1518: TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
1519: |TULIP_CMD_SCRAMBLER);
1520: tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX_FD,
1521: TULIP_GP_EB_INIT,
1522: TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
1523: |TULIP_CMD_SCRAMBLER|TULIP_CMD_FULLDUPLEX);
1524: }
1525:
1526: static const tulip_boardsw_t tulip_21140_eb_boardsw = {
1527: TULIP_21140_DEC_EB,
1528: tulip_21140_evalboard_media_probe,
1529: tulip_media_select,
1530: tulip_null_media_poll,
1531: tulip_2114x_media_preset,
1532: };
1533:
1534: void
1535: tulip_21140_accton_media_probe(tulip_softc_t * const sc)
1536: {
1537: tulip_media_info_t *mip = sc->tulip_mediainfo;
1538: unsigned gpdata;
1539:
1540: sc->tulip_gpinit = TULIP_GP_EB_PINS;
1541: sc->tulip_gpdata = TULIP_GP_EB_INIT;
1542: TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_EB_PINS);
1543: TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_EB_INIT);
1544: TULIP_CSR_WRITE(sc, csr_command,
1545: TULIP_CSR_READ(sc, csr_command) | TULIP_CMD_PORTSELECT |
1546: TULIP_CMD_PCSFUNCTION | TULIP_CMD_SCRAMBLER | TULIP_CMD_MUSTBEONE);
1547: TULIP_CSR_WRITE(sc, csr_command,
1548: TULIP_CSR_READ(sc, csr_command) & ~TULIP_CMD_TXTHRSHLDCTL);
1549: DELAY(1000000);
1550: gpdata = TULIP_CSR_READ(sc, csr_gp);
1551: if ((gpdata & TULIP_GP_EN1207_UTP_INIT) == 0)
1552: sc->tulip_media = TULIP_MEDIA_10BASET;
1553: else {
1554: if ((gpdata & TULIP_GP_EN1207_BNC_INIT) == 0)
1555: sc->tulip_media = TULIP_MEDIA_BNC;
1556: else
1557: sc->tulip_media = TULIP_MEDIA_100BASETX;
1558: }
1559: tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_BNC,
1560: TULIP_GP_EN1207_BNC_INIT,
1561: TULIP_CMD_TXTHRSHLDCTL);
1562: tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_10BASET,
1563: TULIP_GP_EN1207_UTP_INIT,
1564: TULIP_CMD_TXTHRSHLDCTL);
1565: tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_10BASET_FD,
1566: TULIP_GP_EN1207_UTP_INIT,
1567: TULIP_CMD_TXTHRSHLDCTL|TULIP_CMD_FULLDUPLEX);
1568: tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX,
1569: TULIP_GP_EN1207_100_INIT,
1570: TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
1571: |TULIP_CMD_SCRAMBLER);
1572: tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX_FD,
1573: TULIP_GP_EN1207_100_INIT,
1574: TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
1575: |TULIP_CMD_SCRAMBLER|TULIP_CMD_FULLDUPLEX);
1576: }
1577:
1578: static const tulip_boardsw_t tulip_21140_accton_boardsw = {
1579: TULIP_21140_EN1207,
1580: tulip_21140_accton_media_probe,
1581: tulip_media_select,
1582: tulip_null_media_poll,
1583: tulip_2114x_media_preset,
1584: };
1585:
1586: void
1587: tulip_21140_smc9332_media_probe(tulip_softc_t * const sc)
1588: {
1589: tulip_media_info_t *mip = sc->tulip_mediainfo;
1590: int idx, cnt = 0;
1591:
1592: TULIP_CSR_WRITE(sc, csr_command, TULIP_CMD_PORTSELECT|TULIP_CMD_MUSTBEONE);
1593: TULIP_CSR_WRITE(sc, csr_busmode, TULIP_BUSMODE_SWRESET);
1594: DELAY(10); /* Wait 10 microseconds (actually 50 PCI cycles but at
1595: 33MHz that comes to two microseconds but wait a
1596: bit longer anyways) */
1597: TULIP_CSR_WRITE(sc, csr_command, TULIP_CMD_PORTSELECT |
1598: TULIP_CMD_PCSFUNCTION | TULIP_CMD_SCRAMBLER | TULIP_CMD_MUSTBEONE);
1599: sc->tulip_gpinit = TULIP_GP_SMC_9332_PINS;
1600: sc->tulip_gpdata = TULIP_GP_SMC_9332_INIT;
1601: TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_SMC_9332_PINS|TULIP_GP_PINSET);
1602: TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_SMC_9332_INIT);
1603: DELAY(200000);
1604: for (idx = 1000; idx > 0; idx--) {
1605: u_int32_t csr = TULIP_CSR_READ(sc, csr_gp);
1606: if ((csr & (TULIP_GP_SMC_9332_OK10|TULIP_GP_SMC_9332_OK100)) == (TULIP_GP_SMC_9332_OK10|TULIP_GP_SMC_9332_OK100)) {
1607: if (++cnt > 100)
1608: break;
1609: } else if ((csr & TULIP_GP_SMC_9332_OK10) == 0)
1610: break;
1611: else
1612: cnt = 0;
1613: DELAY(1000);
1614: }
1615: sc->tulip_media = cnt > 100 ? TULIP_MEDIA_100BASETX : TULIP_MEDIA_10BASET;
1616: tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX,
1617: TULIP_GP_SMC_9332_INIT,
1618: TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
1619: |TULIP_CMD_SCRAMBLER);
1620: tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX_FD,
1621: TULIP_GP_SMC_9332_INIT,
1622: TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
1623: |TULIP_CMD_SCRAMBLER|TULIP_CMD_FULLDUPLEX);
1624: tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_10BASET,
1625: TULIP_GP_SMC_9332_INIT,
1626: TULIP_CMD_TXTHRSHLDCTL);
1627: tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_10BASET_FD,
1628: TULIP_GP_SMC_9332_INIT,
1629: TULIP_CMD_TXTHRSHLDCTL|TULIP_CMD_FULLDUPLEX);
1630: }
1631:
1632: static const tulip_boardsw_t tulip_21140_smc9332_boardsw = {
1633: TULIP_21140_SMC_9332,
1634: tulip_21140_smc9332_media_probe,
1635: tulip_media_select,
1636: tulip_null_media_poll,
1637: tulip_2114x_media_preset,
1638: };
1639:
1640: void
1641: tulip_21140_cogent_em100_media_probe(tulip_softc_t * const sc)
1642: {
1643: tulip_media_info_t *mip = sc->tulip_mediainfo;
1644: u_int32_t cmdmode = TULIP_CSR_READ(sc, csr_command);
1645:
1646: sc->tulip_gpinit = TULIP_GP_EM100_PINS;
1647: sc->tulip_gpdata = TULIP_GP_EM100_INIT;
1648: TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_EM100_PINS);
1649: TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_EM100_INIT);
1650:
1651: cmdmode = TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION|TULIP_CMD_MUSTBEONE;
1652: cmdmode &= ~(TULIP_CMD_TXTHRSHLDCTL|TULIP_CMD_SCRAMBLER);
1653: if (sc->tulip_rombuf[32] == TULIP_COGENT_EM100FX_ID) {
1654: TULIP_CSR_WRITE(sc, csr_command, cmdmode);
1655: sc->tulip_media = TULIP_MEDIA_100BASEFX;
1656:
1657: tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASEFX,
1658: TULIP_GP_EM100_INIT,
1659: TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION);
1660: tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASEFX_FD,
1661: TULIP_GP_EM100_INIT,
1662: TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
1663: |TULIP_CMD_FULLDUPLEX);
1664: } else {
1665: TULIP_CSR_WRITE(sc, csr_command, cmdmode|TULIP_CMD_SCRAMBLER);
1666: sc->tulip_media = TULIP_MEDIA_100BASETX;
1667: tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX,
1668: TULIP_GP_EM100_INIT,
1669: TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
1670: |TULIP_CMD_SCRAMBLER);
1671: tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX_FD,
1672: TULIP_GP_EM100_INIT,
1673: TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
1674: |TULIP_CMD_SCRAMBLER|TULIP_CMD_FULLDUPLEX);
1675: }
1676: }
1677:
1678: static const tulip_boardsw_t tulip_21140_cogent_em100_boardsw = {
1679: TULIP_21140_COGENT_EM100,
1680: tulip_21140_cogent_em100_media_probe,
1681: tulip_media_select,
1682: tulip_null_media_poll,
1683: tulip_2114x_media_preset
1684: };
1685:
1686: void
1687: tulip_21140_znyx_zx34x_media_probe(tulip_softc_t * const sc)
1688: {
1689: tulip_media_info_t *mip = sc->tulip_mediainfo;
1690: int cnt10 = 0, cnt100 = 0, idx;
1691:
1692: sc->tulip_gpinit = TULIP_GP_ZX34X_PINS;
1693: sc->tulip_gpdata = TULIP_GP_ZX34X_INIT;
1694: TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_ZX34X_PINS);
1695: TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_ZX34X_INIT);
1696: TULIP_CSR_WRITE(sc, csr_command,
1697: TULIP_CSR_READ(sc, csr_command) | TULIP_CMD_PORTSELECT |
1698: TULIP_CMD_PCSFUNCTION | TULIP_CMD_SCRAMBLER | TULIP_CMD_MUSTBEONE);
1699: TULIP_CSR_WRITE(sc, csr_command,
1700: TULIP_CSR_READ(sc, csr_command) & ~TULIP_CMD_TXTHRSHLDCTL);
1701:
1702: DELAY(200000);
1703: for (idx = 1000; idx > 0; idx--) {
1704: u_int32_t csr = TULIP_CSR_READ(sc, csr_gp);
1705: 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)) {
1706: if (++cnt100 > 100)
1707: break;
1708: } else if ((csr & TULIP_GP_ZX34X_LNKFAIL) == 0) {
1709: if (++cnt10 > 100)
1710: break;
1711: } else {
1712: cnt10 = 0;
1713: cnt100 = 0;
1714: }
1715: DELAY(1000);
1716: }
1717: sc->tulip_media = cnt100 > 100 ? TULIP_MEDIA_100BASETX : TULIP_MEDIA_10BASET;
1718: tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_10BASET,
1719: TULIP_GP_ZX34X_INIT,
1720: TULIP_CMD_TXTHRSHLDCTL);
1721: tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_10BASET_FD,
1722: TULIP_GP_ZX34X_INIT,
1723: TULIP_CMD_TXTHRSHLDCTL|TULIP_CMD_FULLDUPLEX);
1724: tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX,
1725: TULIP_GP_ZX34X_INIT,
1726: TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
1727: |TULIP_CMD_SCRAMBLER);
1728: tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX_FD,
1729: TULIP_GP_ZX34X_INIT,
1730: TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
1731: |TULIP_CMD_SCRAMBLER|TULIP_CMD_FULLDUPLEX);
1732: }
1733:
1734: static const tulip_boardsw_t tulip_21140_znyx_zx34x_boardsw = {
1735: TULIP_21140_ZNYX_ZX34X,
1736: tulip_21140_znyx_zx34x_media_probe,
1737: tulip_media_select,
1738: tulip_null_media_poll,
1739: tulip_2114x_media_preset,
1740: };
1741:
1742: void
1743: tulip_2114x_media_probe(tulip_softc_t * const sc)
1744: {
1745: sc->tulip_cmdmode |= TULIP_CMD_MUSTBEONE
1746: |TULIP_CMD_BACKOFFCTR|TULIP_CMD_THRSHLD72;
1747: }
1748:
1749: static const tulip_boardsw_t tulip_2114x_isv_boardsw = {
1750: TULIP_21140_ISV,
1751: tulip_2114x_media_probe,
1752: tulip_media_select,
1753: tulip_media_poll,
1754: tulip_2114x_media_preset,
1755: };
1756:
1757: /*
1758: * ******** END of chip-specific handlers. ***********
1759: */
1760:
1761: /*
1762: * Code the read the SROM and MII bit streams (I2C)
1763: */
1764: void
1765: tulip_delay_300ns(tulip_softc_t * const sc)
1766: {
1767: int idx;
1768: for (idx = (300 / 33) + 1; idx > 0; idx--)
1769: (void) TULIP_CSR_READ(sc, csr_busmode);
1770: }
1771:
1772: void
1773: tulip_srom_idle(tulip_softc_t * const sc)
1774: {
1775: unsigned bit, csr;
1776:
1777: csr = SROMSEL ; EMIT;
1778: csr = SROMSEL | SROMRD; EMIT;
1779: csr ^= SROMCS; EMIT;
1780: csr ^= SROMCLKON; EMIT;
1781:
1782: /*
1783: * Write 25 cycles of 0 which will force the SROM to be idle.
1784: */
1785: for (bit = 3 + SROM_BITWIDTH + 16; bit > 0; bit--) {
1786: csr ^= SROMCLKOFF; EMIT; /* clock low; data not valid */
1787: csr ^= SROMCLKON; EMIT; /* clock high; data valid */
1788: }
1789: csr ^= SROMCLKOFF; EMIT;
1790: csr ^= SROMCS; EMIT;
1791: csr = 0; EMIT;
1792: }
1793:
1794: void
1795: tulip_srom_read(tulip_softc_t * const sc)
1796: {
1797: unsigned idx;
1798: const unsigned bitwidth = SROM_BITWIDTH;
1799: const unsigned cmdmask = (SROMCMD_RD << bitwidth);
1800: const unsigned msb = 1 << (bitwidth + 3 - 1);
1801: unsigned lastidx = (1 << bitwidth) - 1;
1802:
1803: tulip_srom_idle(sc);
1804:
1805: for (idx = 0; idx <= lastidx; idx++) {
1806: unsigned lastbit, data, bits, bit, csr;
1807: csr = SROMSEL ; EMIT;
1808: csr = SROMSEL | SROMRD; EMIT;
1809: csr ^= SROMCSON; EMIT;
1810: csr ^= SROMCLKON; EMIT;
1811:
1812: lastbit = 0;
1813: for (bits = idx|cmdmask, bit = bitwidth + 3; bit > 0; bit--, bits <<= 1) {
1814: const unsigned thisbit = bits & msb;
1815: csr ^= SROMCLKOFF; EMIT; /* clock low; data not valid */
1816: if (thisbit != lastbit) {
1817: csr ^= SROMDOUT; EMIT; /* clock low; invert data */
1818: } else {
1819: EMIT;
1820: }
1821: csr ^= SROMCLKON; EMIT; /* clock high; data valid */
1822: lastbit = thisbit;
1823: }
1824: csr ^= SROMCLKOFF; EMIT;
1825:
1826: for (data = 0, bits = 0; bits < 16; bits++) {
1827: data <<= 1;
1828: csr ^= SROMCLKON; EMIT; /* clock high; data valid */
1829: data |= TULIP_CSR_READ(sc, csr_srom_mii) & SROMDIN ? 1 : 0;
1830: csr ^= SROMCLKOFF; EMIT; /* clock low; data not valid */
1831: }
1832: sc->tulip_rombuf[idx*2] = data & 0xFF;
1833: sc->tulip_rombuf[idx*2+1] = data >> 8;
1834: csr = SROMSEL | SROMRD; EMIT;
1835: csr = 0; EMIT;
1836: }
1837: tulip_srom_idle(sc);
1838: }
1839:
1840: void
1841: tulip_mii_writebits(tulip_softc_t * const sc, unsigned data, unsigned bits)
1842: {
1843: unsigned msb = 1 << (bits - 1);
1844: unsigned csr = TULIP_CSR_READ(sc, csr_srom_mii) & (MII_RD|MII_DOUT|MII_CLK);
1845: unsigned lastbit = (csr & MII_DOUT) ? msb : 0;
1846:
1847: csr |= MII_WR; MII_EMIT; /* clock low; assert write */
1848:
1849: for (; bits > 0; bits--, data <<= 1) {
1850: const unsigned thisbit = data & msb;
1851: if (thisbit != lastbit)
1852: csr ^= MII_DOUT; MII_EMIT; /* clock low; invert data */
1853: csr ^= MII_CLKON; MII_EMIT; /* clock high; data valid */
1854: lastbit = thisbit;
1855: csr ^= MII_CLKOFF; MII_EMIT; /* clock low; data not valid */
1856: }
1857: }
1858:
1859: void
1860: tulip_mii_turnaround(tulip_softc_t * const sc, unsigned cmd)
1861: {
1862: unsigned csr = TULIP_CSR_READ(sc, csr_srom_mii) & (MII_RD|MII_DOUT|MII_CLK);
1863:
1864: if (cmd == MII_WRCMD) {
1865: csr |= MII_DOUT; MII_EMIT; /* clock low; change data */
1866: csr ^= MII_CLKON; MII_EMIT; /* clock high; data valid */
1867: csr ^= MII_CLKOFF; MII_EMIT; /* clock low; data not valid */
1868: csr ^= MII_DOUT; MII_EMIT; /* clock low; change data */
1869: } else
1870: csr |= MII_RD; MII_EMIT; /* clock low; switch to read */
1871: csr ^= MII_CLKON; MII_EMIT; /* clock high; data valid */
1872: csr ^= MII_CLKOFF; MII_EMIT; /* clock low; data not valid */
1873: }
1874:
1875: unsigned
1876: tulip_mii_readbits(tulip_softc_t * const sc)
1877: {
1878: unsigned data;
1879: unsigned csr = TULIP_CSR_READ(sc, csr_srom_mii) & (MII_RD|MII_DOUT|MII_CLK);
1880: int idx;
1881:
1882: for (idx = 0, data = 0; idx < 16; idx++) {
1883: data <<= 1; /* this is NOOP on the first pass through */
1884: csr ^= MII_CLKON; MII_EMIT; /* clock high; data valid */
1885: if (TULIP_CSR_READ(sc, csr_srom_mii) & MII_DIN)
1886: data |= 1;
1887: csr ^= MII_CLKOFF; MII_EMIT; /* clock low; data not valid */
1888: }
1889: csr ^= MII_RD; MII_EMIT; /* clock low; turn off read */
1890:
1891: return (data);
1892: }
1893:
1894: unsigned
1895: tulip_mii_readreg(tulip_softc_t * const sc, unsigned devaddr, unsigned regno)
1896: {
1897: unsigned csr = TULIP_CSR_READ(sc, csr_srom_mii) & (MII_RD|MII_DOUT|MII_CLK);
1898: unsigned data;
1899:
1900: csr &= ~(MII_RD|MII_CLK); MII_EMIT;
1901: tulip_mii_writebits(sc, MII_PREAMBLE, 32);
1902: tulip_mii_writebits(sc, MII_RDCMD, 8);
1903: tulip_mii_writebits(sc, devaddr, 5);
1904: tulip_mii_writebits(sc, regno, 5);
1905: tulip_mii_turnaround(sc, MII_RDCMD);
1906:
1907: data = tulip_mii_readbits(sc);
1908: #if defined(TULIP_DEBUG)
1909: sc->tulip_dbg.dbg_phyregs[regno][0] = data;
1910: sc->tulip_dbg.dbg_phyregs[regno][1]++;
1911: #endif
1912: return (data);
1913: }
1914:
1915: void
1916: tulip_mii_writereg(tulip_softc_t * const sc, unsigned devaddr,
1917: unsigned regno, unsigned data)
1918: {
1919: unsigned csr;
1920:
1921: csr = TULIP_CSR_READ(sc, csr_srom_mii) & (MII_RD|MII_DOUT|MII_CLK);
1922: csr &= ~(MII_RD|MII_CLK); MII_EMIT;
1923: tulip_mii_writebits(sc, MII_PREAMBLE, 32);
1924: tulip_mii_writebits(sc, MII_WRCMD, 8);
1925: tulip_mii_writebits(sc, devaddr, 5);
1926: tulip_mii_writebits(sc, regno, 5);
1927: tulip_mii_turnaround(sc, MII_WRCMD);
1928: tulip_mii_writebits(sc, data, 16);
1929: #if defined(TULIP_DEBUG)
1930: sc->tulip_dbg.dbg_phyregs[regno][2] = data;
1931: sc->tulip_dbg.dbg_phyregs[regno][3]++;
1932: #endif
1933: }
1934:
1935: void
1936: tulip_identify_dec_nic(tulip_softc_t * const sc)
1937: {
1938: strlcpy(sc->tulip_boardid, "DEC ", sizeof(sc->tulip_boardid));
1939: #define D0 4
1940: if (sc->tulip_chipid <= TULIP_DE425)
1941: return;
1942: if (bcmp(sc->tulip_rombuf + 29, "DE500", 5) == 0
1943: || bcmp(sc->tulip_rombuf + 29, "DE450", 5) == 0) {
1944: bcopy(sc->tulip_rombuf + 29, &sc->tulip_boardid[D0], 8);
1945: sc->tulip_boardid[D0+8] = ' ';
1946: }
1947: #undef D0
1948: }
1949:
1950: void
1951: tulip_identify_znyx_nic(tulip_softc_t * const sc)
1952: {
1953: unsigned id = 0;
1954: strlcpy(sc->tulip_boardid, "ZNYX ZX3XX ", sizeof(sc->tulip_boardid));
1955: if (sc->tulip_chipid == TULIP_21140 || sc->tulip_chipid == TULIP_21140A) {
1956: unsigned znyx_ptr;
1957: sc->tulip_boardid[8] = '4';
1958: znyx_ptr = sc->tulip_rombuf[124] + 256 * sc->tulip_rombuf[125];
1959: if (znyx_ptr < 26 || znyx_ptr > 116) {
1960: sc->tulip_boardsw = &tulip_21140_znyx_zx34x_boardsw;
1961: return;
1962: }
1963: /* ZX344 = 0010 .. 0013FF
1964: */
1965: if (sc->tulip_rombuf[znyx_ptr] == 0x4A
1966: && sc->tulip_rombuf[znyx_ptr + 1] == 0x52
1967: && sc->tulip_rombuf[znyx_ptr + 2] == 0x01) {
1968: id = sc->tulip_rombuf[znyx_ptr + 5] + 256 * sc->tulip_rombuf[znyx_ptr + 4];
1969: if ((id >> 8) == (TULIP_ZNYX_ID_ZX342 >> 8)) {
1970: sc->tulip_boardid[9] = '2';
1971: if (id == TULIP_ZNYX_ID_ZX342B) {
1972: sc->tulip_boardid[10] = 'B';
1973: sc->tulip_boardid[11] = ' ';
1974: }
1975: sc->tulip_boardsw = &tulip_21140_znyx_zx34x_boardsw;
1976: } else if (id == TULIP_ZNYX_ID_ZX344) {
1977: sc->tulip_boardid[10] = '4';
1978: sc->tulip_boardsw = &tulip_21140_znyx_zx34x_boardsw;
1979: } else if (id == TULIP_ZNYX_ID_ZX345) {
1980: sc->tulip_boardid[9] = (sc->tulip_rombuf[19] > 1) ? '8' : '5';
1981: } else if (id == TULIP_ZNYX_ID_ZX346) {
1982: sc->tulip_boardid[9] = '6';
1983: } else if (id == TULIP_ZNYX_ID_ZX351) {
1984: sc->tulip_boardid[8] = '5';
1985: sc->tulip_boardid[9] = '1';
1986: }
1987: }
1988: if (id == 0) {
1989: /*
1990: * Assume it's a ZX342...
1991: */
1992: sc->tulip_boardsw = &tulip_21140_znyx_zx34x_boardsw;
1993: }
1994: return;
1995: }
1996: sc->tulip_boardid[8] = '1';
1997: if (sc->tulip_chipid == TULIP_21041) {
1998: sc->tulip_boardid[10] = '1';
1999: return;
2000: }
2001: if (sc->tulip_rombuf[32] == 0x4A && sc->tulip_rombuf[33] == 0x52) {
2002: id = sc->tulip_rombuf[37] + 256 * sc->tulip_rombuf[36];
2003: if (id == TULIP_ZNYX_ID_ZX312T) {
2004: sc->tulip_boardid[9] = '2';
2005: sc->tulip_boardid[10] = 'T';
2006: sc->tulip_boardid[11] = ' ';
2007: sc->tulip_boardsw = &tulip_21040_10baset_only_boardsw;
2008: } else if (id == TULIP_ZNYX_ID_ZX314_INTA) {
2009: sc->tulip_boardid[9] = '4';
2010: sc->tulip_boardsw = &tulip_21040_10baset_only_boardsw;
2011: sc->tulip_features |= TULIP_HAVE_SHAREDINTR|TULIP_HAVE_BASEROM;
2012: } else if (id == TULIP_ZNYX_ID_ZX314) {
2013: sc->tulip_boardid[9] = '4';
2014: sc->tulip_boardsw = &tulip_21040_10baset_only_boardsw;
2015: sc->tulip_features |= TULIP_HAVE_BASEROM;
2016: } else if (id == TULIP_ZNYX_ID_ZX315_INTA) {
2017: sc->tulip_boardid[9] = '5';
2018: sc->tulip_features |= TULIP_HAVE_SHAREDINTR|TULIP_HAVE_BASEROM;
2019: } else if (id == TULIP_ZNYX_ID_ZX315) {
2020: sc->tulip_boardid[9] = '5';
2021: sc->tulip_features |= TULIP_HAVE_BASEROM;
2022: } else
2023: id = 0;
2024: }
2025: if (id == 0) {
2026: if ((sc->tulip_enaddr[3] & ~3) == 0xF0 && (sc->tulip_enaddr[5] & 3) == 0) {
2027: sc->tulip_boardid[9] = '4';
2028: sc->tulip_boardsw = &tulip_21040_10baset_only_boardsw;
2029: sc->tulip_features |= TULIP_HAVE_SHAREDINTR|TULIP_HAVE_BASEROM;
2030: } else if ((sc->tulip_enaddr[3] & ~3) == 0xF4 && (sc->tulip_enaddr[5] & 1) == 0) {
2031: sc->tulip_boardid[9] = '5';
2032: sc->tulip_boardsw = &tulip_21040_boardsw;
2033: sc->tulip_features |= TULIP_HAVE_SHAREDINTR|TULIP_HAVE_BASEROM;
2034: } else if ((sc->tulip_enaddr[3] & ~3) == 0xEC) {
2035: sc->tulip_boardid[9] = '2';
2036: sc->tulip_boardsw = &tulip_21040_boardsw;
2037: }
2038: }
2039: }
2040:
2041: void
2042: tulip_identify_smc_nic(tulip_softc_t * const sc)
2043: {
2044: u_int32_t id1, id2, ei;
2045: int auibnc = 0, utp = 0;
2046: char *cp;
2047:
2048: strlcpy(sc->tulip_boardid, "SMC ", sizeof(sc->tulip_boardid));
2049: if (sc->tulip_chipid == TULIP_21041)
2050: return;
2051: if (sc->tulip_chipid != TULIP_21040) {
2052: if (sc->tulip_boardsw != &tulip_2114x_isv_boardsw) {
2053: strlcat(sc->tulip_boardid, "9332DST ", sizeof(sc->tulip_boardid));
2054: sc->tulip_boardsw = &tulip_21140_smc9332_boardsw;
2055: } else if (sc->tulip_features & (TULIP_HAVE_BASEROM|TULIP_HAVE_SLAVEDROM))
2056: strlcat(sc->tulip_boardid, "9334BDT ", sizeof(sc->tulip_boardid));
2057: else
2058: strlcat(sc->tulip_boardid, "9332BDT ", sizeof(sc->tulip_boardid));
2059: return;
2060: }
2061: id1 = sc->tulip_rombuf[0x60] | (sc->tulip_rombuf[0x61] << 8);
2062: id2 = sc->tulip_rombuf[0x62] | (sc->tulip_rombuf[0x63] << 8);
2063: ei = sc->tulip_rombuf[0x66] | (sc->tulip_rombuf[0x67] << 8);
2064:
2065: strlcat(sc->tulip_boardid, "8432", sizeof(sc->tulip_boardid));
2066: cp = &sc->tulip_boardid[8];
2067: if ((id1 & 1) == 0)
2068: *cp++ = 'B', auibnc = 1;
2069: if ((id1 & 0xFF) > 0x32)
2070: *cp++ = 'T', utp = 1;
2071: if ((id1 & 0x4000) == 0)
2072: *cp++ = 'A', auibnc = 1;
2073: if (id2 == 0x15) {
2074: sc->tulip_boardid[7] = '4';
2075: *cp++ = '-';
2076: *cp++ = 'C';
2077: *cp++ = 'H';
2078: *cp++ = (ei ? '2' : '1');
2079: }
2080: *cp++ = ' ';
2081: *cp = '\0';
2082: if (utp && !auibnc)
2083: sc->tulip_boardsw = &tulip_21040_10baset_only_boardsw;
2084: else if (!utp && auibnc)
2085: sc->tulip_boardsw = &tulip_21040_auibnc_only_boardsw;
2086: }
2087:
2088: void
2089: tulip_identify_cogent_nic(tulip_softc_t * const sc)
2090: {
2091: strlcpy(sc->tulip_boardid, "Cogent ", sizeof(sc->tulip_boardid));
2092: if (sc->tulip_chipid == TULIP_21140 || sc->tulip_chipid == TULIP_21140A) {
2093: if (sc->tulip_rombuf[32] == TULIP_COGENT_EM100TX_ID) {
2094: strlcat(sc->tulip_boardid, "EM100TX ", sizeof(sc->tulip_boardid));
2095: sc->tulip_boardsw = &tulip_21140_cogent_em100_boardsw;
2096: #if defined(TULIP_COGENT_EM110TX_ID)
2097: } else if (sc->tulip_rombuf[32] == TULIP_COGENT_EM110TX_ID) {
2098: strlcat(sc->tulip_boardid, "EM110TX ", sizeof(sc->tulip_boardid));
2099: sc->tulip_boardsw = &tulip_21140_cogent_em100_boardsw;
2100: #endif
2101: } else if (sc->tulip_rombuf[32] == TULIP_COGENT_EM100FX_ID) {
2102: strlcat(sc->tulip_boardid, "EM100FX ", sizeof(sc->tulip_boardid));
2103: sc->tulip_boardsw = &tulip_21140_cogent_em100_boardsw;
2104: }
2105: /*
2106: * Magic number (0x24001109U) is the SubVendor (0x2400) and
2107: * SubDevId (0x1109) for the ANA6944TX (EM440TX).
2108: */
2109: if (*(u_int32_t *) sc->tulip_rombuf == 0x24001109U
2110: && (sc->tulip_features & TULIP_HAVE_BASEROM)) {
2111: /*
2112: * Cogent (Adaptec) is still mapping all INTs to INTA of
2113: * first 21140. Dumb! Dumb!
2114: */
2115: strlcat(sc->tulip_boardid, "EM440TX ", sizeof(sc->tulip_boardid));
2116: sc->tulip_features |= TULIP_HAVE_SHAREDINTR;
2117: }
2118: } else if (sc->tulip_chipid == TULIP_21040)
2119: sc->tulip_features |= TULIP_HAVE_SHAREDINTR|TULIP_HAVE_BASEROM;
2120: }
2121:
2122: void
2123: tulip_identify_accton_nic(tulip_softc_t * const sc)
2124: {
2125: strlcpy(sc->tulip_boardid, "ACCTON ", sizeof(sc->tulip_boardid));
2126: switch (sc->tulip_chipid) {
2127: case TULIP_21140A:
2128: strlcat(sc->tulip_boardid, "EN1207 ", sizeof(sc->tulip_boardid));
2129: if (sc->tulip_boardsw != &tulip_2114x_isv_boardsw)
2130: sc->tulip_boardsw = &tulip_21140_accton_boardsw;
2131: break;
2132: case TULIP_21140:
2133: strlcat(sc->tulip_boardid, "EN1207TX ", sizeof(sc->tulip_boardid));
2134: if (sc->tulip_boardsw != &tulip_2114x_isv_boardsw)
2135: sc->tulip_boardsw = &tulip_21140_eb_boardsw;
2136: break;
2137: case TULIP_21040:
2138: strlcat(sc->tulip_boardid, "EN1203 ", sizeof(sc->tulip_boardid));
2139: sc->tulip_boardsw = &tulip_21040_boardsw;
2140: break;
2141: case TULIP_21041:
2142: strlcat(sc->tulip_boardid, "EN1203 ", sizeof(sc->tulip_boardid));
2143: sc->tulip_boardsw = &tulip_21041_boardsw;
2144: break;
2145: default:
2146: sc->tulip_boardsw = &tulip_2114x_isv_boardsw;
2147: break;
2148: }
2149: }
2150:
2151: void
2152: tulip_identify_asante_nic(tulip_softc_t * const sc)
2153: {
2154: strlcpy(sc->tulip_boardid, "Asante ", sizeof(sc->tulip_boardid));
2155: if ((sc->tulip_chipid == TULIP_21140 || sc->tulip_chipid == TULIP_21140A)
2156: && sc->tulip_boardsw != &tulip_2114x_isv_boardsw) {
2157: tulip_media_info_t *mi = sc->tulip_mediainfo;
2158: int idx;
2159: /*
2160: * The Asante Fast Ethernet doesn't always ship with a valid
2161: * new format SROM. So if isn't in the new format, we cheat
2162: * set it up as if we had.
2163: */
2164:
2165: sc->tulip_gpinit = TULIP_GP_ASANTE_PINS;
2166: sc->tulip_gpdata = 0;
2167:
2168: TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_ASANTE_PINS|TULIP_GP_PINSET);
2169: TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_ASANTE_PHYRESET);
2170: DELAY(100);
2171: TULIP_CSR_WRITE(sc, csr_gp, 0);
2172:
2173: mi->mi_type = TULIP_MEDIAINFO_MII;
2174: mi->mi_gpr_length = 0;
2175: mi->mi_gpr_offset = 0;
2176: mi->mi_reset_length = 0;
2177: mi->mi_reset_offset = 0;
2178:
2179: mi->mi_phyaddr = TULIP_MII_NOPHY;
2180: for (idx = 20; idx > 0 && mi->mi_phyaddr == TULIP_MII_NOPHY; idx--) {
2181: DELAY(10000);
2182: mi->mi_phyaddr = tulip_mii_get_phyaddr(sc, 0);
2183: }
2184: if (mi->mi_phyaddr == TULIP_MII_NOPHY) {
2185: #ifdef TULIP_DEBUG
2186: printf(TULIP_PRINTF_FMT ": can't find phy 0\n", TULIP_PRINTF_ARGS);
2187: #endif
2188: return;
2189: }
2190:
2191: sc->tulip_features |= TULIP_HAVE_MII;
2192: mi->mi_capabilities = PHYSTS_10BASET|PHYSTS_10BASET_FD|PHYSTS_100BASETX|PHYSTS_100BASETX_FD;
2193: mi->mi_advertisement = PHYSTS_10BASET|PHYSTS_10BASET_FD|PHYSTS_100BASETX|PHYSTS_100BASETX_FD;
2194: mi->mi_full_duplex = PHYSTS_10BASET_FD|PHYSTS_100BASETX_FD;
2195: mi->mi_tx_threshold = PHYSTS_10BASET|PHYSTS_10BASET_FD;
2196: TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASETX_FD);
2197: TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASETX);
2198: TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASET4);
2199: TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 10BASET_FD);
2200: TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 10BASET);
2201: mi->mi_phyid = (tulip_mii_readreg(sc, mi->mi_phyaddr, PHYREG_IDLOW) << 16) |
2202: tulip_mii_readreg(sc, mi->mi_phyaddr, PHYREG_IDHIGH);
2203:
2204: sc->tulip_boardsw = &tulip_2114x_isv_boardsw;
2205: }
2206: }
2207:
2208: void
2209: tulip_identify_compex_nic(tulip_softc_t * const sc)
2210: {
2211: strlcpy(sc->tulip_boardid, "COMPEX ", sizeof(sc->tulip_boardid));
2212: if (sc->tulip_chipid == TULIP_21140A) {
2213: int root_unit;
2214: tulip_softc_t *root_sc = NULL;
2215:
2216: strlcat(sc->tulip_boardid, "400TX/PCI ", sizeof(sc->tulip_boardid));
2217: /*
2218: * All 4 chips on these boards share an interrupt. This code
2219: * copied from tulip_read_macaddr.
2220: */
2221: sc->tulip_features |= TULIP_HAVE_SHAREDINTR;
2222: for (root_unit = sc->tulip_unit - 1; root_unit >= 0; root_unit--) {
2223: root_sc = TULIP_UNIT_TO_SOFTC(root_unit);
2224: if (root_sc == NULL
2225: || !(root_sc->tulip_features & TULIP_HAVE_SLAVEDINTR))
2226: break;
2227: root_sc = NULL;
2228: }
2229: if (root_sc != NULL
2230: && root_sc->tulip_chipid == sc->tulip_chipid
2231: && root_sc->tulip_pci_busno == sc->tulip_pci_busno) {
2232: sc->tulip_features |= TULIP_HAVE_SLAVEDINTR;
2233: sc->tulip_slaves = root_sc->tulip_slaves;
2234: root_sc->tulip_slaves = sc;
2235: } else if(sc->tulip_features & TULIP_HAVE_SLAVEDINTR)
2236: printf("\nCannot find master device for de%d interrupts", sc->tulip_unit);
2237: } else
2238: strlcat(sc->tulip_boardid, "unknown ", sizeof(sc->tulip_boardid));
2239:
2240: /* sc->tulip_boardsw = &tulip_21140_eb_boardsw; */
2241: }
2242:
2243: int
2244: tulip_srom_decode(tulip_softc_t * const sc)
2245: {
2246: unsigned idx1, idx2, idx3;
2247:
2248: const tulip_srom_header_t *shp = (tulip_srom_header_t *) &sc->tulip_rombuf[0];
2249: const tulip_srom_adapter_info_t *saip = (tulip_srom_adapter_info_t *) (shp + 1);
2250: tulip_srom_media_t srom_media;
2251: tulip_media_info_t *mi = sc->tulip_mediainfo;
2252: const u_int8_t *dp;
2253: u_int32_t leaf_offset, blocks, data;
2254:
2255: for (idx1 = 0; idx1 < shp->sh_adapter_count; idx1++, saip++) {
2256: if (shp->sh_adapter_count == 1)
2257: break;
2258: if (saip->sai_device == sc->tulip_pci_devno)
2259: break;
2260: }
2261: /*
2262: * Didn't find the right media block for this card.
2263: */
2264: if (idx1 == shp->sh_adapter_count)
2265: return (0);
2266:
2267: /*
2268: * Save the hardware address.
2269: */
2270: bcopy((caddr_t) shp->sh_ieee802_address, (caddr_t) sc->tulip_enaddr,
2271: ETHER_ADDR_LEN);
2272: /*
2273: * If this is a multiple port card, add the adapter index to the last
2274: * byte of the hardware address. (if it isn't multiport, adding 0
2275: * won't hurt.
2276: */
2277: sc->tulip_enaddr[5] += idx1;
2278:
2279: leaf_offset = saip->sai_leaf_offset_lowbyte
2280: + saip->sai_leaf_offset_highbyte * 256;
2281: dp = sc->tulip_rombuf + leaf_offset;
2282:
2283: sc->tulip_conntype = (tulip_srom_connection_t) (dp[0] + dp[1] * 256); dp += 2;
2284:
2285: for (idx2 = 0;; idx2++) {
2286: if (tulip_srom_conninfo[idx2].sc_type == sc->tulip_conntype
2287: || tulip_srom_conninfo[idx2].sc_type == TULIP_SROM_CONNTYPE_NOT_USED)
2288: break;
2289: }
2290: sc->tulip_connidx = idx2;
2291:
2292: if (sc->tulip_chipid == TULIP_21041) {
2293: blocks = *dp++;
2294: for (idx2 = 0; idx2 < blocks; idx2++) {
2295: tulip_media_t media;
2296: data = *dp++;
2297: srom_media = (tulip_srom_media_t) (data & 0x3F);
2298: for (idx3 = 0; tulip_srom_mediums[idx3].sm_type != TULIP_MEDIA_UNKNOWN; idx3++) {
2299: if (tulip_srom_mediums[idx3].sm_srom_type == srom_media)
2300: break;
2301: }
2302: media = tulip_srom_mediums[idx3].sm_type;
2303: if (media != TULIP_MEDIA_UNKNOWN) {
2304: if (data & TULIP_SROM_21041_EXTENDED) {
2305: mi->mi_type = TULIP_MEDIAINFO_SIA;
2306: sc->tulip_mediums[media] = mi;
2307: mi->mi_sia_connectivity = dp[0] + dp[1] * 256;
2308: mi->mi_sia_tx_rx = dp[2] + dp[3] * 256;
2309: mi->mi_sia_general = dp[4] + dp[5] * 256;
2310: mi++;
2311: } else {
2312: switch (media) {
2313: case TULIP_MEDIA_BNC: {
2314: TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21041, BNC);
2315: mi++;
2316: break;
2317: }
2318: case TULIP_MEDIA_AUI: {
2319: TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21041, AUI);
2320: mi++;
2321: break;
2322: }
2323: case TULIP_MEDIA_10BASET: {
2324: TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21041, 10BASET);
2325: mi++;
2326: break;
2327: }
2328: case TULIP_MEDIA_10BASET_FD: {
2329: TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21041, 10BASET_FD);
2330: mi++;
2331: break;
2332: }
2333: default: {
2334: break;
2335: }
2336: }
2337: }
2338: }
2339: if (data & TULIP_SROM_21041_EXTENDED)
2340: dp += 6;
2341: }
2342: } else {
2343: unsigned length, type;
2344: tulip_media_t gp_media = TULIP_MEDIA_UNKNOWN;
2345: if (sc->tulip_features & TULIP_HAVE_GPR)
2346: sc->tulip_gpinit = *dp++;
2347: blocks = *dp++;
2348: for (idx2 = 0; idx2 < blocks; idx2++) {
2349: const u_int8_t *ep;
2350: if ((*dp & 0x80) == 0) {
2351: length = 4;
2352: type = 0;
2353: } else {
2354: length = (*dp++ & 0x7f) - 1;
2355: type = *dp++ & 0x3f;
2356: }
2357: ep = dp + length;
2358: switch (type & 0x3f) {
2359: case 0: { /* 21140[A] GPR block */
2360: tulip_media_t media;
2361: srom_media = (tulip_srom_media_t)(dp[0] & 0x3f);
2362: for (idx3 = 0; tulip_srom_mediums[idx3].sm_type != TULIP_MEDIA_UNKNOWN; idx3++) {
2363: if (tulip_srom_mediums[idx3].sm_srom_type == srom_media)
2364: break;
2365: }
2366: media = tulip_srom_mediums[idx3].sm_type;
2367: if (media == TULIP_MEDIA_UNKNOWN)
2368: break;
2369: mi->mi_type = TULIP_MEDIAINFO_GPR;
2370: sc->tulip_mediums[media] = mi;
2371: mi->mi_gpdata = dp[1];
2372: if (media > gp_media && !TULIP_IS_MEDIA_FD(media)) {
2373: sc->tulip_gpdata = mi->mi_gpdata;
2374: gp_media = media;
2375: }
2376: data = dp[2] + dp[3] * 256;
2377: mi->mi_cmdmode = TULIP_SROM_2114X_CMDBITS(data);
2378: if (data & TULIP_SROM_2114X_NOINDICATOR)
2379: mi->mi_actmask = 0;
2380: else {
2381: mi->mi_actmask = TULIP_SROM_2114X_BITPOS(data);
2382: mi->mi_actdata = (data & TULIP_SROM_2114X_POLARITY) ? 0 : mi->mi_actmask;
2383: }
2384: mi++;
2385: break;
2386: }
2387: case 1: { /* 21140[A] MII block */
2388: const unsigned phyno = *dp++;
2389: mi->mi_type = TULIP_MEDIAINFO_MII;
2390: mi->mi_gpr_length = *dp++;
2391: mi->mi_gpr_offset = dp - sc->tulip_rombuf;
2392: dp += mi->mi_gpr_length;
2393: mi->mi_reset_length = *dp++;
2394: mi->mi_reset_offset = dp - sc->tulip_rombuf;
2395: dp += mi->mi_reset_length;
2396:
2397: /*
2398: * Before we probe for a PHY, use the GPR information
2399: * to select it. If we don't, it may be inaccessible.
2400: */
2401: TULIP_CSR_WRITE(sc, csr_gp, sc->tulip_gpinit|TULIP_GP_PINSET);
2402: for (idx3 = 0; idx3 < mi->mi_reset_length; idx3++) {
2403: DELAY(10);
2404: TULIP_CSR_WRITE(sc, csr_gp, sc->tulip_rombuf[mi->mi_reset_offset + idx3]);
2405: }
2406: sc->tulip_phyaddr = mi->mi_phyaddr;
2407: for (idx3 = 0; idx3 < mi->mi_gpr_length; idx3++) {
2408: DELAY(10);
2409: TULIP_CSR_WRITE(sc, csr_gp, sc->tulip_rombuf[mi->mi_gpr_offset + idx3]);
2410: }
2411:
2412: /*
2413: * At least write something!
2414: */
2415: if (mi->mi_reset_length == 0 && mi->mi_gpr_length == 0)
2416: TULIP_CSR_WRITE(sc, csr_gp, 0);
2417:
2418: mi->mi_phyaddr = TULIP_MII_NOPHY;
2419: for (idx3 = 20; idx3 > 0 && mi->mi_phyaddr == TULIP_MII_NOPHY; idx3--) {
2420: DELAY(10000);
2421: mi->mi_phyaddr = tulip_mii_get_phyaddr(sc, phyno);
2422: }
2423: if (mi->mi_phyaddr == TULIP_MII_NOPHY) {
2424: #if defined(TULIP_DEBUG)
2425: printf(TULIP_PRINTF_FMT ": can't find phy %d\n",
2426: TULIP_PRINTF_ARGS, phyno);
2427: #endif
2428: break;
2429: }
2430: sc->tulip_features |= TULIP_HAVE_MII;
2431: mi->mi_capabilities = dp[0] + dp[1] * 256; dp += 2;
2432: mi->mi_advertisement = dp[0] + dp[1] * 256; dp += 2;
2433: mi->mi_full_duplex = dp[0] + dp[1] * 256; dp += 2;
2434: mi->mi_tx_threshold = dp[0] + dp[1] * 256; dp += 2;
2435: TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASETX_FD);
2436: TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASETX);
2437: TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASET4);
2438: TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 10BASET_FD);
2439: TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 10BASET);
2440: mi->mi_phyid = (tulip_mii_readreg(sc, mi->mi_phyaddr, PHYREG_IDLOW) << 16) |
2441: tulip_mii_readreg(sc, mi->mi_phyaddr, PHYREG_IDHIGH);
2442: mi++;
2443: break;
2444: }
2445: case 2: { /* 2114[23] SIA block */
2446: tulip_media_t media;
2447: srom_media = (tulip_srom_media_t)(dp[0] & 0x3f);
2448: for (idx3 = 0; tulip_srom_mediums[idx3].sm_type != TULIP_MEDIA_UNKNOWN; idx3++) {
2449: if (tulip_srom_mediums[idx3].sm_srom_type == srom_media)
2450: break;
2451: }
2452: media = tulip_srom_mediums[idx3].sm_type;
2453: if (media == TULIP_MEDIA_UNKNOWN)
2454: break;
2455: mi->mi_type = TULIP_MEDIAINFO_SIA;
2456: sc->tulip_mediums[media] = mi;
2457: if (dp[0] & 0x40) {
2458: mi->mi_sia_connectivity = dp[1] + dp[2] * 256;
2459: mi->mi_sia_tx_rx = dp[3] + dp[4] * 256;
2460: mi->mi_sia_general = dp[5] + dp[6] * 256;
2461: dp += 6;
2462: } else {
2463: switch (media) {
2464: case TULIP_MEDIA_BNC: {
2465: TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21142, BNC);
2466: break;
2467: }
2468: case TULIP_MEDIA_AUI: {
2469: TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21142, AUI);
2470: break;
2471: }
2472: case TULIP_MEDIA_10BASET: {
2473: TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21142, 10BASET);
2474: sc->tulip_intrmask |= TULIP_STS_LINKPASS|TULIP_STS_LINKFAIL;
2475: break;
2476: }
2477: case TULIP_MEDIA_10BASET_FD: {
2478: TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21142, 10BASET_FD);
2479: sc->tulip_intrmask |= TULIP_STS_LINKPASS|TULIP_STS_LINKFAIL;
2480: break;
2481: }
2482: default: {
2483: goto bad_media;
2484: }
2485: }
2486: }
2487: mi->mi_sia_gp_control = (dp[1] + dp[2] * 256) << 16;
2488: mi->mi_sia_gp_data = (dp[3] + dp[4] * 256) << 16;
2489: mi++;
2490: bad_media:
2491: break;
2492: }
2493: case 3: { /* 2114[23] MII PHY block */
2494: const unsigned phyno = *dp++;
2495: const u_int8_t *dp0;
2496: mi->mi_type = TULIP_MEDIAINFO_MII;
2497: mi->mi_gpr_length = *dp++;
2498: mi->mi_gpr_offset = dp - sc->tulip_rombuf;
2499: dp += 2 * mi->mi_gpr_length;
2500: mi->mi_reset_length = *dp++;
2501: mi->mi_reset_offset = dp - sc->tulip_rombuf;
2502: dp += 2 * mi->mi_reset_length;
2503:
2504: dp0 = &sc->tulip_rombuf[mi->mi_reset_offset];
2505: for (idx3 = 0; idx3 < mi->mi_reset_length; idx3++, dp0 += 2) {
2506: DELAY(10);
2507: TULIP_CSR_WRITE(sc, csr_sia_general, (dp0[0] + 256 * dp0[1]) << 16);
2508: }
2509: sc->tulip_phyaddr = mi->mi_phyaddr;
2510: dp0 = &sc->tulip_rombuf[mi->mi_gpr_offset];
2511: for (idx3 = 0; idx3 < mi->mi_gpr_length; idx3++, dp0 += 2) {
2512: DELAY(10);
2513: TULIP_CSR_WRITE(sc, csr_sia_general, (dp0[0] + 256 * dp0[1]) << 16);
2514: }
2515:
2516: if (mi->mi_reset_length == 0 && mi->mi_gpr_length == 0)
2517: TULIP_CSR_WRITE(sc, csr_sia_general, 0);
2518:
2519: mi->mi_phyaddr = TULIP_MII_NOPHY;
2520: for (idx3 = 20; idx3 > 0 && mi->mi_phyaddr == TULIP_MII_NOPHY; idx3--) {
2521: DELAY(10000);
2522: mi->mi_phyaddr = tulip_mii_get_phyaddr(sc, phyno);
2523: }
2524: if (mi->mi_phyaddr == TULIP_MII_NOPHY) {
2525: #if defined(TULIP_DEBUG)
2526: printf(TULIP_PRINTF_FMT ": can't find phy %d\n",
2527: TULIP_PRINTF_ARGS, phyno);
2528: #endif
2529: break;
2530: }
2531: sc->tulip_features |= TULIP_HAVE_MII;
2532: mi->mi_capabilities = dp[0] + dp[1] * 256; dp += 2;
2533: mi->mi_advertisement = dp[0] + dp[1] * 256; dp += 2;
2534: mi->mi_full_duplex = dp[0] + dp[1] * 256; dp += 2;
2535: mi->mi_tx_threshold = dp[0] + dp[1] * 256; dp += 2;
2536: mi->mi_mii_interrupt = dp[0] + dp[1] * 256; dp += 2;
2537: TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASETX_FD);
2538: TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASETX);
2539: TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASET4);
2540: TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 10BASET_FD);
2541: TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 10BASET);
2542: mi->mi_phyid = (tulip_mii_readreg(sc, mi->mi_phyaddr, PHYREG_IDLOW) << 16) |
2543: tulip_mii_readreg(sc, mi->mi_phyaddr, PHYREG_IDHIGH);
2544: mi++;
2545: break;
2546: }
2547: case 4: { /* 21143 SYM block */
2548: tulip_media_t media;
2549: srom_media = (tulip_srom_media_t) dp[0];
2550: for (idx3 = 0; tulip_srom_mediums[idx3].sm_type != TULIP_MEDIA_UNKNOWN; idx3++) {
2551: if (tulip_srom_mediums[idx3].sm_srom_type == srom_media)
2552: break;
2553: }
2554: media = tulip_srom_mediums[idx3].sm_type;
2555: if (media == TULIP_MEDIA_UNKNOWN)
2556: break;
2557: mi->mi_type = TULIP_MEDIAINFO_SYM;
2558: sc->tulip_mediums[media] = mi;
2559: mi->mi_gpcontrol = (dp[1] + dp[2] * 256) << 16;
2560: mi->mi_gpdata = (dp[3] + dp[4] * 256) << 16;
2561: data = dp[5] + dp[6] * 256;
2562: mi->mi_cmdmode = TULIP_SROM_2114X_CMDBITS(data);
2563: if (data & TULIP_SROM_2114X_NOINDICATOR)
2564: mi->mi_actmask = 0;
2565: else {
2566: mi->mi_default = (data & TULIP_SROM_2114X_DEFAULT) != 0;
2567: mi->mi_actmask = TULIP_SROM_2114X_BITPOS(data);
2568: mi->mi_actdata = (data & TULIP_SROM_2114X_POLARITY) ? 0 : mi->mi_actmask;
2569: }
2570: if (TULIP_IS_MEDIA_TP(media))
2571: sc->tulip_intrmask |= TULIP_STS_LINKPASS|TULIP_STS_LINKFAIL;
2572: mi++;
2573: break;
2574: }
2575: default: {
2576: }
2577: }
2578: dp = ep;
2579: }
2580: }
2581: return (mi - sc->tulip_mediainfo);
2582: }
2583:
2584: static const struct {
2585: void (*vendor_identify_nic)(tulip_softc_t * const sc);
2586: unsigned char vendor_oui[3];
2587: } tulip_vendors[] = {
2588: { tulip_identify_dec_nic, { 0x08, 0x00, 0x2B } },
2589: { tulip_identify_dec_nic, { 0x00, 0x00, 0xF8 } },
2590: { tulip_identify_smc_nic, { 0x00, 0x00, 0xC0 } },
2591: { tulip_identify_smc_nic, { 0x00, 0xE0, 0x29 } },
2592: { tulip_identify_znyx_nic, { 0x00, 0xC0, 0x95 } },
2593: { tulip_identify_cogent_nic, { 0x00, 0x00, 0x92 } },
2594: { tulip_identify_cogent_nic, { 0x00, 0x00, 0xD1 } },
2595: { tulip_identify_asante_nic, { 0x00, 0x00, 0x94 } },
2596: { tulip_identify_accton_nic, { 0x00, 0x00, 0xE8 } },
2597: { tulip_identify_compex_nic, { 0x00, 0x80, 0x48 } },
2598: { NULL }
2599: };
2600:
2601: /*
2602: * This deals with the vagaries of the address roms and the
2603: * brain-deadness that various vendors commit in using them.
2604: */
2605: int
2606: tulip_read_macaddr(tulip_softc_t * const sc)
2607: {
2608: unsigned cksum, rom_cksum, idx;
2609: u_int32_t csr;
2610: unsigned char tmpbuf[8];
2611: static const u_char testpat[] = { 0xFF, 0, 0x55, 0xAA, 0xFF, 0, 0x55, 0xAA };
2612:
2613: sc->tulip_connidx = TULIP_SROM_LASTCONNIDX;
2614:
2615: if (sc->tulip_chipid == TULIP_21040) {
2616: TULIP_CSR_WRITE(sc, csr_enetrom, 1);
2617: for (idx = 0; idx < sizeof(sc->tulip_rombuf); idx++) {
2618: int cnt = 0;
2619: while (((csr = TULIP_CSR_READ(sc, csr_enetrom)) & 0x80000000L) && cnt < 10000)
2620: cnt++;
2621: sc->tulip_rombuf[idx] = csr & 0xFF;
2622: }
2623: sc->tulip_boardsw = &tulip_21040_boardsw;
2624: } else {
2625: if (sc->tulip_chipid == TULIP_21041) {
2626: /*
2627: * Thankfully all 21041's act the same.
2628: */
2629: sc->tulip_boardsw = &tulip_21041_boardsw;
2630: } else {
2631: /*
2632: * Assume all 21140 board are compatible with the
2633: * DEC 10/100 evaluation board. Not really valid but
2634: * it's the best we can do until every one switches to
2635: * the new SROM format.
2636: */
2637:
2638: sc->tulip_boardsw = &tulip_21140_eb_boardsw;
2639: }
2640: tulip_srom_read(sc);
2641: if (tulip_srom_crcok(sc->tulip_rombuf)) {
2642: /*
2643: * SROM CRC is valid therefore it must be in the
2644: * new format.
2645: */
2646: sc->tulip_features |= TULIP_HAVE_ISVSROM|TULIP_HAVE_OKSROM;
2647: } else if (sc->tulip_rombuf[126] == 0xff && sc->tulip_rombuf[127] == 0xFF) {
2648: /*
2649: * No checksum is present. See if the SROM id checks out;
2650: * the first 18 bytes should be 0 followed by a 1 followed
2651: * by the number of adapters (which we don't deal with yet).
2652: */
2653: for (idx = 0; idx < 18; idx++) {
2654: if (sc->tulip_rombuf[idx] != 0)
2655: break;
2656: }
2657: if (idx == 18 && sc->tulip_rombuf[18] == 1 && sc->tulip_rombuf[19] != 0)
2658: sc->tulip_features |= TULIP_HAVE_ISVSROM;
2659: } else if (sc->tulip_chipid >= TULIP_21142) {
2660: sc->tulip_features |= TULIP_HAVE_ISVSROM;
2661: sc->tulip_boardsw = &tulip_2114x_isv_boardsw;
2662: }
2663: if ((sc->tulip_features & TULIP_HAVE_ISVSROM) && tulip_srom_decode(sc)) {
2664: if (sc->tulip_chipid != TULIP_21041)
2665: sc->tulip_boardsw = &tulip_2114x_isv_boardsw;
2666:
2667: /*
2668: * If the SROM specifies more than one adapter, tag this as a
2669: * BASE rom.
2670: */
2671: if (sc->tulip_rombuf[19] > 1)
2672: sc->tulip_features |= TULIP_HAVE_BASEROM;
2673: if (sc->tulip_boardsw == NULL)
2674: return (-6);
2675: goto check_oui;
2676: }
2677: }
2678:
2679: if (bcmp(&sc->tulip_rombuf[0], &sc->tulip_rombuf[16], 8) != 0) {
2680: /*
2681: * Some folks don't use the standard ethernet rom format
2682: * but instead just put the address in the first 6 bytes
2683: * of the rom and let the rest be all 0xffs. (Can we say
2684: * ZNYX???) (well sometimes they put in a checksum so we'll
2685: * start at 8).
2686: */
2687: for (idx = 8; idx < 32; idx++) {
2688: if (sc->tulip_rombuf[idx] != 0xFF)
2689: return (-4);
2690: }
2691: /*
2692: * Make sure the address is not multicast or locally assigned
2693: * that the OUI is not 00-00-00.
2694: */
2695: if ((sc->tulip_rombuf[0] & 3) != 0)
2696: return (-4);
2697: if (sc->tulip_rombuf[0] == 0 && sc->tulip_rombuf[1] == 0
2698: && sc->tulip_rombuf[2] == 0)
2699: return (-4);
2700: bcopy(sc->tulip_rombuf, sc->tulip_enaddr, ETHER_ADDR_LEN);
2701: sc->tulip_features |= TULIP_HAVE_OKROM;
2702: goto check_oui;
2703: } else {
2704: /*
2705: * A number of makers of multiport boards (ZNYX and Cogent)
2706: * only put on one address ROM on their 21040 boards. So
2707: * if the ROM is all zeros (or all 0xFFs), look at the
2708: * previous configured boards (as long as they are on the same
2709: * PCI bus and the bus number is non-zero) until we find the
2710: * master board with address ROM. We then use its address ROM
2711: * as the base for this board. (we add our relative board
2712: * to the last byte of its address).
2713: */
2714: for (idx = 0; idx < sizeof(sc->tulip_rombuf); idx++) {
2715: if (sc->tulip_rombuf[idx] != 0 && sc->tulip_rombuf[idx] != 0xFF)
2716: break;
2717: }
2718: if (idx == sizeof(sc->tulip_rombuf)) {
2719: int root_unit;
2720: tulip_softc_t *root_sc = NULL;
2721: for (root_unit = sc->tulip_unit - 1; root_unit >= 0; root_unit--) {
2722: root_sc = TULIP_UNIT_TO_SOFTC(root_unit);
2723: if (root_sc == NULL || (root_sc->tulip_features & (TULIP_HAVE_OKROM|TULIP_HAVE_SLAVEDROM)) == TULIP_HAVE_OKROM)
2724: break;
2725: root_sc = NULL;
2726: }
2727: if (root_sc != NULL && (root_sc->tulip_features & TULIP_HAVE_BASEROM)
2728: && root_sc->tulip_chipid == sc->tulip_chipid
2729: && root_sc->tulip_pci_busno == sc->tulip_pci_busno) {
2730: sc->tulip_features |= TULIP_HAVE_SLAVEDROM;
2731: sc->tulip_boardsw = root_sc->tulip_boardsw;
2732: strlcpy(sc->tulip_boardid, root_sc->tulip_boardid,
2733: sizeof(sc->tulip_boardid));
2734: if (sc->tulip_boardsw->bd_type == TULIP_21140_ISV) {
2735: bcopy(root_sc->tulip_rombuf, sc->tulip_rombuf,
2736: sizeof(sc->tulip_rombuf));
2737: if (!tulip_srom_decode(sc))
2738: return (-5);
2739: } else {
2740: bcopy(root_sc->tulip_enaddr, sc->tulip_enaddr,
2741: ETHER_ADDR_LEN);
2742: sc->tulip_enaddr[5] += sc->tulip_unit - root_sc->tulip_unit;
2743: }
2744: /*
2745: * Now for a truly disgusting kludge: all 4 21040s on
2746: * the ZX314 share the same INTA line so the mapping
2747: * setup by the BIOS on the PCI bridge is worthless.
2748: * Rather than reprogramming the value in the config
2749: * register, we will handle this internally.
2750: */
2751: if (root_sc->tulip_features & TULIP_HAVE_SHAREDINTR) {
2752: sc->tulip_slaves = root_sc->tulip_slaves;
2753: root_sc->tulip_slaves = sc;
2754: sc->tulip_features |= TULIP_HAVE_SLAVEDINTR;
2755: }
2756: return (0);
2757: }
2758: }
2759: }
2760:
2761: /*
2762: * This is the standard DEC address ROM test.
2763: */
2764:
2765: if (bcmp(&sc->tulip_rombuf[24], testpat, 8) != 0)
2766: return (-3);
2767:
2768: tmpbuf[0] = sc->tulip_rombuf[15]; tmpbuf[1] = sc->tulip_rombuf[14];
2769: tmpbuf[2] = sc->tulip_rombuf[13]; tmpbuf[3] = sc->tulip_rombuf[12];
2770: tmpbuf[4] = sc->tulip_rombuf[11]; tmpbuf[5] = sc->tulip_rombuf[10];
2771: tmpbuf[6] = sc->tulip_rombuf[9]; tmpbuf[7] = sc->tulip_rombuf[8];
2772: if (bcmp(&sc->tulip_rombuf[0], tmpbuf, 8) != 0)
2773: return (-2);
2774:
2775: bcopy(sc->tulip_rombuf, sc->tulip_enaddr, ETHER_ADDR_LEN);
2776:
2777: cksum = *(u_int16_t *) &sc->tulip_enaddr[0];
2778: cksum *= 2;
2779: if (cksum > 65535) cksum -= 65535;
2780: cksum += *(u_int16_t *) &sc->tulip_enaddr[2];
2781: if (cksum > 65535) cksum -= 65535;
2782: cksum *= 2;
2783: if (cksum > 65535) cksum -= 65535;
2784: cksum += *(u_int16_t *) &sc->tulip_enaddr[4];
2785: if (cksum >= 65535) cksum -= 65535;
2786:
2787: rom_cksum = *(u_int16_t *) &sc->tulip_rombuf[6];
2788:
2789: if (cksum != rom_cksum)
2790: return (-1);
2791:
2792: check_oui:
2793: /*
2794: * Check for various boards based on OUI. Did I say braindead?
2795: */
2796: for (idx = 0; tulip_vendors[idx].vendor_identify_nic != NULL; idx++) {
2797: if (bcmp((caddr_t) sc->tulip_enaddr,
2798: (caddr_t) tulip_vendors[idx].vendor_oui, 3) == 0) {
2799: (*tulip_vendors[idx].vendor_identify_nic)(sc);
2800: break;
2801: }
2802: }
2803:
2804: sc->tulip_features |= TULIP_HAVE_OKROM;
2805: return (0);
2806: }
2807:
2808: void
2809: tulip_ifmedia_add(tulip_softc_t * const sc)
2810: {
2811: tulip_media_t media;
2812: int medias = 0;
2813:
2814: for (media = TULIP_MEDIA_UNKNOWN; media < TULIP_MEDIA_MAX; media++) {
2815: if (sc->tulip_mediums[media] != NULL) {
2816: ifmedia_add(&sc->tulip_ifmedia, tulip_media_to_ifmedia[media],
2817: 0, 0);
2818: medias++;
2819: }
2820: }
2821: if (medias == 0) {
2822: sc->tulip_features |= TULIP_HAVE_NOMEDIA;
2823: ifmedia_add(&sc->tulip_ifmedia, IFM_ETHER | IFM_NONE, 0, 0);
2824: ifmedia_set(&sc->tulip_ifmedia, IFM_ETHER | IFM_NONE);
2825: } else if (sc->tulip_media == TULIP_MEDIA_UNKNOWN) {
2826: ifmedia_add(&sc->tulip_ifmedia, IFM_ETHER | IFM_AUTO, 0, 0);
2827: ifmedia_set(&sc->tulip_ifmedia, IFM_ETHER | IFM_AUTO);
2828: } else {
2829: ifmedia_set(&sc->tulip_ifmedia, tulip_media_to_ifmedia[sc->tulip_media]);
2830: sc->tulip_flags |= TULIP_PRINTMEDIA;
2831: tulip_linkup(sc, sc->tulip_media);
2832: }
2833: }
2834:
2835: int
2836: tulip_ifmedia_change(struct ifnet * const ifp)
2837: {
2838: tulip_softc_t * const sc = TULIP_IFP_TO_SOFTC(ifp);
2839:
2840: sc->tulip_flags |= TULIP_NEEDRESET;
2841: sc->tulip_probe_state = TULIP_PROBE_INACTIVE;
2842: sc->tulip_media = TULIP_MEDIA_UNKNOWN;
2843: if (IFM_SUBTYPE(sc->tulip_ifmedia.ifm_media) != IFM_AUTO) {
2844: tulip_media_t media;
2845: for (media = TULIP_MEDIA_UNKNOWN; media < TULIP_MEDIA_MAX; media++) {
2846: if (sc->tulip_mediums[media] != NULL
2847: && sc->tulip_ifmedia.ifm_media == tulip_media_to_ifmedia[media]) {
2848: sc->tulip_flags |= TULIP_PRINTMEDIA;
2849: sc->tulip_flags &= ~TULIP_DIDNWAY;
2850: tulip_linkup(sc, media);
2851: return (0);
2852: }
2853: }
2854: }
2855: sc->tulip_flags &= ~(TULIP_TXPROBE_ACTIVE|TULIP_WANTRXACT);
2856: tulip_reset(sc);
2857: tulip_init(sc);
2858: return (0);
2859: }
2860:
2861: /*
2862: * Media status callback
2863: */
2864: void
2865: tulip_ifmedia_status(struct ifnet * const ifp, struct ifmediareq *req)
2866: {
2867: tulip_softc_t *sc = TULIP_IFP_TO_SOFTC(ifp);
2868:
2869: if (sc->tulip_media == TULIP_MEDIA_UNKNOWN)
2870: return;
2871:
2872: req->ifm_status = IFM_AVALID;
2873: if (sc->tulip_flags & TULIP_LINKUP)
2874: req->ifm_status |= IFM_ACTIVE;
2875:
2876: req->ifm_active = tulip_media_to_ifmedia[sc->tulip_media];
2877: }
2878:
2879: void
2880: tulip_addr_filter(tulip_softc_t * const sc)
2881: {
2882: struct ether_multistep step;
2883: struct ether_multi *enm;
2884:
2885: sc->tulip_flags &= ~(TULIP_WANTHASHPERFECT|TULIP_WANTHASHONLY|TULIP_ALLMULTI);
2886: sc->tulip_flags |= TULIP_WANTSETUP|TULIP_WANTTXSTART;
2887: sc->tulip_cmdmode &= ~TULIP_CMD_RXRUN;
2888: sc->tulip_intrmask &= ~TULIP_STS_RXSTOPPED;
2889: sc->tulip_if.if_flags &= ~IFF_ALLMULTI;
2890: sc->tulip_if.if_start = tulip_ifstart; /* so the setup packet gets queued */
2891: if (sc->tulip_multicnt > 14) {
2892: u_int32_t *sp = sc->tulip_setupdata;
2893: unsigned hash;
2894: /*
2895: * Some early passes of the 21140 have broken implementations of
2896: * hash-perfect mode. When we get too many multicasts for perfect
2897: * filtering with these chips, we need to switch into hash-only
2898: * mode (this is better than all-multicast on network with lots
2899: * of multicast traffic).
2900: */
2901: if (sc->tulip_features & TULIP_HAVE_BROKEN_HASH)
2902: sc->tulip_flags |= TULIP_WANTHASHONLY;
2903: else
2904: sc->tulip_flags |= TULIP_WANTHASHPERFECT;
2905: /*
2906: * If we have more than 14 multicasts, we have
2907: * go into hash perfect mode (512 bit multicast
2908: * hash and one perfect hardware).
2909: */
2910: bzero(sc->tulip_setupdata, sizeof(sc->tulip_setupdata));
2911: ETHER_FIRST_MULTI(step, &sc->tulip_ac, enm);
2912: while (enm != NULL) {
2913: if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) == 0) {
2914: hash = tulip_mchash(enm->enm_addrlo);
2915: #if BYTE_ORDER == BIG_ENDIAN
2916: sp[hash >> 4] |= swap32(1 << (hash & 0xF));
2917: #else
2918: sp[hash >> 4] |= 1 << (hash & 0xF);
2919: #endif
2920: } else {
2921: sc->tulip_flags |= TULIP_ALLMULTI;
2922: sc->tulip_flags &= ~(TULIP_WANTHASHONLY|TULIP_WANTHASHPERFECT);
2923: break;
2924: }
2925: ETHER_NEXT_MULTI(step, enm);
2926: }
2927: /*
2928: * No reason to use a hash if we are going to be
2929: * receiving every multicast.
2930: */
2931: if ((sc->tulip_flags & TULIP_ALLMULTI) == 0) {
2932: hash = tulip_mchash(etherbroadcastaddr);
2933: #if BYTE_ORDER == BIG_ENDIAN
2934: sp[hash >> 4] |= swap32(1 << (hash & 0xF));
2935: #else
2936: sp[hash >> 4] |= 1 << (hash & 0xF);
2937: #endif
2938: if (sc->tulip_flags & TULIP_WANTHASHONLY) {
2939: hash = tulip_mchash(sc->tulip_enaddr);
2940: #if BYTE_ORDER == BIG_ENDIAN
2941: sp[hash >> 4] |= swap32(1 << (hash & 0xF));
2942: #else
2943: sp[hash >> 4] |= 1 << (hash & 0xF);
2944: #endif
2945: } else {
2946: #if BYTE_ORDER == BIG_ENDIAN
2947: sp[39] = ((u_int16_t *) sc->tulip_enaddr)[0] << 16;
2948: sp[40] = ((u_int16_t *) sc->tulip_enaddr)[1] << 16;
2949: sp[41] = ((u_int16_t *) sc->tulip_enaddr)[2] << 16;
2950: #else
2951: sp[39] = ((u_int16_t *) sc->tulip_enaddr)[0];
2952: sp[40] = ((u_int16_t *) sc->tulip_enaddr)[1];
2953: sp[41] = ((u_int16_t *) sc->tulip_enaddr)[2];
2954: #endif
2955: }
2956: }
2957: }
2958: if ((sc->tulip_flags & (TULIP_WANTHASHPERFECT|TULIP_WANTHASHONLY)) == 0) {
2959: u_int32_t *sp = sc->tulip_setupdata;
2960: int idx = 0;
2961: if ((sc->tulip_flags & TULIP_ALLMULTI) == 0) {
2962: /*
2963: * Else can get perfect filtering for 16 addresses.
2964: */
2965: ETHER_FIRST_MULTI(step, &sc->tulip_ac, enm);
2966: for (; enm != NULL; idx++) {
2967: if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) == 0) {
2968: #if BYTE_ORDER == BIG_ENDIAN
2969: *sp++ = ((u_int16_t *) enm->enm_addrlo)[0] << 16;
2970: *sp++ = ((u_int16_t *) enm->enm_addrlo)[1] << 16;
2971: *sp++ = ((u_int16_t *) enm->enm_addrlo)[2] << 16;
2972: #else
2973: *sp++ = ((u_int16_t *) enm->enm_addrlo)[0];
2974: *sp++ = ((u_int16_t *) enm->enm_addrlo)[1];
2975: *sp++ = ((u_int16_t *) enm->enm_addrlo)[2];
2976: #endif
2977: } else {
2978: sc->tulip_flags |= TULIP_ALLMULTI;
2979: break;
2980: }
2981: ETHER_NEXT_MULTI(step, enm);
2982: }
2983: /*
2984: * Add the broadcast address.
2985: */
2986: idx++;
2987: #if BYTE_ORDER == BIG_ENDIAN
2988: *sp++ = 0xFFFF << 16;
2989: *sp++ = 0xFFFF << 16;
2990: *sp++ = 0xFFFF << 16;
2991: #else
2992: *sp++ = 0xFFFF;
2993: *sp++ = 0xFFFF;
2994: *sp++ = 0xFFFF;
2995: #endif
2996: }
2997: /*
2998: * Pad the rest with our hardware address
2999: */
3000: for (; idx < 16; idx++) {
3001: #if BYTE_ORDER == BIG_ENDIAN
3002: *sp++ = ((u_int16_t *) sc->tulip_enaddr)[0] << 16;
3003: *sp++ = ((u_int16_t *) sc->tulip_enaddr)[1] << 16;
3004: *sp++ = ((u_int16_t *) sc->tulip_enaddr)[2] << 16;
3005: #else
3006: *sp++ = ((u_int16_t *) sc->tulip_enaddr)[0];
3007: *sp++ = ((u_int16_t *) sc->tulip_enaddr)[1];
3008: *sp++ = ((u_int16_t *) sc->tulip_enaddr)[2];
3009: #endif
3010: }
3011: }
3012: if (sc->tulip_flags & TULIP_ALLMULTI)
3013: sc->tulip_if.if_flags |= IFF_ALLMULTI;
3014: }
3015:
3016: void
3017: tulip_reset(tulip_softc_t * const sc)
3018: {
3019: tulip_ringinfo_t *ri;
3020: tulip_desc_t *di;
3021: u_int32_t inreset = (sc->tulip_flags & TULIP_INRESET);
3022:
3023: /*
3024: * Brilliant. Simply brilliant. When switching modes/speeds
3025: * on a 2114*, you need to set the appriopriate MII/PCS/SCL/PS
3026: * bits in CSR6 and then do a software reset to get the 21140
3027: * to properly reset its internal pathways to the right places.
3028: * Grrrr.
3029: */
3030: if ((sc->tulip_flags & TULIP_DEVICEPROBE) == 0
3031: && sc->tulip_boardsw->bd_media_preset != NULL)
3032: (*sc->tulip_boardsw->bd_media_preset)(sc);
3033:
3034: TULIP_CSR_WRITE(sc, csr_busmode, TULIP_BUSMODE_SWRESET);
3035: DELAY(10); /* Wait 10 microseconds (actually 50 PCI cycles but at
3036: 33MHz that comes to two microseconds but wait a
3037: bit longer anyways) */
3038:
3039: if (!inreset) {
3040: sc->tulip_flags |= TULIP_INRESET;
3041: sc->tulip_flags &= ~(TULIP_NEEDRESET|TULIP_RXBUFSLOW);
3042: sc->tulip_if.if_flags &= ~IFF_OACTIVE;
3043: sc->tulip_if.if_start = tulip_ifstart;
3044: }
3045:
3046: TULIP_CSR_WRITE(sc, csr_txlist, sc->tulip_txdescmap->dm_segs[0].ds_addr);
3047: TULIP_CSR_WRITE(sc, csr_rxlist, sc->tulip_rxdescmap->dm_segs[0].ds_addr);
3048: TULIP_CSR_WRITE(sc, csr_busmode,
3049: (1 << (TULIP_BURSTSIZE(sc->tulip_unit) + 8))
3050: |TULIP_BUSMODE_CACHE_ALIGN8
3051: |TULIP_BUSMODE_READMULTIPLE
3052: |(BYTE_ORDER != LITTLE_ENDIAN ?
3053: TULIP_BUSMODE_DESC_BIGENDIAN : 0));
3054:
3055: sc->tulip_txtimer = 0;
3056: sc->tulip_txq.ifq_maxlen = TULIP_TXDESCS;
3057: /*
3058: * Free all the mbufs that were on the transmit ring.
3059: */
3060: for (;;) {
3061: bus_dmamap_t map;
3062: struct mbuf *m;
3063: IF_DEQUEUE(&sc->tulip_txq, m);
3064: if (m == NULL)
3065: break;
3066: map = TULIP_GETCTX(m, bus_dmamap_t);
3067: bus_dmamap_unload(sc->tulip_dmatag, map);
3068: sc->tulip_txmaps[sc->tulip_txmaps_free++] = map;
3069: m_freem(m);
3070: }
3071:
3072: ri = &sc->tulip_txinfo;
3073: ri->ri_nextin = ri->ri_nextout = ri->ri_first;
3074: ri->ri_free = ri->ri_max;
3075: for (di = ri->ri_first; di < ri->ri_last; di++)
3076: di->d_status = 0;
3077: bus_dmamap_sync(sc->tulip_dmatag, sc->tulip_txdescmap,
3078: 0, sc->tulip_txdescmap->dm_mapsize,
3079: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
3080:
3081: /*
3082: * We need to collect all the mbufs were on the
3083: * receive ring before we reinit it either to put
3084: * them back on or to know if we have to allocate
3085: * more.
3086: */
3087: ri = &sc->tulip_rxinfo;
3088: ri->ri_nextin = ri->ri_nextout = ri->ri_first;
3089: ri->ri_free = ri->ri_max;
3090: for (di = ri->ri_first; di < ri->ri_last; di++) {
3091: di->d_status = 0;
3092: di->d_length1 = 0; di->d_addr1 = 0;
3093: di->d_length2 = 0; di->d_addr2 = 0;
3094: }
3095: bus_dmamap_sync(sc->tulip_dmatag, sc->tulip_rxdescmap,
3096: 0, sc->tulip_rxdescmap->dm_mapsize,
3097: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
3098: for (;;) {
3099: bus_dmamap_t map;
3100: struct mbuf *m;
3101: IF_DEQUEUE(&sc->tulip_rxq, m);
3102: if (m == NULL)
3103: break;
3104: map = TULIP_GETCTX(m, bus_dmamap_t);
3105: bus_dmamap_unload(sc->tulip_dmatag, map);
3106: sc->tulip_rxmaps[sc->tulip_rxmaps_free++] = map;
3107: m_freem(m);
3108: }
3109:
3110: /*
3111: * If tulip_reset is being called recurisvely, exit quickly knowing
3112: * that when the outer tulip_reset returns all the right stuff will
3113: * have happened.
3114: */
3115: if (inreset)
3116: return;
3117:
3118: sc->tulip_intrmask |= TULIP_STS_NORMALINTR|TULIP_STS_RXINTR|TULIP_STS_TXINTR
3119: |TULIP_STS_ABNRMLINTR|TULIP_STS_SYSERROR|TULIP_STS_TXSTOPPED
3120: |TULIP_STS_TXUNDERFLOW|TULIP_STS_TXBABBLE
3121: |TULIP_STS_RXSTOPPED;
3122:
3123: if ((sc->tulip_flags & TULIP_DEVICEPROBE) == 0)
3124: (*sc->tulip_boardsw->bd_media_select)(sc);
3125: #if defined(TULIP_DEBUG)
3126: if ((sc->tulip_flags & TULIP_NEEDRESET) == TULIP_NEEDRESET)
3127: printf(TULIP_PRINTF_FMT ": tulip_reset: additional reset needed?!?\n",
3128: TULIP_PRINTF_ARGS);
3129: #endif
3130: tulip_media_print(sc);
3131: if (sc->tulip_features & TULIP_HAVE_DUALSENSE)
3132: TULIP_CSR_WRITE(sc, csr_sia_status, TULIP_CSR_READ(sc, csr_sia_status));
3133:
3134: sc->tulip_flags &= ~(TULIP_DOINGSETUP|TULIP_WANTSETUP|TULIP_INRESET
3135: |TULIP_RXACT);
3136: tulip_addr_filter(sc);
3137: }
3138:
3139: void
3140: tulip_init(tulip_softc_t * const sc)
3141: {
3142: if (sc->tulip_if.if_flags & IFF_UP) {
3143: if ((sc->tulip_if.if_flags & IFF_RUNNING) == 0) {
3144: /* initialize the media */
3145: tulip_reset(sc);
3146: }
3147: sc->tulip_if.if_flags |= IFF_RUNNING;
3148: if (sc->tulip_if.if_flags & IFF_PROMISC) {
3149: sc->tulip_flags |= TULIP_PROMISC;
3150: sc->tulip_cmdmode |= TULIP_CMD_PROMISCUOUS;
3151: sc->tulip_intrmask |= TULIP_STS_TXINTR;
3152: } else {
3153: sc->tulip_flags &= ~TULIP_PROMISC;
3154: sc->tulip_cmdmode &= ~TULIP_CMD_PROMISCUOUS;
3155: if (sc->tulip_flags & TULIP_ALLMULTI)
3156: sc->tulip_cmdmode |= TULIP_CMD_ALLMULTI;
3157: else
3158: sc->tulip_cmdmode &= ~TULIP_CMD_ALLMULTI;
3159: }
3160: sc->tulip_cmdmode |= TULIP_CMD_TXRUN;
3161: if ((sc->tulip_flags & (TULIP_TXPROBE_ACTIVE|TULIP_WANTSETUP)) == 0) {
3162: tulip_rx_intr(sc);
3163: sc->tulip_cmdmode |= TULIP_CMD_RXRUN;
3164: sc->tulip_intrmask |= TULIP_STS_RXSTOPPED;
3165: } else {
3166: sc->tulip_if.if_flags |= IFF_OACTIVE;
3167: sc->tulip_cmdmode &= ~TULIP_CMD_RXRUN;
3168: sc->tulip_intrmask &= ~TULIP_STS_RXSTOPPED;
3169: }
3170: TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask);
3171: TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode);
3172: if ((sc->tulip_flags & (TULIP_WANTSETUP|TULIP_TXPROBE_ACTIVE)) == TULIP_WANTSETUP)
3173: tulip_txput_setup(sc);
3174: } else {
3175: sc->tulip_if.if_flags &= ~IFF_RUNNING;
3176: tulip_reset(sc);
3177: }
3178: }
3179:
3180: void
3181: tulip_rx_intr(tulip_softc_t * const sc)
3182: {
3183: TULIP_PERFSTART(rxintr)
3184: tulip_ringinfo_t * const ri = &sc->tulip_rxinfo;
3185: struct ifnet * const ifp = &sc->tulip_if;
3186: int fillok = 1;
3187: #if defined(TULIP_DEBUG)
3188: int cnt = 0;
3189: #endif
3190:
3191: for (;;) {
3192: TULIP_PERFSTART(rxget)
3193: tulip_desc_t *eop = ri->ri_nextin;
3194: int total_len = 0, last_offset = 0;
3195: struct mbuf *ms = NULL, *me = NULL;
3196: int accept = 0;
3197: bus_dmamap_t map;
3198: int error;
3199:
3200: if (fillok && sc->tulip_rxq.ifq_len < TULIP_RXQ_TARGET)
3201: goto queue_mbuf;
3202:
3203: #if defined(TULIP_DEBUG)
3204: if (cnt == ri->ri_max)
3205: break;
3206: #endif
3207: /*
3208: * If the TULIP has no descriptors, there can't be any receive
3209: * descriptors to process.
3210: */
3211: if (eop == ri->ri_nextout)
3212: break;
3213:
3214: /*
3215: * 90% of the packets will fit in one descriptor. So we optimize
3216: * for that case.
3217: */
3218: TULIP_RXDESC_POSTSYNC(sc, eop, sizeof(*eop));
3219: if ((((volatile tulip_desc_t *) eop)->d_status & (TULIP_DSTS_OWNER|TULIP_DSTS_RxFIRSTDESC|TULIP_DSTS_RxLASTDESC)) == (TULIP_DSTS_RxFIRSTDESC|TULIP_DSTS_RxLASTDESC)) {
3220: IF_DEQUEUE(&sc->tulip_rxq, ms);
3221: me = ms;
3222: } else {
3223: /*
3224: * If still owned by the TULIP, don't touch it.
3225: */
3226: if (((volatile tulip_desc_t *) eop)->d_status & TULIP_DSTS_OWNER)
3227: break;
3228:
3229: /*
3230: * It is possible (though improbable unless MCLBYTES < 1518) for
3231: * a received packet to cross more than one receive descriptor.
3232: */
3233: while ((((volatile tulip_desc_t *) eop)->d_status & TULIP_DSTS_RxLASTDESC) == 0) {
3234: if (++eop == ri->ri_last)
3235: eop = ri->ri_first;
3236: TULIP_RXDESC_POSTSYNC(sc, eop, sizeof(*eop));
3237: if (eop == ri->ri_nextout || ((((volatile tulip_desc_t *) eop)->d_status & TULIP_DSTS_OWNER))) {
3238: #if defined(TULIP_DEBUG)
3239: sc->tulip_dbg.dbg_rxintrs++;
3240: sc->tulip_dbg.dbg_rxpktsperintr[cnt]++;
3241: #endif
3242: TULIP_PERFEND(rxget);
3243: TULIP_PERFEND(rxintr);
3244: return;
3245: }
3246: total_len++;
3247: }
3248:
3249: /*
3250: * Dequeue the first buffer for the start of the packet. Hopefully
3251: * this will be the only one we need to dequeue. However, if the
3252: * packet consumed multiple descriptors, then we need to dequeue
3253: * those buffers and chain to the starting mbuf. All buffers but
3254: * the last buffer have the same length so we can set that now.
3255: * (we add to last_offset instead of multiplying since we normally
3256: * won't go into the loop and thereby saving a ourselves from
3257: * doing a multiplication by 0 in the normal case).
3258: */
3259: IF_DEQUEUE(&sc->tulip_rxq, ms);
3260: for (me = ms; total_len > 0; total_len--) {
3261: map = TULIP_GETCTX(me, bus_dmamap_t);
3262: TULIP_RXMAP_POSTSYNC(sc, map);
3263: bus_dmamap_unload(sc->tulip_dmatag, map);
3264: sc->tulip_rxmaps[sc->tulip_rxmaps_free++] = map;
3265: #if defined(DIAGNOSTIC)
3266: TULIP_SETCTX(me, NULL);
3267: #endif
3268: me->m_len = TULIP_RX_BUFLEN;
3269: last_offset += TULIP_RX_BUFLEN;
3270: IF_DEQUEUE(&sc->tulip_rxq, me->m_next);
3271: me = me->m_next;
3272: }
3273: }
3274:
3275: /*
3276: * Now get the size of received packet (minus the CRC).
3277: */
3278: total_len = ((eop->d_status >> 16) & 0x7FFF) - 4;
3279: if ((sc->tulip_flags & TULIP_RXIGNORE) == 0
3280: && ((eop->d_status & TULIP_DSTS_ERRSUM) == 0)) {
3281: me->m_len = total_len - last_offset;
3282:
3283: map = TULIP_GETCTX(me, bus_dmamap_t);
3284: bus_dmamap_sync(sc->tulip_dmatag, map, 0, me->m_len,
3285: BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
3286: bus_dmamap_unload(sc->tulip_dmatag, map);
3287: sc->tulip_rxmaps[sc->tulip_rxmaps_free++] = map;
3288: #if defined(DIAGNOSTIC)
3289: TULIP_SETCTX(me, NULL);
3290: #endif
3291:
3292: #if NBPFILTER > 0
3293: if (sc->tulip_bpf != NULL) {
3294: if (me == ms) {
3295: bpf_tap(sc->tulip_if.if_bpf, mtod(ms, caddr_t),
3296: total_len, BPF_DIRECTION_IN);
3297: } else
3298: bpf_mtap(sc->tulip_if.if_bpf, ms, BPF_DIRECTION_IN);
3299: }
3300: #endif
3301: sc->tulip_flags |= TULIP_RXACT;
3302: accept = 1;
3303: } else {
3304: ifp->if_ierrors++;
3305: if (eop->d_status & (TULIP_DSTS_RxBADLENGTH|TULIP_DSTS_RxOVERFLOW|TULIP_DSTS_RxWATCHDOG))
3306: sc->tulip_dot3stats.dot3StatsInternalMacReceiveErrors++;
3307: else {
3308: #ifdef TULIP_DEBUG
3309: const char *error = NULL;
3310: if (eop->d_status & TULIP_DSTS_RxTOOLONG) {
3311: sc->tulip_dot3stats.dot3StatsFrameTooLongs++;
3312: error = "frame too long";
3313: }
3314: if (eop->d_status & TULIP_DSTS_RxBADCRC) {
3315: if (eop->d_status & TULIP_DSTS_RxDRBBLBIT) {
3316: sc->tulip_dot3stats.dot3StatsAlignmentErrors++;
3317: error = "alignment error";
3318: } else {
3319: sc->tulip_dot3stats.dot3StatsFCSErrors++;
3320: error = "bad crc";
3321: }
3322: }
3323: if (error != NULL && (sc->tulip_flags & TULIP_NOMESSAGES) == 0) {
3324: printf(TULIP_PRINTF_FMT ": receive: %s: %s\n",
3325: TULIP_PRINTF_ARGS,
3326: ether_sprintf(mtod(ms, u_char *) + 6),
3327: error);
3328: sc->tulip_flags |= TULIP_NOMESSAGES;
3329: }
3330: #endif
3331: }
3332:
3333: map = TULIP_GETCTX(me, bus_dmamap_t);
3334: bus_dmamap_unload(sc->tulip_dmatag, map);
3335: sc->tulip_rxmaps[sc->tulip_rxmaps_free++] = map;
3336: #if defined(DIAGNOSTIC)
3337: TULIP_SETCTX(me, NULL);
3338: #endif
3339: }
3340: #if defined(TULIP_DEBUG)
3341: cnt++;
3342: #endif
3343: ifp->if_ipackets++;
3344: if (++eop == ri->ri_last)
3345: eop = ri->ri_first;
3346: ri->ri_nextin = eop;
3347: queue_mbuf:
3348: /*
3349: * Either we are priming the TULIP with mbufs (m == NULL)
3350: * or we are about to accept an mbuf for the upper layers
3351: * so we need to allocate an mbuf to replace it. If we
3352: * can't replace it, send up it anyways. This may cause
3353: * us to drop packets in the future but that's better than
3354: * being caught in livelock.
3355: *
3356: * Note that if this packet crossed multiple descriptors
3357: * we don't even try to reallocate all the mbufs here.
3358: * Instead we rely on the test of the beginning of
3359: * the loop to refill for the extra consumed mbufs.
3360: */
3361: if (accept || ms == NULL) {
3362: struct mbuf *m0;
3363: MGETHDR(m0, M_DONTWAIT, MT_DATA);
3364: if (m0 != NULL) {
3365: #if defined(TULIP_COPY_RXDATA)
3366: if (!accept || total_len >= (MHLEN - 2)) {
3367: #endif
3368: MCLGET(m0, M_DONTWAIT);
3369: if ((m0->m_flags & M_EXT) == 0) {
3370: m_freem(m0);
3371: m0 = NULL;
3372: }
3373: #if defined(TULIP_COPY_RXDATA)
3374: }
3375: #endif
3376: }
3377: if (accept
3378: #if defined(TULIP_COPY_RXDATA)
3379: && m0 != NULL
3380: #endif
3381: ) {
3382: #if !defined(TULIP_COPY_RXDATA)
3383: ms->m_pkthdr.len = total_len;
3384: ms->m_pkthdr.rcvif = ifp;
3385: ether_input_mbuf(ifp, ms);
3386: #else
3387: m0->m_data += 2; /* align data after header */
3388: m_copydata(ms, 0, total_len, mtod(m0, caddr_t));
3389: m0->m_len = m0->m_pkthdr.len = total_len;
3390: m0->m_pkthdr.rcvif = ifp;
3391: ether_input_mbuf(ifp, m0);
3392: m0 = ms;
3393: #endif
3394: }
3395: ms = m0;
3396: }
3397: if (ms == NULL) {
3398: /*
3399: * Couldn't allocate a new buffer. Don't bother
3400: * trying to replenish the receive queue.
3401: */
3402: fillok = 0;
3403: sc->tulip_flags |= TULIP_RXBUFSLOW;
3404: #if defined(TULIP_DEBUG)
3405: sc->tulip_dbg.dbg_rxlowbufs++;
3406: #endif
3407: TULIP_PERFEND(rxget);
3408: continue;
3409: }
3410: /*
3411: * Now give the buffer(s) to the TULIP and save in our
3412: * receive queue.
3413: */
3414: do {
3415: tulip_desc_t * const nextout = ri->ri_nextout;
3416: if (sc->tulip_rxmaps_free > 0)
3417: map = sc->tulip_rxmaps[--sc->tulip_rxmaps_free];
3418: else {
3419: m_freem(ms);
3420: sc->tulip_flags |= TULIP_RXBUFSLOW;
3421: #if defined(TULIP_DEBUG)
3422: sc->tulip_dbg.dbg_rxlowbufs++;
3423: #endif
3424: break;
3425: }
3426: TULIP_SETCTX(ms, map);
3427: error = bus_dmamap_load(sc->tulip_dmatag, map, mtod(ms, void *),
3428: TULIP_RX_BUFLEN, NULL, BUS_DMA_NOWAIT);
3429: if (error) {
3430: printf(TULIP_PRINTF_FMT ": unable to load rx map, "
3431: "error = %d\n", TULIP_PRINTF_ARGS, error);
3432: panic("tulip_rx_intr"); /* XXX */
3433: }
3434: nextout->d_addr1 = map->dm_segs[0].ds_addr;
3435: nextout->d_length1 = map->dm_segs[0].ds_len;
3436: if (map->dm_nsegs == 2) {
3437: nextout->d_addr2 = map->dm_segs[1].ds_addr;
3438: nextout->d_length2 = map->dm_segs[1].ds_len;
3439: } else {
3440: nextout->d_addr2 = 0;
3441: nextout->d_length2 = 0;
3442: }
3443: TULIP_RXDESC_POSTSYNC(sc, nextout, sizeof(*nextout));
3444: nextout->d_status = TULIP_DSTS_OWNER;
3445: TULIP_RXDESC_POSTSYNC(sc, nextout, sizeof(u_int32_t));
3446: if (++ri->ri_nextout == ri->ri_last)
3447: ri->ri_nextout = ri->ri_first;
3448: me = ms->m_next;
3449: ms->m_next = NULL;
3450: IF_ENQUEUE(&sc->tulip_rxq, ms);
3451: } while ((ms = me) != NULL);
3452:
3453: if (sc->tulip_rxq.ifq_len >= TULIP_RXQ_TARGET)
3454: sc->tulip_flags &= ~TULIP_RXBUFSLOW;
3455: TULIP_PERFEND(rxget);
3456: }
3457:
3458: #if defined(TULIP_DEBUG)
3459: sc->tulip_dbg.dbg_rxintrs++;
3460: sc->tulip_dbg.dbg_rxpktsperintr[cnt]++;
3461: #endif
3462: TULIP_PERFEND(rxintr);
3463: }
3464:
3465: int
3466: tulip_tx_intr(tulip_softc_t * const sc)
3467: {
3468: TULIP_PERFSTART(txintr)
3469: tulip_ringinfo_t * const ri = &sc->tulip_txinfo;
3470: struct mbuf *m;
3471: int xmits = 0;
3472: int descs = 0;
3473:
3474: while (ri->ri_free < ri->ri_max) {
3475: u_int32_t d_flag;
3476:
3477: TULIP_TXDESC_POSTSYNC(sc, ri->ri_nextin, sizeof(*ri->ri_nextin));
3478: if (((volatile tulip_desc_t *) ri->ri_nextin)->d_status & TULIP_DSTS_OWNER)
3479: break;
3480:
3481: ri->ri_free++;
3482: descs++;
3483: d_flag = ri->ri_nextin->d_flag;
3484: if (d_flag & TULIP_DFLAG_TxLASTSEG) {
3485: if (d_flag & TULIP_DFLAG_TxSETUPPKT) {
3486: /*
3487: * We've just finished processing a setup packet.
3488: * Mark that we finished it. If there's not
3489: * another pending, startup the TULIP receiver.
3490: * Make sure we ack the RXSTOPPED so we won't get
3491: * an abormal interrupt indication.
3492: */
3493: TULIP_TXMAP_POSTSYNC(sc, sc->tulip_setupmap);
3494: sc->tulip_flags &= ~(TULIP_DOINGSETUP|TULIP_HASHONLY);
3495: if (ri->ri_nextin->d_flag & TULIP_DFLAG_TxINVRSFILT)
3496: sc->tulip_flags |= TULIP_HASHONLY;
3497: if ((sc->tulip_flags & (TULIP_WANTSETUP|TULIP_TXPROBE_ACTIVE)) == 0) {
3498: tulip_rx_intr(sc);
3499: sc->tulip_cmdmode |= TULIP_CMD_RXRUN;
3500: sc->tulip_intrmask |= TULIP_STS_RXSTOPPED;
3501: TULIP_CSR_WRITE(sc, csr_status, TULIP_STS_RXSTOPPED);
3502: TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask);
3503: TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode);
3504: }
3505: } else {
3506: const u_int32_t d_status = ri->ri_nextin->d_status;
3507: IF_DEQUEUE(&sc->tulip_txq, m);
3508: if (m != NULL) {
3509: bus_dmamap_t map = TULIP_GETCTX(m, bus_dmamap_t);
3510: TULIP_TXMAP_POSTSYNC(sc, map);
3511: sc->tulip_txmaps[sc->tulip_txmaps_free++] = map;
3512: #if NBPFILTER > 0
3513: if (sc->tulip_bpf != NULL)
3514: bpf_mtap(sc->tulip_if.if_bpf, m, BPF_DIRECTION_OUT);
3515: #endif
3516: m_freem(m);
3517: }
3518: if (sc->tulip_flags & TULIP_TXPROBE_ACTIVE) {
3519: tulip_mediapoll_event_t event = TULIP_MEDIAPOLL_TXPROBE_OK;
3520: if (d_status & (TULIP_DSTS_TxNOCARR|TULIP_DSTS_TxEXCCOLL)) {
3521: #if defined(TULIP_DEBUG)
3522: if (d_status & TULIP_DSTS_TxNOCARR)
3523: sc->tulip_dbg.dbg_txprobe_nocarr++;
3524: if (d_status & TULIP_DSTS_TxEXCCOLL)
3525: sc->tulip_dbg.dbg_txprobe_exccoll++;
3526: #endif
3527: event = TULIP_MEDIAPOLL_TXPROBE_FAILED;
3528: }
3529: (*sc->tulip_boardsw->bd_media_poll)(sc, event);
3530: /*
3531: * Escape from the loop before media poll has reset the TULIP!
3532: */
3533: break;
3534: } else {
3535: xmits++;
3536: if (d_status & TULIP_DSTS_ERRSUM) {
3537: sc->tulip_if.if_oerrors++;
3538: if (d_status & TULIP_DSTS_TxEXCCOLL)
3539: sc->tulip_dot3stats.dot3StatsExcessiveCollisions++;
3540: if (d_status & TULIP_DSTS_TxLATECOLL)
3541: sc->tulip_dot3stats.dot3StatsLateCollisions++;
3542: if (d_status & (TULIP_DSTS_TxNOCARR|TULIP_DSTS_TxCARRLOSS))
3543: sc->tulip_dot3stats.dot3StatsCarrierSenseErrors++;
3544: if (d_status & (TULIP_DSTS_TxUNDERFLOW|TULIP_DSTS_TxBABBLE))
3545: sc->tulip_dot3stats.dot3StatsInternalMacTransmitErrors++;
3546: if (d_status & TULIP_DSTS_TxUNDERFLOW)
3547: sc->tulip_dot3stats.dot3StatsInternalTransmitUnderflows++;
3548: if (d_status & TULIP_DSTS_TxBABBLE)
3549: sc->tulip_dot3stats.dot3StatsInternalTransmitBabbles++;
3550: } else {
3551: u_int32_t collisions =
3552: (d_status & TULIP_DSTS_TxCOLLMASK)
3553: >> TULIP_DSTS_V_TxCOLLCNT;
3554: sc->tulip_if.if_collisions += collisions;
3555: if (collisions == 1)
3556: sc->tulip_dot3stats.dot3StatsSingleCollisionFrames++;
3557: else if (collisions > 1)
3558: sc->tulip_dot3stats.dot3StatsMultipleCollisionFrames++;
3559: else if (d_status & TULIP_DSTS_TxDEFERRED)
3560: sc->tulip_dot3stats.dot3StatsDeferredTransmissions++;
3561: /*
3562: * SQE is only valid for 10baseT/BNC/AUI when not
3563: * running in full-duplex. In order to speed up the
3564: * test, the corresponding bit in tulip_flags needs to
3565: * set as well to get us to count SQE Test Errors.
3566: */
3567: if (d_status & TULIP_DSTS_TxNOHRTBT & sc->tulip_flags)
3568: sc->tulip_dot3stats.dot3StatsSQETestErrors++;
3569: }
3570: }
3571: }
3572: }
3573:
3574: if (++ri->ri_nextin == ri->ri_last)
3575: ri->ri_nextin = ri->ri_first;
3576:
3577: if ((sc->tulip_flags & TULIP_TXPROBE_ACTIVE) == 0)
3578: sc->tulip_if.if_flags &= ~IFF_OACTIVE;
3579: }
3580: /*
3581: * If nothing left to transmit, disable the timer.
3582: * Else if progress, reset the timer back to 2 ticks.
3583: */
3584: if (ri->ri_free == ri->ri_max || (sc->tulip_flags & TULIP_TXPROBE_ACTIVE))
3585: sc->tulip_txtimer = 0;
3586: else if (xmits > 0)
3587: sc->tulip_txtimer = TULIP_TXTIMER;
3588: sc->tulip_if.if_opackets += xmits;
3589: TULIP_PERFEND(txintr);
3590: return (descs);
3591: }
3592:
3593: void
3594: tulip_print_abnormal_interrupt(tulip_softc_t * const sc, u_int32_t csr)
3595: {
3596: #ifdef TULIP_DEBUG
3597: const char * const *msgp = tulip_status_bits;
3598: const char *sep;
3599: u_int32_t mask;
3600: const char thrsh[] = "72|128\0\0\0" "96|256\0\0\0" "128|512\0\0" "160|1024\0";
3601:
3602: csr &= (1 << (sizeof(tulip_status_bits)/sizeof(tulip_status_bits[0]))) - 1;
3603: printf(TULIP_PRINTF_FMT ": abnormal interrupt:", TULIP_PRINTF_ARGS);
3604: for (sep = " ", mask = 1; mask <= csr; mask <<= 1, msgp++) {
3605: if ((csr & mask) && *msgp != NULL) {
3606: printf("%s%s", sep, *msgp);
3607: if (mask == TULIP_STS_TXUNDERFLOW && (sc->tulip_flags & TULIP_NEWTXTHRESH)) {
3608: sc->tulip_flags &= ~TULIP_NEWTXTHRESH;
3609: if (sc->tulip_cmdmode & TULIP_CMD_STOREFWD)
3610: printf(" (switching to store-and-forward mode)");
3611: else {
3612: printf(" (raising TX threshold to %s)",
3613: &thrsh[9 * ((sc->tulip_cmdmode & TULIP_CMD_THRESHOLDCTL) >> 14)]);
3614: }
3615: }
3616: sep = ", ";
3617: }
3618: }
3619: printf("\n");
3620: #endif
3621: }
3622:
3623: void
3624: tulip_intr_handler(tulip_softc_t * const sc, int *progress_p)
3625: {
3626: TULIP_PERFSTART(intr)
3627: u_int32_t csr;
3628:
3629: while ((csr = TULIP_CSR_READ(sc, csr_status)) & sc->tulip_intrmask) {
3630: *progress_p = 1;
3631: TULIP_CSR_WRITE(sc, csr_status, csr);
3632:
3633: if (csr & TULIP_STS_SYSERROR) {
3634: sc->tulip_last_system_error = (csr & TULIP_STS_ERRORMASK) >> TULIP_STS_ERR_SHIFT;
3635: if (sc->tulip_flags & TULIP_NOMESSAGES)
3636: sc->tulip_flags |= TULIP_SYSTEMERROR;
3637: else {
3638: #if defined(TULIP_DEBUG)
3639: printf(TULIP_PRINTF_FMT ": system error: %s\n",
3640: TULIP_PRINTF_ARGS,
3641: tulip_system_errors[sc->tulip_last_system_error]);
3642: #endif
3643: }
3644: sc->tulip_flags |= TULIP_NEEDRESET;
3645: sc->tulip_system_errors++;
3646: break;
3647: }
3648: if (csr & (TULIP_STS_LINKPASS|TULIP_STS_LINKFAIL) & sc->tulip_intrmask) {
3649: #if defined(TULIP_DEBUG)
3650: sc->tulip_dbg.dbg_link_intrs++;
3651: #endif
3652: if (sc->tulip_boardsw->bd_media_poll != NULL) {
3653: (*sc->tulip_boardsw->bd_media_poll)(sc, csr & TULIP_STS_LINKFAIL
3654: ? TULIP_MEDIAPOLL_LINKFAIL
3655: : TULIP_MEDIAPOLL_LINKPASS);
3656: csr &= ~TULIP_STS_ABNRMLINTR;
3657: }
3658: tulip_media_print(sc);
3659: }
3660: if (csr & (TULIP_STS_RXINTR|TULIP_STS_RXNOBUF)) {
3661: u_int32_t misses = TULIP_CSR_READ(sc, csr_missed_frames);
3662: if (csr & TULIP_STS_RXNOBUF)
3663: sc->tulip_dot3stats.dot3StatsMissedFrames += misses & 0xFFFF;
3664: /*
3665: * Pass 2.[012] of the 21140A-A[CDE] may hang and/or corrupt data
3666: * on receive overflows.
3667: */
3668: if ((misses & 0x0FFE0000) && (sc->tulip_features & TULIP_HAVE_RXBADOVRFLW)) {
3669: sc->tulip_dot3stats.dot3StatsInternalMacReceiveErrors++;
3670: /*
3671: * Stop the receiver process and spin until it's stopped.
3672: * Tell rx_intr to drop the packets it dequeues.
3673: */
3674: TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode & ~TULIP_CMD_RXRUN);
3675: while ((TULIP_CSR_READ(sc, csr_status) & TULIP_STS_RXSTOPPED) == 0)
3676: ;
3677: TULIP_CSR_WRITE(sc, csr_status, TULIP_STS_RXSTOPPED);
3678: sc->tulip_flags |= TULIP_RXIGNORE;
3679: }
3680: tulip_rx_intr(sc);
3681: if (sc->tulip_flags & TULIP_RXIGNORE) {
3682: /*
3683: * Restart the receiver.
3684: */
3685: sc->tulip_flags &= ~TULIP_RXIGNORE;
3686: TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode);
3687: }
3688: }
3689: if (csr & TULIP_STS_ABNRMLINTR) {
3690: u_int32_t tmp = csr & sc->tulip_intrmask
3691: & ~(TULIP_STS_NORMALINTR|TULIP_STS_ABNRMLINTR);
3692: if (csr & TULIP_STS_TXUNDERFLOW) {
3693: #if defined(TULIP_DEBUG)
3694: printf ("Underflow interrupt\n");
3695: #endif
3696: if ((sc->tulip_cmdmode & TULIP_CMD_THRESHOLDCTL) != TULIP_CMD_THRSHLD160) {
3697: sc->tulip_cmdmode += TULIP_CMD_THRSHLD96;
3698: sc->tulip_flags |= TULIP_NEWTXTHRESH;
3699: } else if (sc->tulip_features & TULIP_HAVE_STOREFWD) {
3700: sc->tulip_cmdmode |= TULIP_CMD_STOREFWD;
3701: sc->tulip_flags |= TULIP_NEWTXTHRESH;
3702: }
3703: }
3704: if (sc->tulip_flags & TULIP_NOMESSAGES)
3705: sc->tulip_statusbits |= tmp;
3706: else {
3707: tulip_print_abnormal_interrupt(sc, tmp);
3708: sc->tulip_flags |= TULIP_NOMESSAGES;
3709: }
3710: TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode);
3711: }
3712: if (sc->tulip_flags & (TULIP_WANTTXSTART|TULIP_TXPROBE_ACTIVE|TULIP_DOINGSETUP|TULIP_PROMISC)) {
3713: tulip_tx_intr(sc);
3714: if ((sc->tulip_flags & TULIP_TXPROBE_ACTIVE) == 0)
3715: tulip_ifstart(&sc->tulip_if);
3716: }
3717: }
3718: if (sc->tulip_flags & TULIP_NEEDRESET) {
3719: tulip_reset(sc);
3720: tulip_init(sc);
3721: }
3722: TULIP_PERFEND(intr);
3723: }
3724:
3725: int
3726: tulip_intr_shared(void *arg)
3727: {
3728: tulip_softc_t * sc = arg;
3729: int progress = 0;
3730:
3731: for (; sc != NULL; sc = sc->tulip_slaves) {
3732: #if defined(TULIP_DEBUG)
3733: sc->tulip_dbg.dbg_intrs++;
3734: #endif
3735: tulip_intr_handler(sc, &progress);
3736: }
3737: return (progress);
3738: }
3739:
3740: int
3741: tulip_intr_normal(void *arg)
3742: {
3743: tulip_softc_t * sc = (tulip_softc_t *) arg;
3744: int progress = 0;
3745:
3746: #if defined(TULIP_DEBUG)
3747: sc->tulip_dbg.dbg_intrs++;
3748: #endif
3749: tulip_intr_handler(sc, &progress);
3750:
3751: return (progress);
3752: }
3753:
3754: struct mbuf *
3755: tulip_mbuf_compress(struct mbuf *m)
3756: {
3757: struct mbuf *m0;
3758: #if MCLBYTES >= ETHERMTU + 18
3759: MGETHDR(m0, M_DONTWAIT, MT_DATA);
3760: if (m0 != NULL) {
3761: if (m->m_pkthdr.len > MHLEN) {
3762: MCLGET(m0, M_DONTWAIT);
3763: if ((m0->m_flags & M_EXT) == 0) {
3764: m_freem(m);
3765: m_freem(m0);
3766: return (NULL);
3767: }
3768: }
3769: m_copydata(m, 0, m->m_pkthdr.len, mtod(m0, caddr_t));
3770: m0->m_pkthdr.len = m0->m_len = m->m_pkthdr.len;
3771: }
3772: #else
3773: int mlen = MHLEN;
3774: int len = m->m_pkthdr.len;
3775: struct mbuf **mp = &m0;
3776:
3777: while (len > 0) {
3778: if (mlen == MHLEN)
3779: MGETHDR(*mp, M_DONTWAIT, MT_DATA);
3780: else
3781: MGET(*mp, M_DONTWAIT, MT_DATA);
3782: if (*mp == NULL) {
3783: m_freem(m0);
3784: m0 = NULL;
3785: break;
3786: }
3787: if (len > MLEN) {
3788: MCLGET(*mp, M_DONTWAIT);
3789: if (((*mp)->m_flags & M_EXT) == 0) {
3790: m_freem(m0);
3791: m0 = NULL;
3792: break;
3793: }
3794: (*mp)->m_len = len <= MCLBYTES ? len : MCLBYTES;
3795: else
3796: (*mp)->m_len = len <= mlen ? len : mlen;
3797: m_copydata(m, m->m_pkthdr.len - len,
3798: (*mp)->m_len, mtod((*mp), caddr_t));
3799: len -= (*mp)->m_len;
3800: mp = &(*mp)->m_next;
3801: mlen = MLEN;
3802: }
3803: #endif
3804: m_freem(m);
3805: return (m0);
3806: }
3807:
3808: struct mbuf *
3809: tulip_txput(tulip_softc_t * const sc, struct mbuf *m)
3810: {
3811: TULIP_PERFSTART(txput)
3812: tulip_ringinfo_t * const ri = &sc->tulip_txinfo;
3813: tulip_desc_t *eop, *nextout;
3814: int segcnt, freedescs;
3815: u_int32_t d_status;
3816: bus_dmamap_t map;
3817: int error;
3818: struct ifnet *ifp = &sc->tulip_if;
3819: struct mbuf *ombuf = m;
3820: int compressed = 0;
3821:
3822: #if defined(TULIP_DEBUG)
3823: if ((sc->tulip_cmdmode & TULIP_CMD_TXRUN) == 0) {
3824: printf(TULIP_PRINTF_FMT ": txput%s: tx not running\n",
3825: TULIP_PRINTF_ARGS,
3826: (sc->tulip_flags & TULIP_TXPROBE_ACTIVE) ? "(probe)" : "");
3827: sc->tulip_flags |= TULIP_WANTTXSTART;
3828: sc->tulip_dbg.dbg_txput_finishes[0]++;
3829: goto finish;
3830: }
3831: #endif
3832:
3833: /*
3834: * Now we try to fill in our transmit descriptors. This is
3835: * a bit reminiscent of going on the Ark two by two
3836: * since each descriptor for the TULIP can describe
3837: * two buffers. So we advance through packet filling
3838: * each of the two entries at a time to to fill each
3839: * descriptor. Clear the first and last segment bits
3840: * in each descriptor (actually just clear everything
3841: * but the end-of-ring or chain bits) to make sure
3842: * we don't get messed up by previously sent packets.
3843: *
3844: * We may fail to put the entire packet on the ring if
3845: * there is either not enough ring entries free or if the
3846: * packet has more than MAX_TXSEG segments. In the former
3847: * case we will just wait for the ring to empty. In the
3848: * latter case we have to recopy.
3849: */
3850: d_status = 0;
3851: eop = nextout = ri->ri_nextout;
3852: segcnt = 0;
3853: freedescs = ri->ri_free;
3854:
3855: /*
3856: * Reclaim some DMA maps from if we are out.
3857: */
3858: if (sc->tulip_txmaps_free == 0) {
3859: #if defined(TULIP_DEBUG)
3860: sc->tulip_dbg.dbg_no_txmaps++;
3861: #endif
3862: freedescs += tulip_tx_intr(sc);
3863: }
3864: if (sc->tulip_txmaps_free > 0)
3865: map = sc->tulip_txmaps[sc->tulip_txmaps_free-1];
3866: else {
3867: sc->tulip_flags |= TULIP_WANTTXSTART;
3868: #if defined(TULIP_DEBUG)
3869: sc->tulip_dbg.dbg_txput_finishes[1]++;
3870: #endif
3871: goto finish;
3872: }
3873: error = bus_dmamap_load_mbuf(sc->tulip_dmatag, map, m, BUS_DMA_NOWAIT);
3874: if (error != 0) {
3875: if (error == EFBIG) {
3876: /*
3877: * The packet exceeds the number of transmit buffer
3878: * entries that we can use for one packet, so we have
3879: * to recopy it into one mbuf and then try again.
3880: */
3881: struct mbuf *tmp;
3882: /*
3883: * tulip_mbuf_compress() frees the original mbuf.
3884: * thus, we have to remove the mbuf from the queue
3885: * before calling it.
3886: * we don't have to worry about space shortage
3887: * after compressing the mbuf since the compressed
3888: * mbuf will take only two segs.
3889: */
3890: if (compressed) {
3891: /* should not happen */
3892: #ifdef TULIP_DEBUG
3893: printf("tulip_txput: compress called twice!\n");
3894: #endif
3895: goto finish;
3896: }
3897: IFQ_DEQUEUE(&ifp->if_snd, tmp);
3898: if (tmp != ombuf)
3899: panic("tulip_txput: different mbuf dequeued!");
3900: compressed = 1;
3901: m = tulip_mbuf_compress(m);
3902: if (m == NULL) {
3903: #if defined(TULIP_DEBUG)
3904: sc->tulip_dbg.dbg_txput_finishes[2]++;
3905: #endif
3906: goto finish;
3907: }
3908: error = bus_dmamap_load_mbuf(sc->tulip_dmatag, map, m, BUS_DMA_NOWAIT);
3909: }
3910: if (error != 0) {
3911: printf(TULIP_PRINTF_FMT ": unable to load tx map, "
3912: "error = %d\n", TULIP_PRINTF_ARGS, error);
3913: #if defined(TULIP_DEBUG)
3914: sc->tulip_dbg.dbg_txput_finishes[3]++;
3915: #endif
3916: goto finish;
3917: }
3918: }
3919: if ((freedescs -= (map->dm_nsegs + 1) / 2) <= 0
3920: /*
3921: * See if there's any unclaimed space in the transmit ring.
3922: */
3923: && (freedescs += tulip_tx_intr(sc)) <= 0) {
3924: /*
3925: * There's no more room but since nothing
3926: * has been committed at this point, just
3927: * show output is active, put back the
3928: * mbuf and return.
3929: */
3930: sc->tulip_flags |= TULIP_WANTTXSTART;
3931: #if defined(TULIP_DEBUG)
3932: sc->tulip_dbg.dbg_txput_finishes[4]++;
3933: #endif
3934: bus_dmamap_unload(sc->tulip_dmatag, map);
3935: goto finish;
3936: }
3937: for (; map->dm_nsegs - segcnt > 1; segcnt += 2) {
3938: eop = nextout;
3939: eop->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN;
3940: eop->d_status = d_status;
3941: eop->d_addr1 = map->dm_segs[segcnt].ds_addr;
3942: eop->d_length1 = map->dm_segs[segcnt].ds_len;
3943: eop->d_addr2 = map->dm_segs[segcnt+1].ds_addr;
3944: eop->d_length2 = map->dm_segs[segcnt+1].ds_len;
3945: d_status = TULIP_DSTS_OWNER;
3946: if (++nextout == ri->ri_last)
3947: nextout = ri->ri_first;
3948: }
3949: if (segcnt < map->dm_nsegs) {
3950: eop = nextout;
3951: eop->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN;
3952: eop->d_status = d_status;
3953: eop->d_addr1 = map->dm_segs[segcnt].ds_addr;
3954: eop->d_length1 = map->dm_segs[segcnt].ds_len;
3955: eop->d_addr2 = 0;
3956: eop->d_length2 = 0;
3957: if (++nextout == ri->ri_last)
3958: nextout = ri->ri_first;
3959: }
3960: TULIP_TXMAP_PRESYNC(sc, map);
3961: TULIP_SETCTX(m, map);
3962: map = NULL;
3963: --sc->tulip_txmaps_free; /* commit to using the dmamap */
3964:
3965: /*
3966: * The descriptors have been filled in. Now get ready
3967: * to transmit.
3968: */
3969: if (!compressed && (sc->tulip_flags & TULIP_TXPROBE_ACTIVE) == 0) {
3970: /* remove the mbuf from the queue */
3971: struct mbuf *tmp;
3972: IFQ_DEQUEUE(&ifp->if_snd, tmp);
3973: if (tmp != ombuf)
3974: panic("tulip_txput: different mbuf dequeued!");
3975: }
3976:
3977: IF_ENQUEUE(&sc->tulip_txq, m);
3978: m = NULL;
3979:
3980: /*
3981: * Make sure the next descriptor after this packet is owned
3982: * by us since it may have been set up above if we ran out
3983: * of room in the ring.
3984: */
3985: nextout->d_status = 0;
3986: TULIP_TXDESC_PRESYNC(sc, nextout, sizeof(u_int32_t));
3987:
3988: /*
3989: * Mark the last and first segments, indicate we want a transmit
3990: * complete interrupt, and tell it to transmit!
3991: */
3992: eop->d_flag |= TULIP_DFLAG_TxLASTSEG|TULIP_DFLAG_TxWANTINTR;
3993:
3994: /*
3995: * Note that ri->ri_nextout is still the start of the packet
3996: * and until we set the OWNER bit, we can still back out of
3997: * everything we have done.
3998: */
3999: ri->ri_nextout->d_flag |= TULIP_DFLAG_TxFIRSTSEG;
4000: if (eop < ri->ri_nextout) {
4001: TULIP_TXDESC_PRESYNC(sc, ri->ri_nextout,
4002: (caddr_t) ri->ri_last - (caddr_t) ri->ri_nextout);
4003: TULIP_TXDESC_PRESYNC(sc, ri->ri_first,
4004: (caddr_t) (eop + 1) - (caddr_t) ri->ri_first);
4005: } else {
4006: TULIP_TXDESC_PRESYNC(sc, ri->ri_nextout,
4007: (caddr_t) (eop + 1) - (caddr_t) ri->ri_nextout);
4008: }
4009: ri->ri_nextout->d_status = TULIP_DSTS_OWNER;
4010: TULIP_TXDESC_PRESYNC(sc, ri->ri_nextout, sizeof(u_int32_t));
4011:
4012: /*
4013: * This advances the ring for us.
4014: */
4015: ri->ri_nextout = nextout;
4016: ri->ri_free = freedescs;
4017:
4018: TULIP_PERFEND(txput);
4019:
4020: if (sc->tulip_flags & TULIP_TXPROBE_ACTIVE) {
4021: TULIP_CSR_WRITE(sc, csr_txpoll, 1);
4022: sc->tulip_if.if_flags |= IFF_OACTIVE;
4023: sc->tulip_if.if_start = tulip_ifstart;
4024: TULIP_PERFEND(txput);
4025: return (NULL);
4026: }
4027:
4028: /*
4029: * switch back to the single queueing ifstart.
4030: */
4031: sc->tulip_flags &= ~TULIP_WANTTXSTART;
4032: if (sc->tulip_txtimer == 0)
4033: sc->tulip_txtimer = TULIP_TXTIMER;
4034: #if defined(TULIP_DEBUG)
4035: sc->tulip_dbg.dbg_txput_finishes[5]++;
4036: #endif
4037:
4038: /*
4039: * If we want a txstart, there must be not enough space in the
4040: * transmit ring. So we want to enable transmit done interrupts
4041: * so we can immediately reclaim some space. When the transmit
4042: * interrupt is posted, the interrupt handler will call tx_intr
4043: * to reclaim space and then txstart (since WANTTXSTART is set).
4044: * txstart will move the packet into the transmit ring and clear
4045: * WANTTXSTART thereby causing TXINTR to be cleared.
4046: */
4047: finish:
4048: #if defined(TULIP_DEBUG)
4049: sc->tulip_dbg.dbg_txput_finishes[6]++;
4050: #endif
4051: if (sc->tulip_flags & (TULIP_WANTTXSTART|TULIP_DOINGSETUP)) {
4052: sc->tulip_if.if_flags |= IFF_OACTIVE;
4053: sc->tulip_if.if_start = tulip_ifstart;
4054: if ((sc->tulip_intrmask & TULIP_STS_TXINTR) == 0) {
4055: sc->tulip_intrmask |= TULIP_STS_TXINTR;
4056: TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask);
4057: }
4058: } else if ((sc->tulip_flags & TULIP_PROMISC) == 0) {
4059: if (sc->tulip_intrmask & TULIP_STS_TXINTR) {
4060: sc->tulip_intrmask &= ~TULIP_STS_TXINTR;
4061: TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask);
4062: }
4063: }
4064: TULIP_CSR_WRITE(sc, csr_txpoll, 1);
4065: TULIP_PERFEND(txput);
4066: return (m);
4067: }
4068:
4069: void
4070: tulip_txput_setup(tulip_softc_t * const sc)
4071: {
4072: tulip_ringinfo_t * const ri = &sc->tulip_txinfo;
4073: tulip_desc_t *nextout;
4074:
4075: /*
4076: * We will transmit, at most, one setup packet per call to ifstart.
4077: */
4078:
4079: #if defined(TULIP_DEBUG)
4080: if ((sc->tulip_cmdmode & TULIP_CMD_TXRUN) == 0) {
4081: printf(TULIP_PRINTF_FMT ": txput_setup: tx not running\n",
4082: TULIP_PRINTF_ARGS);
4083: sc->tulip_flags |= TULIP_WANTTXSTART;
4084: sc->tulip_if.if_start = tulip_ifstart;
4085: return;
4086: }
4087: #endif
4088: /*
4089: * Try to reclaim some free descriptors..
4090: */
4091: if (ri->ri_free < 2)
4092: tulip_tx_intr(sc);
4093: if ((sc->tulip_flags & TULIP_DOINGSETUP) || ri->ri_free == 1) {
4094: sc->tulip_flags |= TULIP_WANTTXSTART;
4095: sc->tulip_if.if_start = tulip_ifstart;
4096: return;
4097: }
4098: bcopy(sc->tulip_setupdata, sc->tulip_setupbuf,
4099: sizeof(sc->tulip_setupbuf));
4100: /*
4101: * Clear WANTSETUP and set DOINGSETUP. Set know that WANTSETUP is
4102: * set and DOINGSETUP is clear doing an XOR of the two will DTRT.
4103: */
4104: sc->tulip_flags ^= TULIP_WANTSETUP|TULIP_DOINGSETUP;
4105: ri->ri_free--;
4106: nextout = ri->ri_nextout;
4107: nextout->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN;
4108: nextout->d_flag |= TULIP_DFLAG_TxFIRSTSEG|TULIP_DFLAG_TxLASTSEG
4109: |TULIP_DFLAG_TxSETUPPKT|TULIP_DFLAG_TxWANTINTR;
4110: if (sc->tulip_flags & TULIP_WANTHASHPERFECT)
4111: nextout->d_flag |= TULIP_DFLAG_TxHASHFILT;
4112: else if (sc->tulip_flags & TULIP_WANTHASHONLY)
4113: nextout->d_flag |= TULIP_DFLAG_TxHASHFILT|TULIP_DFLAG_TxINVRSFILT;
4114:
4115: nextout->d_length2 = 0;
4116: nextout->d_addr2 = 0;
4117: nextout->d_length1 = sc->tulip_setupmap->dm_segs[0].ds_len;
4118: nextout->d_addr1 = sc->tulip_setupmap->dm_segs[0].ds_addr;
4119: if (sc->tulip_setupmap->dm_nsegs == 2) {
4120: nextout->d_length2 = sc->tulip_setupmap->dm_segs[1].ds_len;
4121: nextout->d_addr2 = sc->tulip_setupmap->dm_segs[1].ds_addr;
4122: }
4123: TULIP_TXMAP_PRESYNC(sc, sc->tulip_setupmap);
4124: TULIP_TXDESC_PRESYNC(sc, nextout, sizeof(*nextout));
4125:
4126: /*
4127: * Advance the ring for the next transmit packet.
4128: */
4129: if (++ri->ri_nextout == ri->ri_last)
4130: ri->ri_nextout = ri->ri_first;
4131:
4132: /*
4133: * Make sure the next descriptor is owned by us since it
4134: * may have been set up above if we ran out of room in the
4135: * ring.
4136: */
4137: ri->ri_nextout->d_status = 0;
4138: TULIP_TXDESC_PRESYNC(sc, ri->ri_nextout, sizeof(u_int32_t));
4139: nextout->d_status = TULIP_DSTS_OWNER;
4140: /*
4141: * Flush the ownwership of the current descriptor
4142: */
4143: TULIP_TXDESC_PRESYNC(sc, nextout, sizeof(u_int32_t));
4144: TULIP_CSR_WRITE(sc, csr_txpoll, 1);
4145: if ((sc->tulip_intrmask & TULIP_STS_TXINTR) == 0) {
4146: sc->tulip_intrmask |= TULIP_STS_TXINTR;
4147: TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask);
4148: }
4149: }
4150:
4151: /*
4152: * This routine is entered at splnet().
4153: */
4154: int
4155: tulip_ifioctl(struct ifnet * ifp, u_long cmd, caddr_t data)
4156: {
4157: TULIP_PERFSTART(ifioctl)
4158: tulip_softc_t * const sc = TULIP_IFP_TO_SOFTC(ifp);
4159: struct ifaddr *ifa = (struct ifaddr *)data;
4160: struct ifreq *ifr = (struct ifreq *) data;
4161: int s;
4162: int error = 0;
4163:
4164: s = splnet();
4165:
4166: if ((error = ether_ioctl(ifp, &sc->tulip_ac, cmd, data)) > 0) {
4167: splx(s);
4168: return (error);
4169: }
4170:
4171: switch (cmd) {
4172: case SIOCSIFADDR: {
4173: ifp->if_flags |= IFF_UP;
4174: tulip_init(sc);
4175: switch(ifa->ifa_addr->sa_family) {
4176: #ifdef INET
4177: case AF_INET: {
4178: arp_ifinit(&sc->tulip_ac, ifa);
4179: break;
4180: }
4181: #endif /* INET */
4182:
4183: default: {
4184: break;
4185: }
4186: }
4187: break;
4188: }
4189:
4190: case SIOCSIFFLAGS: {
4191: tulip_init(sc);
4192: break;
4193: }
4194:
4195: case SIOCSIFMEDIA:
4196: case SIOCGIFMEDIA: {
4197: error = ifmedia_ioctl(ifp, ifr, &sc->tulip_ifmedia, cmd);
4198: break;
4199: }
4200:
4201: case SIOCADDMULTI:
4202: case SIOCDELMULTI: {
4203: /*
4204: * Update multicast listeners
4205: */
4206: if (cmd == SIOCADDMULTI)
4207: error = ether_addmulti(ifr, &sc->tulip_ac);
4208: else
4209: error = ether_delmulti(ifr, &sc->tulip_ac);
4210:
4211: if (error == ENETRESET) {
4212: if (ifp->if_flags & IFF_RUNNING) {
4213: tulip_addr_filter(sc); /* reset multicast filtering */
4214: tulip_init(sc);
4215: }
4216: error = 0;
4217: }
4218: break;
4219: }
4220:
4221: case SIOCSIFMTU:
4222: /*
4223: * Set the interface MTU.
4224: */
4225: if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ETHERMTU)
4226: error = EINVAL;
4227: else if (ifp->if_mtu != ifr->ifr_mtu)
4228: ifp->if_mtu = ifr->ifr_mtu;
4229: break;
4230:
4231: default:
4232: error = ENOTTY;
4233: break;
4234: }
4235:
4236: splx(s);
4237: TULIP_PERFEND(ifioctl);
4238: return (error);
4239: }
4240:
4241: /*
4242: * the original dequeueing policy is dequeue-and-prepend if something
4243: * goes wrong. when altq is used, it is changed to peek-and-dequeue.
4244: * the modification becomes a bit complicated since tulip_txput() might
4245: * copy and modify the mbuf passed.
4246: */
4247: /*
4248: * These routines gets called at device spl (from ether_output).
4249: */
4250:
4251: void
4252: tulip_ifstart(struct ifnet * const ifp)
4253: {
4254: TULIP_PERFSTART(ifstart)
4255: tulip_softc_t * const sc = TULIP_IFP_TO_SOFTC(ifp);
4256:
4257: if (sc->tulip_if.if_flags & IFF_RUNNING) {
4258:
4259: if ((sc->tulip_flags & (TULIP_WANTSETUP|TULIP_TXPROBE_ACTIVE)) == TULIP_WANTSETUP)
4260: tulip_txput_setup(sc);
4261:
4262: while (!IFQ_IS_EMPTY(&sc->tulip_if.if_snd)) {
4263: struct mbuf *m, *m0;
4264: IFQ_POLL(&sc->tulip_if.if_snd, m);
4265: if (m == NULL)
4266: break;
4267: if ((m0 = tulip_txput(sc, m)) != NULL) {
4268: if (m0 != m)
4269: /* should not happen */
4270: printf("tulip_if_start: txput failed!\n");
4271: break;
4272: }
4273: }
4274: #ifdef ALTQ
4275: if (0) /* don't switch to the one packet mode */
4276: #else
4277: if (IFQ_IS_EMPTY(&sc->tulip_if.if_snd))
4278: #endif
4279: sc->tulip_if.if_start = tulip_ifstart_one;
4280: }
4281:
4282: TULIP_PERFEND(ifstart);
4283: }
4284:
4285: void
4286: tulip_ifstart_one(struct ifnet * const ifp)
4287: {
4288: TULIP_PERFSTART(ifstart_one)
4289: tulip_softc_t * const sc = TULIP_IFP_TO_SOFTC(ifp);
4290:
4291: if ((sc->tulip_if.if_flags & IFF_RUNNING)
4292: && !IFQ_IS_EMPTY(&sc->tulip_if.if_snd)) {
4293: struct mbuf *m, *m0;
4294: IFQ_POLL(&sc->tulip_if.if_snd, m);
4295: if (m != NULL && (m0 = tulip_txput(sc, m)) != NULL)
4296: if (m0 != m)
4297: /* should not happen */
4298: printf("tulip_if_start_one: txput failed!\n");
4299: }
4300: TULIP_PERFEND(ifstart_one);
4301: }
4302:
4303: void
4304: tulip_ifwatchdog(struct ifnet *ifp)
4305: {
4306: TULIP_PERFSTART(ifwatchdog)
4307: tulip_softc_t * const sc = TULIP_IFP_TO_SOFTC(ifp);
4308:
4309: #if defined(TULIP_DEBUG)
4310: u_int32_t rxintrs = sc->tulip_dbg.dbg_rxintrs - sc->tulip_dbg.dbg_last_rxintrs;
4311: if (rxintrs > sc->tulip_dbg.dbg_high_rxintrs_hz)
4312: sc->tulip_dbg.dbg_high_rxintrs_hz = rxintrs;
4313: sc->tulip_dbg.dbg_last_rxintrs = sc->tulip_dbg.dbg_rxintrs;
4314: #endif /* TULIP_DEBUG */
4315:
4316: sc->tulip_if.if_timer = 1;
4317: /*
4318: * These should be rare so do a bulk test up front so we can just skip
4319: * them if needed.
4320: */
4321: if (sc->tulip_flags & (TULIP_SYSTEMERROR|TULIP_RXBUFSLOW|TULIP_NOMESSAGES)) {
4322: /*
4323: * If the number of receive buffer is low, try to refill
4324: */
4325: if (sc->tulip_flags & TULIP_RXBUFSLOW)
4326: tulip_rx_intr(sc);
4327:
4328: #if defined(TULIP_DEBUG)
4329: if (sc->tulip_flags & TULIP_SYSTEMERROR) {
4330: printf(TULIP_PRINTF_FMT ": %d system errors: last was %s\n",
4331: TULIP_PRINTF_ARGS, sc->tulip_system_errors,
4332: tulip_system_errors[sc->tulip_last_system_error]);
4333: }
4334: #endif
4335: if (sc->tulip_statusbits) {
4336: tulip_print_abnormal_interrupt(sc, sc->tulip_statusbits);
4337: sc->tulip_statusbits = 0;
4338: }
4339:
4340: sc->tulip_flags &= ~(TULIP_NOMESSAGES|TULIP_SYSTEMERROR);
4341: }
4342:
4343: if (sc->tulip_txtimer)
4344: tulip_tx_intr(sc);
4345: if (sc->tulip_txtimer && --sc->tulip_txtimer == 0) {
4346: printf(TULIP_PRINTF_FMT ": transmission timeout\n", TULIP_PRINTF_ARGS);
4347: if (TULIP_DO_AUTOSENSE(sc)) {
4348: sc->tulip_media = TULIP_MEDIA_UNKNOWN;
4349: sc->tulip_probe_state = TULIP_PROBE_INACTIVE;
4350: sc->tulip_flags &= ~(TULIP_WANTRXACT|TULIP_LINKUP);
4351: }
4352: tulip_reset(sc);
4353: tulip_init(sc);
4354: }
4355:
4356: TULIP_PERFEND(ifwatchdog);
4357: TULIP_PERFMERGE(sc, perf_intr_cycles);
4358: TULIP_PERFMERGE(sc, perf_ifstart_cycles);
4359: TULIP_PERFMERGE(sc, perf_ifioctl_cycles);
4360: TULIP_PERFMERGE(sc, perf_ifwatchdog_cycles);
4361: TULIP_PERFMERGE(sc, perf_timeout_cycles);
4362: TULIP_PERFMERGE(sc, perf_ifstart_one_cycles);
4363: TULIP_PERFMERGE(sc, perf_txput_cycles);
4364: TULIP_PERFMERGE(sc, perf_txintr_cycles);
4365: TULIP_PERFMERGE(sc, perf_rxintr_cycles);
4366: TULIP_PERFMERGE(sc, perf_rxget_cycles);
4367: TULIP_PERFMERGE(sc, perf_intr);
4368: TULIP_PERFMERGE(sc, perf_ifstart);
4369: TULIP_PERFMERGE(sc, perf_ifioctl);
4370: TULIP_PERFMERGE(sc, perf_ifwatchdog);
4371: TULIP_PERFMERGE(sc, perf_timeout);
4372: TULIP_PERFMERGE(sc, perf_ifstart_one);
4373: TULIP_PERFMERGE(sc, perf_txput);
4374: TULIP_PERFMERGE(sc, perf_txintr);
4375: TULIP_PERFMERGE(sc, perf_rxintr);
4376: TULIP_PERFMERGE(sc, perf_rxget);
4377: }
4378:
4379: /*
4380: * All printf's are real as of now!
4381: */
4382: #ifdef printf
4383: #undef printf
4384: #endif
4385:
4386: int
4387: tulip_busdma_allocmem(tulip_softc_t * const sc, size_t size,
4388: bus_dmamap_t *map_p, tulip_desc_t **desc_p)
4389: {
4390: bus_dma_segment_t segs[1];
4391: int nsegs, error;
4392: error = bus_dmamem_alloc(sc->tulip_dmatag, size, 1, PAGE_SIZE,
4393: segs, sizeof(segs)/sizeof(segs[0]),
4394: &nsegs, BUS_DMA_NOWAIT);
4395: if (error == 0) {
4396: void *desc;
4397: error = bus_dmamem_map(sc->tulip_dmatag, segs, nsegs, size,
4398: (void *) &desc, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
4399: if (error == 0) {
4400: bus_dmamap_t map;
4401: error = bus_dmamap_create(sc->tulip_dmatag, size, 1, size, 0,
4402: BUS_DMA_NOWAIT, &map);
4403: if (error == 0) {
4404: error = bus_dmamap_load(sc->tulip_dmatag, map, desc,
4405: size, NULL, BUS_DMA_NOWAIT);
4406: if (error)
4407: bus_dmamap_destroy(sc->tulip_dmatag, map);
4408: else
4409: *map_p = map;
4410: }
4411: if (error)
4412: bus_dmamem_unmap(sc->tulip_dmatag, desc, size);
4413: }
4414: if (error)
4415: bus_dmamem_free(sc->tulip_dmatag, segs, nsegs);
4416: else
4417: *desc_p = desc;
4418: }
4419: return (error);
4420: }
4421:
4422: int
4423: tulip_busdma_init(tulip_softc_t * const sc)
4424: {
4425: int error = 0;
4426:
4427: /*
4428: * Allocate dmamap for setup descriptor
4429: */
4430: error = bus_dmamap_create(sc->tulip_dmatag, sizeof(sc->tulip_setupbuf), 2,
4431: sizeof(sc->tulip_setupbuf), 0, BUS_DMA_NOWAIT,
4432: &sc->tulip_setupmap);
4433: if (error == 0) {
4434: error = bus_dmamap_load(sc->tulip_dmatag, sc->tulip_setupmap,
4435: sc->tulip_setupbuf, sizeof(sc->tulip_setupbuf),
4436: NULL, BUS_DMA_NOWAIT);
4437: if (error)
4438: bus_dmamap_destroy(sc->tulip_dmatag, sc->tulip_setupmap);
4439: }
4440: /*
4441: * Allocate space and dmamap for transmit ring
4442: */
4443: if (error == 0) {
4444: error = tulip_busdma_allocmem(sc, sizeof(tulip_desc_t) * TULIP_TXDESCS,
4445: &sc->tulip_txdescmap,
4446: &sc->tulip_txdescs);
4447: }
4448:
4449: /*
4450: * Allocate dmamaps for each transmit descriptors
4451: */
4452: if (error == 0) {
4453: while (error == 0 && sc->tulip_txmaps_free < TULIP_TXDESCS) {
4454: bus_dmamap_t map;
4455: if ((error = TULIP_TXMAP_CREATE(sc, &map)) == 0)
4456: sc->tulip_txmaps[sc->tulip_txmaps_free++] = map;
4457: }
4458: if (error) {
4459: while (sc->tulip_txmaps_free > 0)
4460: bus_dmamap_destroy(sc->tulip_dmatag,
4461: sc->tulip_txmaps[--sc->tulip_txmaps_free]);
4462: }
4463: }
4464:
4465: /*
4466: * Allocate space and dmamap for receive ring
4467: */
4468: if (error == 0) {
4469: error = tulip_busdma_allocmem(sc, sizeof(tulip_desc_t) * TULIP_RXDESCS,
4470: &sc->tulip_rxdescmap,
4471: &sc->tulip_rxdescs);
4472: }
4473:
4474: /*
4475: * Allocate dmamaps for each receive descriptors
4476: */
4477: if (error == 0) {
4478: while (error == 0 && sc->tulip_rxmaps_free < TULIP_RXDESCS) {
4479: bus_dmamap_t map;
4480: if ((error = TULIP_RXMAP_CREATE(sc, &map)) == 0)
4481: sc->tulip_rxmaps[sc->tulip_rxmaps_free++] = map;
4482: }
4483: if (error) {
4484: while (sc->tulip_rxmaps_free > 0)
4485: bus_dmamap_destroy(sc->tulip_dmatag,
4486: sc->tulip_rxmaps[--sc->tulip_rxmaps_free]);
4487: }
4488: }
4489: return (error);
4490: }
4491:
4492: void
4493: tulip_initcsrs(tulip_softc_t * const sc, bus_addr_t csr_base, size_t csr_size)
4494: {
4495: sc->tulip_csrs.csr_busmode = csr_base + 0 * csr_size;
4496: sc->tulip_csrs.csr_txpoll = csr_base + 1 * csr_size;
4497: sc->tulip_csrs.csr_rxpoll = csr_base + 2 * csr_size;
4498: sc->tulip_csrs.csr_rxlist = csr_base + 3 * csr_size;
4499: sc->tulip_csrs.csr_txlist = csr_base + 4 * csr_size;
4500: sc->tulip_csrs.csr_status = csr_base + 5 * csr_size;
4501: sc->tulip_csrs.csr_command = csr_base + 6 * csr_size;
4502: sc->tulip_csrs.csr_intr = csr_base + 7 * csr_size;
4503: sc->tulip_csrs.csr_missed_frames = csr_base + 8 * csr_size;
4504: sc->tulip_csrs.csr_9 = csr_base + 9 * csr_size;
4505: sc->tulip_csrs.csr_10 = csr_base + 10 * csr_size;
4506: sc->tulip_csrs.csr_11 = csr_base + 11 * csr_size;
4507: sc->tulip_csrs.csr_12 = csr_base + 12 * csr_size;
4508: sc->tulip_csrs.csr_13 = csr_base + 13 * csr_size;
4509: sc->tulip_csrs.csr_14 = csr_base + 14 * csr_size;
4510: sc->tulip_csrs.csr_15 = csr_base + 15 * csr_size;
4511: }
4512:
4513: void
4514: tulip_initring(tulip_softc_t * const sc, tulip_ringinfo_t * const ri,
4515: tulip_desc_t *descs, int ndescs)
4516: {
4517: ri->ri_max = ndescs;
4518: ri->ri_first = descs;
4519: ri->ri_last = ri->ri_first + ri->ri_max;
4520: bzero((caddr_t) ri->ri_first, sizeof(ri->ri_first[0]) * ri->ri_max);
4521: ri->ri_last[-1].d_flag = TULIP_DFLAG_ENDRING;
4522: }
4523:
4524: int
4525: tulip_probe(struct device *parent, void *match, void *aux)
4526: {
4527: struct pci_attach_args *pa = (struct pci_attach_args *) aux;
4528:
4529: if (PCI_VENDORID(pa->pa_id) != DEC_VENDORID)
4530: return (0);
4531: if (PCI_CHIPID(pa->pa_id) == CHIPID_21040
4532: || PCI_CHIPID(pa->pa_id) == CHIPID_21041
4533: || PCI_CHIPID(pa->pa_id) == CHIPID_21140
4534: || PCI_CHIPID(pa->pa_id) == CHIPID_21142)
4535: return (2);
4536:
4537: return (0);
4538: }
4539:
4540: void
4541: tulip_shutdown(void *arg)
4542: {
4543: tulip_softc_t * const sc = arg;
4544: TULIP_CSR_WRITE(sc, csr_busmode, TULIP_BUSMODE_SWRESET);
4545: DELAY(10); /* Wait 10 microseconds (actually 50 PCI cycles but at
4546: 33MHz that comes to two microseconds but wait a
4547: bit longer anyways) */
4548: }
4549:
4550: void
4551: tulip_attach(struct device * const parent, struct device * const self, void * const aux)
4552: {
4553: tulip_softc_t * const sc = (tulip_softc_t *) self;
4554: struct pci_attach_args * const pa = (struct pci_attach_args *) aux;
4555: struct ifnet * const ifp = &sc->tulip_if;
4556: const int unit = sc->tulip_dev.dv_unit;
4557: int retval, idx;
4558: u_int32_t revinfo, cfdainfo, id;
4559: unsigned csroffset = TULIP_PCI_CSROFFSET;
4560: unsigned csrsize = TULIP_PCI_CSRSIZE;
4561: bus_addr_t csr_base;
4562: tulip_chipid_t chipid = TULIP_CHIPID_UNKNOWN;
4563:
4564: if (unit >= TULIP_MAX_DEVICES) {
4565: printf(": not configured; limit of %d reached or exceeded\n",
4566: TULIP_MAX_DEVICES);
4567: return;
4568: }
4569:
4570: revinfo = PCI_CONF_READ(PCI_CFRV) & 0xFF;
4571: id = PCI_CONF_READ(PCI_CFID);
4572: cfdainfo = PCI_CONF_READ(PCI_CFDA);
4573:
4574: if (PCI_VENDORID(id) == DEC_VENDORID) {
4575: if (PCI_CHIPID(id) == CHIPID_21040)
4576: chipid = TULIP_21040;
4577: else if (PCI_CHIPID(id) == CHIPID_21041)
4578: chipid = TULIP_21041;
4579: else if (PCI_CHIPID(id) == CHIPID_21140)
4580: chipid = (revinfo >= 0x20) ? TULIP_21140A : TULIP_21140;
4581: else if (PCI_CHIPID(id) == CHIPID_21142)
4582: chipid = (revinfo >= 0x20) ? TULIP_21143 : TULIP_21142;
4583: }
4584:
4585: if (chipid == TULIP_CHIPID_UNKNOWN)
4586: return;
4587:
4588: if ((chipid == TULIP_21040 || chipid == TULIP_DE425) && revinfo < 0x20) {
4589: printf(": not configured; 21040 pass 2.0 required (%d.%d found)\n",
4590: revinfo >> 4, revinfo & 0x0f);
4591: return;
4592: } else if (chipid == TULIP_21140 && revinfo < 0x11) {
4593: printf(": not configured; 21140 pass 1.1 required (%d.%d found)\n",
4594: revinfo >> 4, revinfo & 0x0f);
4595: return;
4596: }
4597:
4598: PCI_GETBUSDEVINFO(sc);
4599: sc->tulip_chipid = chipid;
4600: sc->tulip_flags |= TULIP_DEVICEPROBE;
4601: if (chipid == TULIP_21140 || chipid == TULIP_21140A)
4602: sc->tulip_features |= TULIP_HAVE_GPR|TULIP_HAVE_STOREFWD;
4603: if (chipid == TULIP_21140A && revinfo <= 0x22)
4604: sc->tulip_features |= TULIP_HAVE_RXBADOVRFLW;
4605: if (chipid == TULIP_21140)
4606: sc->tulip_features |= TULIP_HAVE_BROKEN_HASH;
4607: if (chipid != TULIP_21040 && chipid != TULIP_DE425 && chipid != TULIP_21140)
4608: sc->tulip_features |= TULIP_HAVE_POWERMGMT;
4609: if (chipid == TULIP_21041 || chipid == TULIP_21142 || chipid == TULIP_21143) {
4610: sc->tulip_features |= TULIP_HAVE_DUALSENSE;
4611: if (chipid != TULIP_21041 || revinfo >= 0x20)
4612: sc->tulip_features |= TULIP_HAVE_SIANWAY;
4613: if (chipid != TULIP_21041)
4614: sc->tulip_features |= TULIP_HAVE_SIAGP|TULIP_HAVE_RXBADOVRFLW|TULIP_HAVE_STOREFWD;
4615: if (chipid != TULIP_21041 && revinfo >= 0x20)
4616: sc->tulip_features |= TULIP_HAVE_SIA100;
4617: }
4618:
4619: if (sc->tulip_features & TULIP_HAVE_POWERMGMT
4620: && (cfdainfo & (TULIP_CFDA_SLEEP|TULIP_CFDA_SNOOZE))) {
4621: cfdainfo &= ~(TULIP_CFDA_SLEEP|TULIP_CFDA_SNOOZE);
4622: PCI_CONF_WRITE(PCI_CFDA, cfdainfo);
4623: DELAY(11*1000);
4624: }
4625:
4626: if (sc->tulip_features & TULIP_HAVE_STOREFWD)
4627: sc->tulip_cmdmode |= TULIP_CMD_STOREFWD;
4628:
4629: bcopy(self->dv_xname, sc->tulip_if.if_xname, IFNAMSIZ);
4630: sc->tulip_if.if_softc = sc;
4631: sc->tulip_pc = pa->pa_pc;
4632: sc->tulip_dmatag = pa->pa_dmat;
4633: sc->tulip_revinfo = revinfo;
4634:
4635: timeout_set(&sc->tulip_stmo, tulip_timeout_callback, sc);
4636:
4637: csr_base = 0;
4638: {
4639: bus_space_tag_t iot, memt;
4640: bus_space_handle_t ioh, memh;
4641: int ioh_valid, memh_valid;
4642:
4643: ioh_valid = (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0,
4644: &iot, &ioh, NULL, NULL, 0) == 0);
4645: memh_valid = (pci_mapreg_map(pa, PCI_CBMA,
4646: PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
4647: &memt, &memh, NULL, NULL, 0) == 0);
4648:
4649: if (memh_valid) {
4650: sc->tulip_bustag = memt;
4651: sc->tulip_bushandle = memh;
4652: } else if (ioh_valid) {
4653: sc->tulip_bustag = iot;
4654: sc->tulip_bushandle = ioh;
4655: } else {
4656: printf(": unable to map device registers\n");
4657: return;
4658: }
4659: }
4660:
4661: tulip_initcsrs(sc, csr_base + csroffset, csrsize);
4662:
4663: if ((retval = tulip_busdma_init(sc)) != 0) {
4664: printf(": error initing bus_dma: %d\n", retval);
4665: return;
4666: }
4667:
4668: tulip_initring(sc, &sc->tulip_rxinfo, sc->tulip_rxdescs, TULIP_RXDESCS);
4669: tulip_initring(sc, &sc->tulip_txinfo, sc->tulip_txdescs, TULIP_TXDESCS);
4670:
4671: /*
4672: * Make sure there won't be any interrupts or such...
4673: */
4674: TULIP_CSR_WRITE(sc, csr_busmode, TULIP_BUSMODE_SWRESET);
4675: DELAY(100); /* Wait 10 microseconds (actually 50 PCI cycles but at
4676: 33MHz that comes to two microseconds but wait a
4677: bit longer anyways) */
4678:
4679: if ((retval = tulip_read_macaddr(sc)) < 0) {
4680: printf(", %s%s pass %d.%d", sc->tulip_boardid,
4681: tulip_chipdescs[sc->tulip_chipid],
4682: (sc->tulip_revinfo & 0xF0) >> 4, sc->tulip_revinfo & 0x0F);
4683: printf(": can't read ENET ROM (why=%d) (", retval);
4684: for (idx = 0; idx < 32; idx++)
4685: printf("%02x", sc->tulip_rombuf[idx]);
4686: printf(", address unknown\n");
4687: } else {
4688: int (*intr_rtn)(void *) = tulip_intr_normal;
4689:
4690: if (sc->tulip_features & TULIP_HAVE_SHAREDINTR)
4691: intr_rtn = tulip_intr_shared;
4692:
4693: if ((sc->tulip_features & TULIP_HAVE_SLAVEDINTR) == 0) {
4694: pci_intr_handle_t intrhandle;
4695: const char *intrstr;
4696:
4697: if (pci_intr_map(pa, &intrhandle)) {
4698: printf(": couldn't map interrupt\n");
4699: return;
4700: }
4701:
4702: intrstr = pci_intr_string(pa->pa_pc, intrhandle);
4703: sc->tulip_ih = pci_intr_establish(pa->pa_pc, intrhandle, IPL_NET,
4704: intr_rtn, sc, self->dv_xname);
4705: if (sc->tulip_ih == NULL) {
4706: printf(": couldn't establish interrupt");
4707: if (intrstr != NULL)
4708: printf(" at %s", intrstr);
4709: printf("\n");
4710: return;
4711: }
4712:
4713: printf(", %s%s pass %d.%d%s: %s, address %s\n",
4714: sc->tulip_boardid,
4715: tulip_chipdescs[sc->tulip_chipid],
4716: (sc->tulip_revinfo & 0xF0) >> 4,
4717: sc->tulip_revinfo & 0x0F,
4718: (sc->tulip_features & (TULIP_HAVE_ISVSROM|TULIP_HAVE_OKSROM))
4719: == TULIP_HAVE_ISVSROM ? " (invalid EESPROM checksum)" : "",
4720: intrstr, ether_sprintf(sc->tulip_enaddr));
4721: }
4722:
4723: sc->tulip_ats = shutdownhook_establish(tulip_shutdown, sc);
4724: if (sc->tulip_ats == NULL)
4725: printf("%s: warning: couldn't establish shutdown hook\n",
4726: sc->tulip_xname);
4727:
4728: ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_NOTRAILERS|IFF_MULTICAST;
4729: ifp->if_ioctl = tulip_ifioctl;
4730: ifp->if_start = tulip_ifstart;
4731: ifp->if_watchdog = tulip_ifwatchdog;
4732: ifp->if_timer = 1;
4733:
4734: (*sc->tulip_boardsw->bd_media_probe)(sc);
4735: ifmedia_init(&sc->tulip_ifmedia, 0,
4736: tulip_ifmedia_change, tulip_ifmedia_status);
4737: sc->tulip_flags &= ~TULIP_DEVICEPROBE;
4738: tulip_ifmedia_add(sc);
4739:
4740: tulip_reset(sc);
4741:
4742: IFQ_SET_READY(&ifp->if_snd);
4743: if_attach(ifp);
4744: ether_ifattach(ifp);
4745: }
4746: }
CVSweb