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