Annotation of src/sys/dev/pci/if_sip.c, Revision 1.115.4.1
1.115.4.1! ad 1: /* $NetBSD: if_sip.c,v 1.124 2007/12/16 21:17:00 dyoung Exp $ */
1.28 thorpej 2:
3: /*-
1.45 thorpej 4: * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
1.28 thorpej 5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
8: * by Jason R. Thorpe.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed by the NetBSD
21: * Foundation, Inc. and its contributors.
22: * 4. Neither the name of The NetBSD Foundation nor the names of its
23: * contributors may be used to endorse or promote products derived
24: * from this software without specific prior written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36: * POSSIBILITY OF SUCH DAMAGE.
37: */
1.1 thorpej 38:
39: /*-
40: * Copyright (c) 1999 Network Computer, Inc.
41: * All rights reserved.
42: *
43: * Redistribution and use in source and binary forms, with or without
44: * modification, are permitted provided that the following conditions
45: * are met:
46: * 1. Redistributions of source code must retain the above copyright
47: * notice, this list of conditions and the following disclaimer.
48: * 2. Redistributions in binary form must reproduce the above copyright
49: * notice, this list of conditions and the following disclaimer in the
50: * documentation and/or other materials provided with the distribution.
51: * 3. Neither the name of Network Computer, Inc. nor the names of its
52: * contributors may be used to endorse or promote products derived
53: * from this software without specific prior written permission.
54: *
55: * THIS SOFTWARE IS PROVIDED BY NETWORK COMPUTER, INC. AND CONTRIBUTORS
56: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
57: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
58: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
59: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
60: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
61: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
62: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
63: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
64: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
65: * POSSIBILITY OF SUCH DAMAGE.
66: */
67:
68: /*
1.29 thorpej 69: * Device driver for the Silicon Integrated Systems SiS 900,
70: * SiS 7016 10/100, National Semiconductor DP83815 10/100, and
71: * National Semiconductor DP83820 10/100/1000 PCI Ethernet
72: * controllers.
1.101 perry 73: *
1.32 thorpej 74: * Originally written to support the SiS 900 by Jason R. Thorpe for
75: * Network Computer, Inc.
1.29 thorpej 76: *
77: * TODO:
78: *
1.58 thorpej 79: * - Reduce the Rx interrupt load.
1.1 thorpej 80: */
1.43 lukem 81:
82: #include <sys/cdefs.h>
1.115.4.1! ad 83: __KERNEL_RCSID(0, "$NetBSD: if_sip.c,v 1.124 2007/12/16 21:17:00 dyoung Exp $");
1.1 thorpej 84:
85: #include "bpfilter.h"
1.65 itojun 86: #include "rnd.h"
1.1 thorpej 87:
88: #include <sys/param.h>
89: #include <sys/systm.h>
1.9 thorpej 90: #include <sys/callout.h>
1.1 thorpej 91: #include <sys/mbuf.h>
92: #include <sys/malloc.h>
93: #include <sys/kernel.h>
94: #include <sys/socket.h>
95: #include <sys/ioctl.h>
96: #include <sys/errno.h>
97: #include <sys/device.h>
98: #include <sys/queue.h>
99:
1.12 mrg 100: #include <uvm/uvm_extern.h> /* for PAGE_SIZE */
1.1 thorpej 101:
1.65 itojun 102: #if NRND > 0
103: #include <sys/rnd.h>
104: #endif
105:
1.1 thorpej 106: #include <net/if.h>
107: #include <net/if_dl.h>
108: #include <net/if_media.h>
109: #include <net/if_ether.h>
110:
111: #if NBPFILTER > 0
112: #include <net/bpf.h>
113: #endif
114:
1.115 ad 115: #include <sys/bus.h>
116: #include <sys/intr.h>
1.14 tsutsui 117: #include <machine/endian.h>
1.1 thorpej 118:
1.15 thorpej 119: #include <dev/mii/mii.h>
1.1 thorpej 120: #include <dev/mii/miivar.h>
1.29 thorpej 121: #include <dev/mii/mii_bitbang.h>
1.1 thorpej 122:
123: #include <dev/pci/pcireg.h>
124: #include <dev/pci/pcivar.h>
125: #include <dev/pci/pcidevs.h>
126:
127: #include <dev/pci/if_sipreg.h>
128:
129: /*
130: * Transmit descriptor list size. This is arbitrary, but allocate
1.30 thorpej 131: * enough descriptors for 128 pending transmissions, and 8 segments
1.88 thorpej 132: * per packet (64 for DP83820 for jumbo frames).
133: *
134: * This MUST work out to a power of 2.
1.1 thorpej 135: */
1.115.4.1! ad 136: #define GSIP_NTXSEGS_ALLOC 16
! 137: #define SIP_NTXSEGS_ALLOC 8
1.1 thorpej 138:
1.30 thorpej 139: #define SIP_TXQUEUELEN 256
1.115.4.1! ad 140: #define MAX_SIP_NTXDESC \
! 141: (SIP_TXQUEUELEN * MAX(SIP_NTXSEGS_ALLOC, GSIP_NTXSEGS_ALLOC))
1.46 thorpej 142:
1.1 thorpej 143: /*
144: * Receive descriptor list size. We have one Rx buffer per incoming
145: * packet, so this logic is a little simpler.
1.36 thorpej 146: *
147: * Actually, on the DP83820, we allow the packet to consume more than
148: * one buffer, in order to support jumbo Ethernet frames. In that
149: * case, a packet may consume up to 5 buffers (assuming a 2048 byte
150: * mbuf cluster). 256 receive buffers is only 51 maximum size packets,
151: * so we'd better be quick about handling receive interrupts.
1.1 thorpej 152: */
1.115.4.1! ad 153: #define GSIP_NRXDESC 256
1.30 thorpej 154: #define SIP_NRXDESC 128
1.115.4.1! ad 155:
! 156: #define MAX_SIP_NRXDESC MAX(GSIP_NRXDESC, SIP_NRXDESC)
1.1 thorpej 157:
158: /*
159: * Control structures are DMA'd to the SiS900 chip. We allocate them in
160: * a single clump that maps to a single DMA segment to make several things
161: * easier.
162: */
163: struct sip_control_data {
164: /*
165: * The transmit descriptors.
166: */
1.115.4.1! ad 167: struct sip_desc scd_txdescs[MAX_SIP_NTXDESC];
1.1 thorpej 168:
169: /*
170: * The receive descriptors.
171: */
1.115.4.1! ad 172: struct sip_desc scd_rxdescs[MAX_SIP_NRXDESC];
1.1 thorpej 173: };
174:
175: #define SIP_CDOFF(x) offsetof(struct sip_control_data, x)
176: #define SIP_CDTXOFF(x) SIP_CDOFF(scd_txdescs[(x)])
177: #define SIP_CDRXOFF(x) SIP_CDOFF(scd_rxdescs[(x)])
178:
179: /*
180: * Software state for transmit jobs.
181: */
182: struct sip_txsoft {
183: struct mbuf *txs_mbuf; /* head of our mbuf chain */
184: bus_dmamap_t txs_dmamap; /* our DMA map */
185: int txs_firstdesc; /* first descriptor in packet */
186: int txs_lastdesc; /* last descriptor in packet */
187: SIMPLEQ_ENTRY(sip_txsoft) txs_q;
188: };
189:
190: SIMPLEQ_HEAD(sip_txsq, sip_txsoft);
191:
192: /*
193: * Software state for receive jobs.
194: */
195: struct sip_rxsoft {
196: struct mbuf *rxs_mbuf; /* head of our mbuf chain */
197: bus_dmamap_t rxs_dmamap; /* our DMA map */
198: };
199:
1.115.4.1! ad 200: enum sip_attach_stage {
! 201: SIP_ATTACH_FIN = 0
! 202: , SIP_ATTACH_CREATE_RXMAP
! 203: , SIP_ATTACH_CREATE_TXMAP
! 204: , SIP_ATTACH_LOAD_MAP
! 205: , SIP_ATTACH_CREATE_MAP
! 206: , SIP_ATTACH_MAP_MEM
! 207: , SIP_ATTACH_ALLOC_MEM
! 208: , SIP_ATTACH_INTR
! 209: , SIP_ATTACH_MAP
! 210: };
! 211:
1.1 thorpej 212: /*
213: * Software state per device.
214: */
215: struct sip_softc {
216: struct device sc_dev; /* generic device information */
217: bus_space_tag_t sc_st; /* bus space tag */
218: bus_space_handle_t sc_sh; /* bus space handle */
1.115.4.1! ad 219: bus_size_t sc_sz; /* bus space size */
1.1 thorpej 220: bus_dma_tag_t sc_dmat; /* bus DMA tag */
1.115.4.1! ad 221: pci_chipset_tag_t sc_pc;
! 222: bus_dma_segment_t sc_seg;
1.1 thorpej 223: struct ethercom sc_ethercom; /* ethernet common data */
224: void *sc_sdhook; /* shutdown hook */
1.15 thorpej 225:
226: const struct sip_product *sc_model; /* which model are we? */
1.115.4.1! ad 227: int sc_gigabit; /* 1: 83820, 0: other */
1.45 thorpej 228: int sc_rev; /* chip revision */
1.1 thorpej 229:
230: void *sc_ih; /* interrupt cookie */
231:
232: struct mii_data sc_mii; /* MII/media information */
233:
1.113 ad 234: callout_t sc_tick_ch; /* tick callout */
1.9 thorpej 235:
1.1 thorpej 236: bus_dmamap_t sc_cddmamap; /* control data DMA map */
237: #define sc_cddma sc_cddmamap->dm_segs[0].ds_addr
238:
239: /*
240: * Software state for transmit and receive descriptors.
241: */
242: struct sip_txsoft sc_txsoft[SIP_TXQUEUELEN];
1.115.4.1! ad 243: struct sip_rxsoft sc_rxsoft[MAX_SIP_NRXDESC];
1.1 thorpej 244:
245: /*
246: * Control data structures.
247: */
248: struct sip_control_data *sc_control_data;
249: #define sc_txdescs sc_control_data->scd_txdescs
250: #define sc_rxdescs sc_control_data->scd_rxdescs
251:
1.30 thorpej 252: #ifdef SIP_EVENT_COUNTERS
253: /*
254: * Event counters.
255: */
256: struct evcnt sc_ev_txsstall; /* Tx stalled due to no txs */
257: struct evcnt sc_ev_txdstall; /* Tx stalled due to no txd */
1.56 thorpej 258: struct evcnt sc_ev_txforceintr; /* Tx interrupts forced */
259: struct evcnt sc_ev_txdintr; /* Tx descriptor interrupts */
260: struct evcnt sc_ev_txiintr; /* Tx idle interrupts */
1.30 thorpej 261: struct evcnt sc_ev_rxintr; /* Rx interrupts */
1.62 thorpej 262: struct evcnt sc_ev_hiberr; /* HIBERR interrupts */
1.94 thorpej 263: struct evcnt sc_ev_rxpause; /* PAUSE received */
1.115.4.1! ad 264: /* DP83820 only */
1.94 thorpej 265: struct evcnt sc_ev_txpause; /* PAUSE transmitted */
1.31 thorpej 266: struct evcnt sc_ev_rxipsum; /* IP checksums checked in-bound */
267: struct evcnt sc_ev_rxtcpsum; /* TCP checksums checked in-bound */
268: struct evcnt sc_ev_rxudpsum; /* UDP checksums checked in-boudn */
269: struct evcnt sc_ev_txipsum; /* IP checksums comp. out-bound */
270: struct evcnt sc_ev_txtcpsum; /* TCP checksums comp. out-bound */
271: struct evcnt sc_ev_txudpsum; /* UDP checksums comp. out-bound */
1.30 thorpej 272: #endif /* SIP_EVENT_COUNTERS */
273:
1.1 thorpej 274: u_int32_t sc_txcfg; /* prototype TXCFG register */
275: u_int32_t sc_rxcfg; /* prototype RXCFG register */
276: u_int32_t sc_imr; /* prototype IMR register */
277: u_int32_t sc_rfcr; /* prototype RFCR register */
278:
1.29 thorpej 279: u_int32_t sc_cfg; /* prototype CFG register */
280:
281: u_int32_t sc_gpior; /* prototype GPIOR register */
282:
1.1 thorpej 283: u_int32_t sc_tx_fill_thresh; /* transmit fill threshold */
284: u_int32_t sc_tx_drain_thresh; /* transmit drain threshold */
285:
286: u_int32_t sc_rx_drain_thresh; /* receive drain threshold */
287:
1.89 thorpej 288: int sc_flowflags; /* 802.3x flow control flags */
289: int sc_rx_flow_thresh; /* Rx FIFO threshold for flow control */
290: int sc_paused; /* paused indication */
1.1 thorpej 291:
292: int sc_txfree; /* number of free Tx descriptors */
293: int sc_txnext; /* next ready Tx descriptor */
1.56 thorpej 294: int sc_txwin; /* Tx descriptors since last intr */
1.1 thorpej 295:
296: struct sip_txsq sc_txfreeq; /* free Tx descsofts */
297: struct sip_txsq sc_txdirtyq; /* dirty Tx descsofts */
298:
1.106 pavel 299: /* values of interface state at last init */
300: struct {
301: /* if_capenable */
302: uint64_t if_capenable;
303: /* ec_capenable */
304: int ec_capenable;
305: /* VLAN_ATTACHED */
306: int is_vlan;
307: } sc_prev;
308:
1.98 kim 309: short sc_if_flags;
310:
1.1 thorpej 311: int sc_rxptr; /* next ready Rx descriptor/descsoft */
1.36 thorpej 312: int sc_rxdiscard;
313: int sc_rxlen;
314: struct mbuf *sc_rxhead;
315: struct mbuf *sc_rxtail;
316: struct mbuf **sc_rxtailp;
1.115.4.1! ad 317:
! 318: int sc_ntxdesc;
! 319: int sc_ntxdesc_mask;
! 320:
! 321: int sc_nrxdesc_mask;
! 322:
! 323: const struct sip_parm {
! 324: const struct sip_regs {
! 325: int r_rxcfg;
! 326: int r_txcfg;
! 327: } p_regs;
! 328:
! 329: const struct sip_bits {
! 330: uint32_t b_txcfg_mxdma_8;
! 331: uint32_t b_txcfg_mxdma_16;
! 332: uint32_t b_txcfg_mxdma_32;
! 333: uint32_t b_txcfg_mxdma_64;
! 334: uint32_t b_txcfg_mxdma_128;
! 335: uint32_t b_txcfg_mxdma_256;
! 336: uint32_t b_txcfg_mxdma_512;
! 337: uint32_t b_txcfg_flth_mask;
! 338: uint32_t b_txcfg_drth_mask;
! 339:
! 340: uint32_t b_rxcfg_mxdma_8;
! 341: uint32_t b_rxcfg_mxdma_16;
! 342: uint32_t b_rxcfg_mxdma_32;
! 343: uint32_t b_rxcfg_mxdma_64;
! 344: uint32_t b_rxcfg_mxdma_128;
! 345: uint32_t b_rxcfg_mxdma_256;
! 346: uint32_t b_rxcfg_mxdma_512;
! 347:
! 348: uint32_t b_isr_txrcmp;
! 349: uint32_t b_isr_rxrcmp;
! 350: uint32_t b_isr_dperr;
! 351: uint32_t b_isr_sserr;
! 352: uint32_t b_isr_rmabt;
! 353: uint32_t b_isr_rtabt;
! 354:
! 355: uint32_t b_cmdsts_size_mask;
! 356: } p_bits;
! 357: int p_filtmem;
! 358: int p_rxbuf_len;
! 359: bus_size_t p_tx_dmamap_size;
! 360: int p_ntxsegs;
! 361: int p_ntxsegs_alloc;
! 362: int p_nrxdesc;
! 363: } *sc_parm;
! 364:
! 365: void (*sc_rxintr)(struct sip_softc *);
1.65 itojun 366:
367: #if NRND > 0
368: rndsource_element_t rnd_source; /* random source */
369: #endif
1.1 thorpej 370: };
371:
1.115.4.1! ad 372: #define sc_bits sc_parm->p_bits
! 373: #define sc_regs sc_parm->p_regs
! 374:
! 375: static const struct sip_parm sip_parm = {
! 376: .p_filtmem = OTHER_RFCR_NS_RFADDR_FILTMEM
! 377: , .p_rxbuf_len = MCLBYTES - 1 /* field width */
! 378: , .p_tx_dmamap_size = MCLBYTES
! 379: , .p_ntxsegs = 16
! 380: , .p_ntxsegs_alloc = SIP_NTXSEGS_ALLOC
! 381: , .p_nrxdesc = SIP_NRXDESC
! 382: , .p_bits = {
! 383: .b_txcfg_mxdma_8 = 0x00200000 /* 8 bytes */
! 384: , .b_txcfg_mxdma_16 = 0x00300000 /* 16 bytes */
! 385: , .b_txcfg_mxdma_32 = 0x00400000 /* 32 bytes */
! 386: , .b_txcfg_mxdma_64 = 0x00500000 /* 64 bytes */
! 387: , .b_txcfg_mxdma_128 = 0x00600000 /* 128 bytes */
! 388: , .b_txcfg_mxdma_256 = 0x00700000 /* 256 bytes */
! 389: , .b_txcfg_mxdma_512 = 0x00000000 /* 512 bytes */
! 390: , .b_txcfg_flth_mask = 0x00003f00 /* Tx fill threshold */
! 391: , .b_txcfg_drth_mask = 0x0000003f /* Tx drain threshold */
! 392:
! 393: , .b_rxcfg_mxdma_8 = 0x00200000 /* 8 bytes */
! 394: , .b_rxcfg_mxdma_16 = 0x00300000 /* 16 bytes */
! 395: , .b_rxcfg_mxdma_32 = 0x00400000 /* 32 bytes */
! 396: , .b_rxcfg_mxdma_64 = 0x00500000 /* 64 bytes */
! 397: , .b_rxcfg_mxdma_128 = 0x00600000 /* 128 bytes */
! 398: , .b_rxcfg_mxdma_256 = 0x00700000 /* 256 bytes */
! 399: , .b_rxcfg_mxdma_512 = 0x00000000 /* 512 bytes */
! 400:
! 401: , .b_isr_txrcmp = 0x02000000 /* transmit reset complete */
! 402: , .b_isr_rxrcmp = 0x01000000 /* receive reset complete */
! 403: , .b_isr_dperr = 0x00800000 /* detected parity error */
! 404: , .b_isr_sserr = 0x00400000 /* signalled system error */
! 405: , .b_isr_rmabt = 0x00200000 /* received master abort */
! 406: , .b_isr_rtabt = 0x00100000 /* received target abort */
! 407: , .b_cmdsts_size_mask = OTHER_CMDSTS_SIZE_MASK
! 408: }
! 409: , .p_regs = {
! 410: .r_rxcfg = OTHER_SIP_RXCFG,
! 411: .r_txcfg = OTHER_SIP_TXCFG
! 412: }
! 413: }, gsip_parm = {
! 414: .p_filtmem = DP83820_RFCR_NS_RFADDR_FILTMEM
! 415: , .p_rxbuf_len = MCLBYTES - 8
! 416: , .p_tx_dmamap_size = ETHER_MAX_LEN_JUMBO
! 417: , .p_ntxsegs = 64
! 418: , .p_ntxsegs_alloc = GSIP_NTXSEGS_ALLOC
! 419: , .p_nrxdesc = GSIP_NRXDESC
! 420: , .p_bits = {
! 421: .b_txcfg_mxdma_8 = 0x00100000 /* 8 bytes */
! 422: , .b_txcfg_mxdma_16 = 0x00200000 /* 16 bytes */
! 423: , .b_txcfg_mxdma_32 = 0x00300000 /* 32 bytes */
! 424: , .b_txcfg_mxdma_64 = 0x00400000 /* 64 bytes */
! 425: , .b_txcfg_mxdma_128 = 0x00500000 /* 128 bytes */
! 426: , .b_txcfg_mxdma_256 = 0x00600000 /* 256 bytes */
! 427: , .b_txcfg_mxdma_512 = 0x00700000 /* 512 bytes */
! 428: , .b_txcfg_flth_mask = 0x0000ff00 /* Fx fill threshold */
! 429: , .b_txcfg_drth_mask = 0x000000ff /* Tx drain threshold */
! 430:
! 431: , .b_rxcfg_mxdma_8 = 0x00100000 /* 8 bytes */
! 432: , .b_rxcfg_mxdma_16 = 0x00200000 /* 16 bytes */
! 433: , .b_rxcfg_mxdma_32 = 0x00300000 /* 32 bytes */
! 434: , .b_rxcfg_mxdma_64 = 0x00400000 /* 64 bytes */
! 435: , .b_rxcfg_mxdma_128 = 0x00500000 /* 128 bytes */
! 436: , .b_rxcfg_mxdma_256 = 0x00600000 /* 256 bytes */
! 437: , .b_rxcfg_mxdma_512 = 0x00700000 /* 512 bytes */
! 438:
! 439: , .b_isr_txrcmp = 0x00400000 /* transmit reset complete */
! 440: , .b_isr_rxrcmp = 0x00200000 /* receive reset complete */
! 441: , .b_isr_dperr = 0x00100000 /* detected parity error */
! 442: , .b_isr_sserr = 0x00080000 /* signalled system error */
! 443: , .b_isr_rmabt = 0x00040000 /* received master abort */
! 444: , .b_isr_rtabt = 0x00020000 /* received target abort */
! 445: , .b_cmdsts_size_mask = DP83820_CMDSTS_SIZE_MASK
! 446: }
! 447: , .p_regs = {
! 448: .r_rxcfg = DP83820_SIP_RXCFG,
! 449: .r_txcfg = DP83820_SIP_TXCFG
! 450: }
! 451: };
! 452:
! 453: static inline int
! 454: sip_nexttx(const struct sip_softc *sc, int x)
! 455: {
! 456: return (x + 1) & sc->sc_ntxdesc_mask;
! 457: }
! 458:
! 459: static inline int
! 460: sip_nextrx(const struct sip_softc *sc, int x)
! 461: {
! 462: return (x + 1) & sc->sc_nrxdesc_mask;
! 463: }
! 464:
! 465: /* 83820 only */
! 466: static inline void
! 467: sip_rxchain_reset(struct sip_softc *sc)
! 468: {
! 469: sc->sc_rxtailp = &sc->sc_rxhead;
! 470: *sc->sc_rxtailp = NULL;
! 471: sc->sc_rxlen = 0;
! 472: }
! 473:
! 474: /* 83820 only */
! 475: static inline void
! 476: sip_rxchain_link(struct sip_softc *sc, struct mbuf *m)
! 477: {
! 478: *sc->sc_rxtailp = sc->sc_rxtail = m;
! 479: sc->sc_rxtailp = &m->m_next;
! 480: }
1.36 thorpej 481:
1.30 thorpej 482: #ifdef SIP_EVENT_COUNTERS
483: #define SIP_EVCNT_INCR(ev) (ev)->ev_count++
484: #else
485: #define SIP_EVCNT_INCR(ev) /* nothing */
486: #endif
487:
1.1 thorpej 488: #define SIP_CDTXADDR(sc, x) ((sc)->sc_cddma + SIP_CDTXOFF((x)))
489: #define SIP_CDRXADDR(sc, x) ((sc)->sc_cddma + SIP_CDRXOFF((x)))
490:
1.115.4.1! ad 491: static inline void
! 492: sip_cdtxsync(struct sip_softc *sc, const int x0, const int n0, const int ops)
! 493: {
! 494: int x, n;
! 495:
! 496: x = x0;
! 497: n = n0;
! 498:
! 499: /* If it will wrap around, sync to the end of the ring. */
! 500: if (x + n > sc->sc_ntxdesc) {
! 501: bus_dmamap_sync(sc->sc_dmat, sc->sc_cddmamap,
! 502: SIP_CDTXOFF(x), sizeof(struct sip_desc) *
! 503: (sc->sc_ntxdesc - x), ops);
! 504: n -= (sc->sc_ntxdesc - x);
! 505: x = 0;
! 506: }
! 507:
! 508: /* Now sync whatever is left. */
! 509: bus_dmamap_sync(sc->sc_dmat, sc->sc_cddmamap,
! 510: SIP_CDTXOFF(x), sizeof(struct sip_desc) * n, ops);
! 511: }
! 512:
! 513: static inline void
! 514: sip_cdrxsync(struct sip_softc *sc, int x, int ops)
! 515: {
! 516: bus_dmamap_sync(sc->sc_dmat, sc->sc_cddmamap,
! 517: SIP_CDRXOFF(x), sizeof(struct sip_desc), ops);
! 518: }
1.1 thorpej 519:
1.115.4.1! ad 520: #if 0
1.31 thorpej 521: #ifdef DP83820
1.115.4.1! ad 522: u_int32_t sipd_bufptr; /* pointer to DMA segment */
! 523: u_int32_t sipd_cmdsts; /* command/status word */
1.31 thorpej 524: #else
1.115.4.1! ad 525: u_int32_t sipd_cmdsts; /* command/status word */
! 526: u_int32_t sipd_bufptr; /* pointer to DMA segment */
! 527: #endif /* DP83820 */
! 528: #endif /* 0 */
! 529:
! 530: static inline volatile uint32_t *
! 531: sipd_cmdsts(struct sip_softc *sc, struct sip_desc *sipd)
! 532: {
! 533: return &sipd->sipd_cbs[(sc->sc_gigabit) ? 1 : 0];
! 534: }
! 535:
! 536: static inline volatile uint32_t *
! 537: sipd_bufptr(struct sip_softc *sc, struct sip_desc *sipd)
! 538: {
! 539: return &sipd->sipd_cbs[(sc->sc_gigabit) ? 0 : 1];
! 540: }
! 541:
! 542: static inline void
! 543: sip_init_rxdesc(struct sip_softc *sc, int x)
! 544: {
! 545: struct sip_rxsoft *rxs = &sc->sc_rxsoft[x];
! 546: struct sip_desc *sipd = &sc->sc_rxdescs[x];
! 547:
! 548: sipd->sipd_link = htole32(SIP_CDRXADDR(sc, sip_nextrx(sc, x)));
! 549: *sipd_bufptr(sc, sipd) = htole32(rxs->rxs_dmamap->dm_segs[0].ds_addr);
! 550: *sipd_cmdsts(sc, sipd) = htole32(CMDSTS_INTR |
! 551: (sc->sc_parm->p_rxbuf_len & sc->sc_bits.b_cmdsts_size_mask));
! 552: sipd->sipd_extsts = 0;
! 553: sip_cdrxsync(sc, x, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
! 554: }
1.1 thorpej 555:
1.45 thorpej 556: #define SIP_CHIP_VERS(sc, v, p, r) \
557: ((sc)->sc_model->sip_vendor == (v) && \
558: (sc)->sc_model->sip_product == (p) && \
559: (sc)->sc_rev == (r))
560:
561: #define SIP_CHIP_MODEL(sc, v, p) \
562: ((sc)->sc_model->sip_vendor == (v) && \
563: (sc)->sc_model->sip_product == (p))
564:
565: #define SIP_SIS900_REV(sc, rev) \
566: SIP_CHIP_VERS((sc), PCI_VENDOR_SIS, PCI_PRODUCT_SIS_900, (rev))
567:
1.14 tsutsui 568: #define SIP_TIMEOUT 1000
569:
1.115.4.1! ad 570: static void sipcom_start(struct ifnet *);
! 571: static void sipcom_watchdog(struct ifnet *);
! 572: static int sipcom_ioctl(struct ifnet *, u_long, void *);
! 573: static int sipcom_init(struct ifnet *);
! 574: static void sipcom_stop(struct ifnet *, int);
! 575:
! 576: static void sipcom_shutdown(void *);
! 577:
! 578: static bool sipcom_reset(struct sip_softc *);
! 579: static void sipcom_rxdrain(struct sip_softc *);
! 580: static int sipcom_add_rxbuf(struct sip_softc *, int);
! 581: static void sipcom_read_eeprom(struct sip_softc *, int, int,
1.95 thorpej 582: u_int16_t *);
1.115.4.1! ad 583: static void sipcom_tick(void *);
1.1 thorpej 584:
1.115.4.1! ad 585: static void sipcom_sis900_set_filter(struct sip_softc *);
! 586: static void sipcom_dp83815_set_filter(struct sip_softc *);
1.15 thorpej 587:
1.115.4.1! ad 588: static void sipcom_dp83820_read_macaddr(struct sip_softc *,
1.95 thorpej 589: const struct pci_attach_args *, u_int8_t *);
1.115.4.1! ad 590: static void sipcom_sis900_eeprom_delay(struct sip_softc *sc);
! 591: static void sipcom_sis900_read_macaddr(struct sip_softc *,
1.95 thorpej 592: const struct pci_attach_args *, u_int8_t *);
1.115.4.1! ad 593: static void sipcom_dp83815_read_macaddr(struct sip_softc *,
1.95 thorpej 594: const struct pci_attach_args *, u_int8_t *);
1.25 briggs 595:
1.115.4.1! ad 596: static int sipcom_intr(void *);
! 597: static void sipcom_txintr(struct sip_softc *);
! 598: static void sip_rxintr(struct sip_softc *);
! 599: static void gsip_rxintr(struct sip_softc *);
! 600:
! 601: static int sipcom_dp83820_mii_readreg(struct device *, int, int);
! 602: static void sipcom_dp83820_mii_writereg(struct device *, int, int, int);
! 603: static void sipcom_dp83820_mii_statchg(struct device *);
! 604:
! 605: static int sipcom_sis900_mii_readreg(struct device *, int, int);
! 606: static void sipcom_sis900_mii_writereg(struct device *, int, int, int);
! 607: static void sipcom_sis900_mii_statchg(struct device *);
! 608:
! 609: static int sipcom_dp83815_mii_readreg(struct device *, int, int);
! 610: static void sipcom_dp83815_mii_writereg(struct device *, int, int, int);
! 611: static void sipcom_dp83815_mii_statchg(struct device *);
! 612:
! 613: static int sipcom_mediachange(struct ifnet *);
! 614: static void sipcom_mediastatus(struct ifnet *, struct ifmediareq *);
! 615:
! 616: static int sipcom_match(struct device *, struct cfdata *, void *);
! 617: static void sipcom_attach(struct device *, struct device *, void *);
! 618: static void sipcom_do_detach(device_t, enum sip_attach_stage);
! 619: static int sipcom_detach(device_t, int);
! 620: static bool sipcom_resume(device_t);
1.1 thorpej 621:
1.115.4.1! ad 622: int gsip_copy_small = 0;
! 623: int sip_copy_small = 0;
1.2 thorpej 624:
1.71 thorpej 625: CFATTACH_DECL(gsip, sizeof(struct sip_softc),
1.115.4.1! ad 626: sipcom_match, sipcom_attach, sipcom_detach, NULL);
1.71 thorpej 627: CFATTACH_DECL(sip, sizeof(struct sip_softc),
1.115.4.1! ad 628: sipcom_match, sipcom_attach, sipcom_detach, NULL);
1.1 thorpej 629:
1.15 thorpej 630: /*
631: * Descriptions of the variants of the SiS900.
632: */
633: struct sip_variant {
1.28 thorpej 634: int (*sipv_mii_readreg)(struct device *, int, int);
635: void (*sipv_mii_writereg)(struct device *, int, int, int);
636: void (*sipv_mii_statchg)(struct device *);
637: void (*sipv_set_filter)(struct sip_softc *);
1.101 perry 638: void (*sipv_read_macaddr)(struct sip_softc *,
1.44 thorpej 639: const struct pci_attach_args *, u_int8_t *);
1.15 thorpej 640: };
641:
1.115.4.1! ad 642: static u_int32_t sipcom_mii_bitbang_read(struct device *);
! 643: static void sipcom_mii_bitbang_write(struct device *, u_int32_t);
1.29 thorpej 644:
1.115.4.1! ad 645: static const struct mii_bitbang_ops sipcom_mii_bitbang_ops = {
! 646: sipcom_mii_bitbang_read,
! 647: sipcom_mii_bitbang_write,
1.29 thorpej 648: {
649: EROMAR_MDIO, /* MII_BIT_MDO */
650: EROMAR_MDIO, /* MII_BIT_MDI */
651: EROMAR_MDC, /* MII_BIT_MDC */
652: EROMAR_MDDIR, /* MII_BIT_DIR_HOST_PHY */
653: 0, /* MII_BIT_DIR_PHY_HOST */
654: }
655: };
656:
1.115.4.1! ad 657: static const struct sip_variant sipcom_variant_dp83820 = {
! 658: sipcom_dp83820_mii_readreg,
! 659: sipcom_dp83820_mii_writereg,
! 660: sipcom_dp83820_mii_statchg,
! 661: sipcom_dp83815_set_filter,
! 662: sipcom_dp83820_read_macaddr,
1.29 thorpej 663: };
1.115.4.1! ad 664:
! 665: static const struct sip_variant sipcom_variant_sis900 = {
! 666: sipcom_sis900_mii_readreg,
! 667: sipcom_sis900_mii_writereg,
! 668: sipcom_sis900_mii_statchg,
! 669: sipcom_sis900_set_filter,
! 670: sipcom_sis900_read_macaddr,
1.15 thorpej 671: };
672:
1.115.4.1! ad 673: static const struct sip_variant sipcom_variant_dp83815 = {
! 674: sipcom_dp83815_mii_readreg,
! 675: sipcom_dp83815_mii_writereg,
! 676: sipcom_dp83815_mii_statchg,
! 677: sipcom_dp83815_set_filter,
! 678: sipcom_dp83815_read_macaddr,
1.15 thorpej 679: };
1.115.4.1! ad 680:
1.15 thorpej 681:
682: /*
683: * Devices supported by this driver.
684: */
1.95 thorpej 685: static const struct sip_product {
1.15 thorpej 686: pci_vendor_id_t sip_vendor;
687: pci_product_id_t sip_product;
688: const char *sip_name;
689: const struct sip_variant *sip_variant;
1.115.4.1! ad 690: int sip_gigabit;
! 691: } sipcom_products[] = {
1.29 thorpej 692: { PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83820,
693: "NatSemi DP83820 Gigabit Ethernet",
1.115.4.1! ad 694: &sipcom_variant_dp83820, 1 },
1.15 thorpej 695: { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_900,
696: "SiS 900 10/100 Ethernet",
1.115.4.1! ad 697: &sipcom_variant_sis900, 0 },
1.15 thorpej 698: { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_7016,
699: "SiS 7016 10/100 Ethernet",
1.115.4.1! ad 700: &sipcom_variant_sis900, 0 },
1.15 thorpej 701:
702: { PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83815,
703: "NatSemi DP83815 10/100 Ethernet",
1.115.4.1! ad 704: &sipcom_variant_dp83815, 0 },
1.15 thorpej 705:
706: { 0, 0,
707: NULL,
1.115.4.1! ad 708: NULL, 0 },
1.15 thorpej 709: };
710:
1.28 thorpej 711: static const struct sip_product *
1.115.4.1! ad 712: sipcom_lookup(const struct pci_attach_args *pa, bool gigabit)
1.1 thorpej 713: {
714: const struct sip_product *sip;
715:
1.115.4.1! ad 716: for (sip = sipcom_products; sip->sip_name != NULL; sip++) {
1.1 thorpej 717: if (PCI_VENDOR(pa->pa_id) == sip->sip_vendor &&
1.115.4.1! ad 718: PCI_PRODUCT(pa->pa_id) == sip->sip_product &&
! 719: sip->sip_gigabit == gigabit)
! 720: return sip;
1.1 thorpej 721: }
1.115.4.1! ad 722: return NULL;
1.1 thorpej 723: }
724:
1.60 thorpej 725: /*
726: * I really hate stupid hardware vendors. There's a bit in the EEPROM
727: * which indicates if the card can do 64-bit data transfers. Unfortunately,
728: * several vendors of 32-bit cards fail to clear this bit in the EEPROM,
729: * which means we try to use 64-bit data transfers on those cards if we
730: * happen to be plugged into a 32-bit slot.
731: *
732: * What we do is use this table of cards known to be 64-bit cards. If
733: * you have a 64-bit card who's subsystem ID is not listed in this table,
734: * send the output of "pcictl dump ..." of the device to me so that your
735: * card will use the 64-bit data path when plugged into a 64-bit slot.
736: *
1.85 keihan 737: * -- Jason R. Thorpe <thorpej@NetBSD.org>
1.60 thorpej 738: * June 30, 2002
739: */
740: static int
1.115.4.1! ad 741: sipcom_check_64bit(const struct pci_attach_args *pa)
1.60 thorpej 742: {
743: static const struct {
744: pci_vendor_id_t c64_vendor;
745: pci_product_id_t c64_product;
746: } card64[] = {
747: /* Asante GigaNIX */
748: { 0x128a, 0x0002 },
1.61 thorpej 749:
750: /* Accton EN1407-T, Planex GN-1000TE */
751: { 0x1113, 0x1407 },
1.60 thorpej 752:
1.69 thorpej 753: /* Netgear GA-621 */
754: { 0x1385, 0x621a },
1.77 briggs 755:
756: /* SMC EZ Card */
757: { 0x10b8, 0x9462 },
1.69 thorpej 758:
1.60 thorpej 759: { 0, 0}
760: };
761: pcireg_t subsys;
762: int i;
763:
764: subsys = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
765:
766: for (i = 0; card64[i].c64_vendor != 0; i++) {
767: if (PCI_VENDOR(subsys) == card64[i].c64_vendor &&
768: PCI_PRODUCT(subsys) == card64[i].c64_product)
769: return (1);
770: }
771:
772: return (0);
773: }
774:
1.95 thorpej 775: static int
1.115.4.1! ad 776: sipcom_match(struct device *parent, struct cfdata *cf, void *aux)
1.1 thorpej 777: {
778: struct pci_attach_args *pa = aux;
779:
1.115.4.1! ad 780: if (sipcom_lookup(pa, strcmp(cf->cf_name, "gsip") == 0) != NULL)
! 781: return 1;
1.1 thorpej 782:
1.115.4.1! ad 783: return 0;
! 784: }
! 785:
! 786: static void
! 787: sipcom_dp83820_attach(struct sip_softc *sc, struct pci_attach_args *pa)
! 788: {
! 789: u_int32_t reg;
! 790: int i;
! 791:
! 792: /*
! 793: * Cause the chip to load configuration data from the EEPROM.
! 794: */
! 795: bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_PTSCR, PTSCR_EELOAD_EN);
! 796: for (i = 0; i < 10000; i++) {
! 797: delay(10);
! 798: if ((bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_PTSCR) &
! 799: PTSCR_EELOAD_EN) == 0)
! 800: break;
! 801: }
! 802: if (bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_PTSCR) &
! 803: PTSCR_EELOAD_EN) {
! 804: printf("%s: timeout loading configuration from EEPROM\n",
! 805: sc->sc_dev.dv_xname);
! 806: return;
! 807: }
! 808:
! 809: sc->sc_gpior = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_GPIOR);
! 810:
! 811: reg = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_CFG);
! 812: if (reg & CFG_PCI64_DET) {
! 813: printf("%s: 64-bit PCI slot detected", sc->sc_dev.dv_xname);
! 814: /*
! 815: * Check to see if this card is 64-bit. If so, enable 64-bit
! 816: * data transfers.
! 817: *
! 818: * We can't use the DATA64_EN bit in the EEPROM, because
! 819: * vendors of 32-bit cards fail to clear that bit in many
! 820: * cases (yet the card still detects that it's in a 64-bit
! 821: * slot; go figure).
! 822: */
! 823: if (sipcom_check_64bit(pa)) {
! 824: sc->sc_cfg |= CFG_DATA64_EN;
! 825: printf(", using 64-bit data transfers");
! 826: }
! 827: printf("\n");
! 828: }
! 829:
! 830: /*
! 831: * XXX Need some PCI flags indicating support for
! 832: * XXX 64-bit addressing.
! 833: */
! 834: #if 0
! 835: if (reg & CFG_M64ADDR)
! 836: sc->sc_cfg |= CFG_M64ADDR;
! 837: if (reg & CFG_T64ADDR)
! 838: sc->sc_cfg |= CFG_T64ADDR;
! 839: #endif
! 840:
! 841: if (reg & (CFG_TBI_EN|CFG_EXT_125)) {
! 842: const char *sep = "";
! 843: printf("%s: using ", sc->sc_dev.dv_xname);
! 844: if (reg & CFG_EXT_125) {
! 845: sc->sc_cfg |= CFG_EXT_125;
! 846: printf("%s125MHz clock", sep);
! 847: sep = ", ";
! 848: }
! 849: if (reg & CFG_TBI_EN) {
! 850: sc->sc_cfg |= CFG_TBI_EN;
! 851: printf("%sten-bit interface", sep);
! 852: sep = ", ";
! 853: }
! 854: printf("\n");
! 855: }
! 856: if ((pa->pa_flags & PCI_FLAGS_MRM_OKAY) == 0 ||
! 857: (reg & CFG_MRM_DIS) != 0)
! 858: sc->sc_cfg |= CFG_MRM_DIS;
! 859: if ((pa->pa_flags & PCI_FLAGS_MWI_OKAY) == 0 ||
! 860: (reg & CFG_MWI_DIS) != 0)
! 861: sc->sc_cfg |= CFG_MWI_DIS;
! 862:
! 863: /*
! 864: * Use the extended descriptor format on the DP83820. This
! 865: * gives us an interface to VLAN tagging and IPv4/TCP/UDP
! 866: * checksumming.
! 867: */
! 868: sc->sc_cfg |= CFG_EXTSTS_EN;
! 869: }
! 870:
! 871: static int
! 872: sipcom_detach(device_t self, int flags)
! 873: {
! 874: int s;
! 875:
! 876: s = splnet();
! 877: sipcom_do_detach(self, SIP_ATTACH_FIN);
! 878: splx(s);
! 879:
! 880: return 0;
! 881: }
! 882:
! 883: static void
! 884: sipcom_do_detach(device_t self, enum sip_attach_stage stage)
! 885: {
! 886: int i;
! 887: struct sip_softc *sc = device_private(self);
! 888: struct ifnet *ifp = &sc->sc_ethercom.ec_if;
! 889:
! 890: /*
! 891: * Free any resources we've allocated during attach.
! 892: * Do this in reverse order and fall through.
! 893: */
! 894: switch (stage) {
! 895: case SIP_ATTACH_FIN:
! 896: sipcom_stop(ifp, 1);
! 897: pmf_device_deregister(self);
! 898: #ifdef SIP_EVENT_COUNTERS
! 899: /*
! 900: * Attach event counters.
! 901: */
! 902: evcnt_detach(&sc->sc_ev_txforceintr);
! 903: evcnt_detach(&sc->sc_ev_txdstall);
! 904: evcnt_detach(&sc->sc_ev_txsstall);
! 905: evcnt_detach(&sc->sc_ev_hiberr);
! 906: evcnt_detach(&sc->sc_ev_rxintr);
! 907: evcnt_detach(&sc->sc_ev_txiintr);
! 908: evcnt_detach(&sc->sc_ev_txdintr);
! 909: if (!sc->sc_gigabit) {
! 910: evcnt_detach(&sc->sc_ev_rxpause);
! 911: } else {
! 912: evcnt_detach(&sc->sc_ev_txudpsum);
! 913: evcnt_detach(&sc->sc_ev_txtcpsum);
! 914: evcnt_detach(&sc->sc_ev_txipsum);
! 915: evcnt_detach(&sc->sc_ev_rxudpsum);
! 916: evcnt_detach(&sc->sc_ev_rxtcpsum);
! 917: evcnt_detach(&sc->sc_ev_rxipsum);
! 918: evcnt_detach(&sc->sc_ev_txpause);
! 919: evcnt_detach(&sc->sc_ev_rxpause);
! 920: }
! 921: #endif /* SIP_EVENT_COUNTERS */
! 922:
! 923: #if NRND > 0
! 924: rnd_detach_source(&sc->rnd_source);
! 925: #endif
! 926:
! 927: ether_ifdetach(ifp);
! 928: if_detach(ifp);
! 929: mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
! 930:
! 931: if (sc->sc_sdhook != NULL)
! 932: shutdownhook_disestablish(sc->sc_sdhook);
! 933:
! 934: /*FALLTHROUGH*/
! 935: case SIP_ATTACH_CREATE_RXMAP:
! 936: for (i = 0; i < sc->sc_parm->p_nrxdesc; i++) {
! 937: if (sc->sc_rxsoft[i].rxs_dmamap != NULL)
! 938: bus_dmamap_destroy(sc->sc_dmat,
! 939: sc->sc_rxsoft[i].rxs_dmamap);
! 940: }
! 941: /*FALLTHROUGH*/
! 942: case SIP_ATTACH_CREATE_TXMAP:
! 943: for (i = 0; i < SIP_TXQUEUELEN; i++) {
! 944: if (sc->sc_txsoft[i].txs_dmamap != NULL)
! 945: bus_dmamap_destroy(sc->sc_dmat,
! 946: sc->sc_txsoft[i].txs_dmamap);
! 947: }
! 948: /*FALLTHROUGH*/
! 949: case SIP_ATTACH_LOAD_MAP:
! 950: bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap);
! 951: /*FALLTHROUGH*/
! 952: case SIP_ATTACH_CREATE_MAP:
! 953: bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap);
! 954: /*FALLTHROUGH*/
! 955: case SIP_ATTACH_MAP_MEM:
! 956: bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_control_data,
! 957: sizeof(struct sip_control_data));
! 958: /*FALLTHROUGH*/
! 959: case SIP_ATTACH_ALLOC_MEM:
! 960: bus_dmamem_free(sc->sc_dmat, &sc->sc_seg, 1);
! 961: /* FALLTHROUGH*/
! 962: case SIP_ATTACH_INTR:
! 963: pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
! 964: /* FALLTHROUGH*/
! 965: case SIP_ATTACH_MAP:
! 966: bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz);
! 967: break;
! 968: default:
! 969: break;
! 970: }
! 971: return;
! 972: }
! 973:
! 974: static bool
! 975: sipcom_resume(device_t self)
! 976: {
! 977: struct sip_softc *sc = device_private(self);
! 978:
! 979: return sipcom_reset(sc);
1.1 thorpej 980: }
981:
1.95 thorpej 982: static void
1.115.4.1! ad 983: sipcom_attach(device_t parent, device_t self, void *aux)
1.1 thorpej 984: {
985: struct sip_softc *sc = (struct sip_softc *) self;
986: struct pci_attach_args *pa = aux;
987: struct ifnet *ifp = &sc->sc_ethercom.ec_if;
988: pci_chipset_tag_t pc = pa->pa_pc;
989: pci_intr_handle_t ih;
990: const char *intrstr = NULL;
991: bus_space_tag_t iot, memt;
992: bus_space_handle_t ioh, memh;
1.115.4.1! ad 993: bus_size_t iosz, memsz;
1.1 thorpej 994: int ioh_valid, memh_valid;
995: int i, rseg, error;
996: const struct sip_product *sip;
1.14 tsutsui 997: u_int8_t enaddr[ETHER_ADDR_LEN];
1.108 christos 998: pcireg_t pmreg;
1.29 thorpej 999: pcireg_t memtype;
1.115.4.1! ad 1000: bus_size_t tx_dmamap_size;
! 1001: int ntxsegs_alloc;
! 1002: cfdata_t cf = device_cfdata(self);
1.1 thorpej 1003:
1.113 ad 1004: callout_init(&sc->sc_tick_ch, 0);
1.9 thorpej 1005:
1.115.4.1! ad 1006: sip = sipcom_lookup(pa, strcmp(cf->cf_name, "gsip") == 0);
1.1 thorpej 1007: if (sip == NULL) {
1008: printf("\n");
1.115.4.1! ad 1009: panic("%s: impossible", __func__);
! 1010: }
! 1011: sc->sc_gigabit = sip->sip_gigabit;
! 1012:
! 1013: sc->sc_pc = pc;
! 1014:
! 1015: if (sc->sc_gigabit) {
! 1016: sc->sc_rxintr = gsip_rxintr;
! 1017: sc->sc_parm = &gsip_parm;
! 1018: } else {
! 1019: sc->sc_rxintr = sip_rxintr;
! 1020: sc->sc_parm = &sip_parm;
1.1 thorpej 1021: }
1.115.4.1! ad 1022: tx_dmamap_size = sc->sc_parm->p_tx_dmamap_size;
! 1023: ntxsegs_alloc = sc->sc_parm->p_ntxsegs_alloc;
! 1024: sc->sc_ntxdesc = SIP_TXQUEUELEN * ntxsegs_alloc;
! 1025: sc->sc_ntxdesc_mask = sc->sc_ntxdesc - 1;
! 1026: sc->sc_nrxdesc_mask = sc->sc_parm->p_nrxdesc - 1;
! 1027:
1.45 thorpej 1028: sc->sc_rev = PCI_REVISION(pa->pa_class);
1.1 thorpej 1029:
1.50 briggs 1030: printf(": %s, rev %#02x\n", sip->sip_name, sc->sc_rev);
1.1 thorpej 1031:
1.15 thorpej 1032: sc->sc_model = sip;
1.5 thorpej 1033:
1.1 thorpej 1034: /*
1.46 thorpej 1035: * XXX Work-around broken PXE firmware on some boards.
1036: *
1037: * The DP83815 shares an address decoder with the MEM BAR
1038: * and the ROM BAR. Make sure the ROM BAR is disabled,
1039: * so that memory mapped access works.
1040: */
1041: pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM,
1042: pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM) &
1043: ~PCI_MAPREG_ROM_ENABLE);
1044:
1045: /*
1.1 thorpej 1046: * Map the device.
1047: */
1048: ioh_valid = (pci_mapreg_map(pa, SIP_PCI_CFGIOA,
1049: PCI_MAPREG_TYPE_IO, 0,
1.115.4.1! ad 1050: &iot, &ioh, NULL, &iosz) == 0);
! 1051: if (sc->sc_gigabit) {
! 1052: memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, SIP_PCI_CFGMA);
! 1053: switch (memtype) {
! 1054: case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
! 1055: case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
! 1056: memh_valid = (pci_mapreg_map(pa, SIP_PCI_CFGMA,
! 1057: memtype, 0, &memt, &memh, NULL, &memsz) == 0);
! 1058: break;
! 1059: default:
! 1060: memh_valid = 0;
! 1061: }
! 1062: } else {
1.29 thorpej 1063: memh_valid = (pci_mapreg_map(pa, SIP_PCI_CFGMA,
1.115.4.1! ad 1064: PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
! 1065: &memt, &memh, NULL, &memsz) == 0);
1.29 thorpej 1066: }
1067:
1.1 thorpej 1068: if (memh_valid) {
1069: sc->sc_st = memt;
1070: sc->sc_sh = memh;
1.115.4.1! ad 1071: sc->sc_sz = memsz;
1.1 thorpej 1072: } else if (ioh_valid) {
1073: sc->sc_st = iot;
1074: sc->sc_sh = ioh;
1.115.4.1! ad 1075: sc->sc_sz = iosz;
1.1 thorpej 1076: } else {
1077: printf("%s: unable to map device registers\n",
1078: sc->sc_dev.dv_xname);
1079: return;
1080: }
1081:
1082: sc->sc_dmat = pa->pa_dmat;
1083:
1.48 thorpej 1084: /*
1085: * Make sure bus mastering is enabled. Also make sure
1086: * Write/Invalidate is enabled if we're allowed to use it.
1087: */
1088: pmreg = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
1089: if (pa->pa_flags & PCI_FLAGS_MWI_OKAY)
1090: pmreg |= PCI_COMMAND_INVALIDATE_ENABLE;
1.1 thorpej 1091: pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
1.48 thorpej 1092: pmreg | PCI_COMMAND_MASTER_ENABLE);
1.1 thorpej 1093:
1.108 christos 1094: /* power up chip */
1095: if ((error = pci_activate(pa->pa_pc, pa->pa_tag, sc,
1096: NULL)) && error != EOPNOTSUPP) {
1097: aprint_error("%s: cannot activate %d\n", sc->sc_dev.dv_xname,
1098: error);
1099: return;
1.1 thorpej 1100: }
1101:
1102: /*
1103: * Map and establish our interrupt.
1104: */
1.23 sommerfe 1105: if (pci_intr_map(pa, &ih)) {
1.1 thorpej 1106: printf("%s: unable to map interrupt\n", sc->sc_dev.dv_xname);
1107: return;
1108: }
1109: intrstr = pci_intr_string(pc, ih);
1.115.4.1! ad 1110: sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, sipcom_intr, sc);
1.1 thorpej 1111: if (sc->sc_ih == NULL) {
1112: printf("%s: unable to establish interrupt",
1113: sc->sc_dev.dv_xname);
1114: if (intrstr != NULL)
1115: printf(" at %s", intrstr);
1116: printf("\n");
1.115.4.1! ad 1117: return sipcom_do_detach(self, SIP_ATTACH_MAP);
1.1 thorpej 1118: }
1119: printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
1120:
1121: SIMPLEQ_INIT(&sc->sc_txfreeq);
1122: SIMPLEQ_INIT(&sc->sc_txdirtyq);
1123:
1124: /*
1125: * Allocate the control data structures, and create and load the
1126: * DMA map for it.
1127: */
1128: if ((error = bus_dmamem_alloc(sc->sc_dmat,
1.115.4.1! ad 1129: sizeof(struct sip_control_data), PAGE_SIZE, 0, &sc->sc_seg, 1,
! 1130: &rseg, 0)) != 0) {
1.1 thorpej 1131: printf("%s: unable to allocate control data, error = %d\n",
1132: sc->sc_dev.dv_xname, error);
1.115.4.1! ad 1133: return sipcom_do_detach(self, SIP_ATTACH_INTR);
1.1 thorpej 1134: }
1135:
1.115.4.1! ad 1136: if ((error = bus_dmamem_map(sc->sc_dmat, &sc->sc_seg, rseg,
1.111 christos 1137: sizeof(struct sip_control_data), (void **)&sc->sc_control_data,
1.115.4.1! ad 1138: BUS_DMA_COHERENT|BUS_DMA_NOCACHE)) != 0) {
1.1 thorpej 1139: printf("%s: unable to map control data, error = %d\n",
1140: sc->sc_dev.dv_xname, error);
1.115.4.1! ad 1141: sipcom_do_detach(self, SIP_ATTACH_ALLOC_MEM);
1.1 thorpej 1142: }
1143:
1144: if ((error = bus_dmamap_create(sc->sc_dmat,
1145: sizeof(struct sip_control_data), 1,
1146: sizeof(struct sip_control_data), 0, 0, &sc->sc_cddmamap)) != 0) {
1147: printf("%s: unable to create control data DMA map, "
1148: "error = %d\n", sc->sc_dev.dv_xname, error);
1.115.4.1! ad 1149: sipcom_do_detach(self, SIP_ATTACH_MAP_MEM);
1.1 thorpej 1150: }
1151:
1152: if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap,
1153: sc->sc_control_data, sizeof(struct sip_control_data), NULL,
1154: 0)) != 0) {
1155: printf("%s: unable to load control data DMA map, error = %d\n",
1156: sc->sc_dev.dv_xname, error);
1.115.4.1! ad 1157: sipcom_do_detach(self, SIP_ATTACH_CREATE_MAP);
1.1 thorpej 1158: }
1159:
1160: /*
1161: * Create the transmit buffer DMA maps.
1162: */
1163: for (i = 0; i < SIP_TXQUEUELEN; i++) {
1.115.4.1! ad 1164: if ((error = bus_dmamap_create(sc->sc_dmat, tx_dmamap_size,
! 1165: sc->sc_parm->p_ntxsegs, MCLBYTES, 0, 0,
1.1 thorpej 1166: &sc->sc_txsoft[i].txs_dmamap)) != 0) {
1167: printf("%s: unable to create tx DMA map %d, "
1168: "error = %d\n", sc->sc_dev.dv_xname, i, error);
1.115.4.1! ad 1169: sipcom_do_detach(self, SIP_ATTACH_CREATE_TXMAP);
1.1 thorpej 1170: }
1171: }
1172:
1173: /*
1174: * Create the receive buffer DMA maps.
1175: */
1.115.4.1! ad 1176: for (i = 0; i < sc->sc_parm->p_nrxdesc; i++) {
1.1 thorpej 1177: if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
1178: MCLBYTES, 0, 0, &sc->sc_rxsoft[i].rxs_dmamap)) != 0) {
1179: printf("%s: unable to create rx DMA map %d, "
1180: "error = %d\n", sc->sc_dev.dv_xname, i, error);
1.115.4.1! ad 1181: sipcom_do_detach(self, SIP_ATTACH_CREATE_RXMAP);
1.1 thorpej 1182: }
1.2 thorpej 1183: sc->sc_rxsoft[i].rxs_mbuf = NULL;
1.1 thorpej 1184: }
1185:
1186: /*
1187: * Reset the chip to a known state.
1188: */
1.115.4.1! ad 1189: sipcom_reset(sc);
1.1 thorpej 1190:
1191: /*
1.29 thorpej 1192: * Read the Ethernet address from the EEPROM. This might
1.115.4.1! ad 1193: * also fetch other stuff from the EEPROM and stash it
! 1194: * in the softc.
! 1195: */
! 1196: sc->sc_cfg = 0;
! 1197: if (!sc->sc_gigabit) {
! 1198: if (SIP_SIS900_REV(sc,SIS_REV_635) ||
! 1199: SIP_SIS900_REV(sc,SIS_REV_900B))
! 1200: sc->sc_cfg |= (CFG_PESEL | CFG_RNDCNT);
! 1201:
! 1202: if (SIP_SIS900_REV(sc,SIS_REV_635) ||
! 1203: SIP_SIS900_REV(sc,SIS_REV_960) ||
! 1204: SIP_SIS900_REV(sc,SIS_REV_900B))
! 1205: sc->sc_cfg |=
! 1206: (bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_CFG) &
! 1207: CFG_EDBMASTEN);
! 1208: }
! 1209:
! 1210: (*sip->sip_variant->sipv_read_macaddr)(sc, pa, enaddr);
! 1211:
! 1212: printf("%s: Ethernet address %s\n", sc->sc_dev.dv_xname,
! 1213: ether_sprintf(enaddr));
1.29 thorpej 1214:
1215: /*
1.115.4.1! ad 1216: * Initialize the configuration register: aggressive PCI
! 1217: * bus request algorithm, default backoff, default OW timer,
! 1218: * default parity error detection.
! 1219: *
! 1220: * NOTE: "Big endian mode" is useless on the SiS900 and
! 1221: * friends -- it affects packet data, not descriptors.
1.29 thorpej 1222: */
1.115.4.1! ad 1223: if (sc->sc_gigabit)
! 1224: sipcom_dp83820_attach(sc, pa);
1.29 thorpej 1225:
1226: /*
1.1 thorpej 1227: * Initialize our media structures and probe the MII.
1228: */
1229: sc->sc_mii.mii_ifp = ifp;
1.15 thorpej 1230: sc->sc_mii.mii_readreg = sip->sip_variant->sipv_mii_readreg;
1231: sc->sc_mii.mii_writereg = sip->sip_variant->sipv_mii_writereg;
1232: sc->sc_mii.mii_statchg = sip->sip_variant->sipv_mii_statchg;
1.115.4.1! ad 1233: ifmedia_init(&sc->sc_mii.mii_media, IFM_IMASK, sipcom_mediachange,
! 1234: sipcom_mediastatus);
1.63 thorpej 1235:
1.89 thorpej 1236: /*
1237: * XXX We cannot handle flow control on the DP83815.
1238: */
1239: if (SIP_CHIP_MODEL(sc, PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83815))
1240: mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY,
1241: MII_OFFSET_ANY, 0);
1242: else
1243: mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY,
1244: MII_OFFSET_ANY, MIIF_DOPAUSE);
1.1 thorpej 1245: if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
1246: ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
1247: ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
1248: } else
1249: ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
1250:
1251: ifp = &sc->sc_ethercom.ec_if;
1252: strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
1253: ifp->if_softc = sc;
1254: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1.98 kim 1255: sc->sc_if_flags = ifp->if_flags;
1.115.4.1! ad 1256: ifp->if_ioctl = sipcom_ioctl;
! 1257: ifp->if_start = sipcom_start;
! 1258: ifp->if_watchdog = sipcom_watchdog;
! 1259: ifp->if_init = sipcom_init;
! 1260: ifp->if_stop = sipcom_stop;
1.21 thorpej 1261: IFQ_SET_READY(&ifp->if_snd);
1.1 thorpej 1262:
1263: /*
1.29 thorpej 1264: * We can support 802.1Q VLAN-sized frames.
1265: */
1266: sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU;
1267:
1.115.4.1! ad 1268: if (sc->sc_gigabit) {
! 1269: /*
! 1270: * And the DP83820 can do VLAN tagging in hardware, and
! 1271: * support the jumbo Ethernet MTU.
! 1272: */
! 1273: sc->sc_ethercom.ec_capabilities |=
! 1274: ETHERCAP_VLAN_HWTAGGING | ETHERCAP_JUMBO_MTU;
1.31 thorpej 1275:
1.115.4.1! ad 1276: /*
! 1277: * The DP83820 can do IPv4, TCPv4, and UDPv4 checksums
! 1278: * in hardware.
! 1279: */
! 1280: ifp->if_capabilities |=
! 1281: IFCAP_CSUM_IPv4_Tx | IFCAP_CSUM_IPv4_Rx |
! 1282: IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_TCPv4_Rx |
! 1283: IFCAP_CSUM_UDPv4_Tx | IFCAP_CSUM_UDPv4_Rx;
! 1284: }
1.29 thorpej 1285:
1286: /*
1.1 thorpej 1287: * Attach the interface.
1288: */
1289: if_attach(ifp);
1.14 tsutsui 1290: ether_ifattach(ifp, enaddr);
1.106 pavel 1291: sc->sc_prev.ec_capenable = sc->sc_ethercom.ec_capenable;
1292: sc->sc_prev.is_vlan = VLAN_ATTACHED(&(sc)->sc_ethercom);
1293: sc->sc_prev.if_capenable = ifp->if_capenable;
1.65 itojun 1294: #if NRND > 0
1295: rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname,
1296: RND_TYPE_NET, 0);
1297: #endif
1.1 thorpej 1298:
1.46 thorpej 1299: /*
1300: * The number of bytes that must be available in
1301: * the Tx FIFO before the bus master can DMA more
1302: * data into the FIFO.
1303: */
1304: sc->sc_tx_fill_thresh = 64 / 32;
1305:
1306: /*
1307: * Start at a drain threshold of 512 bytes. We will
1308: * increase it if a DMA underrun occurs.
1309: *
1310: * XXX The minimum value of this variable should be
1311: * tuned. We may be able to improve performance
1312: * by starting with a lower value. That, however,
1313: * may trash the first few outgoing packets if the
1314: * PCI bus is saturated.
1315: */
1.115.4.1! ad 1316: if (sc->sc_gigabit)
! 1317: sc->sc_tx_drain_thresh = 6400 / 32; /* from FreeBSD nge(4) */
! 1318: else
! 1319: sc->sc_tx_drain_thresh = 1504 / 32;
1.46 thorpej 1320:
1321: /*
1.47 thorpej 1322: * Initialize the Rx FIFO drain threshold.
1323: *
1.46 thorpej 1324: * This is in units of 8 bytes.
1325: *
1326: * We should never set this value lower than 2; 14 bytes are
1327: * required to filter the packet.
1328: */
1.47 thorpej 1329: sc->sc_rx_drain_thresh = 128 / 8;
1.46 thorpej 1330:
1.30 thorpej 1331: #ifdef SIP_EVENT_COUNTERS
1332: /*
1333: * Attach event counters.
1334: */
1335: evcnt_attach_dynamic(&sc->sc_ev_txsstall, EVCNT_TYPE_MISC,
1336: NULL, sc->sc_dev.dv_xname, "txsstall");
1337: evcnt_attach_dynamic(&sc->sc_ev_txdstall, EVCNT_TYPE_MISC,
1338: NULL, sc->sc_dev.dv_xname, "txdstall");
1.56 thorpej 1339: evcnt_attach_dynamic(&sc->sc_ev_txforceintr, EVCNT_TYPE_INTR,
1340: NULL, sc->sc_dev.dv_xname, "txforceintr");
1341: evcnt_attach_dynamic(&sc->sc_ev_txdintr, EVCNT_TYPE_INTR,
1342: NULL, sc->sc_dev.dv_xname, "txdintr");
1343: evcnt_attach_dynamic(&sc->sc_ev_txiintr, EVCNT_TYPE_INTR,
1344: NULL, sc->sc_dev.dv_xname, "txiintr");
1.30 thorpej 1345: evcnt_attach_dynamic(&sc->sc_ev_rxintr, EVCNT_TYPE_INTR,
1346: NULL, sc->sc_dev.dv_xname, "rxintr");
1.62 thorpej 1347: evcnt_attach_dynamic(&sc->sc_ev_hiberr, EVCNT_TYPE_INTR,
1348: NULL, sc->sc_dev.dv_xname, "hiberr");
1.115.4.1! ad 1349: if (!sc->sc_gigabit) {
! 1350: evcnt_attach_dynamic(&sc->sc_ev_rxpause, EVCNT_TYPE_INTR,
! 1351: NULL, sc->sc_dev.dv_xname, "rxpause");
! 1352: } else {
! 1353: evcnt_attach_dynamic(&sc->sc_ev_rxpause, EVCNT_TYPE_MISC,
! 1354: NULL, sc->sc_dev.dv_xname, "rxpause");
! 1355: evcnt_attach_dynamic(&sc->sc_ev_txpause, EVCNT_TYPE_MISC,
! 1356: NULL, sc->sc_dev.dv_xname, "txpause");
! 1357: evcnt_attach_dynamic(&sc->sc_ev_rxipsum, EVCNT_TYPE_MISC,
! 1358: NULL, sc->sc_dev.dv_xname, "rxipsum");
! 1359: evcnt_attach_dynamic(&sc->sc_ev_rxtcpsum, EVCNT_TYPE_MISC,
! 1360: NULL, sc->sc_dev.dv_xname, "rxtcpsum");
! 1361: evcnt_attach_dynamic(&sc->sc_ev_rxudpsum, EVCNT_TYPE_MISC,
! 1362: NULL, sc->sc_dev.dv_xname, "rxudpsum");
! 1363: evcnt_attach_dynamic(&sc->sc_ev_txipsum, EVCNT_TYPE_MISC,
! 1364: NULL, sc->sc_dev.dv_xname, "txipsum");
! 1365: evcnt_attach_dynamic(&sc->sc_ev_txtcpsum, EVCNT_TYPE_MISC,
! 1366: NULL, sc->sc_dev.dv_xname, "txtcpsum");
! 1367: evcnt_attach_dynamic(&sc->sc_ev_txudpsum, EVCNT_TYPE_MISC,
! 1368: NULL, sc->sc_dev.dv_xname, "txudpsum");
! 1369: }
1.30 thorpej 1370: #endif /* SIP_EVENT_COUNTERS */
1371:
1.115.4.1! ad 1372: if (!pmf_device_register(self, NULL, sipcom_resume))
! 1373: aprint_error_dev(self, "couldn't establish power handler\n");
! 1374: else
! 1375: pmf_class_network_register(self, ifp);
! 1376:
1.1 thorpej 1377: /*
1378: * Make sure the interface is shutdown during reboot.
1379: */
1.115.4.1! ad 1380: sc->sc_sdhook = shutdownhook_establish(sipcom_shutdown, sc);
1.1 thorpej 1381: if (sc->sc_sdhook == NULL)
1382: printf("%s: WARNING: unable to establish shutdown hook\n",
1383: sc->sc_dev.dv_xname);
1384: }
1385:
1386: /*
1387: * sip_shutdown:
1388: *
1389: * Make sure the interface is stopped at reboot time.
1390: */
1.95 thorpej 1391: static void
1.115.4.1! ad 1392: sipcom_shutdown(void *arg)
1.1 thorpej 1393: {
1394: struct sip_softc *sc = arg;
1395:
1.115.4.1! ad 1396: sipcom_stop(&sc->sc_ethercom.ec_if, 1);
! 1397: }
! 1398:
! 1399: static inline void
! 1400: sipcom_set_extsts(struct sip_softc *sc, int lasttx, struct mbuf *m0,
! 1401: uint64_t capenable)
! 1402: {
! 1403: struct m_tag *mtag;
! 1404: u_int32_t extsts;
! 1405: #ifdef DEBUG
! 1406: struct ifnet *ifp = &sc->sc_ethercom.ec_if;
! 1407: #endif
! 1408: /*
! 1409: * If VLANs are enabled and the packet has a VLAN tag, set
! 1410: * up the descriptor to encapsulate the packet for us.
! 1411: *
! 1412: * This apparently has to be on the last descriptor of
! 1413: * the packet.
! 1414: */
! 1415:
! 1416: /*
! 1417: * Byte swapping is tricky. We need to provide the tag
! 1418: * in a network byte order. On a big-endian machine,
! 1419: * the byteorder is correct, but we need to swap it
! 1420: * anyway, because this will be undone by the outside
! 1421: * htole32(). That's why there must be an
! 1422: * unconditional swap instead of htons() inside.
! 1423: */
! 1424: if ((mtag = VLAN_OUTPUT_TAG(&sc->sc_ethercom, m0)) != NULL) {
! 1425: sc->sc_txdescs[lasttx].sipd_extsts |=
! 1426: htole32(EXTSTS_VPKT |
! 1427: (bswap16(VLAN_TAG_VALUE(mtag)) &
! 1428: EXTSTS_VTCI));
! 1429: }
! 1430:
! 1431: /*
! 1432: * If the upper-layer has requested IPv4/TCPv4/UDPv4
! 1433: * checksumming, set up the descriptor to do this work
! 1434: * for us.
! 1435: *
! 1436: * This apparently has to be on the first descriptor of
! 1437: * the packet.
! 1438: *
! 1439: * Byte-swap constants so the compiler can optimize.
! 1440: */
! 1441: extsts = 0;
! 1442: if (m0->m_pkthdr.csum_flags & M_CSUM_IPv4) {
! 1443: KDASSERT(ifp->if_capenable & IFCAP_CSUM_IPv4_Tx);
! 1444: SIP_EVCNT_INCR(&sc->sc_ev_txipsum);
! 1445: extsts |= htole32(EXTSTS_IPPKT);
! 1446: }
! 1447: if (m0->m_pkthdr.csum_flags & M_CSUM_TCPv4) {
! 1448: KDASSERT(ifp->if_capenable & IFCAP_CSUM_TCPv4_Tx);
! 1449: SIP_EVCNT_INCR(&sc->sc_ev_txtcpsum);
! 1450: extsts |= htole32(EXTSTS_TCPPKT);
! 1451: } else if (m0->m_pkthdr.csum_flags & M_CSUM_UDPv4) {
! 1452: KDASSERT(ifp->if_capenable & IFCAP_CSUM_UDPv4_Tx);
! 1453: SIP_EVCNT_INCR(&sc->sc_ev_txudpsum);
! 1454: extsts |= htole32(EXTSTS_UDPPKT);
! 1455: }
! 1456: sc->sc_txdescs[sc->sc_txnext].sipd_extsts |= extsts;
1.1 thorpej 1457: }
1458:
1459: /*
1460: * sip_start: [ifnet interface function]
1461: *
1462: * Start packet transmission on the interface.
1463: */
1.95 thorpej 1464: static void
1.115.4.1! ad 1465: sipcom_start(struct ifnet *ifp)
1.1 thorpej 1466: {
1467: struct sip_softc *sc = ifp->if_softc;
1.83 mycroft 1468: struct mbuf *m0;
1469: struct mbuf *m;
1.1 thorpej 1470: struct sip_txsoft *txs;
1471: bus_dmamap_t dmamap;
1.57 thorpej 1472: int error, nexttx, lasttx, seg;
1473: int ofree = sc->sc_txfree;
1474: #if 0
1475: int firsttx = sc->sc_txnext;
1476: #endif
1.1 thorpej 1477:
1478: /*
1479: * If we've been told to pause, don't transmit any more packets.
1480: */
1.115.4.1! ad 1481: if (!sc->sc_gigabit && sc->sc_paused)
1.1 thorpej 1482: ifp->if_flags |= IFF_OACTIVE;
1483:
1484: if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
1485: return;
1486:
1487: /*
1488: * Loop through the send queue, setting up transmit descriptors
1489: * until we drain the queue, or use up all available transmit
1490: * descriptors.
1491: */
1.30 thorpej 1492: for (;;) {
1493: /* Get a work queue entry. */
1494: if ((txs = SIMPLEQ_FIRST(&sc->sc_txfreeq)) == NULL) {
1495: SIP_EVCNT_INCR(&sc->sc_ev_txsstall);
1496: break;
1497: }
1498:
1.1 thorpej 1499: /*
1500: * Grab a packet off the queue.
1501: */
1.21 thorpej 1502: IFQ_POLL(&ifp->if_snd, m0);
1.1 thorpej 1503: if (m0 == NULL)
1504: break;
1.22 thorpej 1505: m = NULL;
1.1 thorpej 1506:
1507: dmamap = txs->txs_dmamap;
1508:
1.36 thorpej 1509: /*
1510: * Load the DMA map. If this fails, the packet either
1.115.4.1! ad 1511: * didn't fit in the alloted number of segments, or we
! 1512: * were short on resources.
1.36 thorpej 1513: */
1514: error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0,
1.41 thorpej 1515: BUS_DMA_WRITE|BUS_DMA_NOWAIT);
1.115.4.1! ad 1516: /* In the non-gigabit case, we'll copy and try again. */
! 1517: if (error != 0 && !sc->sc_gigabit) {
1.1 thorpej 1518: MGETHDR(m, M_DONTWAIT, MT_DATA);
1519: if (m == NULL) {
1520: printf("%s: unable to allocate Tx mbuf\n",
1521: sc->sc_dev.dv_xname);
1522: break;
1523: }
1.105 bouyer 1524: MCLAIM(m, &sc->sc_ethercom.ec_tx_mowner);
1.1 thorpej 1525: if (m0->m_pkthdr.len > MHLEN) {
1526: MCLGET(m, M_DONTWAIT);
1527: if ((m->m_flags & M_EXT) == 0) {
1528: printf("%s: unable to allocate Tx "
1529: "cluster\n", sc->sc_dev.dv_xname);
1530: m_freem(m);
1531: break;
1532: }
1533: }
1.111 christos 1534: m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, void *));
1.1 thorpej 1535: m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len;
1536: error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap,
1.41 thorpej 1537: m, BUS_DMA_WRITE|BUS_DMA_NOWAIT);
1.1 thorpej 1538: if (error) {
1539: printf("%s: unable to load Tx buffer, "
1540: "error = %d\n", sc->sc_dev.dv_xname, error);
1541: break;
1542: }
1.115.4.1! ad 1543: } else if (error == EFBIG) {
! 1544: /*
! 1545: * For the too-many-segments case, we simply
! 1546: * report an error and drop the packet,
! 1547: * since we can't sanely copy a jumbo packet
! 1548: * to a single buffer.
! 1549: */
! 1550: printf("%s: Tx packet consumes too many "
! 1551: "DMA segments, dropping...\n", sc->sc_dev.dv_xname);
! 1552: IFQ_DEQUEUE(&ifp->if_snd, m0);
! 1553: m_freem(m0);
! 1554: continue;
! 1555: } else if (error != 0) {
! 1556: /*
! 1557: * Short on resources, just stop for now.
! 1558: */
! 1559: break;
1.1 thorpej 1560: }
1.21 thorpej 1561:
1.1 thorpej 1562: /*
1563: * Ensure we have enough descriptors free to describe
1.30 thorpej 1564: * the packet. Note, we always reserve one descriptor
1565: * at the end of the ring as a termination point, to
1566: * prevent wrap-around.
1.1 thorpej 1567: */
1.30 thorpej 1568: if (dmamap->dm_nsegs > (sc->sc_txfree - 1)) {
1.1 thorpej 1569: /*
1570: * Not enough free descriptors to transmit this
1571: * packet. We haven't committed anything yet,
1572: * so just unload the DMA map, put the packet
1573: * back on the queue, and punt. Notify the upper
1574: * layer that there are not more slots left.
1575: *
1576: * XXX We could allocate an mbuf and copy, but
1577: * XXX is it worth it?
1578: */
1579: ifp->if_flags |= IFF_OACTIVE;
1580: bus_dmamap_unload(sc->sc_dmat, dmamap);
1.22 thorpej 1581: if (m != NULL)
1582: m_freem(m);
1.30 thorpej 1583: SIP_EVCNT_INCR(&sc->sc_ev_txdstall);
1.1 thorpej 1584: break;
1.22 thorpej 1585: }
1586:
1587: IFQ_DEQUEUE(&ifp->if_snd, m0);
1588: if (m != NULL) {
1589: m_freem(m0);
1590: m0 = m;
1.1 thorpej 1591: }
1592:
1593: /*
1594: * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET.
1595: */
1596:
1597: /* Sync the DMA map. */
1598: bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize,
1599: BUS_DMASYNC_PREWRITE);
1600:
1601: /*
1602: * Initialize the transmit descriptors.
1603: */
1.74 scw 1604: for (nexttx = lasttx = sc->sc_txnext, seg = 0;
1.1 thorpej 1605: seg < dmamap->dm_nsegs;
1.115.4.1! ad 1606: seg++, nexttx = sip_nexttx(sc, nexttx)) {
1.1 thorpej 1607: /*
1608: * If this is the first descriptor we're
1609: * enqueueing, don't set the OWN bit just
1610: * yet. That could cause a race condition.
1611: * We'll do it below.
1612: */
1.115.4.1! ad 1613: *sipd_bufptr(sc, &sc->sc_txdescs[nexttx]) =
1.14 tsutsui 1614: htole32(dmamap->dm_segs[seg].ds_addr);
1.115.4.1! ad 1615: *sipd_cmdsts(sc, &sc->sc_txdescs[nexttx]) =
1.57 thorpej 1616: htole32((nexttx == sc->sc_txnext ? 0 : CMDSTS_OWN) |
1.14 tsutsui 1617: CMDSTS_MORE | dmamap->dm_segs[seg].ds_len);
1.29 thorpej 1618: sc->sc_txdescs[nexttx].sipd_extsts = 0;
1.1 thorpej 1619: lasttx = nexttx;
1620: }
1621:
1622: /* Clear the MORE bit on the last segment. */
1.115.4.1! ad 1623: *sipd_cmdsts(sc, &sc->sc_txdescs[lasttx]) &=
! 1624: htole32(~CMDSTS_MORE);
1.1 thorpej 1625:
1.56 thorpej 1626: /*
1627: * If we're in the interrupt delay window, delay the
1628: * interrupt.
1629: */
1630: if (++sc->sc_txwin >= (SIP_TXQUEUELEN * 2 / 3)) {
1631: SIP_EVCNT_INCR(&sc->sc_ev_txforceintr);
1.115.4.1! ad 1632: *sipd_cmdsts(sc, &sc->sc_txdescs[lasttx]) |=
1.56 thorpej 1633: htole32(CMDSTS_INTR);
1634: sc->sc_txwin = 0;
1635: }
1636:
1.115.4.1! ad 1637: if (sc->sc_gigabit)
! 1638: sipcom_set_extsts(sc, lasttx, m0, ifp->if_capenable);
1.29 thorpej 1639:
1.1 thorpej 1640: /* Sync the descriptors we're using. */
1.115.4.1! ad 1641: sip_cdtxsync(sc, sc->sc_txnext, dmamap->dm_nsegs,
1.1 thorpej 1642: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
1643:
1644: /*
1.57 thorpej 1645: * The entire packet is set up. Give the first descrptor
1646: * to the chip now.
1647: */
1.115.4.1! ad 1648: *sipd_cmdsts(sc, &sc->sc_txdescs[sc->sc_txnext]) |=
1.57 thorpej 1649: htole32(CMDSTS_OWN);
1.115.4.1! ad 1650: sip_cdtxsync(sc, sc->sc_txnext, 1,
1.57 thorpej 1651: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
1652:
1653: /*
1.1 thorpej 1654: * Store a pointer to the packet so we can free it later,
1655: * and remember what txdirty will be once the packet is
1656: * done.
1657: */
1658: txs->txs_mbuf = m0;
1659: txs->txs_firstdesc = sc->sc_txnext;
1660: txs->txs_lastdesc = lasttx;
1661:
1662: /* Advance the tx pointer. */
1663: sc->sc_txfree -= dmamap->dm_nsegs;
1664: sc->sc_txnext = nexttx;
1665:
1.54 lukem 1666: SIMPLEQ_REMOVE_HEAD(&sc->sc_txfreeq, txs_q);
1.1 thorpej 1667: SIMPLEQ_INSERT_TAIL(&sc->sc_txdirtyq, txs, txs_q);
1668:
1669: #if NBPFILTER > 0
1670: /*
1671: * Pass the packet to any BPF listeners.
1672: */
1673: if (ifp->if_bpf)
1674: bpf_mtap(ifp->if_bpf, m0);
1675: #endif /* NBPFILTER > 0 */
1676: }
1677:
1678: if (txs == NULL || sc->sc_txfree == 0) {
1679: /* No more slots left; notify upper layer. */
1680: ifp->if_flags |= IFF_OACTIVE;
1681: }
1682:
1683: if (sc->sc_txfree != ofree) {
1.30 thorpej 1684: /*
1685: * Start the transmit process. Note, the manual says
1686: * that if there are no pending transmissions in the
1687: * chip's internal queue (indicated by TXE being clear),
1688: * then the driver software must set the TXDP to the
1689: * first descriptor to be transmitted. However, if we
1690: * do this, it causes serious performance degredation on
1691: * the DP83820 under load, not setting TXDP doesn't seem
1692: * to adversely affect the SiS 900 or DP83815.
1693: *
1694: * Well, I guess it wouldn't be the first time a manual
1695: * has lied -- and they could be speaking of the NULL-
1696: * terminated descriptor list case, rather than OWN-
1697: * terminated rings.
1698: */
1699: #if 0
1.1 thorpej 1700: if ((bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_CR) &
1701: CR_TXE) == 0) {
1702: bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_TXDP,
1703: SIP_CDTXADDR(sc, firsttx));
1704: bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_CR, CR_TXE);
1705: }
1.30 thorpej 1706: #else
1707: bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_CR, CR_TXE);
1708: #endif
1.1 thorpej 1709:
1710: /* Set a watchdog timer in case the chip flakes out. */
1.88 thorpej 1711: /* Gigabit autonegotiation takes 5 seconds. */
1.115.4.1! ad 1712: ifp->if_timer = (sc->sc_gigabit) ? 10 : 5;
1.1 thorpej 1713: }
1714: }
1715:
1716: /*
1717: * sip_watchdog: [ifnet interface function]
1718: *
1719: * Watchdog timer handler.
1720: */
1.95 thorpej 1721: static void
1.115.4.1! ad 1722: sipcom_watchdog(struct ifnet *ifp)
1.1 thorpej 1723: {
1724: struct sip_softc *sc = ifp->if_softc;
1725:
1726: /*
1727: * The chip seems to ignore the CMDSTS_INTR bit sometimes!
1728: * If we get a timeout, try and sweep up transmit descriptors.
1729: * If we manage to sweep them all up, ignore the lack of
1730: * interrupt.
1731: */
1.115.4.1! ad 1732: sipcom_txintr(sc);
1.1 thorpej 1733:
1.115.4.1! ad 1734: if (sc->sc_txfree != sc->sc_ntxdesc) {
1.1 thorpej 1735: printf("%s: device timeout\n", sc->sc_dev.dv_xname);
1736: ifp->if_oerrors++;
1737:
1738: /* Reset the interface. */
1.115.4.1! ad 1739: (void) sipcom_init(ifp);
1.1 thorpej 1740: } else if (ifp->if_flags & IFF_DEBUG)
1741: printf("%s: recovered from device timeout\n",
1742: sc->sc_dev.dv_xname);
1743:
1744: /* Try to get more packets going. */
1.115.4.1! ad 1745: sipcom_start(ifp);
1.1 thorpej 1746: }
1747:
1748: /*
1749: * sip_ioctl: [ifnet interface function]
1750: *
1751: * Handle control requests from the operator.
1752: */
1.95 thorpej 1753: static int
1.115.4.1! ad 1754: sipcom_ioctl(struct ifnet *ifp, u_long cmd, void *data)
1.1 thorpej 1755: {
1756: struct sip_softc *sc = ifp->if_softc;
1757: struct ifreq *ifr = (struct ifreq *)data;
1.17 thorpej 1758: int s, error;
1.1 thorpej 1759:
1760: s = splnet();
1761:
1762: switch (cmd) {
1.17 thorpej 1763: case SIOCSIFMEDIA:
1.89 thorpej 1764: /* Flow control requires full-duplex mode. */
1765: if (IFM_SUBTYPE(ifr->ifr_media) == IFM_AUTO ||
1766: (ifr->ifr_media & IFM_FDX) == 0)
1767: ifr->ifr_media &= ~IFM_ETH_FMASK;
1.115.4.1! ad 1768:
1.89 thorpej 1769: /* XXX */
1770: if (SIP_CHIP_MODEL(sc, PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83815))
1771: ifr->ifr_media &= ~IFM_ETH_FMASK;
1772: if (IFM_SUBTYPE(ifr->ifr_media) != IFM_AUTO) {
1.115.4.1! ad 1773: if (sc->sc_gigabit &&
! 1774: (ifr->ifr_media & IFM_ETH_FMASK) == IFM_FLOW) {
! 1775: /* We can do both TXPAUSE and RXPAUSE. */
! 1776: ifr->ifr_media |=
! 1777: IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE;
! 1778: } else if (ifr->ifr_media & IFM_FLOW) {
1.89 thorpej 1779: /*
1780: * Both TXPAUSE and RXPAUSE must be set.
1781: * (SiS900 and DP83815 don't have PAUSE_ASYM
1782: * feature.)
1783: *
1784: * XXX Can SiS900 and DP83815 send PAUSE?
1785: */
1786: ifr->ifr_media |=
1787: IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE;
1788: }
1789: sc->sc_flowflags = ifr->ifr_media & IFM_ETH_FMASK;
1790: }
1791: /* FALLTHROUGH */
1.17 thorpej 1792: case SIOCGIFMEDIA:
1793: error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
1.1 thorpej 1794: break;
1.98 kim 1795: case SIOCSIFFLAGS:
1796: /* If the interface is up and running, only modify the receive
1797: * filter when setting promiscuous or debug mode. Otherwise
1798: * fall through to ether_ioctl, which will reset the chip.
1799: */
1.106 pavel 1800:
1801: #define COMPARE_EC(sc) (((sc)->sc_prev.ec_capenable \
1802: == (sc)->sc_ethercom.ec_capenable) \
1803: && ((sc)->sc_prev.is_vlan == \
1804: VLAN_ATTACHED(&(sc)->sc_ethercom) ))
1805:
1806: #define COMPARE_IC(sc, ifp) ((sc)->sc_prev.if_capenable == (ifp)->if_capenable)
1807:
1.98 kim 1808: #define RESETIGN (IFF_CANTCHANGE|IFF_DEBUG)
1809: if (((ifp->if_flags & (IFF_UP|IFF_RUNNING))
1810: == (IFF_UP|IFF_RUNNING))
1811: && ((ifp->if_flags & (~RESETIGN))
1.106 pavel 1812: == (sc->sc_if_flags & (~RESETIGN)))
1813: && COMPARE_EC(sc) && COMPARE_IC(sc, ifp)) {
1.98 kim 1814: /* Set up the receive filter. */
1815: (*sc->sc_model->sip_variant->sipv_set_filter)(sc);
1.99 cube 1816: error = 0;
1.98 kim 1817: break;
1818: #undef RESETIGN
1819: }
1820: /* FALLTHROUGH */
1.17 thorpej 1821: default:
1822: error = ether_ioctl(ifp, cmd, data);
1.101 perry 1823: if (error == ENETRESET) {
1.1 thorpej 1824: /*
1825: * Multicast list has changed; set the hardware filter
1826: * accordingly.
1827: */
1.96 thorpej 1828: if (ifp->if_flags & IFF_RUNNING)
1829: (*sc->sc_model->sip_variant->sipv_set_filter)(sc);
1.1 thorpej 1830: error = 0;
1831: }
1832: break;
1833: }
1834:
1835: /* Try to get more packets going. */
1.115.4.1! ad 1836: sipcom_start(ifp);
1.1 thorpej 1837:
1.98 kim 1838: sc->sc_if_flags = ifp->if_flags;
1.1 thorpej 1839: splx(s);
1840: return (error);
1841: }
1842:
1843: /*
1844: * sip_intr:
1845: *
1846: * Interrupt service routine.
1847: */
1.95 thorpej 1848: static int
1.115.4.1! ad 1849: sipcom_intr(void *arg)
1.1 thorpej 1850: {
1851: struct sip_softc *sc = arg;
1852: struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1853: u_int32_t isr;
1854: int handled = 0;
1855:
1.88 thorpej 1856: /* Disable interrupts. */
1857: bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_IER, 0);
1858:
1.1 thorpej 1859: for (;;) {
1860: /* Reading clears interrupt. */
1861: isr = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_ISR);
1862: if ((isr & sc->sc_imr) == 0)
1863: break;
1.65 itojun 1864:
1865: #if NRND > 0
1.66 itojun 1866: if (RND_ENABLED(&sc->rnd_source))
1867: rnd_add_uint32(&sc->rnd_source, isr);
1.65 itojun 1868: #endif
1.1 thorpej 1869:
1870: handled = 1;
1871:
1872: if (isr & (ISR_RXORN|ISR_RXIDLE|ISR_RXDESC)) {
1.30 thorpej 1873: SIP_EVCNT_INCR(&sc->sc_ev_rxintr);
1874:
1.1 thorpej 1875: /* Grab any new packets. */
1.115.4.1! ad 1876: (*sc->sc_rxintr)(sc);
1.1 thorpej 1877:
1878: if (isr & ISR_RXORN) {
1879: printf("%s: receive FIFO overrun\n",
1880: sc->sc_dev.dv_xname);
1881:
1882: /* XXX adjust rx_drain_thresh? */
1883: }
1884:
1885: if (isr & ISR_RXIDLE) {
1886: printf("%s: receive ring overrun\n",
1887: sc->sc_dev.dv_xname);
1888:
1889: /* Get the receive process going again. */
1890: bus_space_write_4(sc->sc_st, sc->sc_sh,
1891: SIP_RXDP, SIP_CDRXADDR(sc, sc->sc_rxptr));
1892: bus_space_write_4(sc->sc_st, sc->sc_sh,
1893: SIP_CR, CR_RXE);
1894: }
1895: }
1896:
1.56 thorpej 1897: if (isr & (ISR_TXURN|ISR_TXDESC|ISR_TXIDLE)) {
1898: #ifdef SIP_EVENT_COUNTERS
1899: if (isr & ISR_TXDESC)
1900: SIP_EVCNT_INCR(&sc->sc_ev_txdintr);
1901: else if (isr & ISR_TXIDLE)
1902: SIP_EVCNT_INCR(&sc->sc_ev_txiintr);
1903: #endif
1.30 thorpej 1904:
1.1 thorpej 1905: /* Sweep up transmit descriptors. */
1.115.4.1! ad 1906: sipcom_txintr(sc);
1.1 thorpej 1907:
1908: if (isr & ISR_TXURN) {
1909: u_int32_t thresh;
1.115.4.1! ad 1910: int txfifo_size = (sc->sc_gigabit)
! 1911: ? DP83820_SIP_TXFIFO_SIZE
! 1912: : OTHER_SIP_TXFIFO_SIZE;
1.1 thorpej 1913:
1914: printf("%s: transmit FIFO underrun",
1915: sc->sc_dev.dv_xname);
1916: thresh = sc->sc_tx_drain_thresh + 1;
1.115.4.1! ad 1917: if (thresh <= __SHIFTOUT_MASK(sc->sc_bits.b_txcfg_drth_mask)
! 1918: && (thresh * 32) <= (txfifo_size -
1.1 thorpej 1919: (sc->sc_tx_fill_thresh * 32))) {
1920: printf("; increasing Tx drain "
1921: "threshold to %u bytes\n",
1922: thresh * 32);
1923: sc->sc_tx_drain_thresh = thresh;
1.115.4.1! ad 1924: (void) sipcom_init(ifp);
1.1 thorpej 1925: } else {
1.115.4.1! ad 1926: (void) sipcom_init(ifp);
1.1 thorpej 1927: printf("\n");
1928: }
1929: }
1930: }
1931:
1932: if (sc->sc_imr & (ISR_PAUSE_END|ISR_PAUSE_ST)) {
1933: if (isr & ISR_PAUSE_ST) {
1.89 thorpej 1934: sc->sc_paused = 1;
1.94 thorpej 1935: SIP_EVCNT_INCR(&sc->sc_ev_rxpause);
1.1 thorpej 1936: ifp->if_flags |= IFF_OACTIVE;
1937: }
1938: if (isr & ISR_PAUSE_END) {
1.89 thorpej 1939: sc->sc_paused = 0;
1.1 thorpej 1940: ifp->if_flags &= ~IFF_OACTIVE;
1941: }
1942: }
1943:
1944: if (isr & ISR_HIBERR) {
1.62 thorpej 1945: int want_init = 0;
1946:
1947: SIP_EVCNT_INCR(&sc->sc_ev_hiberr);
1948:
1.1 thorpej 1949: #define PRINTERR(bit, str) \
1.62 thorpej 1950: do { \
1.68 itojun 1951: if ((isr & (bit)) != 0) { \
1952: if ((ifp->if_flags & IFF_DEBUG) != 0) \
1953: printf("%s: %s\n", \
1954: sc->sc_dev.dv_xname, str); \
1.62 thorpej 1955: want_init = 1; \
1956: } \
1957: } while (/*CONSTCOND*/0)
1958:
1.115.4.1! ad 1959: PRINTERR(sc->sc_bits.b_isr_dperr, "parity error");
! 1960: PRINTERR(sc->sc_bits.b_isr_sserr, "system error");
! 1961: PRINTERR(sc->sc_bits.b_isr_rmabt, "master abort");
! 1962: PRINTERR(sc->sc_bits.b_isr_rtabt, "target abort");
1.1 thorpej 1963: PRINTERR(ISR_RXSOVR, "receive status FIFO overrun");
1.62 thorpej 1964: /*
1965: * Ignore:
1966: * Tx reset complete
1967: * Rx reset complete
1968: */
1969: if (want_init)
1.115.4.1! ad 1970: (void) sipcom_init(ifp);
1.1 thorpej 1971: #undef PRINTERR
1972: }
1973: }
1974:
1.88 thorpej 1975: /* Re-enable interrupts. */
1976: bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_IER, IER_IE);
1977:
1.1 thorpej 1978: /* Try to get more packets going. */
1.115.4.1! ad 1979: sipcom_start(ifp);
1.1 thorpej 1980:
1981: return (handled);
1982: }
1983:
1984: /*
1985: * sip_txintr:
1986: *
1987: * Helper; handle transmit interrupts.
1988: */
1.95 thorpej 1989: static void
1.115.4.1! ad 1990: sipcom_txintr(struct sip_softc *sc)
1.1 thorpej 1991: {
1992: struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1993: struct sip_txsoft *txs;
1994: u_int32_t cmdsts;
1995:
1.89 thorpej 1996: if (sc->sc_paused == 0)
1.1 thorpej 1997: ifp->if_flags &= ~IFF_OACTIVE;
1998:
1999: /*
2000: * Go through our Tx list and free mbufs for those
2001: * frames which have been transmitted.
2002: */
2003: while ((txs = SIMPLEQ_FIRST(&sc->sc_txdirtyq)) != NULL) {
1.115.4.1! ad 2004: sip_cdtxsync(sc, txs->txs_firstdesc, txs->txs_dmamap->dm_nsegs,
1.1 thorpej 2005: BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
2006:
1.115.4.1! ad 2007: cmdsts = le32toh(*sipd_cmdsts(sc, &sc->sc_txdescs[txs->txs_lastdesc]));
1.1 thorpej 2008: if (cmdsts & CMDSTS_OWN)
2009: break;
2010:
1.54 lukem 2011: SIMPLEQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q);
1.1 thorpej 2012:
2013: sc->sc_txfree += txs->txs_dmamap->dm_nsegs;
2014:
2015: bus_dmamap_sync(sc->sc_dmat, txs->txs_dmamap,
2016: 0, txs->txs_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
2017: bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap);
2018: m_freem(txs->txs_mbuf);
2019: txs->txs_mbuf = NULL;
2020:
2021: SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
2022:
2023: /*
2024: * Check for errors and collisions.
2025: */
2026: if (cmdsts &
2027: (CMDSTS_Tx_TXA|CMDSTS_Tx_TFU|CMDSTS_Tx_ED|CMDSTS_Tx_EC)) {
1.34 simonb 2028: ifp->if_oerrors++;
2029: if (cmdsts & CMDSTS_Tx_EC)
2030: ifp->if_collisions += 16;
1.1 thorpej 2031: if (ifp->if_flags & IFF_DEBUG) {
1.34 simonb 2032: if (cmdsts & CMDSTS_Tx_ED)
1.1 thorpej 2033: printf("%s: excessive deferral\n",
2034: sc->sc_dev.dv_xname);
1.34 simonb 2035: if (cmdsts & CMDSTS_Tx_EC)
1.1 thorpej 2036: printf("%s: excessive collisions\n",
2037: sc->sc_dev.dv_xname);
2038: }
2039: } else {
2040: /* Packet was transmitted successfully. */
2041: ifp->if_opackets++;
2042: ifp->if_collisions += CMDSTS_COLLISIONS(cmdsts);
2043: }
2044: }
2045:
2046: /*
2047: * If there are no more pending transmissions, cancel the watchdog
2048: * timer.
2049: */
1.56 thorpej 2050: if (txs == NULL) {
1.1 thorpej 2051: ifp->if_timer = 0;
1.56 thorpej 2052: sc->sc_txwin = 0;
2053: }
1.1 thorpej 2054: }
2055:
2056: /*
1.115.4.1! ad 2057: * gsip_rxintr:
1.1 thorpej 2058: *
1.115.4.1! ad 2059: * Helper; handle receive interrupts on gigabit parts.
1.1 thorpej 2060: */
1.95 thorpej 2061: static void
1.115.4.1! ad 2062: gsip_rxintr(struct sip_softc *sc)
1.1 thorpej 2063: {
2064: struct ifnet *ifp = &sc->sc_ethercom.ec_if;
2065: struct sip_rxsoft *rxs;
1.97 thorpej 2066: struct mbuf *m;
1.35 thorpej 2067: u_int32_t cmdsts, extsts;
1.97 thorpej 2068: int i, len;
1.1 thorpej 2069:
1.115.4.1! ad 2070: for (i = sc->sc_rxptr;; i = sip_nextrx(sc, i)) {
1.1 thorpej 2071: rxs = &sc->sc_rxsoft[i];
2072:
1.115.4.1! ad 2073: sip_cdrxsync(sc, i, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1.1 thorpej 2074:
1.115.4.1! ad 2075: cmdsts = le32toh(*sipd_cmdsts(sc, &sc->sc_rxdescs[i]));
1.29 thorpej 2076: extsts = le32toh(sc->sc_rxdescs[i].sipd_extsts);
1.115.4.1! ad 2077: len = CMDSTS_SIZE(sc, cmdsts);
1.1 thorpej 2078:
2079: /*
2080: * NOTE: OWN is set if owned by _consumer_. We're the
2081: * consumer of the receive ring, so if the bit is clear,
2082: * we have processed all of the packets.
2083: */
2084: if ((cmdsts & CMDSTS_OWN) == 0) {
2085: /*
2086: * We have processed all of the receive buffers.
2087: */
2088: break;
2089: }
2090:
1.36 thorpej 2091: if (__predict_false(sc->sc_rxdiscard)) {
1.115.4.1! ad 2092: sip_init_rxdesc(sc, i);
1.36 thorpej 2093: if ((cmdsts & CMDSTS_MORE) == 0) {
2094: /* Reset our state. */
2095: sc->sc_rxdiscard = 0;
2096: }
2097: continue;
2098: }
2099:
2100: bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
2101: rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
2102:
2103: m = rxs->rxs_mbuf;
2104:
2105: /*
2106: * Add a new receive buffer to the ring.
2107: */
1.115.4.1! ad 2108: if (sipcom_add_rxbuf(sc, i) != 0) {
1.36 thorpej 2109: /*
2110: * Failed, throw away what we've done so
2111: * far, and discard the rest of the packet.
2112: */
2113: ifp->if_ierrors++;
2114: bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
2115: rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
1.115.4.1! ad 2116: sip_init_rxdesc(sc, i);
1.36 thorpej 2117: if (cmdsts & CMDSTS_MORE)
2118: sc->sc_rxdiscard = 1;
2119: if (sc->sc_rxhead != NULL)
2120: m_freem(sc->sc_rxhead);
1.115.4.1! ad 2121: sip_rxchain_reset(sc);
1.36 thorpej 2122: continue;
2123: }
2124:
1.115.4.1! ad 2125: sip_rxchain_link(sc, m);
1.36 thorpej 2126:
1.97 thorpej 2127: m->m_len = len;
2128:
1.36 thorpej 2129: /*
2130: * If this is not the end of the packet, keep
2131: * looking.
2132: */
2133: if (cmdsts & CMDSTS_MORE) {
1.97 thorpej 2134: sc->sc_rxlen += len;
1.36 thorpej 2135: continue;
2136: }
2137:
1.1 thorpej 2138: /*
1.97 thorpej 2139: * Okay, we have the entire packet now. The chip includes
2140: * the FCS, so we need to trim it.
1.36 thorpej 2141: */
1.97 thorpej 2142: m->m_len -= ETHER_CRC_LEN;
2143:
1.36 thorpej 2144: *sc->sc_rxtailp = NULL;
1.104 thorpej 2145: len = m->m_len + sc->sc_rxlen;
1.36 thorpej 2146: m = sc->sc_rxhead;
2147:
1.115.4.1! ad 2148: sip_rxchain_reset(sc);
1.36 thorpej 2149:
2150: /*
2151: * If an error occurred, update stats and drop the packet.
1.1 thorpej 2152: */
1.36 thorpej 2153: if (cmdsts & (CMDSTS_Rx_RXA|CMDSTS_Rx_RUNT|
1.1 thorpej 2154: CMDSTS_Rx_ISE|CMDSTS_Rx_CRCE|CMDSTS_Rx_FAE)) {
2155: ifp->if_ierrors++;
2156: if ((cmdsts & CMDSTS_Rx_RXA) != 0 &&
2157: (cmdsts & CMDSTS_Rx_RXO) == 0) {
2158: /* Receive overrun handled elsewhere. */
2159: printf("%s: receive descriptor error\n",
2160: sc->sc_dev.dv_xname);
2161: }
2162: #define PRINTERR(bit, str) \
1.67 itojun 2163: if ((ifp->if_flags & IFF_DEBUG) != 0 && \
2164: (cmdsts & (bit)) != 0) \
1.1 thorpej 2165: printf("%s: %s\n", sc->sc_dev.dv_xname, str)
2166: PRINTERR(CMDSTS_Rx_RUNT, "runt packet");
2167: PRINTERR(CMDSTS_Rx_ISE, "invalid symbol error");
2168: PRINTERR(CMDSTS_Rx_CRCE, "CRC error");
2169: PRINTERR(CMDSTS_Rx_FAE, "frame alignment error");
2170: #undef PRINTERR
1.36 thorpej 2171: m_freem(m);
1.1 thorpej 2172: continue;
2173: }
2174:
2175: /*
1.2 thorpej 2176: * If the packet is small enough to fit in a
2177: * single header mbuf, allocate one and copy
2178: * the data into it. This greatly reduces
2179: * memory consumption when we receive lots
2180: * of small packets.
1.1 thorpej 2181: */
1.115.4.1! ad 2182: if (gsip_copy_small != 0 && len <= (MHLEN - 2)) {
1.36 thorpej 2183: struct mbuf *nm;
2184: MGETHDR(nm, M_DONTWAIT, MT_DATA);
2185: if (nm == NULL) {
1.2 thorpej 2186: ifp->if_ierrors++;
1.36 thorpej 2187: m_freem(m);
1.2 thorpej 2188: continue;
2189: }
1.105 bouyer 2190: MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner);
1.36 thorpej 2191: nm->m_data += 2;
2192: nm->m_pkthdr.len = nm->m_len = len;
1.111 christos 2193: m_copydata(m, 0, len, mtod(nm, void *));
1.36 thorpej 2194: m_freem(m);
2195: m = nm;
1.1 thorpej 2196: }
1.36 thorpej 2197: #ifndef __NO_STRICT_ALIGNMENT
2198: else {
2199: /*
2200: * The DP83820's receive buffers must be 4-byte
2201: * aligned. But this means that the data after
2202: * the Ethernet header is misaligned. To compensate,
2203: * we have artificially shortened the buffer size
2204: * in the descriptor, and we do an overlapping copy
2205: * of the data two bytes further in (in the first
2206: * buffer of the chain only).
2207: */
1.112 yamt 2208: memmove(mtod(m, char *) + 2, mtod(m, void *),
1.36 thorpej 2209: m->m_len);
2210: m->m_data += 2;
1.1 thorpej 2211: }
1.36 thorpej 2212: #endif /* ! __NO_STRICT_ALIGNMENT */
1.1 thorpej 2213:
1.29 thorpej 2214: /*
2215: * If VLANs are enabled, VLAN packets have been unwrapped
2216: * for us. Associate the tag with the packet.
2217: */
1.107 pavel 2218:
2219: /*
2220: * Again, byte swapping is tricky. Hardware provided
2221: * the tag in the network byte order, but extsts was
2222: * passed through le32toh() in the meantime. On a
2223: * big-endian machine, we need to swap it again. On a
2224: * little-endian machine, we need to convert from the
2225: * network to host byte order. This means that we must
2226: * swap it in any case, so unconditional swap instead
2227: * of htons() is used.
2228: */
1.100 jdolecek 2229: if ((extsts & EXTSTS_VPKT) != 0) {
1.107 pavel 2230: VLAN_INPUT_TAG(ifp, m, bswap16(extsts & EXTSTS_VTCI),
1.100 jdolecek 2231: continue);
1.29 thorpej 2232: }
1.31 thorpej 2233:
2234: /*
2235: * Set the incoming checksum information for the
2236: * packet.
2237: */
2238: if ((extsts & EXTSTS_IPPKT) != 0) {
2239: SIP_EVCNT_INCR(&sc->sc_ev_rxipsum);
2240: m->m_pkthdr.csum_flags |= M_CSUM_IPv4;
2241: if (extsts & EXTSTS_Rx_IPERR)
2242: m->m_pkthdr.csum_flags |= M_CSUM_IPv4_BAD;
2243: if (extsts & EXTSTS_TCPPKT) {
2244: SIP_EVCNT_INCR(&sc->sc_ev_rxtcpsum);
2245: m->m_pkthdr.csum_flags |= M_CSUM_TCPv4;
2246: if (extsts & EXTSTS_Rx_TCPERR)
2247: m->m_pkthdr.csum_flags |=
2248: M_CSUM_TCP_UDP_BAD;
2249: } else if (extsts & EXTSTS_UDPPKT) {
2250: SIP_EVCNT_INCR(&sc->sc_ev_rxudpsum);
2251: m->m_pkthdr.csum_flags |= M_CSUM_UDPv4;
2252: if (extsts & EXTSTS_Rx_UDPERR)
2253: m->m_pkthdr.csum_flags |=
2254: M_CSUM_TCP_UDP_BAD;
2255: }
2256: }
1.40 thorpej 2257:
2258: ifp->if_ipackets++;
2259: m->m_pkthdr.rcvif = ifp;
1.97 thorpej 2260: m->m_pkthdr.len = len;
1.40 thorpej 2261:
2262: #if NBPFILTER > 0
2263: /*
2264: * Pass this up to any BPF listeners, but only
2265: * pass if up the stack if it's for us.
2266: */
2267: if (ifp->if_bpf)
2268: bpf_mtap(ifp->if_bpf, m);
2269: #endif /* NBPFILTER > 0 */
1.29 thorpej 2270:
1.1 thorpej 2271: /* Pass it on. */
2272: (*ifp->if_input)(ifp, m);
2273: }
2274:
2275: /* Update the receive pointer. */
2276: sc->sc_rxptr = i;
2277: }
1.115.4.1! ad 2278:
1.35 thorpej 2279: /*
2280: * sip_rxintr:
2281: *
1.115.4.1! ad 2282: * Helper; handle receive interrupts on 10/100 parts.
1.35 thorpej 2283: */
1.95 thorpej 2284: static void
1.115.4.1! ad 2285: sip_rxintr(struct sip_softc *sc)
1.35 thorpej 2286: {
2287: struct ifnet *ifp = &sc->sc_ethercom.ec_if;
2288: struct sip_rxsoft *rxs;
2289: struct mbuf *m;
2290: u_int32_t cmdsts;
2291: int i, len;
2292:
1.115.4.1! ad 2293: for (i = sc->sc_rxptr;; i = sip_nextrx(sc, i)) {
1.35 thorpej 2294: rxs = &sc->sc_rxsoft[i];
2295:
1.115.4.1! ad 2296: sip_cdrxsync(sc, i, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1.35 thorpej 2297:
1.115.4.1! ad 2298: cmdsts = le32toh(*sipd_cmdsts(sc, &sc->sc_rxdescs[i]));
1.35 thorpej 2299:
2300: /*
2301: * NOTE: OWN is set if owned by _consumer_. We're the
2302: * consumer of the receive ring, so if the bit is clear,
2303: * we have processed all of the packets.
2304: */
2305: if ((cmdsts & CMDSTS_OWN) == 0) {
2306: /*
2307: * We have processed all of the receive buffers.
2308: */
2309: break;
2310: }
2311:
2312: /*
2313: * If any collisions were seen on the wire, count one.
2314: */
2315: if (cmdsts & CMDSTS_Rx_COL)
2316: ifp->if_collisions++;
2317:
2318: /*
2319: * If an error occurred, update stats, clear the status
2320: * word, and leave the packet buffer in place. It will
2321: * simply be reused the next time the ring comes around.
2322: */
1.36 thorpej 2323: if (cmdsts & (CMDSTS_Rx_RXA|CMDSTS_Rx_RUNT|
1.35 thorpej 2324: CMDSTS_Rx_ISE|CMDSTS_Rx_CRCE|CMDSTS_Rx_FAE)) {
2325: ifp->if_ierrors++;
2326: if ((cmdsts & CMDSTS_Rx_RXA) != 0 &&
2327: (cmdsts & CMDSTS_Rx_RXO) == 0) {
2328: /* Receive overrun handled elsewhere. */
2329: printf("%s: receive descriptor error\n",
2330: sc->sc_dev.dv_xname);
2331: }
2332: #define PRINTERR(bit, str) \
1.67 itojun 2333: if ((ifp->if_flags & IFF_DEBUG) != 0 && \
2334: (cmdsts & (bit)) != 0) \
1.35 thorpej 2335: printf("%s: %s\n", sc->sc_dev.dv_xname, str)
2336: PRINTERR(CMDSTS_Rx_RUNT, "runt packet");
2337: PRINTERR(CMDSTS_Rx_ISE, "invalid symbol error");
2338: PRINTERR(CMDSTS_Rx_CRCE, "CRC error");
2339: PRINTERR(CMDSTS_Rx_FAE, "frame alignment error");
2340: #undef PRINTERR
1.115.4.1! ad 2341: sip_init_rxdesc(sc, i);
1.35 thorpej 2342: continue;
2343: }
2344:
2345: bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
2346: rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
2347:
2348: /*
2349: * No errors; receive the packet. Note, the SiS 900
2350: * includes the CRC with every packet.
2351: */
1.115.4.1! ad 2352: len = CMDSTS_SIZE(sc, cmdsts) - ETHER_CRC_LEN;
1.35 thorpej 2353:
2354: #ifdef __NO_STRICT_ALIGNMENT
2355: /*
2356: * If the packet is small enough to fit in a
2357: * single header mbuf, allocate one and copy
2358: * the data into it. This greatly reduces
2359: * memory consumption when we receive lots
2360: * of small packets.
2361: *
2362: * Otherwise, we add a new buffer to the receive
2363: * chain. If this fails, we drop the packet and
2364: * recycle the old buffer.
2365: */
1.115.4.1! ad 2366: if (sip_copy_small != 0 && len <= MHLEN) {
1.35 thorpej 2367: MGETHDR(m, M_DONTWAIT, MT_DATA);
2368: if (m == NULL)
2369: goto dropit;
1.105 bouyer 2370: MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner);
1.111 christos 2371: memcpy(mtod(m, void *),
2372: mtod(rxs->rxs_mbuf, void *), len);
1.115.4.1! ad 2373: sip_init_rxdesc(sc, i);
1.35 thorpej 2374: bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
2375: rxs->rxs_dmamap->dm_mapsize,
2376: BUS_DMASYNC_PREREAD);
2377: } else {
2378: m = rxs->rxs_mbuf;
1.115.4.1! ad 2379: if (sipcom_add_rxbuf(sc, i) != 0) {
1.35 thorpej 2380: dropit:
2381: ifp->if_ierrors++;
1.115.4.1! ad 2382: sip_init_rxdesc(sc, i);
1.35 thorpej 2383: bus_dmamap_sync(sc->sc_dmat,
2384: rxs->rxs_dmamap, 0,
2385: rxs->rxs_dmamap->dm_mapsize,
2386: BUS_DMASYNC_PREREAD);
2387: continue;
2388: }
2389: }
2390: #else
2391: /*
2392: * The SiS 900's receive buffers must be 4-byte aligned.
2393: * But this means that the data after the Ethernet header
2394: * is misaligned. We must allocate a new buffer and
2395: * copy the data, shifted forward 2 bytes.
2396: */
2397: MGETHDR(m, M_DONTWAIT, MT_DATA);
2398: if (m == NULL) {
2399: dropit:
2400: ifp->if_ierrors++;
1.115.4.1! ad 2401: sip_init_rxdesc(sc, i);
1.35 thorpej 2402: bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
2403: rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
2404: continue;
2405: }
1.105 bouyer 2406: MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner);
1.35 thorpej 2407: if (len > (MHLEN - 2)) {
2408: MCLGET(m, M_DONTWAIT);
2409: if ((m->m_flags & M_EXT) == 0) {
2410: m_freem(m);
2411: goto dropit;
2412: }
2413: }
2414: m->m_data += 2;
2415:
2416: /*
2417: * Note that we use clusters for incoming frames, so the
2418: * buffer is virtually contiguous.
2419: */
1.111 christos 2420: memcpy(mtod(m, void *), mtod(rxs->rxs_mbuf, void *), len);
1.35 thorpej 2421:
2422: /* Allow the receive descriptor to continue using its mbuf. */
1.115.4.1! ad 2423: sip_init_rxdesc(sc, i);
1.35 thorpej 2424: bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
2425: rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
2426: #endif /* __NO_STRICT_ALIGNMENT */
2427:
2428: ifp->if_ipackets++;
2429: m->m_pkthdr.rcvif = ifp;
2430: m->m_pkthdr.len = m->m_len = len;
2431:
2432: #if NBPFILTER > 0
2433: /*
2434: * Pass this up to any BPF listeners, but only
2435: * pass if up the stack if it's for us.
2436: */
2437: if (ifp->if_bpf)
2438: bpf_mtap(ifp->if_bpf, m);
2439: #endif /* NBPFILTER > 0 */
2440:
2441: /* Pass it on. */
2442: (*ifp->if_input)(ifp, m);
2443: }
2444:
2445: /* Update the receive pointer. */
2446: sc->sc_rxptr = i;
2447: }
1.1 thorpej 2448:
2449: /*
2450: * sip_tick:
2451: *
2452: * One second timer, used to tick the MII.
2453: */
1.95 thorpej 2454: static void
1.115.4.1! ad 2455: sipcom_tick(void *arg)
1.1 thorpej 2456: {
2457: struct sip_softc *sc = arg;
2458: int s;
2459:
2460: s = splnet();
1.94 thorpej 2461: #ifdef SIP_EVENT_COUNTERS
1.115.4.1! ad 2462: if (sc->sc_gigabit) {
! 2463: /* Read PAUSE related counts from MIB registers. */
! 2464: sc->sc_ev_rxpause.ev_count +=
! 2465: bus_space_read_4(sc->sc_st, sc->sc_sh,
! 2466: SIP_NS_MIB(MIB_RXPauseFrames)) & 0xffff;
! 2467: sc->sc_ev_txpause.ev_count +=
! 2468: bus_space_read_4(sc->sc_st, sc->sc_sh,
! 2469: SIP_NS_MIB(MIB_TXPauseFrames)) & 0xffff;
! 2470: bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_NS_MIBC, MIBC_ACLR);
! 2471: }
1.94 thorpej 2472: #endif /* SIP_EVENT_COUNTERS */
1.1 thorpej 2473: mii_tick(&sc->sc_mii);
2474: splx(s);
2475:
1.115.4.1! ad 2476: callout_reset(&sc->sc_tick_ch, hz, sipcom_tick, sc);
1.1 thorpej 2477: }
2478:
2479: /*
2480: * sip_reset:
2481: *
2482: * Perform a soft reset on the SiS 900.
2483: */
1.115.4.1! ad 2484: static bool
! 2485: sipcom_reset(struct sip_softc *sc)
1.1 thorpej 2486: {
2487: bus_space_tag_t st = sc->sc_st;
2488: bus_space_handle_t sh = sc->sc_sh;
2489: int i;
2490:
1.45 thorpej 2491: bus_space_write_4(st, sh, SIP_IER, 0);
2492: bus_space_write_4(st, sh, SIP_IMR, 0);
2493: bus_space_write_4(st, sh, SIP_RFCR, 0);
1.1 thorpej 2494: bus_space_write_4(st, sh, SIP_CR, CR_RST);
2495:
1.14 tsutsui 2496: for (i = 0; i < SIP_TIMEOUT; i++) {
2497: if ((bus_space_read_4(st, sh, SIP_CR) & CR_RST) == 0)
2498: break;
1.1 thorpej 2499: delay(2);
2500: }
2501:
1.115.4.1! ad 2502: if (i == SIP_TIMEOUT) {
1.14 tsutsui 2503: printf("%s: reset failed to complete\n", sc->sc_dev.dv_xname);
1.115.4.1! ad 2504: return false;
! 2505: }
1.14 tsutsui 2506:
2507: delay(1000);
1.29 thorpej 2508:
1.115.4.1! ad 2509: if (sc->sc_gigabit) {
! 2510: /*
! 2511: * Set the general purpose I/O bits. Do it here in case we
! 2512: * need to have GPIO set up to talk to the media interface.
! 2513: */
! 2514: bus_space_write_4(st, sh, SIP_GPIOR, sc->sc_gpior);
! 2515: delay(1000);
! 2516: }
! 2517: return true;
! 2518: }
! 2519:
! 2520: static void
! 2521: sipcom_dp83820_init(struct sip_softc *sc, uint64_t capenable)
! 2522: {
! 2523: u_int32_t reg;
! 2524: bus_space_tag_t st = sc->sc_st;
! 2525: bus_space_handle_t sh = sc->sc_sh;
! 2526: /*
! 2527: * Initialize the VLAN/IP receive control register.
! 2528: * We enable checksum computation on all incoming
! 2529: * packets, and do not reject packets w/ bad checksums.
! 2530: */
! 2531: reg = 0;
! 2532: if (capenable &
! 2533: (IFCAP_CSUM_IPv4_Rx|IFCAP_CSUM_TCPv4_Rx|IFCAP_CSUM_UDPv4_Rx))
! 2534: reg |= VRCR_IPEN;
! 2535: if (VLAN_ATTACHED(&sc->sc_ethercom))
! 2536: reg |= VRCR_VTDEN|VRCR_VTREN;
! 2537: bus_space_write_4(st, sh, SIP_VRCR, reg);
! 2538:
1.29 thorpej 2539: /*
1.115.4.1! ad 2540: * Initialize the VLAN/IP transmit control register.
! 2541: * We enable outgoing checksum computation on a
! 2542: * per-packet basis.
1.29 thorpej 2543: */
1.115.4.1! ad 2544: reg = 0;
! 2545: if (capenable &
! 2546: (IFCAP_CSUM_IPv4_Tx|IFCAP_CSUM_TCPv4_Tx|IFCAP_CSUM_UDPv4_Tx))
! 2547: reg |= VTCR_PPCHK;
! 2548: if (VLAN_ATTACHED(&sc->sc_ethercom))
! 2549: reg |= VTCR_VPPTI;
! 2550: bus_space_write_4(st, sh, SIP_VTCR, reg);
! 2551:
! 2552: /*
! 2553: * If we're using VLANs, initialize the VLAN data register.
! 2554: * To understand why we bswap the VLAN Ethertype, see section
! 2555: * 4.2.36 of the DP83820 manual.
! 2556: */
! 2557: if (VLAN_ATTACHED(&sc->sc_ethercom))
! 2558: bus_space_write_4(st, sh, SIP_VDR, bswap16(ETHERTYPE_VLAN));
1.1 thorpej 2559: }
2560:
2561: /*
1.17 thorpej 2562: * sip_init: [ ifnet interface function ]
1.1 thorpej 2563: *
2564: * Initialize the interface. Must be called at splnet().
2565: */
1.95 thorpej 2566: static int
1.115.4.1! ad 2567: sipcom_init(struct ifnet *ifp)
1.1 thorpej 2568: {
1.17 thorpej 2569: struct sip_softc *sc = ifp->if_softc;
1.1 thorpej 2570: bus_space_tag_t st = sc->sc_st;
2571: bus_space_handle_t sh = sc->sc_sh;
2572: struct sip_txsoft *txs;
1.2 thorpej 2573: struct sip_rxsoft *rxs;
1.1 thorpej 2574: struct sip_desc *sipd;
1.2 thorpej 2575: int i, error = 0;
1.1 thorpej 2576:
1.115.4.1! ad 2577: if (!device_has_power(&sc->sc_dev))
! 2578: return EBUSY;
! 2579:
1.1 thorpej 2580: /*
2581: * Cancel any pending I/O.
2582: */
1.115.4.1! ad 2583: sipcom_stop(ifp, 0);
1.1 thorpej 2584:
2585: /*
2586: * Reset the chip to a known state.
2587: */
1.115.4.1! ad 2588: if (!sipcom_reset(sc))
! 2589: return EBUSY;
1.1 thorpej 2590:
1.45 thorpej 2591: if (SIP_CHIP_MODEL(sc, PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83815)) {
1.25 briggs 2592: /*
2593: * DP83815 manual, page 78:
2594: * 4.4 Recommended Registers Configuration
2595: * For optimum performance of the DP83815, version noted
2596: * as DP83815CVNG (SRR = 203h), the listed register
2597: * modifications must be followed in sequence...
2598: *
2599: * It's not clear if this should be 302h or 203h because that
2600: * chip name is listed as SRR 302h in the description of the
1.26 briggs 2601: * SRR register. However, my revision 302h DP83815 on the
2602: * Netgear FA311 purchased in 02/2001 needs these settings
2603: * to avoid tons of errors in AcceptPerfectMatch (non-
2604: * IFF_PROMISC) mode. I do not know if other revisions need
2605: * this set or not. [briggs -- 09 March 2001]
2606: *
2607: * Note that only the low-order 12 bits of 0xe4 are documented
2608: * and that this sets reserved bits in that register.
1.25 briggs 2609: */
1.78 thorpej 2610: bus_space_write_4(st, sh, 0x00cc, 0x0001);
2611:
2612: bus_space_write_4(st, sh, 0x00e4, 0x189C);
2613: bus_space_write_4(st, sh, 0x00fc, 0x0000);
2614: bus_space_write_4(st, sh, 0x00f4, 0x5040);
2615: bus_space_write_4(st, sh, 0x00f8, 0x008c);
2616:
2617: bus_space_write_4(st, sh, 0x00cc, 0x0000);
1.25 briggs 2618: }
2619:
1.1 thorpej 2620: /*
2621: * Initialize the transmit descriptor ring.
2622: */
1.115.4.1! ad 2623: for (i = 0; i < sc->sc_ntxdesc; i++) {
1.1 thorpej 2624: sipd = &sc->sc_txdescs[i];
2625: memset(sipd, 0, sizeof(struct sip_desc));
1.115.4.1! ad 2626: sipd->sipd_link = htole32(SIP_CDTXADDR(sc, sip_nexttx(sc, i)));
1.1 thorpej 2627: }
1.115.4.1! ad 2628: sip_cdtxsync(sc, 0, sc->sc_ntxdesc,
1.1 thorpej 2629: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
1.115.4.1! ad 2630: sc->sc_txfree = sc->sc_ntxdesc;
1.1 thorpej 2631: sc->sc_txnext = 0;
1.56 thorpej 2632: sc->sc_txwin = 0;
1.1 thorpej 2633:
2634: /*
2635: * Initialize the transmit job descriptors.
2636: */
2637: SIMPLEQ_INIT(&sc->sc_txfreeq);
2638: SIMPLEQ_INIT(&sc->sc_txdirtyq);
2639: for (i = 0; i < SIP_TXQUEUELEN; i++) {
2640: txs = &sc->sc_txsoft[i];
2641: txs->txs_mbuf = NULL;
2642: SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
2643: }
2644:
2645: /*
2646: * Initialize the receive descriptor and receive job
1.2 thorpej 2647: * descriptor rings.
1.1 thorpej 2648: */
1.115.4.1! ad 2649: for (i = 0; i < sc->sc_parm->p_nrxdesc; i++) {
1.2 thorpej 2650: rxs = &sc->sc_rxsoft[i];
2651: if (rxs->rxs_mbuf == NULL) {
1.115.4.1! ad 2652: if ((error = sipcom_add_rxbuf(sc, i)) != 0) {
1.2 thorpej 2653: printf("%s: unable to allocate or map rx "
2654: "buffer %d, error = %d\n",
2655: sc->sc_dev.dv_xname, i, error);
2656: /*
2657: * XXX Should attempt to run with fewer receive
2658: * XXX buffers instead of just failing.
2659: */
1.115.4.1! ad 2660: sipcom_rxdrain(sc);
1.2 thorpej 2661: goto out;
2662: }
1.42 thorpej 2663: } else
1.115.4.1! ad 2664: sip_init_rxdesc(sc, i);
1.2 thorpej 2665: }
1.1 thorpej 2666: sc->sc_rxptr = 0;
1.36 thorpej 2667: sc->sc_rxdiscard = 0;
1.115.4.1! ad 2668: sip_rxchain_reset(sc);
1.1 thorpej 2669:
2670: /*
1.29 thorpej 2671: * Set the configuration register; it's already initialized
2672: * in sip_attach().
1.1 thorpej 2673: */
1.29 thorpej 2674: bus_space_write_4(st, sh, SIP_CFG, sc->sc_cfg);
1.1 thorpej 2675:
2676: /*
2677: * Initialize the prototype TXCFG register.
2678: */
1.115.4.1! ad 2679: if (sc->sc_gigabit) {
! 2680: sc->sc_txcfg = sc->sc_bits.b_txcfg_mxdma_512;
! 2681: sc->sc_rxcfg = sc->sc_bits.b_rxcfg_mxdma_512;
! 2682: } else if ((SIP_SIS900_REV(sc, SIS_REV_635) ||
1.87 cube 2683: SIP_SIS900_REV(sc, SIS_REV_960) ||
1.45 thorpej 2684: SIP_SIS900_REV(sc, SIS_REV_900B)) &&
1.89 thorpej 2685: (sc->sc_cfg & CFG_EDBMASTEN)) {
1.115.4.1! ad 2686: sc->sc_txcfg = sc->sc_bits.b_txcfg_mxdma_64;
! 2687: sc->sc_rxcfg = sc->sc_bits.b_rxcfg_mxdma_64;
1.45 thorpej 2688: } else {
1.115.4.1! ad 2689: sc->sc_txcfg = sc->sc_bits.b_txcfg_mxdma_512;
! 2690: sc->sc_rxcfg = sc->sc_bits.b_rxcfg_mxdma_512;
1.45 thorpej 2691: }
2692:
2693: sc->sc_txcfg |= TXCFG_ATP |
1.115.4.1! ad 2694: __SHIFTIN(sc->sc_tx_fill_thresh, sc->sc_bits.b_txcfg_flth_mask) |
1.1 thorpej 2695: sc->sc_tx_drain_thresh;
1.115.4.1! ad 2696: bus_space_write_4(st, sh, sc->sc_regs.r_txcfg, sc->sc_txcfg);
1.1 thorpej 2697:
2698: /*
2699: * Initialize the receive drain threshold if we have never
2700: * done so.
2701: */
2702: if (sc->sc_rx_drain_thresh == 0) {
2703: /*
2704: * XXX This value should be tuned. This is set to the
2705: * maximum of 248 bytes, and we may be able to improve
2706: * performance by decreasing it (although we should never
2707: * set this value lower than 2; 14 bytes are required to
2708: * filter the packet).
2709: */
1.115.4.1! ad 2710: sc->sc_rx_drain_thresh = __SHIFTOUT_MASK(RXCFG_DRTH_MASK);
1.1 thorpej 2711: }
2712:
2713: /*
2714: * Initialize the prototype RXCFG register.
2715: */
1.115.4.1! ad 2716: sc->sc_rxcfg |= __SHIFTIN(sc->sc_rx_drain_thresh, RXCFG_DRTH_MASK);
1.88 thorpej 2717: /*
2718: * Accept long packets (including FCS) so we can handle
2719: * 802.1q-tagged frames and jumbo frames properly.
2720: */
1.115.4.1! ad 2721: if ((sc->sc_gigabit && ifp->if_mtu > ETHERMTU) ||
1.88 thorpej 2722: (sc->sc_ethercom.ec_capenable & ETHERCAP_VLAN_MTU))
2723: sc->sc_rxcfg |= RXCFG_ALP;
2724:
2725: /*
2726: * Checksum offloading is disabled if the user selects an MTU
2727: * larger than 8109. (FreeBSD says 8152, but there is emperical
2728: * evidence that >8109 does not work on some boards, such as the
2729: * Planex GN-1000TE).
2730: */
1.115.4.1! ad 2731: if (sc->sc_gigabit && ifp->if_mtu > 8109 &&
1.88 thorpej 2732: (ifp->if_capenable &
1.102 yamt 2733: (IFCAP_CSUM_IPv4_Tx|IFCAP_CSUM_IPv4_Rx|
2734: IFCAP_CSUM_TCPv4_Tx|IFCAP_CSUM_TCPv4_Rx|
2735: IFCAP_CSUM_UDPv4_Tx|IFCAP_CSUM_UDPv4_Rx))) {
1.88 thorpej 2736: printf("%s: Checksum offloading does not work if MTU > 8109 - "
2737: "disabled.\n", sc->sc_dev.dv_xname);
1.102 yamt 2738: ifp->if_capenable &=
2739: ~(IFCAP_CSUM_IPv4_Tx|IFCAP_CSUM_IPv4_Rx|
2740: IFCAP_CSUM_TCPv4_Tx|IFCAP_CSUM_TCPv4_Rx|
2741: IFCAP_CSUM_UDPv4_Tx|IFCAP_CSUM_UDPv4_Rx);
1.88 thorpej 2742: ifp->if_csum_flags_tx = 0;
2743: ifp->if_csum_flags_rx = 0;
2744: }
1.29 thorpej 2745:
1.115.4.1! ad 2746: bus_space_write_4(st, sh, sc->sc_regs.r_rxcfg, sc->sc_rxcfg);
1.29 thorpej 2747:
1.115.4.1! ad 2748: if (sc->sc_gigabit)
! 2749: sipcom_dp83820_init(sc, ifp->if_capenable);
1.29 thorpej 2750:
1.1 thorpej 2751: /*
2752: * Give the transmit and receive rings to the chip.
2753: */
2754: bus_space_write_4(st, sh, SIP_TXDP, SIP_CDTXADDR(sc, sc->sc_txnext));
2755: bus_space_write_4(st, sh, SIP_RXDP, SIP_CDRXADDR(sc, sc->sc_rxptr));
2756:
2757: /*
2758: * Initialize the interrupt mask.
2759: */
1.115.4.1! ad 2760: sc->sc_imr = sc->sc_bits.b_isr_dperr |
! 2761: sc->sc_bits.b_isr_sserr |
! 2762: sc->sc_bits.b_isr_rmabt |
! 2763: sc->sc_bits.b_isr_rtabt | ISR_RXSOVR |
1.56 thorpej 2764: ISR_TXURN|ISR_TXDESC|ISR_TXIDLE|ISR_RXORN|ISR_RXIDLE|ISR_RXDESC;
1.1 thorpej 2765: bus_space_write_4(st, sh, SIP_IMR, sc->sc_imr);
2766:
1.45 thorpej 2767: /* Set up the receive filter. */
2768: (*sc->sc_model->sip_variant->sipv_set_filter)(sc);
2769:
1.89 thorpej 2770: /*
2771: * Tune sc_rx_flow_thresh.
2772: * XXX "More than 8KB" is too short for jumbo frames.
2773: * XXX TODO: Threshold value should be user-settable.
2774: */
2775: sc->sc_rx_flow_thresh = (PCR_PS_STHI_8 | PCR_PS_STLO_4 |
2776: PCR_PS_FFHI_8 | PCR_PS_FFLO_4 |
2777: (PCR_PAUSE_CNT & PCR_PAUSE_CNT_MASK));
2778:
1.1 thorpej 2779: /*
2780: * Set the current media. Do this after initializing the prototype
2781: * IMR, since sip_mii_statchg() modifies the IMR for 802.3x flow
2782: * control.
2783: */
2784: mii_mediachg(&sc->sc_mii);
2785:
1.88 thorpej 2786: /*
2787: * Set the interrupt hold-off timer to 100us.
2788: */
1.115.4.1! ad 2789: if (sc->sc_gigabit)
! 2790: bus_space_write_4(st, sh, SIP_IHR, 0x01);
1.88 thorpej 2791:
1.1 thorpej 2792: /*
2793: * Enable interrupts.
2794: */
2795: bus_space_write_4(st, sh, SIP_IER, IER_IE);
2796:
2797: /*
2798: * Start the transmit and receive processes.
2799: */
2800: bus_space_write_4(st, sh, SIP_CR, CR_RXE | CR_TXE);
2801:
2802: /*
2803: * Start the one second MII clock.
2804: */
1.115.4.1! ad 2805: callout_reset(&sc->sc_tick_ch, hz, sipcom_tick, sc);
1.1 thorpej 2806:
2807: /*
2808: * ...all done!
2809: */
2810: ifp->if_flags |= IFF_RUNNING;
2811: ifp->if_flags &= ~IFF_OACTIVE;
1.98 kim 2812: sc->sc_if_flags = ifp->if_flags;
1.106 pavel 2813: sc->sc_prev.ec_capenable = sc->sc_ethercom.ec_capenable;
2814: sc->sc_prev.is_vlan = VLAN_ATTACHED(&(sc)->sc_ethercom);
2815: sc->sc_prev.if_capenable = ifp->if_capenable;
1.2 thorpej 2816:
2817: out:
2818: if (error)
2819: printf("%s: interface not running\n", sc->sc_dev.dv_xname);
2820: return (error);
2821: }
2822:
2823: /*
2824: * sip_drain:
2825: *
2826: * Drain the receive queue.
2827: */
1.95 thorpej 2828: static void
1.115.4.1! ad 2829: sipcom_rxdrain(struct sip_softc *sc)
1.2 thorpej 2830: {
2831: struct sip_rxsoft *rxs;
2832: int i;
2833:
1.115.4.1! ad 2834: for (i = 0; i < sc->sc_parm->p_nrxdesc; i++) {
1.2 thorpej 2835: rxs = &sc->sc_rxsoft[i];
2836: if (rxs->rxs_mbuf != NULL) {
2837: bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap);
2838: m_freem(rxs->rxs_mbuf);
2839: rxs->rxs_mbuf = NULL;
2840: }
2841: }
1.1 thorpej 2842: }
2843:
2844: /*
1.17 thorpej 2845: * sip_stop: [ ifnet interface function ]
1.1 thorpej 2846: *
2847: * Stop transmission on the interface.
2848: */
1.95 thorpej 2849: static void
1.115.4.1! ad 2850: sipcom_stop(struct ifnet *ifp, int disable)
1.1 thorpej 2851: {
1.17 thorpej 2852: struct sip_softc *sc = ifp->if_softc;
1.1 thorpej 2853: bus_space_tag_t st = sc->sc_st;
2854: bus_space_handle_t sh = sc->sc_sh;
2855: struct sip_txsoft *txs;
2856: u_int32_t cmdsts = 0; /* DEBUG */
2857:
2858: /*
2859: * Stop the one second clock.
2860: */
1.9 thorpej 2861: callout_stop(&sc->sc_tick_ch);
1.4 thorpej 2862:
2863: /* Down the MII. */
2864: mii_down(&sc->sc_mii);
1.1 thorpej 2865:
2866: /*
2867: * Disable interrupts.
2868: */
2869: bus_space_write_4(st, sh, SIP_IER, 0);
2870:
2871: /*
2872: * Stop receiver and transmitter.
2873: */
2874: bus_space_write_4(st, sh, SIP_CR, CR_RXD | CR_TXD);
2875:
2876: /*
2877: * Release any queued transmit buffers.
2878: */
2879: while ((txs = SIMPLEQ_FIRST(&sc->sc_txdirtyq)) != NULL) {
2880: if ((ifp->if_flags & IFF_DEBUG) != 0 &&
2881: SIMPLEQ_NEXT(txs, txs_q) == NULL &&
1.115.4.1! ad 2882: (le32toh(*sipd_cmdsts(sc, &sc->sc_txdescs[txs->txs_lastdesc])) &
1.1 thorpej 2883: CMDSTS_INTR) == 0)
2884: printf("%s: sip_stop: last descriptor does not "
2885: "have INTR bit set\n", sc->sc_dev.dv_xname);
1.54 lukem 2886: SIMPLEQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q);
1.1 thorpej 2887: #ifdef DIAGNOSTIC
2888: if (txs->txs_mbuf == NULL) {
2889: printf("%s: dirty txsoft with no mbuf chain\n",
2890: sc->sc_dev.dv_xname);
2891: panic("sip_stop");
2892: }
2893: #endif
2894: cmdsts |= /* DEBUG */
1.115.4.1! ad 2895: le32toh(*sipd_cmdsts(sc, &sc->sc_txdescs[txs->txs_lastdesc]));
1.1 thorpej 2896: bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap);
2897: m_freem(txs->txs_mbuf);
2898: txs->txs_mbuf = NULL;
2899: SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
1.2 thorpej 2900: }
2901:
1.17 thorpej 2902: if (disable)
1.115.4.1! ad 2903: sipcom_rxdrain(sc);
1.1 thorpej 2904:
2905: /*
2906: * Mark the interface down and cancel the watchdog timer.
2907: */
2908: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
2909: ifp->if_timer = 0;
2910:
2911: if ((ifp->if_flags & IFF_DEBUG) != 0 &&
1.115.4.1! ad 2912: (cmdsts & CMDSTS_INTR) == 0 && sc->sc_txfree != sc->sc_ntxdesc)
1.1 thorpej 2913: printf("%s: sip_stop: no INTR bits set in dirty tx "
2914: "descriptors\n", sc->sc_dev.dv_xname);
2915: }
2916:
2917: /*
2918: * sip_read_eeprom:
2919: *
2920: * Read data from the serial EEPROM.
2921: */
1.95 thorpej 2922: static void
1.115.4.1! ad 2923: sipcom_read_eeprom(struct sip_softc *sc, int word, int wordcnt,
1.28 thorpej 2924: u_int16_t *data)
1.1 thorpej 2925: {
2926: bus_space_tag_t st = sc->sc_st;
2927: bus_space_handle_t sh = sc->sc_sh;
2928: u_int16_t reg;
2929: int i, x;
2930:
2931: for (i = 0; i < wordcnt; i++) {
2932: /* Send CHIP SELECT. */
2933: reg = EROMAR_EECS;
2934: bus_space_write_4(st, sh, SIP_EROMAR, reg);
2935:
2936: /* Shift in the READ opcode. */
2937: for (x = 3; x > 0; x--) {
2938: if (SIP_EEPROM_OPC_READ & (1 << (x - 1)))
2939: reg |= EROMAR_EEDI;
2940: else
2941: reg &= ~EROMAR_EEDI;
2942: bus_space_write_4(st, sh, SIP_EROMAR, reg);
2943: bus_space_write_4(st, sh, SIP_EROMAR,
2944: reg | EROMAR_EESK);
2945: delay(4);
2946: bus_space_write_4(st, sh, SIP_EROMAR, reg);
2947: delay(4);
2948: }
1.101 perry 2949:
1.1 thorpej 2950: /* Shift in address. */
2951: for (x = 6; x > 0; x--) {
2952: if ((word + i) & (1 << (x - 1)))
2953: reg |= EROMAR_EEDI;
2954: else
1.101 perry 2955: reg &= ~EROMAR_EEDI;
1.1 thorpej 2956: bus_space_write_4(st, sh, SIP_EROMAR, reg);
2957: bus_space_write_4(st, sh, SIP_EROMAR,
2958: reg | EROMAR_EESK);
2959: delay(4);
2960: bus_space_write_4(st, sh, SIP_EROMAR, reg);
2961: delay(4);
2962: }
2963:
2964: /* Shift out data. */
2965: reg = EROMAR_EECS;
2966: data[i] = 0;
2967: for (x = 16; x > 0; x--) {
2968: bus_space_write_4(st, sh, SIP_EROMAR,
2969: reg | EROMAR_EESK);
2970: delay(4);
2971: if (bus_space_read_4(st, sh, SIP_EROMAR) & EROMAR_EEDO)
2972: data[i] |= (1 << (x - 1));
2973: bus_space_write_4(st, sh, SIP_EROMAR, reg);
1.13 tsutsui 2974: delay(4);
1.1 thorpej 2975: }
2976:
2977: /* Clear CHIP SELECT. */
2978: bus_space_write_4(st, sh, SIP_EROMAR, 0);
2979: delay(4);
2980: }
2981: }
2982:
2983: /*
1.115.4.1! ad 2984: * sipcom_add_rxbuf:
1.1 thorpej 2985: *
2986: * Add a receive buffer to the indicated descriptor.
2987: */
1.95 thorpej 2988: static int
1.115.4.1! ad 2989: sipcom_add_rxbuf(struct sip_softc *sc, int idx)
1.1 thorpej 2990: {
2991: struct sip_rxsoft *rxs = &sc->sc_rxsoft[idx];
2992: struct mbuf *m;
2993: int error;
2994:
2995: MGETHDR(m, M_DONTWAIT, MT_DATA);
1.101 perry 2996: if (m == NULL)
1.1 thorpej 2997: return (ENOBUFS);
1.105 bouyer 2998: MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner);
1.1 thorpej 2999:
3000: MCLGET(m, M_DONTWAIT);
3001: if ((m->m_flags & M_EXT) == 0) {
3002: m_freem(m);
3003: return (ENOBUFS);
3004: }
1.36 thorpej 3005:
1.115.4.1! ad 3006: /* XXX I don't believe this is necessary. --dyoung */
! 3007: if (sc->sc_gigabit)
! 3008: m->m_len = sc->sc_parm->p_rxbuf_len;
1.1 thorpej 3009:
3010: if (rxs->rxs_mbuf != NULL)
3011: bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap);
3012:
3013: rxs->rxs_mbuf = m;
3014:
3015: error = bus_dmamap_load(sc->sc_dmat, rxs->rxs_dmamap,
1.41 thorpej 3016: m->m_ext.ext_buf, m->m_ext.ext_size, NULL,
3017: BUS_DMA_READ|BUS_DMA_NOWAIT);
1.1 thorpej 3018: if (error) {
3019: printf("%s: can't load rx DMA map %d, error = %d\n",
3020: sc->sc_dev.dv_xname, idx, error);
1.115.4.1! ad 3021: panic("%s", __func__); /* XXX */
1.1 thorpej 3022: }
3023:
3024: bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
3025: rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
3026:
1.115.4.1! ad 3027: sip_init_rxdesc(sc, idx);
1.1 thorpej 3028:
3029: return (0);
3030: }
3031:
3032: /*
1.15 thorpej 3033: * sip_sis900_set_filter:
1.1 thorpej 3034: *
3035: * Set up the receive filter.
3036: */
1.95 thorpej 3037: static void
1.115.4.1! ad 3038: sipcom_sis900_set_filter(struct sip_softc *sc)
1.1 thorpej 3039: {
3040: bus_space_tag_t st = sc->sc_st;
3041: bus_space_handle_t sh = sc->sc_sh;
3042: struct ethercom *ec = &sc->sc_ethercom;
3043: struct ifnet *ifp = &sc->sc_ethercom.ec_if;
3044: struct ether_multi *enm;
1.114 dyoung 3045: const u_int8_t *cp;
1.1 thorpej 3046: struct ether_multistep step;
1.45 thorpej 3047: u_int32_t crc, mchash[16];
1.1 thorpej 3048:
3049: /*
3050: * Initialize the prototype RFCR.
3051: */
3052: sc->sc_rfcr = RFCR_RFEN;
3053: if (ifp->if_flags & IFF_BROADCAST)
3054: sc->sc_rfcr |= RFCR_AAB;
3055: if (ifp->if_flags & IFF_PROMISC) {
3056: sc->sc_rfcr |= RFCR_AAP;
3057: goto allmulti;
3058: }
3059:
3060: /*
3061: * Set up the multicast address filter by passing all multicast
3062: * addresses through a CRC generator, and then using the high-order
3063: * 6 bits as an index into the 128 bit multicast hash table (only
3064: * the lower 16 bits of each 32 bit multicast hash register are
3065: * valid). The high order bits select the register, while the
3066: * rest of the bits select the bit within the register.
3067: */
3068:
3069: memset(mchash, 0, sizeof(mchash));
3070:
1.92 thorpej 3071: /*
3072: * SiS900 (at least SiS963) requires us to register the address of
3073: * the PAUSE packet (01:80:c2:00:00:01) into the address filter.
3074: */
3075: crc = 0x0ed423f9;
3076:
3077: if (SIP_SIS900_REV(sc, SIS_REV_635) ||
3078: SIP_SIS900_REV(sc, SIS_REV_960) ||
3079: SIP_SIS900_REV(sc, SIS_REV_900B)) {
3080: /* Just want the 8 most significant bits. */
3081: crc >>= 24;
3082: } else {
3083: /* Just want the 7 most significant bits. */
3084: crc >>= 25;
3085: }
3086:
3087: /* Set the corresponding bit in the hash table. */
3088: mchash[crc >> 4] |= 1 << (crc & 0xf);
3089:
1.1 thorpej 3090: ETHER_FIRST_MULTI(step, ec, enm);
3091: while (enm != NULL) {
1.37 thorpej 3092: if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
1.1 thorpej 3093: /*
3094: * We must listen to a range of multicast addresses.
3095: * For now, just accept all multicasts, rather than
3096: * trying to set only those filter bits needed to match
3097: * the range. (At this time, the only use of address
3098: * ranges is for IP multicast routing, for which the
3099: * range is big enough to require all bits set.)
3100: */
3101: goto allmulti;
3102: }
3103:
1.45 thorpej 3104: crc = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN);
1.11 thorpej 3105:
1.45 thorpej 3106: if (SIP_SIS900_REV(sc, SIS_REV_635) ||
1.84 cube 3107: SIP_SIS900_REV(sc, SIS_REV_960) ||
1.45 thorpej 3108: SIP_SIS900_REV(sc, SIS_REV_900B)) {
3109: /* Just want the 8 most significant bits. */
3110: crc >>= 24;
3111: } else {
3112: /* Just want the 7 most significant bits. */
3113: crc >>= 25;
3114: }
1.1 thorpej 3115:
3116: /* Set the corresponding bit in the hash table. */
3117: mchash[crc >> 4] |= 1 << (crc & 0xf);
3118:
3119: ETHER_NEXT_MULTI(step, enm);
3120: }
3121:
3122: ifp->if_flags &= ~IFF_ALLMULTI;
3123: goto setit;
3124:
3125: allmulti:
3126: ifp->if_flags |= IFF_ALLMULTI;
3127: sc->sc_rfcr |= RFCR_AAM;
3128:
3129: setit:
3130: #define FILTER_EMIT(addr, data) \
3131: bus_space_write_4(st, sh, SIP_RFCR, (addr)); \
1.14 tsutsui 3132: delay(1); \
3133: bus_space_write_4(st, sh, SIP_RFDR, (data)); \
3134: delay(1)
1.1 thorpej 3135:
3136: /*
3137: * Disable receive filter, and program the node address.
3138: */
1.114 dyoung 3139: cp = CLLADDR(ifp->if_sadl);
1.1 thorpej 3140: FILTER_EMIT(RFCR_RFADDR_NODE0, (cp[1] << 8) | cp[0]);
3141: FILTER_EMIT(RFCR_RFADDR_NODE2, (cp[3] << 8) | cp[2]);
3142: FILTER_EMIT(RFCR_RFADDR_NODE4, (cp[5] << 8) | cp[4]);
3143:
3144: if ((ifp->if_flags & IFF_ALLMULTI) == 0) {
3145: /*
3146: * Program the multicast hash table.
3147: */
3148: FILTER_EMIT(RFCR_RFADDR_MC0, mchash[0]);
3149: FILTER_EMIT(RFCR_RFADDR_MC1, mchash[1]);
3150: FILTER_EMIT(RFCR_RFADDR_MC2, mchash[2]);
3151: FILTER_EMIT(RFCR_RFADDR_MC3, mchash[3]);
3152: FILTER_EMIT(RFCR_RFADDR_MC4, mchash[4]);
3153: FILTER_EMIT(RFCR_RFADDR_MC5, mchash[5]);
3154: FILTER_EMIT(RFCR_RFADDR_MC6, mchash[6]);
3155: FILTER_EMIT(RFCR_RFADDR_MC7, mchash[7]);
1.45 thorpej 3156: if (SIP_SIS900_REV(sc, SIS_REV_635) ||
1.84 cube 3157: SIP_SIS900_REV(sc, SIS_REV_960) ||
1.45 thorpej 3158: SIP_SIS900_REV(sc, SIS_REV_900B)) {
3159: FILTER_EMIT(RFCR_RFADDR_MC8, mchash[8]);
3160: FILTER_EMIT(RFCR_RFADDR_MC9, mchash[9]);
3161: FILTER_EMIT(RFCR_RFADDR_MC10, mchash[10]);
3162: FILTER_EMIT(RFCR_RFADDR_MC11, mchash[11]);
3163: FILTER_EMIT(RFCR_RFADDR_MC12, mchash[12]);
3164: FILTER_EMIT(RFCR_RFADDR_MC13, mchash[13]);
3165: FILTER_EMIT(RFCR_RFADDR_MC14, mchash[14]);
3166: FILTER_EMIT(RFCR_RFADDR_MC15, mchash[15]);
3167: }
1.1 thorpej 3168: }
3169: #undef FILTER_EMIT
3170:
3171: /*
3172: * Re-enable the receiver filter.
3173: */
3174: bus_space_write_4(st, sh, SIP_RFCR, sc->sc_rfcr);
3175: }
3176:
3177: /*
1.15 thorpej 3178: * sip_dp83815_set_filter:
3179: *
3180: * Set up the receive filter.
3181: */
1.95 thorpej 3182: static void
1.115.4.1! ad 3183: sipcom_dp83815_set_filter(struct sip_softc *sc)
1.15 thorpej 3184: {
3185: bus_space_tag_t st = sc->sc_st;
3186: bus_space_handle_t sh = sc->sc_sh;
3187: struct ethercom *ec = &sc->sc_ethercom;
1.101 perry 3188: struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1.15 thorpej 3189: struct ether_multi *enm;
1.114 dyoung 3190: const u_int8_t *cp;
1.101 perry 3191: struct ether_multistep step;
1.29 thorpej 3192: u_int32_t crc, hash, slot, bit;
1.115.4.1! ad 3193: #define MCHASH_NWORDS_83820 128
! 3194: #define MCHASH_NWORDS_83815 32
! 3195: #define MCHASH_NWORDS MAX(MCHASH_NWORDS_83820, MCHASH_NWORDS_83815)
1.29 thorpej 3196: u_int16_t mchash[MCHASH_NWORDS];
1.15 thorpej 3197: int i;
3198:
3199: /*
3200: * Initialize the prototype RFCR.
1.27 briggs 3201: * Enable the receive filter, and accept on
3202: * Perfect (destination address) Match
1.26 briggs 3203: * If IFF_BROADCAST, also accept all broadcast packets.
3204: * If IFF_PROMISC, accept all unicast packets (and later, set
3205: * IFF_ALLMULTI and accept all multicast, too).
1.15 thorpej 3206: */
1.27 briggs 3207: sc->sc_rfcr = RFCR_RFEN | RFCR_APM;
1.15 thorpej 3208: if (ifp->if_flags & IFF_BROADCAST)
3209: sc->sc_rfcr |= RFCR_AAB;
3210: if (ifp->if_flags & IFF_PROMISC) {
3211: sc->sc_rfcr |= RFCR_AAP;
3212: goto allmulti;
3213: }
3214:
1.29 thorpej 3215: /*
1.115.4.1! ad 3216: * Set up the DP83820/DP83815 multicast address filter by
! 3217: * passing all multicast addresses through a CRC generator,
! 3218: * and then using the high-order 11/9 bits as an index into
! 3219: * the 2048/512 bit multicast hash table. The high-order
! 3220: * 7/5 bits select the slot, while the low-order 4 bits
! 3221: * select the bit within the slot. Note that only the low
! 3222: * 16-bits of each filter word are used, and there are
! 3223: * 128/32 filter words.
1.15 thorpej 3224: */
3225:
3226: memset(mchash, 0, sizeof(mchash));
3227:
1.26 briggs 3228: ifp->if_flags &= ~IFF_ALLMULTI;
1.15 thorpej 3229: ETHER_FIRST_MULTI(step, ec, enm);
1.38 thorpej 3230: if (enm == NULL)
3231: goto setit;
3232: while (enm != NULL) {
1.39 thorpej 3233: if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
1.15 thorpej 3234: /*
3235: * We must listen to a range of multicast addresses.
3236: * For now, just accept all multicasts, rather than
3237: * trying to set only those filter bits needed to match
3238: * the range. (At this time, the only use of address
3239: * ranges is for IP multicast routing, for which the
3240: * range is big enough to require all bits set.)
3241: */
1.38 thorpej 3242: goto allmulti;
3243: }
1.26 briggs 3244:
1.38 thorpej 3245: crc = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN);
1.29 thorpej 3246:
1.115.4.1! ad 3247: if (sc->sc_gigabit) {
! 3248: /* Just want the 11 most significant bits. */
! 3249: hash = crc >> 21;
! 3250: } else {
! 3251: /* Just want the 9 most significant bits. */
! 3252: hash = crc >> 23;
! 3253: }
1.49 is 3254:
1.38 thorpej 3255: slot = hash >> 4;
3256: bit = hash & 0xf;
1.15 thorpej 3257:
1.38 thorpej 3258: /* Set the corresponding bit in the hash table. */
3259: mchash[slot] |= 1 << bit;
1.15 thorpej 3260:
1.38 thorpej 3261: ETHER_NEXT_MULTI(step, enm);
1.15 thorpej 3262: }
1.38 thorpej 3263: sc->sc_rfcr |= RFCR_MHEN;
1.15 thorpej 3264: goto setit;
3265:
3266: allmulti:
3267: ifp->if_flags |= IFF_ALLMULTI;
3268: sc->sc_rfcr |= RFCR_AAM;
3269:
3270: setit:
3271: #define FILTER_EMIT(addr, data) \
3272: bus_space_write_4(st, sh, SIP_RFCR, (addr)); \
3273: delay(1); \
3274: bus_space_write_4(st, sh, SIP_RFDR, (data)); \
1.39 thorpej 3275: delay(1)
1.15 thorpej 3276:
3277: /*
3278: * Disable receive filter, and program the node address.
3279: */
1.114 dyoung 3280: cp = CLLADDR(ifp->if_sadl);
1.26 briggs 3281: FILTER_EMIT(RFCR_NS_RFADDR_PMATCH0, (cp[1] << 8) | cp[0]);
3282: FILTER_EMIT(RFCR_NS_RFADDR_PMATCH2, (cp[3] << 8) | cp[2]);
3283: FILTER_EMIT(RFCR_NS_RFADDR_PMATCH4, (cp[5] << 8) | cp[4]);
1.15 thorpej 3284:
3285: if ((ifp->if_flags & IFF_ALLMULTI) == 0) {
1.115.4.1! ad 3286: int nwords =
! 3287: sc->sc_gigabit ? MCHASH_NWORDS_83820 : MCHASH_NWORDS_83815;
1.15 thorpej 3288: /*
3289: * Program the multicast hash table.
3290: */
1.115.4.1! ad 3291: for (i = 0; i < nwords; i++) {
! 3292: FILTER_EMIT(sc->sc_parm->p_filtmem + (i * 2), mchash[i]);
1.39 thorpej 3293: }
1.15 thorpej 3294: }
3295: #undef FILTER_EMIT
1.29 thorpej 3296: #undef MCHASH_NWORDS
1.115.4.1! ad 3297: #undef MCHASH_NWORDS_83815
! 3298: #undef MCHASH_NWORDS_83820
1.15 thorpej 3299:
3300: /*
3301: * Re-enable the receiver filter.
3302: */
3303: bus_space_write_4(st, sh, SIP_RFCR, sc->sc_rfcr);
1.101 perry 3304: }
1.29 thorpej 3305:
3306: /*
3307: * sip_dp83820_mii_readreg: [mii interface function]
3308: *
3309: * Read a PHY register on the MII of the DP83820.
3310: */
1.95 thorpej 3311: static int
1.115.4.1! ad 3312: sipcom_dp83820_mii_readreg(struct device *self, int phy, int reg)
1.29 thorpej 3313: {
1.63 thorpej 3314: struct sip_softc *sc = (void *) self;
3315:
3316: if (sc->sc_cfg & CFG_TBI_EN) {
3317: bus_addr_t tbireg;
3318: int rv;
3319:
3320: if (phy != 0)
3321: return (0);
3322:
3323: switch (reg) {
3324: case MII_BMCR: tbireg = SIP_TBICR; break;
3325: case MII_BMSR: tbireg = SIP_TBISR; break;
3326: case MII_ANAR: tbireg = SIP_TANAR; break;
3327: case MII_ANLPAR: tbireg = SIP_TANLPAR; break;
3328: case MII_ANER: tbireg = SIP_TANER; break;
1.64 thorpej 3329: case MII_EXTSR:
3330: /*
3331: * Don't even bother reading the TESR register.
3332: * The manual documents that the device has
3333: * 1000baseX full/half capability, but the
3334: * register itself seems read back 0 on some
3335: * boards. Just hard-code the result.
3336: */
3337: return (EXTSR_1000XFDX|EXTSR_1000XHDX);
3338:
1.63 thorpej 3339: default:
3340: return (0);
3341: }
3342:
3343: rv = bus_space_read_4(sc->sc_st, sc->sc_sh, tbireg) & 0xffff;
3344: if (tbireg == SIP_TBISR) {
3345: /* LINK and ACOMP are switched! */
3346: int val = rv;
3347:
3348: rv = 0;
3349: if (val & TBISR_MR_LINK_STATUS)
3350: rv |= BMSR_LINK;
3351: if (val & TBISR_MR_AN_COMPLETE)
3352: rv |= BMSR_ACOMP;
1.64 thorpej 3353:
3354: /*
3355: * The manual claims this register reads back 0
3356: * on hard and soft reset. But we want to let
3357: * the gentbi driver know that we support auto-
3358: * negotiation, so hard-code this bit in the
3359: * result.
3360: */
1.69 thorpej 3361: rv |= BMSR_ANEG | BMSR_EXTSTAT;
1.63 thorpej 3362: }
3363:
3364: return (rv);
3365: }
1.29 thorpej 3366:
1.115.4.1! ad 3367: return mii_bitbang_readreg(self, &sipcom_mii_bitbang_ops, phy, reg);
1.29 thorpej 3368: }
3369:
3370: /*
3371: * sip_dp83820_mii_writereg: [mii interface function]
3372: *
3373: * Write a PHY register on the MII of the DP83820.
3374: */
1.95 thorpej 3375: static void
1.115.4.1! ad 3376: sipcom_dp83820_mii_writereg(struct device *self, int phy, int reg, int val)
1.29 thorpej 3377: {
1.63 thorpej 3378: struct sip_softc *sc = (void *) self;
3379:
3380: if (sc->sc_cfg & CFG_TBI_EN) {
3381: bus_addr_t tbireg;
3382:
3383: if (phy != 0)
3384: return;
3385:
3386: switch (reg) {
3387: case MII_BMCR: tbireg = SIP_TBICR; break;
3388: case MII_ANAR: tbireg = SIP_TANAR; break;
3389: case MII_ANLPAR: tbireg = SIP_TANLPAR; break;
3390: default:
3391: return;
3392: }
3393:
3394: bus_space_write_4(sc->sc_st, sc->sc_sh, tbireg, val);
3395: return;
3396: }
1.29 thorpej 3397:
1.115.4.1! ad 3398: mii_bitbang_writereg(self, &sipcom_mii_bitbang_ops, phy, reg, val);
1.29 thorpej 3399: }
3400:
3401: /*
1.88 thorpej 3402: * sip_dp83820_mii_statchg: [mii interface function]
1.29 thorpej 3403: *
3404: * Callback from MII layer when media changes.
3405: */
1.95 thorpej 3406: static void
1.115.4.1! ad 3407: sipcom_dp83820_mii_statchg(struct device *self)
1.29 thorpej 3408: {
3409: struct sip_softc *sc = (struct sip_softc *) self;
1.89 thorpej 3410: struct mii_data *mii = &sc->sc_mii;
3411: u_int32_t cfg, pcr;
3412:
3413: /*
3414: * Get flow control negotiation result.
3415: */
3416: if (IFM_SUBTYPE(mii->mii_media.ifm_cur->ifm_media) == IFM_AUTO &&
3417: (mii->mii_media_active & IFM_ETH_FMASK) != sc->sc_flowflags) {
3418: sc->sc_flowflags = mii->mii_media_active & IFM_ETH_FMASK;
3419: mii->mii_media_active &= ~IFM_ETH_FMASK;
3420: }
1.29 thorpej 3421:
3422: /*
3423: * Update TXCFG for full-duplex operation.
3424: */
1.89 thorpej 3425: if ((mii->mii_media_active & IFM_FDX) != 0)
1.29 thorpej 3426: sc->sc_txcfg |= (TXCFG_CSI | TXCFG_HBI);
3427: else
3428: sc->sc_txcfg &= ~(TXCFG_CSI | TXCFG_HBI);
3429:
3430: /*
3431: * Update RXCFG for full-duplex or loopback.
3432: */
1.89 thorpej 3433: if ((mii->mii_media_active & IFM_FDX) != 0 ||
3434: IFM_SUBTYPE(mii->mii_media_active) == IFM_LOOP)
1.29 thorpej 3435: sc->sc_rxcfg |= RXCFG_ATX;
3436: else
3437: sc->sc_rxcfg &= ~RXCFG_ATX;
3438:
3439: /*
3440: * Update CFG for MII/GMII.
3441: */
3442: if (sc->sc_ethercom.ec_if.if_baudrate == IF_Mbps(1000))
3443: cfg = sc->sc_cfg | CFG_MODE_1000;
3444: else
3445: cfg = sc->sc_cfg;
3446:
3447: /*
1.89 thorpej 3448: * 802.3x flow control.
1.29 thorpej 3449: */
1.89 thorpej 3450: pcr = 0;
3451: if (sc->sc_flowflags & IFM_FLOW) {
3452: if (sc->sc_flowflags & IFM_ETH_TXPAUSE)
3453: pcr |= sc->sc_rx_flow_thresh;
3454: if (sc->sc_flowflags & IFM_ETH_RXPAUSE)
1.93 thorpej 3455: pcr |= PCR_PSEN | PCR_PS_MCAST;
1.89 thorpej 3456: }
1.29 thorpej 3457:
3458: bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_CFG, cfg);
1.115.4.1! ad 3459: bus_space_write_4(sc->sc_st, sc->sc_sh, sc->sc_regs.r_txcfg,
! 3460: sc->sc_txcfg);
! 3461: bus_space_write_4(sc->sc_st, sc->sc_sh, sc->sc_regs.r_rxcfg,
! 3462: sc->sc_rxcfg);
1.89 thorpej 3463: bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_NS_PCR, pcr);
1.15 thorpej 3464: }
3465:
3466: /*
1.86 cube 3467: * sip_mii_bitbang_read: [mii bit-bang interface function]
1.29 thorpej 3468: *
3469: * Read the MII serial port for the MII bit-bang module.
3470: */
1.95 thorpej 3471: static u_int32_t
1.115.4.1! ad 3472: sipcom_mii_bitbang_read(struct device *self)
1.29 thorpej 3473: {
3474: struct sip_softc *sc = (void *) self;
3475:
3476: return (bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_EROMAR));
3477: }
3478:
3479: /*
1.86 cube 3480: * sip_mii_bitbang_write: [mii big-bang interface function]
1.29 thorpej 3481: *
3482: * Write the MII serial port for the MII bit-bang module.
3483: */
1.95 thorpej 3484: static void
1.115.4.1! ad 3485: sipcom_mii_bitbang_write(struct device *self, u_int32_t val)
1.29 thorpej 3486: {
3487: struct sip_softc *sc = (void *) self;
3488:
3489: bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_EROMAR, val);
3490: }
1.84 cube 3491:
1.29 thorpej 3492: /*
1.15 thorpej 3493: * sip_sis900_mii_readreg: [mii interface function]
1.1 thorpej 3494: *
3495: * Read a PHY register on the MII.
3496: */
1.95 thorpej 3497: static int
1.115.4.1! ad 3498: sipcom_sis900_mii_readreg(struct device *self, int phy, int reg)
1.1 thorpej 3499: {
3500: struct sip_softc *sc = (struct sip_softc *) self;
1.86 cube 3501: u_int32_t enphy;
1.1 thorpej 3502:
3503: /*
1.86 cube 3504: * The PHY of recent SiS chipsets is accessed through bitbang
3505: * operations.
1.1 thorpej 3506: */
1.91 fair 3507: if (sc->sc_model->sip_product == PCI_PRODUCT_SIS_900)
1.115.4.1! ad 3508: return mii_bitbang_readreg(self, &sipcom_mii_bitbang_ops,
! 3509: phy, reg);
1.84 cube 3510:
1.91 fair 3511: #ifndef SIS900_MII_RESTRICT
1.84 cube 3512: /*
1.86 cube 3513: * The SiS 900 has only an internal PHY on the MII. Only allow
3514: * MII address 0.
1.84 cube 3515: */
1.86 cube 3516: if (sc->sc_model->sip_product == PCI_PRODUCT_SIS_900 && phy != 0)
3517: return (0);
1.91 fair 3518: #endif
1.84 cube 3519:
1.86 cube 3520: bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_ENPHY,
3521: (phy << ENPHY_PHYADDR_SHIFT) | (reg << ENPHY_REGADDR_SHIFT) |
3522: ENPHY_RWCMD | ENPHY_ACCESS);
3523: do {
3524: enphy = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_ENPHY);
3525: } while (enphy & ENPHY_ACCESS);
3526: return ((enphy & ENPHY_PHYDATA) >> ENPHY_DATA_SHIFT);
1.1 thorpej 3527: }
3528:
3529: /*
1.15 thorpej 3530: * sip_sis900_mii_writereg: [mii interface function]
1.1 thorpej 3531: *
3532: * Write a PHY register on the MII.
3533: */
1.95 thorpej 3534: static void
1.115.4.1! ad 3535: sipcom_sis900_mii_writereg(struct device *self, int phy, int reg, int val)
1.1 thorpej 3536: {
3537: struct sip_softc *sc = (struct sip_softc *) self;
3538: u_int32_t enphy;
1.86 cube 3539:
1.91 fair 3540: if (sc->sc_model->sip_product == PCI_PRODUCT_SIS_900) {
1.115.4.1! ad 3541: mii_bitbang_writereg(self, &sipcom_mii_bitbang_ops,
1.86 cube 3542: phy, reg, val);
3543: return;
3544: }
1.1 thorpej 3545:
1.91 fair 3546: #ifndef SIS900_MII_RESTRICT
1.1 thorpej 3547: /*
3548: * The SiS 900 has only an internal PHY on the MII. Only allow
3549: * MII address 0.
3550: */
1.86 cube 3551: if (sc->sc_model->sip_product == PCI_PRODUCT_SIS_900 && phy != 0)
1.1 thorpej 3552: return;
1.91 fair 3553: #endif
1.84 cube 3554:
1.86 cube 3555: bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_ENPHY,
3556: (val << ENPHY_DATA_SHIFT) | (phy << ENPHY_PHYADDR_SHIFT) |
3557: (reg << ENPHY_REGADDR_SHIFT) | ENPHY_ACCESS);
3558: do {
3559: enphy = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_ENPHY);
3560: } while (enphy & ENPHY_ACCESS);
1.1 thorpej 3561: }
3562:
3563: /*
1.15 thorpej 3564: * sip_sis900_mii_statchg: [mii interface function]
1.1 thorpej 3565: *
3566: * Callback from MII layer when media changes.
3567: */
1.95 thorpej 3568: static void
1.115.4.1! ad 3569: sipcom_sis900_mii_statchg(struct device *self)
1.1 thorpej 3570: {
3571: struct sip_softc *sc = (struct sip_softc *) self;
1.89 thorpej 3572: struct mii_data *mii = &sc->sc_mii;
1.1 thorpej 3573: u_int32_t flowctl;
3574:
3575: /*
1.89 thorpej 3576: * Get flow control negotiation result.
3577: */
3578: if (IFM_SUBTYPE(mii->mii_media.ifm_cur->ifm_media) == IFM_AUTO &&
3579: (mii->mii_media_active & IFM_ETH_FMASK) != sc->sc_flowflags) {
3580: sc->sc_flowflags = mii->mii_media_active & IFM_ETH_FMASK;
3581: mii->mii_media_active &= ~IFM_ETH_FMASK;
3582: }
3583:
3584: /*
1.1 thorpej 3585: * Update TXCFG for full-duplex operation.
3586: */
1.89 thorpej 3587: if ((mii->mii_media_active & IFM_FDX) != 0)
1.1 thorpej 3588: sc->sc_txcfg |= (TXCFG_CSI | TXCFG_HBI);
3589: else
3590: sc->sc_txcfg &= ~(TXCFG_CSI | TXCFG_HBI);
3591:
3592: /*
3593: * Update RXCFG for full-duplex or loopback.
3594: */
1.89 thorpej 3595: if ((mii->mii_media_active & IFM_FDX) != 0 ||
3596: IFM_SUBTYPE(mii->mii_media_active) == IFM_LOOP)
1.1 thorpej 3597: sc->sc_rxcfg |= RXCFG_ATX;
3598: else
3599: sc->sc_rxcfg &= ~RXCFG_ATX;
3600:
3601: /*
3602: * Update IMR for use of 802.3x flow control.
3603: */
1.89 thorpej 3604: if (sc->sc_flowflags & IFM_FLOW) {
1.1 thorpej 3605: sc->sc_imr |= (ISR_PAUSE_END|ISR_PAUSE_ST);
3606: flowctl = FLOWCTL_FLOWEN;
3607: } else {
3608: sc->sc_imr &= ~(ISR_PAUSE_END|ISR_PAUSE_ST);
3609: flowctl = 0;
3610: }
3611:
1.115.4.1! ad 3612: bus_space_write_4(sc->sc_st, sc->sc_sh, sc->sc_regs.r_txcfg,
! 3613: sc->sc_txcfg);
! 3614: bus_space_write_4(sc->sc_st, sc->sc_sh, sc->sc_regs.r_rxcfg,
! 3615: sc->sc_rxcfg);
1.1 thorpej 3616: bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_IMR, sc->sc_imr);
3617: bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_FLOWCTL, flowctl);
1.15 thorpej 3618: }
3619:
3620: /*
3621: * sip_dp83815_mii_readreg: [mii interface function]
3622: *
3623: * Read a PHY register on the MII.
3624: */
1.95 thorpej 3625: static int
1.115.4.1! ad 3626: sipcom_dp83815_mii_readreg(struct device *self, int phy, int reg)
1.15 thorpej 3627: {
3628: struct sip_softc *sc = (struct sip_softc *) self;
3629: u_int32_t val;
3630:
3631: /*
3632: * The DP83815 only has an internal PHY. Only allow
3633: * MII address 0.
3634: */
3635: if (phy != 0)
3636: return (0);
3637:
3638: /*
3639: * Apparently, after a reset, the DP83815 can take a while
3640: * to respond. During this recovery period, the BMSR returns
3641: * a value of 0. Catch this -- it's not supposed to happen
3642: * (the BMSR has some hardcoded-to-1 bits), and wait for the
3643: * PHY to come back to life.
3644: *
3645: * This works out because the BMSR is the first register
3646: * read during the PHY probe process.
3647: */
3648: do {
3649: val = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_NS_PHY(reg));
3650: } while (reg == MII_BMSR && val == 0);
3651:
3652: return (val & 0xffff);
3653: }
3654:
3655: /*
3656: * sip_dp83815_mii_writereg: [mii interface function]
3657: *
3658: * Write a PHY register to the MII.
3659: */
1.95 thorpej 3660: static void
1.115.4.1! ad 3661: sipcom_dp83815_mii_writereg(struct device *self, int phy, int reg, int val)
1.15 thorpej 3662: {
3663: struct sip_softc *sc = (struct sip_softc *) self;
3664:
3665: /*
3666: * The DP83815 only has an internal PHY. Only allow
3667: * MII address 0.
3668: */
3669: if (phy != 0)
3670: return;
3671:
3672: bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_NS_PHY(reg), val);
3673: }
3674:
3675: /*
3676: * sip_dp83815_mii_statchg: [mii interface function]
3677: *
3678: * Callback from MII layer when media changes.
3679: */
1.95 thorpej 3680: static void
1.115.4.1! ad 3681: sipcom_dp83815_mii_statchg(struct device *self)
1.15 thorpej 3682: {
3683: struct sip_softc *sc = (struct sip_softc *) self;
3684:
3685: /*
3686: * Update TXCFG for full-duplex operation.
3687: */
3688: if ((sc->sc_mii.mii_media_active & IFM_FDX) != 0)
3689: sc->sc_txcfg |= (TXCFG_CSI | TXCFG_HBI);
3690: else
3691: sc->sc_txcfg &= ~(TXCFG_CSI | TXCFG_HBI);
3692:
3693: /*
3694: * Update RXCFG for full-duplex or loopback.
3695: */
3696: if ((sc->sc_mii.mii_media_active & IFM_FDX) != 0 ||
3697: IFM_SUBTYPE(sc->sc_mii.mii_media_active) == IFM_LOOP)
3698: sc->sc_rxcfg |= RXCFG_ATX;
3699: else
3700: sc->sc_rxcfg &= ~RXCFG_ATX;
3701:
3702: /*
3703: * XXX 802.3x flow control.
3704: */
3705:
1.115.4.1! ad 3706: bus_space_write_4(sc->sc_st, sc->sc_sh, sc->sc_regs.r_txcfg,
! 3707: sc->sc_txcfg);
! 3708: bus_space_write_4(sc->sc_st, sc->sc_sh, sc->sc_regs.r_rxcfg,
! 3709: sc->sc_rxcfg);
1.78 thorpej 3710:
3711: /*
3712: * Some DP83815s experience problems when used with short
3713: * (< 30m/100ft) Ethernet cables in 100BaseTX mode. This
3714: * sequence adjusts the DSP's signal attenuation to fix the
3715: * problem.
3716: */
3717: if (IFM_SUBTYPE(sc->sc_mii.mii_media_active) == IFM_100_TX) {
3718: uint32_t reg;
3719:
3720: bus_space_write_4(sc->sc_st, sc->sc_sh, 0x00cc, 0x0001);
3721:
3722: reg = bus_space_read_4(sc->sc_st, sc->sc_sh, 0x00f4);
3723: reg &= 0x0fff;
3724: bus_space_write_4(sc->sc_st, sc->sc_sh, 0x00f4, reg | 0x1000);
3725: delay(100);
3726: reg = bus_space_read_4(sc->sc_st, sc->sc_sh, 0x00fc);
3727: reg &= 0x00ff;
3728: if ((reg & 0x0080) == 0 || (reg >= 0x00d8)) {
3729: bus_space_write_4(sc->sc_st, sc->sc_sh, 0x00fc,
3730: 0x00e8);
3731: reg = bus_space_read_4(sc->sc_st, sc->sc_sh, 0x00f4);
3732: bus_space_write_4(sc->sc_st, sc->sc_sh, 0x00f4,
3733: reg | 0x20);
3734: }
3735:
3736: bus_space_write_4(sc->sc_st, sc->sc_sh, 0x00cc, 0);
3737: }
1.25 briggs 3738: }
1.29 thorpej 3739:
1.95 thorpej 3740: static void
1.115.4.1! ad 3741: sipcom_dp83820_read_macaddr(struct sip_softc *sc,
1.110 christos 3742: const struct pci_attach_args *pa, u_int8_t *enaddr)
1.29 thorpej 3743: {
3744: u_int16_t eeprom_data[SIP_DP83820_EEPROM_LENGTH / 2];
3745: u_int8_t cksum, *e, match;
3746: int i;
3747:
3748: /*
3749: * EEPROM data format for the DP83820 can be found in
3750: * the DP83820 manual, section 4.2.4.
3751: */
1.25 briggs 3752:
1.115.4.1! ad 3753: sipcom_read_eeprom(sc, 0, __arraycount(eeprom_data), eeprom_data);
1.29 thorpej 3754:
3755: match = eeprom_data[SIP_DP83820_EEPROM_CHECKSUM / 2] >> 8;
3756: match = ~(match - 1);
3757:
3758: cksum = 0x55;
3759: e = (u_int8_t *) eeprom_data;
3760: for (i = 0; i < SIP_DP83820_EEPROM_CHECKSUM; i++)
3761: cksum += *e++;
3762:
3763: if (cksum != match)
3764: printf("%s: Checksum (%x) mismatch (%x)",
3765: sc->sc_dev.dv_xname, cksum, match);
3766:
3767: enaddr[0] = eeprom_data[SIP_DP83820_EEPROM_PMATCH2 / 2] & 0xff;
3768: enaddr[1] = eeprom_data[SIP_DP83820_EEPROM_PMATCH2 / 2] >> 8;
3769: enaddr[2] = eeprom_data[SIP_DP83820_EEPROM_PMATCH1 / 2] & 0xff;
3770: enaddr[3] = eeprom_data[SIP_DP83820_EEPROM_PMATCH1 / 2] >> 8;
3771: enaddr[4] = eeprom_data[SIP_DP83820_EEPROM_PMATCH0 / 2] & 0xff;
3772: enaddr[5] = eeprom_data[SIP_DP83820_EEPROM_PMATCH0 / 2] >> 8;
3773: }
1.115.4.1! ad 3774:
1.84 cube 3775: static void
1.115.4.1! ad 3776: sipcom_sis900_eeprom_delay(struct sip_softc *sc)
1.84 cube 3777: {
3778: int i;
3779:
3780: /*
3781: * FreeBSD goes from (300/33)+1 [10] to 0. There must be
3782: * a reason, but I don't know it.
3783: */
3784: for (i = 0; i < 10; i++)
3785: bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_CR);
3786: }
3787:
1.95 thorpej 3788: static void
1.115.4.1! ad 3789: sipcom_sis900_read_macaddr(struct sip_softc *sc,
1.110 christos 3790: const struct pci_attach_args *pa, u_int8_t *enaddr)
1.25 briggs 3791: {
3792: u_int16_t myea[ETHER_ADDR_LEN / 2];
3793:
1.50 briggs 3794: switch (sc->sc_rev) {
1.44 thorpej 3795: case SIS_REV_630S:
3796: case SIS_REV_630E:
3797: case SIS_REV_630EA1:
1.51 briggs 3798: case SIS_REV_630ET:
1.45 thorpej 3799: case SIS_REV_635:
1.44 thorpej 3800: /*
3801: * The MAC address for the on-board Ethernet of
3802: * the SiS 630 chipset is in the NVRAM. Kick
3803: * the chip into re-loading it from NVRAM, and
3804: * read the MAC address out of the filter registers.
3805: */
3806: bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_CR, CR_RLD);
3807:
3808: bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_RFCR,
3809: RFCR_RFADDR_NODE0);
3810: myea[0] = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_RFDR) &
3811: 0xffff;
3812:
3813: bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_RFCR,
3814: RFCR_RFADDR_NODE2);
3815: myea[1] = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_RFDR) &
3816: 0xffff;
3817:
3818: bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_RFCR,
3819: RFCR_RFADDR_NODE4);
3820: myea[2] = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_RFDR) &
3821: 0xffff;
3822: break;
1.84 cube 3823:
3824: case SIS_REV_960:
3825: {
1.86 cube 3826: #define SIS_SET_EROMAR(x,y) bus_space_write_4(x->sc_st, x->sc_sh, SIP_EROMAR, \
3827: bus_space_read_4(x->sc_st, x->sc_sh, SIP_EROMAR) | (y))
3828:
3829: #define SIS_CLR_EROMAR(x,y) bus_space_write_4(x->sc_st, x->sc_sh, SIP_EROMAR, \
3830: bus_space_read_4(x->sc_st, x->sc_sh, SIP_EROMAR) & ~(y))
3831:
1.84 cube 3832: int waittime, i;
3833:
3834: /* Allow to read EEPROM from LAN. It is shared
3835: * between a 1394 controller and the NIC and each
3836: * time we access it, we need to set SIS_EECMD_REQ.
3837: */
3838: SIS_SET_EROMAR(sc, EROMAR_REQ);
3839:
3840: for (waittime = 0; waittime < 1000; waittime++) { /* 1 ms max */
3841: /* Force EEPROM to idle state. */
3842:
3843: /*
3844: * XXX-cube This is ugly. I'll look for docs about it.
3845: */
3846: SIS_SET_EROMAR(sc, EROMAR_EECS);
1.115.4.1! ad 3847: sipcom_sis900_eeprom_delay(sc);
1.84 cube 3848: for (i = 0; i <= 25; i++) { /* Yes, 26 times. */
3849: SIS_SET_EROMAR(sc, EROMAR_EESK);
1.115.4.1! ad 3850: sipcom_sis900_eeprom_delay(sc);
1.84 cube 3851: SIS_CLR_EROMAR(sc, EROMAR_EESK);
1.115.4.1! ad 3852: sipcom_sis900_eeprom_delay(sc);
1.84 cube 3853: }
3854: SIS_CLR_EROMAR(sc, EROMAR_EECS);
1.115.4.1! ad 3855: sipcom_sis900_eeprom_delay(sc);
1.84 cube 3856: bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_EROMAR, 0);
3857:
3858: if (bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_EROMAR) & EROMAR_GNT) {
1.115.4.1! ad 3859: sipcom_read_eeprom(sc, SIP_EEPROM_ETHERNET_ID0 >> 1,
1.84 cube 3860: sizeof(myea) / sizeof(myea[0]), myea);
3861: break;
3862: }
3863: DELAY(1);
3864: }
3865:
3866: /*
3867: * Set SIS_EECTL_CLK to high, so a other master
3868: * can operate on the i2c bus.
3869: */
3870: SIS_SET_EROMAR(sc, EROMAR_EESK);
3871:
3872: /* Refuse EEPROM access by LAN */
3873: SIS_SET_EROMAR(sc, EROMAR_DONE);
3874: } break;
1.44 thorpej 3875:
3876: default:
1.115.4.1! ad 3877: sipcom_read_eeprom(sc, SIP_EEPROM_ETHERNET_ID0 >> 1,
1.44 thorpej 3878: sizeof(myea) / sizeof(myea[0]), myea);
3879: }
1.25 briggs 3880:
3881: enaddr[0] = myea[0] & 0xff;
3882: enaddr[1] = myea[0] >> 8;
3883: enaddr[2] = myea[1] & 0xff;
3884: enaddr[3] = myea[1] >> 8;
3885: enaddr[4] = myea[2] & 0xff;
3886: enaddr[5] = myea[2] >> 8;
3887: }
3888:
1.29 thorpej 3889: /* Table and macro to bit-reverse an octet. */
3890: static const u_int8_t bbr4[] = {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15};
1.25 briggs 3891: #define bbr(v) ((bbr4[(v)&0xf] << 4) | bbr4[((v)>>4) & 0xf])
3892:
1.95 thorpej 3893: static void
1.115.4.1! ad 3894: sipcom_dp83815_read_macaddr(struct sip_softc *sc,
1.110 christos 3895: const struct pci_attach_args *pa, u_int8_t *enaddr)
1.25 briggs 3896: {
3897: u_int16_t eeprom_data[SIP_DP83815_EEPROM_LENGTH / 2], *ea;
3898: u_int8_t cksum, *e, match;
3899: int i;
3900:
1.115.4.1! ad 3901: sipcom_read_eeprom(sc, 0, sizeof(eeprom_data) /
1.29 thorpej 3902: sizeof(eeprom_data[0]), eeprom_data);
1.25 briggs 3903:
3904: match = eeprom_data[SIP_DP83815_EEPROM_CHECKSUM/2] >> 8;
3905: match = ~(match - 1);
3906:
3907: cksum = 0x55;
3908: e = (u_int8_t *) eeprom_data;
3909: for (i=0 ; i<SIP_DP83815_EEPROM_CHECKSUM ; i++) {
3910: cksum += *e++;
3911: }
3912: if (cksum != match) {
3913: printf("%s: Checksum (%x) mismatch (%x)",
3914: sc->sc_dev.dv_xname, cksum, match);
3915: }
3916:
3917: /*
3918: * Unrolled because it makes slightly more sense this way.
3919: * The DP83815 stores the MAC address in bit 0 of word 6
3920: * through bit 15 of word 8.
3921: */
3922: ea = &eeprom_data[6];
3923: enaddr[0] = ((*ea & 0x1) << 7);
3924: ea++;
3925: enaddr[0] |= ((*ea & 0xFE00) >> 9);
3926: enaddr[1] = ((*ea & 0x1FE) >> 1);
3927: enaddr[2] = ((*ea & 0x1) << 7);
3928: ea++;
3929: enaddr[2] |= ((*ea & 0xFE00) >> 9);
3930: enaddr[3] = ((*ea & 0x1FE) >> 1);
3931: enaddr[4] = ((*ea & 0x1) << 7);
3932: ea++;
3933: enaddr[4] |= ((*ea & 0xFE00) >> 9);
3934: enaddr[5] = ((*ea & 0x1FE) >> 1);
3935:
3936: /*
3937: * In case that's not weird enough, we also need to reverse
3938: * the bits in each byte. This all actually makes more sense
3939: * if you think about the EEPROM storage as an array of bits
3940: * being shifted into bytes, but that's not how we're looking
3941: * at it here...
3942: */
1.28 thorpej 3943: for (i = 0; i < 6 ;i++)
1.25 briggs 3944: enaddr[i] = bbr(enaddr[i]);
1.1 thorpej 3945: }
3946:
3947: /*
3948: * sip_mediastatus: [ifmedia interface function]
3949: *
3950: * Get the current interface media status.
3951: */
1.95 thorpej 3952: static void
1.115.4.1! ad 3953: sipcom_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
1.1 thorpej 3954: {
3955: struct sip_softc *sc = ifp->if_softc;
3956:
3957: mii_pollstat(&sc->sc_mii);
3958: ifmr->ifm_status = sc->sc_mii.mii_media_status;
1.89 thorpej 3959: ifmr->ifm_active = (sc->sc_mii.mii_media_active & ~IFM_ETH_FMASK) |
3960: sc->sc_flowflags;
1.1 thorpej 3961: }
3962:
3963: /*
3964: * sip_mediachange: [ifmedia interface function]
3965: *
3966: * Set hardware to newly-selected media.
3967: */
1.95 thorpej 3968: static int
1.115.4.1! ad 3969: sipcom_mediachange(struct ifnet *ifp)
1.1 thorpej 3970: {
3971: struct sip_softc *sc = ifp->if_softc;
3972:
3973: if (ifp->if_flags & IFF_UP)
3974: mii_mediachg(&sc->sc_mii);
3975: return (0);
3976: }
CVSweb <webmaster@jp.NetBSD.org>