| @@ -1,1078 +1,1078 @@ | | | @@ -1,1078 +1,1078 @@ |
1 | /* $NetBSD: if_wm.c,v 1.254 2013/06/11 10:07:09 msaitoh Exp $ */ | | 1 | /* $NetBSD: if_wm.c,v 1.255 2013/06/11 14:39:35 msaitoh Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc. | | 4 | * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Written by Jason R. Thorpe for Wasabi Systems, Inc. | | 7 | * Written by Jason R. Thorpe for Wasabi Systems, Inc. |
8 | * | | 8 | * |
9 | * Redistribution and use in source and binary forms, with or without | | 9 | * Redistribution and use in source and binary forms, with or without |
10 | * modification, are permitted provided that the following conditions | | 10 | * modification, are permitted provided that the following conditions |
11 | * are met: | | 11 | * are met: |
12 | * 1. Redistributions of source code must retain the above copyright | | 12 | * 1. Redistributions of source code must retain the above copyright |
13 | * notice, this list of conditions and the following disclaimer. | | 13 | * notice, this list of conditions and the following disclaimer. |
14 | * 2. Redistributions in binary form must reproduce the above copyright | | 14 | * 2. Redistributions in binary form must reproduce the above copyright |
15 | * notice, this list of conditions and the following disclaimer in the | | 15 | * notice, this list of conditions and the following disclaimer in the |
16 | * documentation and/or other materials provided with the distribution. | | 16 | * documentation and/or other materials provided with the distribution. |
17 | * 3. All advertising materials mentioning features or use of this software | | 17 | * 3. All advertising materials mentioning features or use of this software |
18 | * must display the following acknowledgement: | | 18 | * must display the following acknowledgement: |
19 | * This product includes software developed for the NetBSD Project by | | 19 | * This product includes software developed for the NetBSD Project by |
20 | * Wasabi Systems, Inc. | | 20 | * Wasabi Systems, Inc. |
21 | * 4. The name of Wasabi Systems, Inc. may not be used to endorse | | 21 | * 4. The name of Wasabi Systems, Inc. may not be used to endorse |
22 | * or promote products derived from this software without specific prior | | 22 | * or promote products derived from this software without specific prior |
23 | * written permission. | | 23 | * written permission. |
24 | * | | 24 | * |
25 | * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND | | 25 | * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND |
26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
27 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 27 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
28 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC | | 28 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC |
29 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 29 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
30 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 30 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
31 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 31 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
32 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 32 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
33 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 33 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
34 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 34 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
35 | * POSSIBILITY OF SUCH DAMAGE. | | 35 | * POSSIBILITY OF SUCH DAMAGE. |
36 | */ | | 36 | */ |
37 | | | 37 | |
38 | /******************************************************************************* | | 38 | /******************************************************************************* |
39 | | | 39 | |
40 | Copyright (c) 2001-2005, Intel Corporation | | 40 | Copyright (c) 2001-2005, Intel Corporation |
41 | All rights reserved. | | 41 | All rights reserved. |
42 | | | 42 | |
43 | Redistribution and use in source and binary forms, with or without | | 43 | Redistribution and use in source and binary forms, with or without |
44 | modification, are permitted provided that the following conditions are met: | | 44 | modification, are permitted provided that the following conditions are met: |
45 | | | 45 | |
46 | 1. Redistributions of source code must retain the above copyright notice, | | 46 | 1. Redistributions of source code must retain the above copyright notice, |
47 | this list of conditions and the following disclaimer. | | 47 | this list of conditions and the following disclaimer. |
48 | | | 48 | |
49 | 2. Redistributions in binary form must reproduce the above copyright | | 49 | 2. Redistributions in binary form must reproduce the above copyright |
50 | notice, this list of conditions and the following disclaimer in the | | 50 | notice, this list of conditions and the following disclaimer in the |
51 | documentation and/or other materials provided with the distribution. | | 51 | documentation and/or other materials provided with the distribution. |
52 | | | 52 | |
53 | 3. Neither the name of the Intel Corporation nor the names of its | | 53 | 3. Neither the name of the Intel Corporation nor the names of its |
54 | contributors may be used to endorse or promote products derived from | | 54 | contributors may be used to endorse or promote products derived from |
55 | this software without specific prior written permission. | | 55 | this software without specific prior written permission. |
56 | | | 56 | |
57 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | | 57 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
58 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 58 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
59 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 59 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
60 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | | 60 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
61 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 61 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
62 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 62 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
63 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 63 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
64 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 64 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
65 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 65 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
66 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 66 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
67 | POSSIBILITY OF SUCH DAMAGE. | | 67 | POSSIBILITY OF SUCH DAMAGE. |
68 | | | 68 | |
69 | *******************************************************************************/ | | 69 | *******************************************************************************/ |
70 | /* | | 70 | /* |
71 | * Device driver for the Intel i8254x family of Gigabit Ethernet chips. | | 71 | * Device driver for the Intel i8254x family of Gigabit Ethernet chips. |
72 | * | | 72 | * |
73 | * TODO (in order of importance): | | 73 | * TODO (in order of importance): |
74 | * | | 74 | * |
75 | * - Rework how parameters are loaded from the EEPROM. | | 75 | * - Rework how parameters are loaded from the EEPROM. |
76 | */ | | 76 | */ |
77 | | | 77 | |
78 | #include <sys/cdefs.h> | | 78 | #include <sys/cdefs.h> |
79 | __KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.254 2013/06/11 10:07:09 msaitoh Exp $"); | | 79 | __KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.255 2013/06/11 14:39:35 msaitoh Exp $"); |
80 | | | 80 | |
81 | #include <sys/param.h> | | 81 | #include <sys/param.h> |
82 | #include <sys/systm.h> | | 82 | #include <sys/systm.h> |
83 | #include <sys/callout.h> | | 83 | #include <sys/callout.h> |
84 | #include <sys/mbuf.h> | | 84 | #include <sys/mbuf.h> |
85 | #include <sys/malloc.h> | | 85 | #include <sys/malloc.h> |
86 | #include <sys/kernel.h> | | 86 | #include <sys/kernel.h> |
87 | #include <sys/socket.h> | | 87 | #include <sys/socket.h> |
88 | #include <sys/ioctl.h> | | 88 | #include <sys/ioctl.h> |
89 | #include <sys/errno.h> | | 89 | #include <sys/errno.h> |
90 | #include <sys/device.h> | | 90 | #include <sys/device.h> |
91 | #include <sys/queue.h> | | 91 | #include <sys/queue.h> |
92 | #include <sys/syslog.h> | | 92 | #include <sys/syslog.h> |
93 | | | 93 | |
94 | #include <sys/rnd.h> | | 94 | #include <sys/rnd.h> |
95 | | | 95 | |
96 | #include <net/if.h> | | 96 | #include <net/if.h> |
97 | #include <net/if_dl.h> | | 97 | #include <net/if_dl.h> |
98 | #include <net/if_media.h> | | 98 | #include <net/if_media.h> |
99 | #include <net/if_ether.h> | | 99 | #include <net/if_ether.h> |
100 | | | 100 | |
101 | #include <net/bpf.h> | | 101 | #include <net/bpf.h> |
102 | | | 102 | |
103 | #include <netinet/in.h> /* XXX for struct ip */ | | 103 | #include <netinet/in.h> /* XXX for struct ip */ |
104 | #include <netinet/in_systm.h> /* XXX for struct ip */ | | 104 | #include <netinet/in_systm.h> /* XXX for struct ip */ |
105 | #include <netinet/ip.h> /* XXX for struct ip */ | | 105 | #include <netinet/ip.h> /* XXX for struct ip */ |
106 | #include <netinet/ip6.h> /* XXX for struct ip6_hdr */ | | 106 | #include <netinet/ip6.h> /* XXX for struct ip6_hdr */ |
107 | #include <netinet/tcp.h> /* XXX for struct tcphdr */ | | 107 | #include <netinet/tcp.h> /* XXX for struct tcphdr */ |
108 | | | 108 | |
109 | #include <sys/bus.h> | | 109 | #include <sys/bus.h> |
110 | #include <sys/intr.h> | | 110 | #include <sys/intr.h> |
111 | #include <machine/endian.h> | | 111 | #include <machine/endian.h> |
112 | | | 112 | |
113 | #include <dev/mii/mii.h> | | 113 | #include <dev/mii/mii.h> |
114 | #include <dev/mii/miivar.h> | | 114 | #include <dev/mii/miivar.h> |
115 | #include <dev/mii/miidevs.h> | | 115 | #include <dev/mii/miidevs.h> |
116 | #include <dev/mii/mii_bitbang.h> | | 116 | #include <dev/mii/mii_bitbang.h> |
117 | #include <dev/mii/ikphyreg.h> | | 117 | #include <dev/mii/ikphyreg.h> |
118 | #include <dev/mii/igphyreg.h> | | 118 | #include <dev/mii/igphyreg.h> |
119 | #include <dev/mii/igphyvar.h> | | 119 | #include <dev/mii/igphyvar.h> |
120 | #include <dev/mii/inbmphyreg.h> | | 120 | #include <dev/mii/inbmphyreg.h> |
121 | | | 121 | |
122 | #include <dev/pci/pcireg.h> | | 122 | #include <dev/pci/pcireg.h> |
123 | #include <dev/pci/pcivar.h> | | 123 | #include <dev/pci/pcivar.h> |
124 | #include <dev/pci/pcidevs.h> | | 124 | #include <dev/pci/pcidevs.h> |
125 | | | 125 | |
126 | #include <dev/pci/if_wmreg.h> | | 126 | #include <dev/pci/if_wmreg.h> |
127 | #include <dev/pci/if_wmvar.h> | | 127 | #include <dev/pci/if_wmvar.h> |
128 | | | 128 | |
129 | #ifdef WM_DEBUG | | 129 | #ifdef WM_DEBUG |
130 | #define WM_DEBUG_LINK 0x01 | | 130 | #define WM_DEBUG_LINK 0x01 |
131 | #define WM_DEBUG_TX 0x02 | | 131 | #define WM_DEBUG_TX 0x02 |
132 | #define WM_DEBUG_RX 0x04 | | 132 | #define WM_DEBUG_RX 0x04 |
133 | #define WM_DEBUG_GMII 0x08 | | 133 | #define WM_DEBUG_GMII 0x08 |
134 | #define WM_DEBUG_MANAGE 0x10 | | 134 | #define WM_DEBUG_MANAGE 0x10 |
135 | #define WM_DEBUG_NVM 0x20 | | 135 | #define WM_DEBUG_NVM 0x20 |
136 | int wm_debug = WM_DEBUG_TX | WM_DEBUG_RX | WM_DEBUG_LINK | WM_DEBUG_GMII | | 136 | int wm_debug = WM_DEBUG_TX | WM_DEBUG_RX | WM_DEBUG_LINK | WM_DEBUG_GMII |
137 | | WM_DEBUG_MANAGE | WM_DEBUG_NVM; | | 137 | | WM_DEBUG_MANAGE | WM_DEBUG_NVM; |
138 | | | 138 | |
139 | #define DPRINTF(x, y) if (wm_debug & (x)) printf y | | 139 | #define DPRINTF(x, y) if (wm_debug & (x)) printf y |
140 | #else | | 140 | #else |
141 | #define DPRINTF(x, y) /* nothing */ | | 141 | #define DPRINTF(x, y) /* nothing */ |
142 | #endif /* WM_DEBUG */ | | 142 | #endif /* WM_DEBUG */ |
143 | | | 143 | |
144 | /* | | 144 | /* |
145 | * Transmit descriptor list size. Due to errata, we can only have | | 145 | * Transmit descriptor list size. Due to errata, we can only have |
146 | * 256 hardware descriptors in the ring on < 82544, but we use 4096 | | 146 | * 256 hardware descriptors in the ring on < 82544, but we use 4096 |
147 | * on >= 82544. We tell the upper layers that they can queue a lot | | 147 | * on >= 82544. We tell the upper layers that they can queue a lot |
148 | * of packets, and we go ahead and manage up to 64 (16 for the i82547) | | 148 | * of packets, and we go ahead and manage up to 64 (16 for the i82547) |
149 | * of them at a time. | | 149 | * of them at a time. |
150 | * | | 150 | * |
151 | * We allow up to 256 (!) DMA segments per packet. Pathological packet | | 151 | * We allow up to 256 (!) DMA segments per packet. Pathological packet |
152 | * chains containing many small mbufs have been observed in zero-copy | | 152 | * chains containing many small mbufs have been observed in zero-copy |
153 | * situations with jumbo frames. | | 153 | * situations with jumbo frames. |
154 | */ | | 154 | */ |
155 | #define WM_NTXSEGS 256 | | 155 | #define WM_NTXSEGS 256 |
156 | #define WM_IFQUEUELEN 256 | | 156 | #define WM_IFQUEUELEN 256 |
157 | #define WM_TXQUEUELEN_MAX 64 | | 157 | #define WM_TXQUEUELEN_MAX 64 |
158 | #define WM_TXQUEUELEN_MAX_82547 16 | | 158 | #define WM_TXQUEUELEN_MAX_82547 16 |
159 | #define WM_TXQUEUELEN(sc) ((sc)->sc_txnum) | | 159 | #define WM_TXQUEUELEN(sc) ((sc)->sc_txnum) |
160 | #define WM_TXQUEUELEN_MASK(sc) (WM_TXQUEUELEN(sc) - 1) | | 160 | #define WM_TXQUEUELEN_MASK(sc) (WM_TXQUEUELEN(sc) - 1) |
161 | #define WM_TXQUEUE_GC(sc) (WM_TXQUEUELEN(sc) / 8) | | 161 | #define WM_TXQUEUE_GC(sc) (WM_TXQUEUELEN(sc) / 8) |
162 | #define WM_NTXDESC_82542 256 | | 162 | #define WM_NTXDESC_82542 256 |
163 | #define WM_NTXDESC_82544 4096 | | 163 | #define WM_NTXDESC_82544 4096 |
164 | #define WM_NTXDESC(sc) ((sc)->sc_ntxdesc) | | 164 | #define WM_NTXDESC(sc) ((sc)->sc_ntxdesc) |
165 | #define WM_NTXDESC_MASK(sc) (WM_NTXDESC(sc) - 1) | | 165 | #define WM_NTXDESC_MASK(sc) (WM_NTXDESC(sc) - 1) |
166 | #define WM_TXDESCSIZE(sc) (WM_NTXDESC(sc) * sizeof(wiseman_txdesc_t)) | | 166 | #define WM_TXDESCSIZE(sc) (WM_NTXDESC(sc) * sizeof(wiseman_txdesc_t)) |
167 | #define WM_NEXTTX(sc, x) (((x) + 1) & WM_NTXDESC_MASK(sc)) | | 167 | #define WM_NEXTTX(sc, x) (((x) + 1) & WM_NTXDESC_MASK(sc)) |
168 | #define WM_NEXTTXS(sc, x) (((x) + 1) & WM_TXQUEUELEN_MASK(sc)) | | 168 | #define WM_NEXTTXS(sc, x) (((x) + 1) & WM_TXQUEUELEN_MASK(sc)) |
169 | | | 169 | |
170 | #define WM_MAXTXDMA round_page(IP_MAXPACKET) /* for TSO */ | | 170 | #define WM_MAXTXDMA round_page(IP_MAXPACKET) /* for TSO */ |
171 | | | 171 | |
172 | /* | | 172 | /* |
173 | * Receive descriptor list size. We have one Rx buffer for normal | | 173 | * Receive descriptor list size. We have one Rx buffer for normal |
174 | * sized packets. Jumbo packets consume 5 Rx buffers for a full-sized | | 174 | * sized packets. Jumbo packets consume 5 Rx buffers for a full-sized |
175 | * packet. We allocate 256 receive descriptors, each with a 2k | | 175 | * packet. We allocate 256 receive descriptors, each with a 2k |
176 | * buffer (MCLBYTES), which gives us room for 50 jumbo packets. | | 176 | * buffer (MCLBYTES), which gives us room for 50 jumbo packets. |
177 | */ | | 177 | */ |
178 | #define WM_NRXDESC 256 | | 178 | #define WM_NRXDESC 256 |
179 | #define WM_NRXDESC_MASK (WM_NRXDESC - 1) | | 179 | #define WM_NRXDESC_MASK (WM_NRXDESC - 1) |
180 | #define WM_NEXTRX(x) (((x) + 1) & WM_NRXDESC_MASK) | | 180 | #define WM_NEXTRX(x) (((x) + 1) & WM_NRXDESC_MASK) |
181 | #define WM_PREVRX(x) (((x) - 1) & WM_NRXDESC_MASK) | | 181 | #define WM_PREVRX(x) (((x) - 1) & WM_NRXDESC_MASK) |
182 | | | 182 | |
183 | /* | | 183 | /* |
184 | * Control structures are DMA'd to the i82542 chip. We allocate them in | | 184 | * Control structures are DMA'd to the i82542 chip. We allocate them in |
185 | * a single clump that maps to a single DMA segment to make several things | | 185 | * a single clump that maps to a single DMA segment to make several things |
186 | * easier. | | 186 | * easier. |
187 | */ | | 187 | */ |
188 | struct wm_control_data_82544 { | | 188 | struct wm_control_data_82544 { |
189 | /* | | 189 | /* |
190 | * The receive descriptors. | | 190 | * The receive descriptors. |
191 | */ | | 191 | */ |
192 | wiseman_rxdesc_t wcd_rxdescs[WM_NRXDESC]; | | 192 | wiseman_rxdesc_t wcd_rxdescs[WM_NRXDESC]; |
193 | | | 193 | |
194 | /* | | 194 | /* |
195 | * The transmit descriptors. Put these at the end, because | | 195 | * The transmit descriptors. Put these at the end, because |
196 | * we might use a smaller number of them. | | 196 | * we might use a smaller number of them. |
197 | */ | | 197 | */ |
198 | union { | | 198 | union { |
199 | wiseman_txdesc_t wcdu_txdescs[WM_NTXDESC_82544]; | | 199 | wiseman_txdesc_t wcdu_txdescs[WM_NTXDESC_82544]; |
200 | nq_txdesc_t wcdu_nq_txdescs[WM_NTXDESC_82544]; | | 200 | nq_txdesc_t wcdu_nq_txdescs[WM_NTXDESC_82544]; |
201 | } wdc_u; | | 201 | } wdc_u; |
202 | }; | | 202 | }; |
203 | | | 203 | |
204 | struct wm_control_data_82542 { | | 204 | struct wm_control_data_82542 { |
205 | wiseman_rxdesc_t wcd_rxdescs[WM_NRXDESC]; | | 205 | wiseman_rxdesc_t wcd_rxdescs[WM_NRXDESC]; |
206 | wiseman_txdesc_t wcd_txdescs[WM_NTXDESC_82542]; | | 206 | wiseman_txdesc_t wcd_txdescs[WM_NTXDESC_82542]; |
207 | }; | | 207 | }; |
208 | | | 208 | |
209 | #define WM_CDOFF(x) offsetof(struct wm_control_data_82544, x) | | 209 | #define WM_CDOFF(x) offsetof(struct wm_control_data_82544, x) |
210 | #define WM_CDTXOFF(x) WM_CDOFF(wdc_u.wcdu_txdescs[(x)]) | | 210 | #define WM_CDTXOFF(x) WM_CDOFF(wdc_u.wcdu_txdescs[(x)]) |
211 | #define WM_CDRXOFF(x) WM_CDOFF(wcd_rxdescs[(x)]) | | 211 | #define WM_CDRXOFF(x) WM_CDOFF(wcd_rxdescs[(x)]) |
212 | | | 212 | |
213 | /* | | 213 | /* |
214 | * Software state for transmit jobs. | | 214 | * Software state for transmit jobs. |
215 | */ | | 215 | */ |
216 | struct wm_txsoft { | | 216 | struct wm_txsoft { |
217 | struct mbuf *txs_mbuf; /* head of our mbuf chain */ | | 217 | struct mbuf *txs_mbuf; /* head of our mbuf chain */ |
218 | bus_dmamap_t txs_dmamap; /* our DMA map */ | | 218 | bus_dmamap_t txs_dmamap; /* our DMA map */ |
219 | int txs_firstdesc; /* first descriptor in packet */ | | 219 | int txs_firstdesc; /* first descriptor in packet */ |
220 | int txs_lastdesc; /* last descriptor in packet */ | | 220 | int txs_lastdesc; /* last descriptor in packet */ |
221 | int txs_ndesc; /* # of descriptors used */ | | 221 | int txs_ndesc; /* # of descriptors used */ |
222 | }; | | 222 | }; |
223 | | | 223 | |
224 | /* | | 224 | /* |
225 | * Software state for receive buffers. Each descriptor gets a | | 225 | * Software state for receive buffers. Each descriptor gets a |
226 | * 2k (MCLBYTES) buffer and a DMA map. For packets which fill | | 226 | * 2k (MCLBYTES) buffer and a DMA map. For packets which fill |
227 | * more than one buffer, we chain them together. | | 227 | * more than one buffer, we chain them together. |
228 | */ | | 228 | */ |
229 | struct wm_rxsoft { | | 229 | struct wm_rxsoft { |
230 | struct mbuf *rxs_mbuf; /* head of our mbuf chain */ | | 230 | struct mbuf *rxs_mbuf; /* head of our mbuf chain */ |
231 | bus_dmamap_t rxs_dmamap; /* our DMA map */ | | 231 | bus_dmamap_t rxs_dmamap; /* our DMA map */ |
232 | }; | | 232 | }; |
233 | | | 233 | |
234 | #define WM_LINKUP_TIMEOUT 50 | | 234 | #define WM_LINKUP_TIMEOUT 50 |
235 | | | 235 | |
236 | static uint16_t swfwphysem[] = { | | 236 | static uint16_t swfwphysem[] = { |
237 | SWFW_PHY0_SM, | | 237 | SWFW_PHY0_SM, |
238 | SWFW_PHY1_SM, | | 238 | SWFW_PHY1_SM, |
239 | SWFW_PHY2_SM, | | 239 | SWFW_PHY2_SM, |
240 | SWFW_PHY3_SM | | 240 | SWFW_PHY3_SM |
241 | }; | | 241 | }; |
242 | | | 242 | |
243 | /* | | 243 | /* |
244 | * Software state per device. | | 244 | * Software state per device. |
245 | */ | | 245 | */ |
246 | struct wm_softc { | | 246 | struct wm_softc { |
247 | device_t sc_dev; /* generic device information */ | | 247 | device_t sc_dev; /* generic device information */ |
248 | bus_space_tag_t sc_st; /* bus space tag */ | | 248 | bus_space_tag_t sc_st; /* bus space tag */ |
249 | bus_space_handle_t sc_sh; /* bus space handle */ | | 249 | bus_space_handle_t sc_sh; /* bus space handle */ |
250 | bus_size_t sc_ss; /* bus space size */ | | 250 | bus_size_t sc_ss; /* bus space size */ |
251 | bus_space_tag_t sc_iot; /* I/O space tag */ | | 251 | bus_space_tag_t sc_iot; /* I/O space tag */ |
252 | bus_space_handle_t sc_ioh; /* I/O space handle */ | | 252 | bus_space_handle_t sc_ioh; /* I/O space handle */ |
253 | bus_size_t sc_ios; /* I/O space size */ | | 253 | bus_size_t sc_ios; /* I/O space size */ |
254 | bus_space_tag_t sc_flasht; /* flash registers space tag */ | | 254 | bus_space_tag_t sc_flasht; /* flash registers space tag */ |
255 | bus_space_handle_t sc_flashh; /* flash registers space handle */ | | 255 | bus_space_handle_t sc_flashh; /* flash registers space handle */ |
256 | bus_dma_tag_t sc_dmat; /* bus DMA tag */ | | 256 | bus_dma_tag_t sc_dmat; /* bus DMA tag */ |
257 | | | 257 | |
258 | struct ethercom sc_ethercom; /* ethernet common data */ | | 258 | struct ethercom sc_ethercom; /* ethernet common data */ |
259 | struct mii_data sc_mii; /* MII/media information */ | | 259 | struct mii_data sc_mii; /* MII/media information */ |
260 | | | 260 | |
261 | pci_chipset_tag_t sc_pc; | | 261 | pci_chipset_tag_t sc_pc; |
262 | pcitag_t sc_pcitag; | | 262 | pcitag_t sc_pcitag; |
263 | int sc_bus_speed; /* PCI/PCIX bus speed */ | | 263 | int sc_bus_speed; /* PCI/PCIX bus speed */ |
264 | int sc_pcixe_capoff; /* PCI[Xe] capability register offset */ | | 264 | int sc_pcixe_capoff; /* PCI[Xe] capability register offset */ |
265 | | | 265 | |
266 | const struct wm_product *sc_wmp; /* Pointer to the wm_product entry */ | | 266 | const struct wm_product *sc_wmp; /* Pointer to the wm_product entry */ |
267 | wm_chip_type sc_type; /* MAC type */ | | 267 | wm_chip_type sc_type; /* MAC type */ |
268 | int sc_rev; /* MAC revision */ | | 268 | int sc_rev; /* MAC revision */ |
269 | wm_phy_type sc_phytype; /* PHY type */ | | 269 | wm_phy_type sc_phytype; /* PHY type */ |
270 | int sc_funcid; /* unit number of the chip (0 to 3) */ | | 270 | int sc_funcid; /* unit number of the chip (0 to 3) */ |
271 | int sc_flags; /* flags; see below */ | | 271 | int sc_flags; /* flags; see below */ |
272 | int sc_if_flags; /* last if_flags */ | | 272 | int sc_if_flags; /* last if_flags */ |
273 | int sc_flowflags; /* 802.3x flow control flags */ | | 273 | int sc_flowflags; /* 802.3x flow control flags */ |
274 | int sc_align_tweak; | | 274 | int sc_align_tweak; |
275 | | | 275 | |
276 | void *sc_ih; /* interrupt cookie */ | | 276 | void *sc_ih; /* interrupt cookie */ |
277 | callout_t sc_tick_ch; /* tick callout */ | | 277 | callout_t sc_tick_ch; /* tick callout */ |
278 | | | 278 | |
279 | int sc_ee_addrbits; /* EEPROM address bits */ | | 279 | int sc_ee_addrbits; /* EEPROM address bits */ |
280 | int sc_ich8_flash_base; | | 280 | int sc_ich8_flash_base; |
281 | int sc_ich8_flash_bank_size; | | 281 | int sc_ich8_flash_bank_size; |
282 | int sc_nvm_k1_enabled; | | 282 | int sc_nvm_k1_enabled; |
283 | | | 283 | |
284 | /* | | 284 | /* |
285 | * Software state for the transmit and receive descriptors. | | 285 | * Software state for the transmit and receive descriptors. |
286 | */ | | 286 | */ |
287 | int sc_txnum; /* must be a power of two */ | | 287 | int sc_txnum; /* must be a power of two */ |
288 | struct wm_txsoft sc_txsoft[WM_TXQUEUELEN_MAX]; | | 288 | struct wm_txsoft sc_txsoft[WM_TXQUEUELEN_MAX]; |
289 | struct wm_rxsoft sc_rxsoft[WM_NRXDESC]; | | 289 | struct wm_rxsoft sc_rxsoft[WM_NRXDESC]; |
290 | | | 290 | |
291 | /* | | 291 | /* |
292 | * Control data structures. | | 292 | * Control data structures. |
293 | */ | | 293 | */ |
294 | int sc_ntxdesc; /* must be a power of two */ | | 294 | int sc_ntxdesc; /* must be a power of two */ |
295 | struct wm_control_data_82544 *sc_control_data; | | 295 | struct wm_control_data_82544 *sc_control_data; |
296 | bus_dmamap_t sc_cddmamap; /* control data DMA map */ | | 296 | bus_dmamap_t sc_cddmamap; /* control data DMA map */ |
297 | bus_dma_segment_t sc_cd_seg; /* control data segment */ | | 297 | bus_dma_segment_t sc_cd_seg; /* control data segment */ |
298 | int sc_cd_rseg; /* real number of control segment */ | | 298 | int sc_cd_rseg; /* real number of control segment */ |
299 | size_t sc_cd_size; /* control data size */ | | 299 | size_t sc_cd_size; /* control data size */ |
300 | #define sc_cddma sc_cddmamap->dm_segs[0].ds_addr | | 300 | #define sc_cddma sc_cddmamap->dm_segs[0].ds_addr |
301 | #define sc_txdescs sc_control_data->wdc_u.wcdu_txdescs | | 301 | #define sc_txdescs sc_control_data->wdc_u.wcdu_txdescs |
302 | #define sc_nq_txdescs sc_control_data->wdc_u.wcdu_nq_txdescs | | 302 | #define sc_nq_txdescs sc_control_data->wdc_u.wcdu_nq_txdescs |
303 | #define sc_rxdescs sc_control_data->wcd_rxdescs | | 303 | #define sc_rxdescs sc_control_data->wcd_rxdescs |
304 | | | 304 | |
305 | #ifdef WM_EVENT_COUNTERS | | 305 | #ifdef WM_EVENT_COUNTERS |
306 | /* Event counters. */ | | 306 | /* Event counters. */ |
307 | struct evcnt sc_ev_txsstall; /* Tx stalled due to no txs */ | | 307 | struct evcnt sc_ev_txsstall; /* Tx stalled due to no txs */ |
308 | struct evcnt sc_ev_txdstall; /* Tx stalled due to no txd */ | | 308 | struct evcnt sc_ev_txdstall; /* Tx stalled due to no txd */ |
309 | struct evcnt sc_ev_txfifo_stall;/* Tx FIFO stalls (82547) */ | | 309 | struct evcnt sc_ev_txfifo_stall;/* Tx FIFO stalls (82547) */ |
310 | struct evcnt sc_ev_txdw; /* Tx descriptor interrupts */ | | 310 | struct evcnt sc_ev_txdw; /* Tx descriptor interrupts */ |
311 | struct evcnt sc_ev_txqe; /* Tx queue empty interrupts */ | | 311 | struct evcnt sc_ev_txqe; /* Tx queue empty interrupts */ |
312 | struct evcnt sc_ev_rxintr; /* Rx interrupts */ | | 312 | struct evcnt sc_ev_rxintr; /* Rx interrupts */ |
313 | struct evcnt sc_ev_linkintr; /* Link interrupts */ | | 313 | struct evcnt sc_ev_linkintr; /* Link interrupts */ |
314 | | | 314 | |
315 | struct evcnt sc_ev_rxipsum; /* IP checksums checked in-bound */ | | 315 | struct evcnt sc_ev_rxipsum; /* IP checksums checked in-bound */ |
316 | struct evcnt sc_ev_rxtusum; /* TCP/UDP cksums checked in-bound */ | | 316 | struct evcnt sc_ev_rxtusum; /* TCP/UDP cksums checked in-bound */ |
317 | struct evcnt sc_ev_txipsum; /* IP checksums comp. out-bound */ | | 317 | struct evcnt sc_ev_txipsum; /* IP checksums comp. out-bound */ |
318 | struct evcnt sc_ev_txtusum; /* TCP/UDP cksums comp. out-bound */ | | 318 | struct evcnt sc_ev_txtusum; /* TCP/UDP cksums comp. out-bound */ |
319 | struct evcnt sc_ev_txtusum6; /* TCP/UDP v6 cksums comp. out-bound */ | | 319 | struct evcnt sc_ev_txtusum6; /* TCP/UDP v6 cksums comp. out-bound */ |
320 | struct evcnt sc_ev_txtso; /* TCP seg offload out-bound (IPv4) */ | | 320 | struct evcnt sc_ev_txtso; /* TCP seg offload out-bound (IPv4) */ |
321 | struct evcnt sc_ev_txtso6; /* TCP seg offload out-bound (IPv6) */ | | 321 | struct evcnt sc_ev_txtso6; /* TCP seg offload out-bound (IPv6) */ |
322 | struct evcnt sc_ev_txtsopain; /* painful header manip. for TSO */ | | 322 | struct evcnt sc_ev_txtsopain; /* painful header manip. for TSO */ |
323 | | | 323 | |
324 | struct evcnt sc_ev_txseg[WM_NTXSEGS]; /* Tx packets w/ N segments */ | | 324 | struct evcnt sc_ev_txseg[WM_NTXSEGS]; /* Tx packets w/ N segments */ |
325 | struct evcnt sc_ev_txdrop; /* Tx packets dropped (too many segs) */ | | 325 | struct evcnt sc_ev_txdrop; /* Tx packets dropped (too many segs) */ |
326 | | | 326 | |
327 | struct evcnt sc_ev_tu; /* Tx underrun */ | | 327 | struct evcnt sc_ev_tu; /* Tx underrun */ |
328 | | | 328 | |
329 | struct evcnt sc_ev_tx_xoff; /* Tx PAUSE(!0) frames */ | | 329 | struct evcnt sc_ev_tx_xoff; /* Tx PAUSE(!0) frames */ |
330 | struct evcnt sc_ev_tx_xon; /* Tx PAUSE(0) frames */ | | 330 | struct evcnt sc_ev_tx_xon; /* Tx PAUSE(0) frames */ |
331 | struct evcnt sc_ev_rx_xoff; /* Rx PAUSE(!0) frames */ | | 331 | struct evcnt sc_ev_rx_xoff; /* Rx PAUSE(!0) frames */ |
332 | struct evcnt sc_ev_rx_xon; /* Rx PAUSE(0) frames */ | | 332 | struct evcnt sc_ev_rx_xon; /* Rx PAUSE(0) frames */ |
333 | struct evcnt sc_ev_rx_macctl; /* Rx Unsupported */ | | 333 | struct evcnt sc_ev_rx_macctl; /* Rx Unsupported */ |
334 | #endif /* WM_EVENT_COUNTERS */ | | 334 | #endif /* WM_EVENT_COUNTERS */ |
335 | | | 335 | |
336 | bus_addr_t sc_tdt_reg; /* offset of TDT register */ | | 336 | bus_addr_t sc_tdt_reg; /* offset of TDT register */ |
337 | | | 337 | |
338 | int sc_txfree; /* number of free Tx descriptors */ | | 338 | int sc_txfree; /* number of free Tx descriptors */ |
339 | int sc_txnext; /* next ready Tx descriptor */ | | 339 | int sc_txnext; /* next ready Tx descriptor */ |
340 | | | 340 | |
341 | int sc_txsfree; /* number of free Tx jobs */ | | 341 | int sc_txsfree; /* number of free Tx jobs */ |
342 | int sc_txsnext; /* next free Tx job */ | | 342 | int sc_txsnext; /* next free Tx job */ |
343 | int sc_txsdirty; /* dirty Tx jobs */ | | 343 | int sc_txsdirty; /* dirty Tx jobs */ |
344 | | | 344 | |
345 | /* These 5 variables are used only on the 82547. */ | | 345 | /* These 5 variables are used only on the 82547. */ |
346 | int sc_txfifo_size; /* Tx FIFO size */ | | 346 | int sc_txfifo_size; /* Tx FIFO size */ |
347 | int sc_txfifo_head; /* current head of FIFO */ | | 347 | int sc_txfifo_head; /* current head of FIFO */ |
348 | uint32_t sc_txfifo_addr; /* internal address of start of FIFO */ | | 348 | uint32_t sc_txfifo_addr; /* internal address of start of FIFO */ |
349 | int sc_txfifo_stall; /* Tx FIFO is stalled */ | | 349 | int sc_txfifo_stall; /* Tx FIFO is stalled */ |
350 | callout_t sc_txfifo_ch; /* Tx FIFO stall work-around timer */ | | 350 | callout_t sc_txfifo_ch; /* Tx FIFO stall work-around timer */ |
351 | | | 351 | |
352 | bus_addr_t sc_rdt_reg; /* offset of RDT register */ | | 352 | bus_addr_t sc_rdt_reg; /* offset of RDT register */ |
353 | | | 353 | |
354 | int sc_rxptr; /* next ready Rx descriptor/queue ent */ | | 354 | int sc_rxptr; /* next ready Rx descriptor/queue ent */ |
355 | int sc_rxdiscard; | | 355 | int sc_rxdiscard; |
356 | int sc_rxlen; | | 356 | int sc_rxlen; |
357 | struct mbuf *sc_rxhead; | | 357 | struct mbuf *sc_rxhead; |
358 | struct mbuf *sc_rxtail; | | 358 | struct mbuf *sc_rxtail; |
359 | struct mbuf **sc_rxtailp; | | 359 | struct mbuf **sc_rxtailp; |
360 | | | 360 | |
361 | uint32_t sc_ctrl; /* prototype CTRL register */ | | 361 | uint32_t sc_ctrl; /* prototype CTRL register */ |
362 | #if 0 | | 362 | #if 0 |
363 | uint32_t sc_ctrl_ext; /* prototype CTRL_EXT register */ | | 363 | uint32_t sc_ctrl_ext; /* prototype CTRL_EXT register */ |
364 | #endif | | 364 | #endif |
365 | uint32_t sc_icr; /* prototype interrupt bits */ | | 365 | uint32_t sc_icr; /* prototype interrupt bits */ |
366 | uint32_t sc_itr; /* prototype intr throttling reg */ | | 366 | uint32_t sc_itr; /* prototype intr throttling reg */ |
367 | uint32_t sc_tctl; /* prototype TCTL register */ | | 367 | uint32_t sc_tctl; /* prototype TCTL register */ |
368 | uint32_t sc_rctl; /* prototype RCTL register */ | | 368 | uint32_t sc_rctl; /* prototype RCTL register */ |
369 | uint32_t sc_txcw; /* prototype TXCW register */ | | 369 | uint32_t sc_txcw; /* prototype TXCW register */ |
370 | uint32_t sc_tipg; /* prototype TIPG register */ | | 370 | uint32_t sc_tipg; /* prototype TIPG register */ |
371 | uint32_t sc_fcrtl; /* prototype FCRTL register */ | | 371 | uint32_t sc_fcrtl; /* prototype FCRTL register */ |
372 | uint32_t sc_pba; /* prototype PBA register */ | | 372 | uint32_t sc_pba; /* prototype PBA register */ |
373 | | | 373 | |
374 | int sc_tbi_linkup; /* TBI link status */ | | 374 | int sc_tbi_linkup; /* TBI link status */ |
375 | int sc_tbi_anegticks; /* autonegotiation ticks */ | | 375 | int sc_tbi_anegticks; /* autonegotiation ticks */ |
376 | int sc_tbi_ticks; /* tbi ticks */ | | 376 | int sc_tbi_ticks; /* tbi ticks */ |
377 | int sc_tbi_nrxcfg; /* count of ICR_RXCFG */ | | 377 | int sc_tbi_nrxcfg; /* count of ICR_RXCFG */ |
378 | int sc_tbi_lastnrxcfg; /* count of ICR_RXCFG (on last tick) */ | | 378 | int sc_tbi_lastnrxcfg; /* count of ICR_RXCFG (on last tick) */ |
379 | | | 379 | |
380 | int sc_mchash_type; /* multicast filter offset */ | | 380 | int sc_mchash_type; /* multicast filter offset */ |
381 | | | 381 | |
382 | krndsource_t rnd_source; /* random source */ | | 382 | krndsource_t rnd_source; /* random source */ |
383 | }; | | 383 | }; |
384 | | | 384 | |
385 | #define WM_RXCHAIN_RESET(sc) \ | | 385 | #define WM_RXCHAIN_RESET(sc) \ |
386 | do { \ | | 386 | do { \ |
387 | (sc)->sc_rxtailp = &(sc)->sc_rxhead; \ | | 387 | (sc)->sc_rxtailp = &(sc)->sc_rxhead; \ |
388 | *(sc)->sc_rxtailp = NULL; \ | | 388 | *(sc)->sc_rxtailp = NULL; \ |
389 | (sc)->sc_rxlen = 0; \ | | 389 | (sc)->sc_rxlen = 0; \ |
390 | } while (/*CONSTCOND*/0) | | 390 | } while (/*CONSTCOND*/0) |
391 | | | 391 | |
392 | #define WM_RXCHAIN_LINK(sc, m) \ | | 392 | #define WM_RXCHAIN_LINK(sc, m) \ |
393 | do { \ | | 393 | do { \ |
394 | *(sc)->sc_rxtailp = (sc)->sc_rxtail = (m); \ | | 394 | *(sc)->sc_rxtailp = (sc)->sc_rxtail = (m); \ |
395 | (sc)->sc_rxtailp = &(m)->m_next; \ | | 395 | (sc)->sc_rxtailp = &(m)->m_next; \ |
396 | } while (/*CONSTCOND*/0) | | 396 | } while (/*CONSTCOND*/0) |
397 | | | 397 | |
398 | #ifdef WM_EVENT_COUNTERS | | 398 | #ifdef WM_EVENT_COUNTERS |
399 | #define WM_EVCNT_INCR(ev) (ev)->ev_count++ | | 399 | #define WM_EVCNT_INCR(ev) (ev)->ev_count++ |
400 | #define WM_EVCNT_ADD(ev, val) (ev)->ev_count += (val) | | 400 | #define WM_EVCNT_ADD(ev, val) (ev)->ev_count += (val) |
401 | #else | | 401 | #else |
402 | #define WM_EVCNT_INCR(ev) /* nothing */ | | 402 | #define WM_EVCNT_INCR(ev) /* nothing */ |
403 | #define WM_EVCNT_ADD(ev, val) /* nothing */ | | 403 | #define WM_EVCNT_ADD(ev, val) /* nothing */ |
404 | #endif | | 404 | #endif |
405 | | | 405 | |
406 | #define CSR_READ(sc, reg) \ | | 406 | #define CSR_READ(sc, reg) \ |
407 | bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (reg)) | | 407 | bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (reg)) |
408 | #define CSR_WRITE(sc, reg, val) \ | | 408 | #define CSR_WRITE(sc, reg, val) \ |
409 | bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (reg), (val)) | | 409 | bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (reg), (val)) |
410 | #define CSR_WRITE_FLUSH(sc) \ | | 410 | #define CSR_WRITE_FLUSH(sc) \ |
411 | (void) CSR_READ((sc), WMREG_STATUS) | | 411 | (void) CSR_READ((sc), WMREG_STATUS) |
412 | | | 412 | |
413 | #define ICH8_FLASH_READ32(sc, reg) \ | | 413 | #define ICH8_FLASH_READ32(sc, reg) \ |
414 | bus_space_read_4((sc)->sc_flasht, (sc)->sc_flashh, (reg)) | | 414 | bus_space_read_4((sc)->sc_flasht, (sc)->sc_flashh, (reg)) |
415 | #define ICH8_FLASH_WRITE32(sc, reg, data) \ | | 415 | #define ICH8_FLASH_WRITE32(sc, reg, data) \ |
416 | bus_space_write_4((sc)->sc_flasht, (sc)->sc_flashh, (reg), (data)) | | 416 | bus_space_write_4((sc)->sc_flasht, (sc)->sc_flashh, (reg), (data)) |
417 | | | 417 | |
418 | #define ICH8_FLASH_READ16(sc, reg) \ | | 418 | #define ICH8_FLASH_READ16(sc, reg) \ |
419 | bus_space_read_2((sc)->sc_flasht, (sc)->sc_flashh, (reg)) | | 419 | bus_space_read_2((sc)->sc_flasht, (sc)->sc_flashh, (reg)) |
420 | #define ICH8_FLASH_WRITE16(sc, reg, data) \ | | 420 | #define ICH8_FLASH_WRITE16(sc, reg, data) \ |
421 | bus_space_write_2((sc)->sc_flasht, (sc)->sc_flashh, (reg), (data)) | | 421 | bus_space_write_2((sc)->sc_flasht, (sc)->sc_flashh, (reg), (data)) |
422 | | | 422 | |
423 | #define WM_CDTXADDR(sc, x) ((sc)->sc_cddma + WM_CDTXOFF((x))) | | 423 | #define WM_CDTXADDR(sc, x) ((sc)->sc_cddma + WM_CDTXOFF((x))) |
424 | #define WM_CDRXADDR(sc, x) ((sc)->sc_cddma + WM_CDRXOFF((x))) | | 424 | #define WM_CDRXADDR(sc, x) ((sc)->sc_cddma + WM_CDRXOFF((x))) |
425 | | | 425 | |
426 | #define WM_CDTXADDR_LO(sc, x) (WM_CDTXADDR((sc), (x)) & 0xffffffffU) | | 426 | #define WM_CDTXADDR_LO(sc, x) (WM_CDTXADDR((sc), (x)) & 0xffffffffU) |
427 | #define WM_CDTXADDR_HI(sc, x) \ | | 427 | #define WM_CDTXADDR_HI(sc, x) \ |
428 | (sizeof(bus_addr_t) == 8 ? \ | | 428 | (sizeof(bus_addr_t) == 8 ? \ |
429 | (uint64_t)WM_CDTXADDR((sc), (x)) >> 32 : 0) | | 429 | (uint64_t)WM_CDTXADDR((sc), (x)) >> 32 : 0) |
430 | | | 430 | |
431 | #define WM_CDRXADDR_LO(sc, x) (WM_CDRXADDR((sc), (x)) & 0xffffffffU) | | 431 | #define WM_CDRXADDR_LO(sc, x) (WM_CDRXADDR((sc), (x)) & 0xffffffffU) |
432 | #define WM_CDRXADDR_HI(sc, x) \ | | 432 | #define WM_CDRXADDR_HI(sc, x) \ |
433 | (sizeof(bus_addr_t) == 8 ? \ | | 433 | (sizeof(bus_addr_t) == 8 ? \ |
434 | (uint64_t)WM_CDRXADDR((sc), (x)) >> 32 : 0) | | 434 | (uint64_t)WM_CDRXADDR((sc), (x)) >> 32 : 0) |
435 | | | 435 | |
436 | #define WM_CDTXSYNC(sc, x, n, ops) \ | | 436 | #define WM_CDTXSYNC(sc, x, n, ops) \ |
437 | do { \ | | 437 | do { \ |
438 | int __x, __n; \ | | 438 | int __x, __n; \ |
439 | \ | | 439 | \ |
440 | __x = (x); \ | | 440 | __x = (x); \ |
441 | __n = (n); \ | | 441 | __n = (n); \ |
442 | \ | | 442 | \ |
443 | /* If it will wrap around, sync to the end of the ring. */ \ | | 443 | /* If it will wrap around, sync to the end of the ring. */ \ |
444 | if ((__x + __n) > WM_NTXDESC(sc)) { \ | | 444 | if ((__x + __n) > WM_NTXDESC(sc)) { \ |
445 | bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ | | 445 | bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ |
446 | WM_CDTXOFF(__x), sizeof(wiseman_txdesc_t) * \ | | 446 | WM_CDTXOFF(__x), sizeof(wiseman_txdesc_t) * \ |
447 | (WM_NTXDESC(sc) - __x), (ops)); \ | | 447 | (WM_NTXDESC(sc) - __x), (ops)); \ |
448 | __n -= (WM_NTXDESC(sc) - __x); \ | | 448 | __n -= (WM_NTXDESC(sc) - __x); \ |
449 | __x = 0; \ | | 449 | __x = 0; \ |
450 | } \ | | 450 | } \ |
451 | \ | | 451 | \ |
452 | /* Now sync whatever is left. */ \ | | 452 | /* Now sync whatever is left. */ \ |
453 | bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ | | 453 | bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ |
454 | WM_CDTXOFF(__x), sizeof(wiseman_txdesc_t) * __n, (ops)); \ | | 454 | WM_CDTXOFF(__x), sizeof(wiseman_txdesc_t) * __n, (ops)); \ |
455 | } while (/*CONSTCOND*/0) | | 455 | } while (/*CONSTCOND*/0) |
456 | | | 456 | |
457 | #define WM_CDRXSYNC(sc, x, ops) \ | | 457 | #define WM_CDRXSYNC(sc, x, ops) \ |
458 | do { \ | | 458 | do { \ |
459 | bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ | | 459 | bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ |
460 | WM_CDRXOFF((x)), sizeof(wiseman_rxdesc_t), (ops)); \ | | 460 | WM_CDRXOFF((x)), sizeof(wiseman_rxdesc_t), (ops)); \ |
461 | } while (/*CONSTCOND*/0) | | 461 | } while (/*CONSTCOND*/0) |
462 | | | 462 | |
463 | #define WM_INIT_RXDESC(sc, x) \ | | 463 | #define WM_INIT_RXDESC(sc, x) \ |
464 | do { \ | | 464 | do { \ |
465 | struct wm_rxsoft *__rxs = &(sc)->sc_rxsoft[(x)]; \ | | 465 | struct wm_rxsoft *__rxs = &(sc)->sc_rxsoft[(x)]; \ |
466 | wiseman_rxdesc_t *__rxd = &(sc)->sc_rxdescs[(x)]; \ | | 466 | wiseman_rxdesc_t *__rxd = &(sc)->sc_rxdescs[(x)]; \ |
467 | struct mbuf *__m = __rxs->rxs_mbuf; \ | | 467 | struct mbuf *__m = __rxs->rxs_mbuf; \ |
468 | \ | | 468 | \ |
469 | /* \ | | 469 | /* \ |
470 | * Note: We scoot the packet forward 2 bytes in the buffer \ | | 470 | * Note: We scoot the packet forward 2 bytes in the buffer \ |
471 | * so that the payload after the Ethernet header is aligned \ | | 471 | * so that the payload after the Ethernet header is aligned \ |
472 | * to a 4-byte boundary. \ | | 472 | * to a 4-byte boundary. \ |
473 | * \ | | 473 | * \ |
474 | * XXX BRAINDAMAGE ALERT! \ | | 474 | * XXX BRAINDAMAGE ALERT! \ |
475 | * The stupid chip uses the same size for every buffer, which \ | | 475 | * The stupid chip uses the same size for every buffer, which \ |
476 | * is set in the Receive Control register. We are using the 2K \ | | 476 | * is set in the Receive Control register. We are using the 2K \ |
477 | * size option, but what we REALLY want is (2K - 2)! For this \ | | 477 | * size option, but what we REALLY want is (2K - 2)! For this \ |
478 | * reason, we can't "scoot" packets longer than the standard \ | | 478 | * reason, we can't "scoot" packets longer than the standard \ |
479 | * Ethernet MTU. On strict-alignment platforms, if the total \ | | 479 | * Ethernet MTU. On strict-alignment platforms, if the total \ |
480 | * size exceeds (2K - 2) we set align_tweak to 0 and let \ | | 480 | * size exceeds (2K - 2) we set align_tweak to 0 and let \ |
481 | * the upper layer copy the headers. \ | | 481 | * the upper layer copy the headers. \ |
482 | */ \ | | 482 | */ \ |
483 | __m->m_data = __m->m_ext.ext_buf + (sc)->sc_align_tweak; \ | | 483 | __m->m_data = __m->m_ext.ext_buf + (sc)->sc_align_tweak; \ |
484 | \ | | 484 | \ |
485 | wm_set_dma_addr(&__rxd->wrx_addr, \ | | 485 | wm_set_dma_addr(&__rxd->wrx_addr, \ |
486 | __rxs->rxs_dmamap->dm_segs[0].ds_addr + (sc)->sc_align_tweak); \ | | 486 | __rxs->rxs_dmamap->dm_segs[0].ds_addr + (sc)->sc_align_tweak); \ |
487 | __rxd->wrx_len = 0; \ | | 487 | __rxd->wrx_len = 0; \ |
488 | __rxd->wrx_cksum = 0; \ | | 488 | __rxd->wrx_cksum = 0; \ |
489 | __rxd->wrx_status = 0; \ | | 489 | __rxd->wrx_status = 0; \ |
490 | __rxd->wrx_errors = 0; \ | | 490 | __rxd->wrx_errors = 0; \ |
491 | __rxd->wrx_special = 0; \ | | 491 | __rxd->wrx_special = 0; \ |
492 | WM_CDRXSYNC((sc), (x), BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); \ | | 492 | WM_CDRXSYNC((sc), (x), BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); \ |
493 | \ | | 493 | \ |
494 | CSR_WRITE((sc), (sc)->sc_rdt_reg, (x)); \ | | 494 | CSR_WRITE((sc), (sc)->sc_rdt_reg, (x)); \ |
495 | } while (/*CONSTCOND*/0) | | 495 | } while (/*CONSTCOND*/0) |
496 | | | 496 | |
497 | static void wm_start(struct ifnet *); | | 497 | static void wm_start(struct ifnet *); |
498 | static void wm_nq_start(struct ifnet *); | | 498 | static void wm_nq_start(struct ifnet *); |
499 | static void wm_watchdog(struct ifnet *); | | 499 | static void wm_watchdog(struct ifnet *); |
500 | static int wm_ifflags_cb(struct ethercom *); | | 500 | static int wm_ifflags_cb(struct ethercom *); |
501 | static int wm_ioctl(struct ifnet *, u_long, void *); | | 501 | static int wm_ioctl(struct ifnet *, u_long, void *); |
502 | static int wm_init(struct ifnet *); | | 502 | static int wm_init(struct ifnet *); |
503 | static void wm_stop(struct ifnet *, int); | | 503 | static void wm_stop(struct ifnet *, int); |
504 | static bool wm_suspend(device_t, const pmf_qual_t *); | | 504 | static bool wm_suspend(device_t, const pmf_qual_t *); |
505 | static bool wm_resume(device_t, const pmf_qual_t *); | | 505 | static bool wm_resume(device_t, const pmf_qual_t *); |
506 | | | 506 | |
507 | static void wm_reset(struct wm_softc *); | | 507 | static void wm_reset(struct wm_softc *); |
508 | static void wm_rxdrain(struct wm_softc *); | | 508 | static void wm_rxdrain(struct wm_softc *); |
509 | static int wm_add_rxbuf(struct wm_softc *, int); | | 509 | static int wm_add_rxbuf(struct wm_softc *, int); |
510 | static int wm_read_eeprom(struct wm_softc *, int, int, u_int16_t *); | | 510 | static int wm_read_eeprom(struct wm_softc *, int, int, u_int16_t *); |
511 | static int wm_read_eeprom_eerd(struct wm_softc *, int, int, u_int16_t *); | | 511 | static int wm_read_eeprom_eerd(struct wm_softc *, int, int, u_int16_t *); |
512 | static int wm_validate_eeprom_checksum(struct wm_softc *); | | 512 | static int wm_validate_eeprom_checksum(struct wm_softc *); |
513 | static int wm_check_alt_mac_addr(struct wm_softc *); | | 513 | static int wm_check_alt_mac_addr(struct wm_softc *); |
514 | static int wm_read_mac_addr(struct wm_softc *, uint8_t *); | | 514 | static int wm_read_mac_addr(struct wm_softc *, uint8_t *); |
515 | static void wm_tick(void *); | | 515 | static void wm_tick(void *); |
516 | | | 516 | |
517 | static void wm_set_filter(struct wm_softc *); | | 517 | static void wm_set_filter(struct wm_softc *); |
518 | static void wm_set_vlan(struct wm_softc *); | | 518 | static void wm_set_vlan(struct wm_softc *); |
519 | | | 519 | |
520 | static int wm_intr(void *); | | 520 | static int wm_intr(void *); |
521 | static void wm_txintr(struct wm_softc *); | | 521 | static void wm_txintr(struct wm_softc *); |
522 | static void wm_rxintr(struct wm_softc *); | | 522 | static void wm_rxintr(struct wm_softc *); |
523 | static void wm_linkintr(struct wm_softc *, uint32_t); | | 523 | static void wm_linkintr(struct wm_softc *, uint32_t); |
524 | | | 524 | |
525 | static void wm_tbi_mediainit(struct wm_softc *); | | 525 | static void wm_tbi_mediainit(struct wm_softc *); |
526 | static int wm_tbi_mediachange(struct ifnet *); | | 526 | static int wm_tbi_mediachange(struct ifnet *); |
527 | static void wm_tbi_mediastatus(struct ifnet *, struct ifmediareq *); | | 527 | static void wm_tbi_mediastatus(struct ifnet *, struct ifmediareq *); |
528 | | | 528 | |
529 | static void wm_tbi_set_linkled(struct wm_softc *); | | 529 | static void wm_tbi_set_linkled(struct wm_softc *); |
530 | static void wm_tbi_check_link(struct wm_softc *); | | 530 | static void wm_tbi_check_link(struct wm_softc *); |
531 | | | 531 | |
532 | static void wm_gmii_reset(struct wm_softc *); | | 532 | static void wm_gmii_reset(struct wm_softc *); |
533 | | | 533 | |
534 | static int wm_gmii_i82543_readreg(device_t, int, int); | | 534 | static int wm_gmii_i82543_readreg(device_t, int, int); |
535 | static void wm_gmii_i82543_writereg(device_t, int, int, int); | | 535 | static void wm_gmii_i82543_writereg(device_t, int, int, int); |
536 | static int wm_gmii_i82544_readreg(device_t, int, int); | | 536 | static int wm_gmii_i82544_readreg(device_t, int, int); |
537 | static void wm_gmii_i82544_writereg(device_t, int, int, int); | | 537 | static void wm_gmii_i82544_writereg(device_t, int, int, int); |
538 | static int wm_gmii_i80003_readreg(device_t, int, int); | | 538 | static int wm_gmii_i80003_readreg(device_t, int, int); |
539 | static void wm_gmii_i80003_writereg(device_t, int, int, int); | | 539 | static void wm_gmii_i80003_writereg(device_t, int, int, int); |
540 | static int wm_gmii_bm_readreg(device_t, int, int); | | 540 | static int wm_gmii_bm_readreg(device_t, int, int); |
541 | static void wm_gmii_bm_writereg(device_t, int, int, int); | | 541 | static void wm_gmii_bm_writereg(device_t, int, int, int); |
542 | static int wm_gmii_hv_readreg(device_t, int, int); | | 542 | static int wm_gmii_hv_readreg(device_t, int, int); |
543 | static void wm_gmii_hv_writereg(device_t, int, int, int); | | 543 | static void wm_gmii_hv_writereg(device_t, int, int, int); |
544 | static int wm_gmii_82580_readreg(device_t, int, int); | | 544 | static int wm_gmii_82580_readreg(device_t, int, int); |
545 | static void wm_gmii_82580_writereg(device_t, int, int, int); | | 545 | static void wm_gmii_82580_writereg(device_t, int, int, int); |
546 | static int wm_sgmii_readreg(device_t, int, int); | | 546 | static int wm_sgmii_readreg(device_t, int, int); |
547 | static void wm_sgmii_writereg(device_t, int, int, int); | | 547 | static void wm_sgmii_writereg(device_t, int, int, int); |
548 | | | 548 | |
549 | static void wm_gmii_statchg(struct ifnet *); | | 549 | static void wm_gmii_statchg(struct ifnet *); |
550 | | | 550 | |
551 | static void wm_gmii_mediainit(struct wm_softc *, pci_product_id_t); | | 551 | static void wm_gmii_mediainit(struct wm_softc *, pci_product_id_t); |
552 | static int wm_gmii_mediachange(struct ifnet *); | | 552 | static int wm_gmii_mediachange(struct ifnet *); |
553 | static void wm_gmii_mediastatus(struct ifnet *, struct ifmediareq *); | | 553 | static void wm_gmii_mediastatus(struct ifnet *, struct ifmediareq *); |
554 | | | 554 | |
555 | static int wm_kmrn_readreg(struct wm_softc *, int); | | 555 | static int wm_kmrn_readreg(struct wm_softc *, int); |
556 | static void wm_kmrn_writereg(struct wm_softc *, int, int); | | 556 | static void wm_kmrn_writereg(struct wm_softc *, int, int); |
557 | | | 557 | |
558 | static void wm_set_spiaddrbits(struct wm_softc *); | | 558 | static void wm_set_spiaddrbits(struct wm_softc *); |
559 | static int wm_match(device_t, cfdata_t, void *); | | 559 | static int wm_match(device_t, cfdata_t, void *); |
560 | static void wm_attach(device_t, device_t, void *); | | 560 | static void wm_attach(device_t, device_t, void *); |
561 | static int wm_detach(device_t, int); | | 561 | static int wm_detach(device_t, int); |
562 | static int wm_is_onboard_nvm_eeprom(struct wm_softc *); | | 562 | static int wm_is_onboard_nvm_eeprom(struct wm_softc *); |
563 | static void wm_get_auto_rd_done(struct wm_softc *); | | 563 | static void wm_get_auto_rd_done(struct wm_softc *); |
564 | static void wm_lan_init_done(struct wm_softc *); | | 564 | static void wm_lan_init_done(struct wm_softc *); |
565 | static void wm_get_cfg_done(struct wm_softc *); | | 565 | static void wm_get_cfg_done(struct wm_softc *); |
566 | static int wm_get_swsm_semaphore(struct wm_softc *); | | 566 | static int wm_get_swsm_semaphore(struct wm_softc *); |
567 | static void wm_put_swsm_semaphore(struct wm_softc *); | | 567 | static void wm_put_swsm_semaphore(struct wm_softc *); |
568 | static int wm_poll_eerd_eewr_done(struct wm_softc *, int); | | 568 | static int wm_poll_eerd_eewr_done(struct wm_softc *, int); |
569 | static int wm_get_swfw_semaphore(struct wm_softc *, uint16_t); | | 569 | static int wm_get_swfw_semaphore(struct wm_softc *, uint16_t); |
570 | static void wm_put_swfw_semaphore(struct wm_softc *, uint16_t); | | 570 | static void wm_put_swfw_semaphore(struct wm_softc *, uint16_t); |
571 | static int wm_get_swfwhw_semaphore(struct wm_softc *); | | 571 | static int wm_get_swfwhw_semaphore(struct wm_softc *); |
572 | static void wm_put_swfwhw_semaphore(struct wm_softc *); | | 572 | static void wm_put_swfwhw_semaphore(struct wm_softc *); |
573 | | | 573 | |
574 | static int wm_read_eeprom_ich8(struct wm_softc *, int, int, uint16_t *); | | 574 | static int wm_read_eeprom_ich8(struct wm_softc *, int, int, uint16_t *); |
575 | static int32_t wm_ich8_cycle_init(struct wm_softc *); | | 575 | static int32_t wm_ich8_cycle_init(struct wm_softc *); |
576 | static int32_t wm_ich8_flash_cycle(struct wm_softc *, uint32_t); | | 576 | static int32_t wm_ich8_flash_cycle(struct wm_softc *, uint32_t); |
577 | static int32_t wm_read_ich8_data(struct wm_softc *, uint32_t, | | 577 | static int32_t wm_read_ich8_data(struct wm_softc *, uint32_t, |
578 | uint32_t, uint16_t *); | | 578 | uint32_t, uint16_t *); |
579 | static int32_t wm_read_ich8_byte(struct wm_softc *, uint32_t, uint8_t *); | | 579 | static int32_t wm_read_ich8_byte(struct wm_softc *, uint32_t, uint8_t *); |
580 | static int32_t wm_read_ich8_word(struct wm_softc *, uint32_t, uint16_t *); | | 580 | static int32_t wm_read_ich8_word(struct wm_softc *, uint32_t, uint16_t *); |
581 | static void wm_82547_txfifo_stall(void *); | | 581 | static void wm_82547_txfifo_stall(void *); |
582 | static void wm_gate_hw_phy_config_ich8lan(struct wm_softc *, int); | | 582 | static void wm_gate_hw_phy_config_ich8lan(struct wm_softc *, int); |
583 | static int wm_check_mng_mode(struct wm_softc *); | | 583 | static int wm_check_mng_mode(struct wm_softc *); |
584 | static int wm_check_mng_mode_ich8lan(struct wm_softc *); | | 584 | static int wm_check_mng_mode_ich8lan(struct wm_softc *); |
585 | static int wm_check_mng_mode_82574(struct wm_softc *); | | 585 | static int wm_check_mng_mode_82574(struct wm_softc *); |
586 | static int wm_check_mng_mode_generic(struct wm_softc *); | | 586 | static int wm_check_mng_mode_generic(struct wm_softc *); |
587 | static int wm_enable_mng_pass_thru(struct wm_softc *); | | 587 | static int wm_enable_mng_pass_thru(struct wm_softc *); |
588 | static int wm_check_reset_block(struct wm_softc *); | | 588 | static int wm_check_reset_block(struct wm_softc *); |
589 | static void wm_get_hw_control(struct wm_softc *); | | 589 | static void wm_get_hw_control(struct wm_softc *); |
590 | static int wm_check_for_link(struct wm_softc *); | | 590 | static int wm_check_for_link(struct wm_softc *); |
591 | static void wm_kmrn_lock_loss_workaround_ich8lan(struct wm_softc *); | | 591 | static void wm_kmrn_lock_loss_workaround_ich8lan(struct wm_softc *); |
592 | static void wm_gig_downshift_workaround_ich8lan(struct wm_softc *); | | 592 | static void wm_gig_downshift_workaround_ich8lan(struct wm_softc *); |
593 | #ifdef WM_WOL | | 593 | #ifdef WM_WOL |
594 | static void wm_igp3_phy_powerdown_workaround_ich8lan(struct wm_softc *); | | 594 | static void wm_igp3_phy_powerdown_workaround_ich8lan(struct wm_softc *); |
595 | #endif | | 595 | #endif |
596 | static void wm_hv_phy_workaround_ich8lan(struct wm_softc *); | | 596 | static void wm_hv_phy_workaround_ich8lan(struct wm_softc *); |
597 | static void wm_lv_phy_workaround_ich8lan(struct wm_softc *); | | 597 | static void wm_lv_phy_workaround_ich8lan(struct wm_softc *); |
598 | static void wm_k1_gig_workaround_hv(struct wm_softc *, int); | | 598 | static void wm_k1_gig_workaround_hv(struct wm_softc *, int); |
599 | static void wm_set_mdio_slow_mode_hv(struct wm_softc *); | | 599 | static void wm_set_mdio_slow_mode_hv(struct wm_softc *); |
600 | static void wm_configure_k1_ich8lan(struct wm_softc *, int); | | 600 | static void wm_configure_k1_ich8lan(struct wm_softc *, int); |
601 | static void wm_smbustopci(struct wm_softc *); | | 601 | static void wm_smbustopci(struct wm_softc *); |
602 | static void wm_set_pcie_completion_timeout(struct wm_softc *); | | 602 | static void wm_set_pcie_completion_timeout(struct wm_softc *); |
603 | static void wm_reset_init_script_82575(struct wm_softc *); | | 603 | static void wm_reset_init_script_82575(struct wm_softc *); |
604 | static void wm_release_manageability(struct wm_softc *); | | 604 | static void wm_release_manageability(struct wm_softc *); |
605 | static void wm_release_hw_control(struct wm_softc *); | | 605 | static void wm_release_hw_control(struct wm_softc *); |
606 | static void wm_get_wakeup(struct wm_softc *); | | 606 | static void wm_get_wakeup(struct wm_softc *); |
607 | #ifdef WM_WOL | | 607 | #ifdef WM_WOL |
608 | static void wm_enable_phy_wakeup(struct wm_softc *); | | 608 | static void wm_enable_phy_wakeup(struct wm_softc *); |
609 | static void wm_enable_wakeup(struct wm_softc *); | | 609 | static void wm_enable_wakeup(struct wm_softc *); |
610 | #endif | | 610 | #endif |
611 | static void wm_init_manageability(struct wm_softc *); | | 611 | static void wm_init_manageability(struct wm_softc *); |
612 | static void wm_set_eee_i350(struct wm_softc *); | | 612 | static void wm_set_eee_i350(struct wm_softc *); |
613 | | | 613 | |
614 | CFATTACH_DECL3_NEW(wm, sizeof(struct wm_softc), | | 614 | CFATTACH_DECL3_NEW(wm, sizeof(struct wm_softc), |
615 | wm_match, wm_attach, wm_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN); | | 615 | wm_match, wm_attach, wm_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN); |
616 | | | 616 | |
617 | /* | | 617 | /* |
618 | * Devices supported by this driver. | | 618 | * Devices supported by this driver. |
619 | */ | | 619 | */ |
620 | static const struct wm_product { | | 620 | static const struct wm_product { |
621 | pci_vendor_id_t wmp_vendor; | | 621 | pci_vendor_id_t wmp_vendor; |
622 | pci_product_id_t wmp_product; | | 622 | pci_product_id_t wmp_product; |
623 | const char *wmp_name; | | 623 | const char *wmp_name; |
624 | wm_chip_type wmp_type; | | 624 | wm_chip_type wmp_type; |
625 | int wmp_flags; | | 625 | int wmp_flags; |
626 | #define WMP_F_1000X 0x01 | | 626 | #define WMP_F_1000X 0x01 |
627 | #define WMP_F_1000T 0x02 | | 627 | #define WMP_F_1000T 0x02 |
628 | #define WMP_F_SERDES 0x04 | | 628 | #define WMP_F_SERDES 0x04 |
629 | } wm_products[] = { | | 629 | } wm_products[] = { |
630 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82542, | | 630 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82542, |
631 | "Intel i82542 1000BASE-X Ethernet", | | 631 | "Intel i82542 1000BASE-X Ethernet", |
632 | WM_T_82542_2_1, WMP_F_1000X }, | | 632 | WM_T_82542_2_1, WMP_F_1000X }, |
633 | | | 633 | |
634 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82543GC_FIBER, | | 634 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82543GC_FIBER, |
635 | "Intel i82543GC 1000BASE-X Ethernet", | | 635 | "Intel i82543GC 1000BASE-X Ethernet", |
636 | WM_T_82543, WMP_F_1000X }, | | 636 | WM_T_82543, WMP_F_1000X }, |
637 | | | 637 | |
638 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82543GC_COPPER, | | 638 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82543GC_COPPER, |
639 | "Intel i82543GC 1000BASE-T Ethernet", | | 639 | "Intel i82543GC 1000BASE-T Ethernet", |
640 | WM_T_82543, WMP_F_1000T }, | | 640 | WM_T_82543, WMP_F_1000T }, |
641 | | | 641 | |
642 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82544EI_COPPER, | | 642 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82544EI_COPPER, |
643 | "Intel i82544EI 1000BASE-T Ethernet", | | 643 | "Intel i82544EI 1000BASE-T Ethernet", |
644 | WM_T_82544, WMP_F_1000T }, | | 644 | WM_T_82544, WMP_F_1000T }, |
645 | | | 645 | |
646 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82544EI_FIBER, | | 646 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82544EI_FIBER, |
647 | "Intel i82544EI 1000BASE-X Ethernet", | | 647 | "Intel i82544EI 1000BASE-X Ethernet", |
648 | WM_T_82544, WMP_F_1000X }, | | 648 | WM_T_82544, WMP_F_1000X }, |
649 | | | 649 | |
650 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82544GC_COPPER, | | 650 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82544GC_COPPER, |
651 | "Intel i82544GC 1000BASE-T Ethernet", | | 651 | "Intel i82544GC 1000BASE-T Ethernet", |
652 | WM_T_82544, WMP_F_1000T }, | | 652 | WM_T_82544, WMP_F_1000T }, |
653 | | | 653 | |
654 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82544GC_LOM, | | 654 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82544GC_LOM, |
655 | "Intel i82544GC (LOM) 1000BASE-T Ethernet", | | 655 | "Intel i82544GC (LOM) 1000BASE-T Ethernet", |
656 | WM_T_82544, WMP_F_1000T }, | | 656 | WM_T_82544, WMP_F_1000T }, |
657 | | | 657 | |
658 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82540EM, | | 658 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82540EM, |
659 | "Intel i82540EM 1000BASE-T Ethernet", | | 659 | "Intel i82540EM 1000BASE-T Ethernet", |
660 | WM_T_82540, WMP_F_1000T }, | | 660 | WM_T_82540, WMP_F_1000T }, |
661 | | | 661 | |
662 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82540EM_LOM, | | 662 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82540EM_LOM, |
663 | "Intel i82540EM (LOM) 1000BASE-T Ethernet", | | 663 | "Intel i82540EM (LOM) 1000BASE-T Ethernet", |
664 | WM_T_82540, WMP_F_1000T }, | | 664 | WM_T_82540, WMP_F_1000T }, |
665 | | | 665 | |
666 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82540EP_LOM, | | 666 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82540EP_LOM, |
667 | "Intel i82540EP 1000BASE-T Ethernet", | | 667 | "Intel i82540EP 1000BASE-T Ethernet", |
668 | WM_T_82540, WMP_F_1000T }, | | 668 | WM_T_82540, WMP_F_1000T }, |
669 | | | 669 | |
670 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82540EP, | | 670 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82540EP, |
671 | "Intel i82540EP 1000BASE-T Ethernet", | | 671 | "Intel i82540EP 1000BASE-T Ethernet", |
672 | WM_T_82540, WMP_F_1000T }, | | 672 | WM_T_82540, WMP_F_1000T }, |
673 | | | 673 | |
674 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82540EP_LP, | | 674 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82540EP_LP, |
675 | "Intel i82540EP 1000BASE-T Ethernet", | | 675 | "Intel i82540EP 1000BASE-T Ethernet", |
676 | WM_T_82540, WMP_F_1000T }, | | 676 | WM_T_82540, WMP_F_1000T }, |
677 | | | 677 | |
678 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82545EM_COPPER, | | 678 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82545EM_COPPER, |
679 | "Intel i82545EM 1000BASE-T Ethernet", | | 679 | "Intel i82545EM 1000BASE-T Ethernet", |
680 | WM_T_82545, WMP_F_1000T }, | | 680 | WM_T_82545, WMP_F_1000T }, |
681 | | | 681 | |
682 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82545GM_COPPER, | | 682 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82545GM_COPPER, |
683 | "Intel i82545GM 1000BASE-T Ethernet", | | 683 | "Intel i82545GM 1000BASE-T Ethernet", |
684 | WM_T_82545_3, WMP_F_1000T }, | | 684 | WM_T_82545_3, WMP_F_1000T }, |
685 | | | 685 | |
686 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82545GM_FIBER, | | 686 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82545GM_FIBER, |
687 | "Intel i82545GM 1000BASE-X Ethernet", | | 687 | "Intel i82545GM 1000BASE-X Ethernet", |
688 | WM_T_82545_3, WMP_F_1000X }, | | 688 | WM_T_82545_3, WMP_F_1000X }, |
689 | #if 0 | | 689 | #if 0 |
690 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82545GM_SERDES, | | 690 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82545GM_SERDES, |
691 | "Intel i82545GM Gigabit Ethernet (SERDES)", | | 691 | "Intel i82545GM Gigabit Ethernet (SERDES)", |
692 | WM_T_82545_3, WMP_F_SERDES }, | | 692 | WM_T_82545_3, WMP_F_SERDES }, |
693 | #endif | | 693 | #endif |
694 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82546EB_COPPER, | | 694 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82546EB_COPPER, |
695 | "Intel i82546EB 1000BASE-T Ethernet", | | 695 | "Intel i82546EB 1000BASE-T Ethernet", |
696 | WM_T_82546, WMP_F_1000T }, | | 696 | WM_T_82546, WMP_F_1000T }, |
697 | | | 697 | |
698 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82546EB_QUAD, | | 698 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82546EB_QUAD, |
699 | "Intel i82546EB 1000BASE-T Ethernet", | | 699 | "Intel i82546EB 1000BASE-T Ethernet", |
700 | WM_T_82546, WMP_F_1000T }, | | 700 | WM_T_82546, WMP_F_1000T }, |
701 | | | 701 | |
702 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82545EM_FIBER, | | 702 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82545EM_FIBER, |
703 | "Intel i82545EM 1000BASE-X Ethernet", | | 703 | "Intel i82545EM 1000BASE-X Ethernet", |
704 | WM_T_82545, WMP_F_1000X }, | | 704 | WM_T_82545, WMP_F_1000X }, |
705 | | | 705 | |
706 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82546EB_FIBER, | | 706 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82546EB_FIBER, |
707 | "Intel i82546EB 1000BASE-X Ethernet", | | 707 | "Intel i82546EB 1000BASE-X Ethernet", |
708 | WM_T_82546, WMP_F_1000X }, | | 708 | WM_T_82546, WMP_F_1000X }, |
709 | | | 709 | |
710 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82546GB_COPPER, | | 710 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82546GB_COPPER, |
711 | "Intel i82546GB 1000BASE-T Ethernet", | | 711 | "Intel i82546GB 1000BASE-T Ethernet", |
712 | WM_T_82546_3, WMP_F_1000T }, | | 712 | WM_T_82546_3, WMP_F_1000T }, |
713 | | | 713 | |
714 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82546GB_FIBER, | | 714 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82546GB_FIBER, |
715 | "Intel i82546GB 1000BASE-X Ethernet", | | 715 | "Intel i82546GB 1000BASE-X Ethernet", |
716 | WM_T_82546_3, WMP_F_1000X }, | | 716 | WM_T_82546_3, WMP_F_1000X }, |
717 | #if 0 | | 717 | #if 0 |
718 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82546GB_SERDES, | | 718 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82546GB_SERDES, |
719 | "Intel i82546GB Gigabit Ethernet (SERDES)", | | 719 | "Intel i82546GB Gigabit Ethernet (SERDES)", |
720 | WM_T_82546_3, WMP_F_SERDES }, | | 720 | WM_T_82546_3, WMP_F_SERDES }, |
721 | #endif | | 721 | #endif |
722 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82546GB_QUAD_COPPER, | | 722 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82546GB_QUAD_COPPER, |
723 | "i82546GB quad-port Gigabit Ethernet", | | 723 | "i82546GB quad-port Gigabit Ethernet", |
724 | WM_T_82546_3, WMP_F_1000T }, | | 724 | WM_T_82546_3, WMP_F_1000T }, |
725 | | | 725 | |
726 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82546GB_QUAD_COPPER_KSP3, | | 726 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82546GB_QUAD_COPPER_KSP3, |
727 | "i82546GB quad-port Gigabit Ethernet (KSP3)", | | 727 | "i82546GB quad-port Gigabit Ethernet (KSP3)", |
728 | WM_T_82546_3, WMP_F_1000T }, | | 728 | WM_T_82546_3, WMP_F_1000T }, |
729 | | | 729 | |
730 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82546GB_PCIE, | | 730 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82546GB_PCIE, |
731 | "Intel PRO/1000MT (82546GB)", | | 731 | "Intel PRO/1000MT (82546GB)", |
732 | WM_T_82546_3, WMP_F_1000T }, | | 732 | WM_T_82546_3, WMP_F_1000T }, |
733 | | | 733 | |
734 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82541EI, | | 734 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82541EI, |
735 | "Intel i82541EI 1000BASE-T Ethernet", | | 735 | "Intel i82541EI 1000BASE-T Ethernet", |
736 | WM_T_82541, WMP_F_1000T }, | | 736 | WM_T_82541, WMP_F_1000T }, |
737 | | | 737 | |
738 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82541ER_LOM, | | 738 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82541ER_LOM, |
739 | "Intel i82541ER (LOM) 1000BASE-T Ethernet", | | 739 | "Intel i82541ER (LOM) 1000BASE-T Ethernet", |
740 | WM_T_82541, WMP_F_1000T }, | | 740 | WM_T_82541, WMP_F_1000T }, |
741 | | | 741 | |
742 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82541EI_MOBILE, | | 742 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82541EI_MOBILE, |
743 | "Intel i82541EI Mobile 1000BASE-T Ethernet", | | 743 | "Intel i82541EI Mobile 1000BASE-T Ethernet", |
744 | WM_T_82541, WMP_F_1000T }, | | 744 | WM_T_82541, WMP_F_1000T }, |
745 | | | 745 | |
746 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82541ER, | | 746 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82541ER, |
747 | "Intel i82541ER 1000BASE-T Ethernet", | | 747 | "Intel i82541ER 1000BASE-T Ethernet", |
748 | WM_T_82541_2, WMP_F_1000T }, | | 748 | WM_T_82541_2, WMP_F_1000T }, |
749 | | | 749 | |
750 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82541GI, | | 750 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82541GI, |
751 | "Intel i82541GI 1000BASE-T Ethernet", | | 751 | "Intel i82541GI 1000BASE-T Ethernet", |
752 | WM_T_82541_2, WMP_F_1000T }, | | 752 | WM_T_82541_2, WMP_F_1000T }, |
753 | | | 753 | |
754 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82541GI_MOBILE, | | 754 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82541GI_MOBILE, |
755 | "Intel i82541GI Mobile 1000BASE-T Ethernet", | | 755 | "Intel i82541GI Mobile 1000BASE-T Ethernet", |
756 | WM_T_82541_2, WMP_F_1000T }, | | 756 | WM_T_82541_2, WMP_F_1000T }, |
757 | | | 757 | |
758 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82541PI, | | 758 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82541PI, |
759 | "Intel i82541PI 1000BASE-T Ethernet", | | 759 | "Intel i82541PI 1000BASE-T Ethernet", |
760 | WM_T_82541_2, WMP_F_1000T }, | | 760 | WM_T_82541_2, WMP_F_1000T }, |
761 | | | 761 | |
762 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82547EI, | | 762 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82547EI, |
763 | "Intel i82547EI 1000BASE-T Ethernet", | | 763 | "Intel i82547EI 1000BASE-T Ethernet", |
764 | WM_T_82547, WMP_F_1000T }, | | 764 | WM_T_82547, WMP_F_1000T }, |
765 | | | 765 | |
766 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82547EI_MOBILE, | | 766 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82547EI_MOBILE, |
767 | "Intel i82547EI Mobile 1000BASE-T Ethernet", | | 767 | "Intel i82547EI Mobile 1000BASE-T Ethernet", |
768 | WM_T_82547, WMP_F_1000T }, | | 768 | WM_T_82547, WMP_F_1000T }, |
769 | | | 769 | |
770 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82547GI, | | 770 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82547GI, |
771 | "Intel i82547GI 1000BASE-T Ethernet", | | 771 | "Intel i82547GI 1000BASE-T Ethernet", |
772 | WM_T_82547_2, WMP_F_1000T }, | | 772 | WM_T_82547_2, WMP_F_1000T }, |
773 | | | 773 | |
774 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82571EB_COPPER, | | 774 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82571EB_COPPER, |
775 | "Intel PRO/1000 PT (82571EB)", | | 775 | "Intel PRO/1000 PT (82571EB)", |
776 | WM_T_82571, WMP_F_1000T }, | | 776 | WM_T_82571, WMP_F_1000T }, |
777 | | | 777 | |
778 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82571EB_FIBER, | | 778 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82571EB_FIBER, |
779 | "Intel PRO/1000 PF (82571EB)", | | 779 | "Intel PRO/1000 PF (82571EB)", |
780 | WM_T_82571, WMP_F_1000X }, | | 780 | WM_T_82571, WMP_F_1000X }, |
781 | #if 0 | | 781 | #if 0 |
782 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82571EB_SERDES, | | 782 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82571EB_SERDES, |
783 | "Intel PRO/1000 PB (82571EB)", | | 783 | "Intel PRO/1000 PB (82571EB)", |
784 | WM_T_82571, WMP_F_SERDES }, | | 784 | WM_T_82571, WMP_F_SERDES }, |
785 | #endif | | 785 | #endif |
786 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82571EB_QUAD_COPPER, | | 786 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82571EB_QUAD_COPPER, |
787 | "Intel PRO/1000 QT (82571EB)", | | 787 | "Intel PRO/1000 QT (82571EB)", |
788 | WM_T_82571, WMP_F_1000T }, | | 788 | WM_T_82571, WMP_F_1000T }, |
789 | | | 789 | |
790 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82572EI_COPPER, | | 790 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82572EI_COPPER, |
791 | "Intel i82572EI 1000baseT Ethernet", | | 791 | "Intel i82572EI 1000baseT Ethernet", |
792 | WM_T_82572, WMP_F_1000T }, | | 792 | WM_T_82572, WMP_F_1000T }, |
793 | | | 793 | |
794 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82571GB_QUAD_COPPER, | | 794 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82571GB_QUAD_COPPER, |
795 | "Intel PRO/1000 PT Quad Port Server Adapter", | | 795 | "Intel PRO/1000 PT Quad Port Server Adapter", |
796 | WM_T_82571, WMP_F_1000T, }, | | 796 | WM_T_82571, WMP_F_1000T, }, |
797 | | | 797 | |
798 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82572EI_FIBER, | | 798 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82572EI_FIBER, |
799 | "Intel i82572EI 1000baseX Ethernet", | | 799 | "Intel i82572EI 1000baseX Ethernet", |
800 | WM_T_82572, WMP_F_1000X }, | | 800 | WM_T_82572, WMP_F_1000X }, |
801 | #if 0 | | 801 | #if 0 |
802 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82572EI_SERDES, | | 802 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82572EI_SERDES, |
803 | "Intel i82572EI Gigabit Ethernet (SERDES)", | | 803 | "Intel i82572EI Gigabit Ethernet (SERDES)", |
804 | WM_T_82572, WMP_F_SERDES }, | | 804 | WM_T_82572, WMP_F_SERDES }, |
805 | #endif | | 805 | #endif |
806 | | | 806 | |
807 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82572EI, | | 807 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82572EI, |
808 | "Intel i82572EI 1000baseT Ethernet", | | 808 | "Intel i82572EI 1000baseT Ethernet", |
809 | WM_T_82572, WMP_F_1000T }, | | 809 | WM_T_82572, WMP_F_1000T }, |
810 | | | 810 | |
811 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82573E, | | 811 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82573E, |
812 | "Intel i82573E", | | 812 | "Intel i82573E", |
813 | WM_T_82573, WMP_F_1000T }, | | 813 | WM_T_82573, WMP_F_1000T }, |
814 | | | 814 | |
815 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82573E_IAMT, | | 815 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82573E_IAMT, |
816 | "Intel i82573E IAMT", | | 816 | "Intel i82573E IAMT", |
817 | WM_T_82573, WMP_F_1000T }, | | 817 | WM_T_82573, WMP_F_1000T }, |
818 | | | 818 | |
819 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82573L, | | 819 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82573L, |
820 | "Intel i82573L Gigabit Ethernet", | | 820 | "Intel i82573L Gigabit Ethernet", |
821 | WM_T_82573, WMP_F_1000T }, | | 821 | WM_T_82573, WMP_F_1000T }, |
822 | | | 822 | |
823 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82574L, | | 823 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82574L, |
824 | "Intel i82574L", | | 824 | "Intel i82574L", |
825 | WM_T_82574, WMP_F_1000T }, | | 825 | WM_T_82574, WMP_F_1000T }, |
826 | | | 826 | |
827 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82583V, | | 827 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82583V, |
828 | "Intel i82583V", | | 828 | "Intel i82583V", |
829 | WM_T_82583, WMP_F_1000T }, | | 829 | WM_T_82583, WMP_F_1000T }, |
830 | | | 830 | |
831 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_80K3LAN_CPR_DPT, | | 831 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_80K3LAN_CPR_DPT, |
832 | "i80003 dual 1000baseT Ethernet", | | 832 | "i80003 dual 1000baseT Ethernet", |
833 | WM_T_80003, WMP_F_1000T }, | | 833 | WM_T_80003, WMP_F_1000T }, |
834 | | | 834 | |
835 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_80K3LAN_FIB_DPT, | | 835 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_80K3LAN_FIB_DPT, |
836 | "i80003 dual 1000baseX Ethernet", | | 836 | "i80003 dual 1000baseX Ethernet", |
837 | WM_T_80003, WMP_F_1000T }, | | 837 | WM_T_80003, WMP_F_1000T }, |
838 | #if 0 | | 838 | #if 0 |
839 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_80K3LAN_SDS_DPT, | | 839 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_80K3LAN_SDS_DPT, |
840 | "Intel i80003ES2 dual Gigabit Ethernet (SERDES)", | | 840 | "Intel i80003ES2 dual Gigabit Ethernet (SERDES)", |
841 | WM_T_80003, WMP_F_SERDES }, | | 841 | WM_T_80003, WMP_F_SERDES }, |
842 | #endif | | 842 | #endif |
843 | | | 843 | |
844 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_80K3LAN_CPR_SPT, | | 844 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_80K3LAN_CPR_SPT, |
845 | "Intel i80003 1000baseT Ethernet", | | 845 | "Intel i80003 1000baseT Ethernet", |
846 | WM_T_80003, WMP_F_1000T }, | | 846 | WM_T_80003, WMP_F_1000T }, |
847 | #if 0 | | 847 | #if 0 |
848 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_80K3LAN_SDS_SPT, | | 848 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_80K3LAN_SDS_SPT, |
849 | "Intel i80003 Gigabit Ethernet (SERDES)", | | 849 | "Intel i80003 Gigabit Ethernet (SERDES)", |
850 | WM_T_80003, WMP_F_SERDES }, | | 850 | WM_T_80003, WMP_F_SERDES }, |
851 | #endif | | 851 | #endif |
852 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801H_M_AMT, | | 852 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801H_M_AMT, |
853 | "Intel i82801H (M_AMT) LAN Controller", | | 853 | "Intel i82801H (M_AMT) LAN Controller", |
854 | WM_T_ICH8, WMP_F_1000T }, | | 854 | WM_T_ICH8, WMP_F_1000T }, |
855 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801H_AMT, | | 855 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801H_AMT, |
856 | "Intel i82801H (AMT) LAN Controller", | | 856 | "Intel i82801H (AMT) LAN Controller", |
857 | WM_T_ICH8, WMP_F_1000T }, | | 857 | WM_T_ICH8, WMP_F_1000T }, |
858 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801H_LAN, | | 858 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801H_LAN, |
859 | "Intel i82801H LAN Controller", | | 859 | "Intel i82801H LAN Controller", |
860 | WM_T_ICH8, WMP_F_1000T }, | | 860 | WM_T_ICH8, WMP_F_1000T }, |
861 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801H_IFE_LAN, | | 861 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801H_IFE_LAN, |
862 | "Intel i82801H (IFE) LAN Controller", | | 862 | "Intel i82801H (IFE) LAN Controller", |
863 | WM_T_ICH8, WMP_F_1000T }, | | 863 | WM_T_ICH8, WMP_F_1000T }, |
864 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801H_M_LAN, | | 864 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801H_M_LAN, |
865 | "Intel i82801H (M) LAN Controller", | | 865 | "Intel i82801H (M) LAN Controller", |
866 | WM_T_ICH8, WMP_F_1000T }, | | 866 | WM_T_ICH8, WMP_F_1000T }, |
867 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801H_IFE_GT, | | 867 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801H_IFE_GT, |
868 | "Intel i82801H IFE (GT) LAN Controller", | | 868 | "Intel i82801H IFE (GT) LAN Controller", |
869 | WM_T_ICH8, WMP_F_1000T }, | | 869 | WM_T_ICH8, WMP_F_1000T }, |
870 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801H_IFE_G, | | 870 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801H_IFE_G, |
871 | "Intel i82801H IFE (G) LAN Controller", | | 871 | "Intel i82801H IFE (G) LAN Controller", |
872 | WM_T_ICH8, WMP_F_1000T }, | | 872 | WM_T_ICH8, WMP_F_1000T }, |
873 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_IGP_AMT, | | 873 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_IGP_AMT, |
874 | "82801I (AMT) LAN Controller", | | 874 | "82801I (AMT) LAN Controller", |
875 | WM_T_ICH9, WMP_F_1000T }, | | 875 | WM_T_ICH9, WMP_F_1000T }, |
876 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_IFE, | | 876 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_IFE, |
877 | "82801I LAN Controller", | | 877 | "82801I LAN Controller", |
878 | WM_T_ICH9, WMP_F_1000T }, | | 878 | WM_T_ICH9, WMP_F_1000T }, |
879 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_IFE_G, | | 879 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_IFE_G, |
880 | "82801I (G) LAN Controller", | | 880 | "82801I (G) LAN Controller", |
881 | WM_T_ICH9, WMP_F_1000T }, | | 881 | WM_T_ICH9, WMP_F_1000T }, |
882 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_IFE_GT, | | 882 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_IFE_GT, |
883 | "82801I (GT) LAN Controller", | | 883 | "82801I (GT) LAN Controller", |
884 | WM_T_ICH9, WMP_F_1000T }, | | 884 | WM_T_ICH9, WMP_F_1000T }, |
885 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_IGP_C, | | 885 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_IGP_C, |
886 | "82801I (C) LAN Controller", | | 886 | "82801I (C) LAN Controller", |
887 | WM_T_ICH9, WMP_F_1000T }, | | 887 | WM_T_ICH9, WMP_F_1000T }, |
888 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_IGP_M, | | 888 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_IGP_M, |
889 | "82801I mobile LAN Controller", | | 889 | "82801I mobile LAN Controller", |
890 | WM_T_ICH9, WMP_F_1000T }, | | 890 | WM_T_ICH9, WMP_F_1000T }, |
891 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801H_IGP_M_V, | | 891 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801H_IGP_M_V, |
892 | "82801I mobile (V) LAN Controller", | | 892 | "82801I mobile (V) LAN Controller", |
893 | WM_T_ICH9, WMP_F_1000T }, | | 893 | WM_T_ICH9, WMP_F_1000T }, |
894 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_IGP_M_AMT, | | 894 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_IGP_M_AMT, |
895 | "82801I mobile (AMT) LAN Controller", | | 895 | "82801I mobile (AMT) LAN Controller", |
896 | WM_T_ICH9, WMP_F_1000T }, | | 896 | WM_T_ICH9, WMP_F_1000T }, |
897 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_BM, | | 897 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_BM, |
898 | "82567LM-4 LAN Controller", | | 898 | "82567LM-4 LAN Controller", |
899 | WM_T_ICH9, WMP_F_1000T }, | | 899 | WM_T_ICH9, WMP_F_1000T }, |
900 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_82567V_3, | | 900 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_82567V_3, |
901 | "82567V-3 LAN Controller", | | 901 | "82567V-3 LAN Controller", |
902 | WM_T_ICH9, WMP_F_1000T }, | | 902 | WM_T_ICH9, WMP_F_1000T }, |
903 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801J_R_BM_LM, | | 903 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801J_R_BM_LM, |
904 | "82567LM-2 LAN Controller", | | 904 | "82567LM-2 LAN Controller", |
905 | WM_T_ICH10, WMP_F_1000T }, | | 905 | WM_T_ICH10, WMP_F_1000T }, |
906 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801J_R_BM_LF, | | 906 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801J_R_BM_LF, |
907 | "82567LF-2 LAN Controller", | | 907 | "82567LF-2 LAN Controller", |
908 | WM_T_ICH10, WMP_F_1000T }, | | 908 | WM_T_ICH10, WMP_F_1000T }, |
909 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801J_D_BM_LM, | | 909 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801J_D_BM_LM, |
910 | "82567LM-3 LAN Controller", | | 910 | "82567LM-3 LAN Controller", |
911 | WM_T_ICH10, WMP_F_1000T }, | | 911 | WM_T_ICH10, WMP_F_1000T }, |
912 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801J_D_BM_LF, | | 912 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801J_D_BM_LF, |
913 | "82567LF-3 LAN Controller", | | 913 | "82567LF-3 LAN Controller", |
914 | WM_T_ICH10, WMP_F_1000T }, | | 914 | WM_T_ICH10, WMP_F_1000T }, |
915 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801J_R_BM_V, | | 915 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801J_R_BM_V, |
916 | "82567V-2 LAN Controller", | | 916 | "82567V-2 LAN Controller", |
917 | WM_T_ICH10, WMP_F_1000T }, | | 917 | WM_T_ICH10, WMP_F_1000T }, |
918 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801J_D_BM_V, | | 918 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801J_D_BM_V, |
919 | "82567V-3? LAN Controller", | | 919 | "82567V-3? LAN Controller", |
920 | WM_T_ICH10, WMP_F_1000T }, | | 920 | WM_T_ICH10, WMP_F_1000T }, |
921 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_HANKSVILLE, | | 921 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_HANKSVILLE, |
922 | "HANKSVILLE LAN Controller", | | 922 | "HANKSVILLE LAN Controller", |
923 | WM_T_ICH10, WMP_F_1000T }, | | 923 | WM_T_ICH10, WMP_F_1000T }, |
924 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PCH_M_LM, | | 924 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PCH_M_LM, |
925 | "PCH LAN (82577LM) Controller", | | 925 | "PCH LAN (82577LM) Controller", |
926 | WM_T_PCH, WMP_F_1000T }, | | 926 | WM_T_PCH, WMP_F_1000T }, |
927 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PCH_M_LC, | | 927 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PCH_M_LC, |
928 | "PCH LAN (82577LC) Controller", | | 928 | "PCH LAN (82577LC) Controller", |
929 | WM_T_PCH, WMP_F_1000T }, | | 929 | WM_T_PCH, WMP_F_1000T }, |
930 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PCH_D_DM, | | 930 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PCH_D_DM, |
931 | "PCH LAN (82578DM) Controller", | | 931 | "PCH LAN (82578DM) Controller", |
932 | WM_T_PCH, WMP_F_1000T }, | | 932 | WM_T_PCH, WMP_F_1000T }, |
933 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PCH_D_DC, | | 933 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PCH_D_DC, |
934 | "PCH LAN (82578DC) Controller", | | 934 | "PCH LAN (82578DC) Controller", |
935 | WM_T_PCH, WMP_F_1000T }, | | 935 | WM_T_PCH, WMP_F_1000T }, |
936 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PCH2_LV_LM, | | 936 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PCH2_LV_LM, |
937 | "PCH2 LAN (82579LM) Controller", | | 937 | "PCH2 LAN (82579LM) Controller", |
938 | WM_T_PCH2, WMP_F_1000T }, | | 938 | WM_T_PCH2, WMP_F_1000T }, |
939 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PCH2_LV_V, | | 939 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PCH2_LV_V, |
940 | "PCH2 LAN (82579V) Controller", | | 940 | "PCH2 LAN (82579V) Controller", |
941 | WM_T_PCH2, WMP_F_1000T }, | | 941 | WM_T_PCH2, WMP_F_1000T }, |
942 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82575EB_COPPER, | | 942 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82575EB_COPPER, |
943 | "82575EB dual-1000baseT Ethernet", | | 943 | "82575EB dual-1000baseT Ethernet", |
944 | WM_T_82575, WMP_F_1000T }, | | 944 | WM_T_82575, WMP_F_1000T }, |
945 | #if 0 | | 945 | #if 0 |
946 | /* | | 946 | /* |
947 | * not sure if WMP_F_1000X or WMP_F_SERDES - we do not have it - so | | 947 | * not sure if WMP_F_1000X or WMP_F_SERDES - we do not have it - so |
948 | * disabled for now ... | | 948 | * disabled for now ... |
949 | */ | | 949 | */ |
950 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82575EB_FIBER_SERDES, | | 950 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82575EB_FIBER_SERDES, |
951 | "82575EB dual-1000baseX Ethernet (SERDES)", | | 951 | "82575EB dual-1000baseX Ethernet (SERDES)", |
952 | WM_T_82575, WMP_F_SERDES }, | | 952 | WM_T_82575, WMP_F_SERDES }, |
953 | #endif | | 953 | #endif |
954 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82575GB_QUAD_COPPER, | | 954 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82575GB_QUAD_COPPER, |
955 | "82575GB quad-1000baseT Ethernet", | | 955 | "82575GB quad-1000baseT Ethernet", |
956 | WM_T_82575, WMP_F_1000T }, | | 956 | WM_T_82575, WMP_F_1000T }, |
957 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82575GB_QUAD_COPPER_PM, | | 957 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82575GB_QUAD_COPPER_PM, |
958 | "82575GB quad-1000baseT Ethernet (PM)", | | 958 | "82575GB quad-1000baseT Ethernet (PM)", |
959 | WM_T_82575, WMP_F_1000T }, | | 959 | WM_T_82575, WMP_F_1000T }, |
960 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82576_COPPER, | | 960 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82576_COPPER, |
961 | "82576 1000BaseT Ethernet", | | 961 | "82576 1000BaseT Ethernet", |
962 | WM_T_82576, WMP_F_1000T }, | | 962 | WM_T_82576, WMP_F_1000T }, |
963 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82576_FIBER, | | 963 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82576_FIBER, |
964 | "82576 1000BaseX Ethernet", | | 964 | "82576 1000BaseX Ethernet", |
965 | WM_T_82576, WMP_F_1000X }, | | 965 | WM_T_82576, WMP_F_1000X }, |
966 | #if 0 | | 966 | #if 0 |
967 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82576_SERDES, | | 967 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82576_SERDES, |
968 | "82576 gigabit Ethernet (SERDES)", | | 968 | "82576 gigabit Ethernet (SERDES)", |
969 | WM_T_82576, WMP_F_SERDES }, | | 969 | WM_T_82576, WMP_F_SERDES }, |
970 | #endif | | 970 | #endif |
971 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82576_QUAD_COPPER, | | 971 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82576_QUAD_COPPER, |
972 | "82576 quad-1000BaseT Ethernet", | | 972 | "82576 quad-1000BaseT Ethernet", |
973 | WM_T_82576, WMP_F_1000T }, | | 973 | WM_T_82576, WMP_F_1000T }, |
974 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82576_NS, | | 974 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82576_NS, |
975 | "82576 gigabit Ethernet", | | 975 | "82576 gigabit Ethernet", |
976 | WM_T_82576, WMP_F_1000T }, | | 976 | WM_T_82576, WMP_F_1000T }, |
977 | #if 0 | | 977 | #if 0 |
978 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82576_NS_SERDES, | | 978 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82576_NS_SERDES, |
979 | "82576 gigabit Ethernet (SERDES)", | | 979 | "82576 gigabit Ethernet (SERDES)", |
980 | WM_T_82576, WMP_F_SERDES }, | | 980 | WM_T_82576, WMP_F_SERDES }, |
981 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82576_SERDES_QUAD, | | 981 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82576_SERDES_QUAD, |
982 | "82576 quad-gigabit Ethernet (SERDES)", | | 982 | "82576 quad-gigabit Ethernet (SERDES)", |
983 | WM_T_82576, WMP_F_SERDES }, | | 983 | WM_T_82576, WMP_F_SERDES }, |
984 | #endif | | 984 | #endif |
985 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_COPPER, | | 985 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_COPPER, |
986 | "82580 1000BaseT Ethernet", | | 986 | "82580 1000BaseT Ethernet", |
987 | WM_T_82580, WMP_F_1000T }, | | 987 | WM_T_82580, WMP_F_1000T }, |
988 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_FIBER, | | 988 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_FIBER, |
989 | "82580 1000BaseX Ethernet", | | 989 | "82580 1000BaseX Ethernet", |
990 | WM_T_82580, WMP_F_1000X }, | | 990 | WM_T_82580, WMP_F_1000X }, |
991 | #if 0 | | 991 | #if 0 |
992 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_SERDES, | | 992 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_SERDES, |
993 | "82580 1000BaseT Ethernet (SERDES)", | | 993 | "82580 1000BaseT Ethernet (SERDES)", |
994 | WM_T_82580, WMP_F_SERDES }, | | 994 | WM_T_82580, WMP_F_SERDES }, |
995 | #endif | | 995 | #endif |
996 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_SGMII, | | 996 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_SGMII, |
997 | "82580 gigabit Ethernet (SGMII)", | | 997 | "82580 gigabit Ethernet (SGMII)", |
998 | WM_T_82580, WMP_F_1000T }, | | 998 | WM_T_82580, WMP_F_1000T }, |
999 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_COPPER_DUAL, | | 999 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_COPPER_DUAL, |
1000 | "82580 dual-1000BaseT Ethernet", | | 1000 | "82580 dual-1000BaseT Ethernet", |
1001 | WM_T_82580, WMP_F_1000T }, | | 1001 | WM_T_82580, WMP_F_1000T }, |
1002 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_ER, | | 1002 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_ER, |
1003 | "82580 1000BaseT Ethernet", | | 1003 | "82580 1000BaseT Ethernet", |
1004 | WM_T_82580ER, WMP_F_1000T }, | | 1004 | WM_T_82580ER, WMP_F_1000T }, |
1005 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_ER_DUAL, | | 1005 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_ER_DUAL, |
1006 | "82580 dual-1000BaseT Ethernet", | | 1006 | "82580 dual-1000BaseT Ethernet", |
1007 | WM_T_82580ER, WMP_F_1000T }, | | 1007 | WM_T_82580ER, WMP_F_1000T }, |
1008 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_QUAD_FIBER, | | 1008 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_QUAD_FIBER, |
1009 | "82580 quad-1000BaseX Ethernet", | | 1009 | "82580 quad-1000BaseX Ethernet", |
1010 | WM_T_82580, WMP_F_1000X }, | | 1010 | WM_T_82580, WMP_F_1000X }, |
1011 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I350_COPPER, | | 1011 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I350_COPPER, |
1012 | "I350 Gigabit Network Connection", | | 1012 | "I350 Gigabit Network Connection", |
1013 | WM_T_I350, WMP_F_1000T }, | | 1013 | WM_T_I350, WMP_F_1000T }, |
1014 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I350_FIBER, | | 1014 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I350_FIBER, |
1015 | "I350 Gigabit Fiber Network Connection", | | 1015 | "I350 Gigabit Fiber Network Connection", |
1016 | WM_T_I350, WMP_F_1000X }, | | 1016 | WM_T_I350, WMP_F_1000X }, |
1017 | #if 0 | | 1017 | #if 0 |
1018 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I350_SERDES, | | 1018 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I350_SERDES, |
1019 | "I350 Gigabit Backplane Connection", | | 1019 | "I350 Gigabit Backplane Connection", |
1020 | WM_T_I350, WMP_F_SERDES }, | | 1020 | WM_T_I350, WMP_F_SERDES }, |
1021 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I350_SGMII, | | 1021 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I350_SGMII, |
1022 | "I350 Gigabit Connection", | | 1022 | "I350 Gigabit Connection", |
1023 | WM_T_I350, WMP_F_1000T }, | | 1023 | WM_T_I350, WMP_F_1000T }, |
1024 | #endif | | 1024 | #endif |
1025 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I210_T1, | | 1025 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I210_T1, |
1026 | "I210-T1 Ethernet Server Adapter", | | 1026 | "I210-T1 Ethernet Server Adapter", |
1027 | WM_T_I210, WMP_F_1000T }, | | 1027 | WM_T_I210, WMP_F_1000T }, |
1028 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I210_COPPER_OEM1, | | 1028 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I210_COPPER_OEM1, |
1029 | "I210 Ethernet (Copper OEM)", | | 1029 | "I210 Ethernet (Copper OEM)", |
1030 | WM_T_I210, WMP_F_1000T }, | | 1030 | WM_T_I210, WMP_F_1000T }, |
1031 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I210_COPPER_IT, | | 1031 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I210_COPPER_IT, |
1032 | "I210 Ethernet (Copper IT)", | | 1032 | "I210 Ethernet (Copper IT)", |
1033 | WM_T_I210, WMP_F_1000T }, | | 1033 | WM_T_I210, WMP_F_1000T }, |
1034 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I210_FIBER, | | 1034 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I210_FIBER, |
1035 | "I210 Gigabit Ethernet (Fiber)", | | 1035 | "I210 Gigabit Ethernet (Fiber)", |
1036 | WM_T_I210, WMP_F_1000X }, | | 1036 | WM_T_I210, WMP_F_1000X }, |
1037 | #if 0 | | 1037 | #if 0 |
1038 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I210_SERDES, | | 1038 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I210_SERDES, |
1039 | "I210 Gigabit Ethernet (SERDES)", | | 1039 | "I210 Gigabit Ethernet (SERDES)", |
1040 | WM_T_I210, WMP_F_SERDES }, | | 1040 | WM_T_I210, WMP_F_SERDES }, |
1041 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I210_SGMII, | | 1041 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I210_SGMII, |
1042 | "I210 Gigabit Ethernet (SGMII)", | | 1042 | "I210 Gigabit Ethernet (SGMII)", |
1043 | WM_T_I210, WMP_F_SERDES }, | | 1043 | WM_T_I210, WMP_F_SERDES }, |
1044 | #endif | | 1044 | #endif |
1045 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I211_COPPER, | | 1045 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I211_COPPER, |
1046 | "I211 Ethernet (COPPER)", | | 1046 | "I211 Ethernet (COPPER)", |
1047 | WM_T_I211, WMP_F_1000T }, | | 1047 | WM_T_I211, WMP_F_1000T }, |
1048 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I217_V, | | 1048 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I217_V, |
1049 | "I217 V Ethernet Connection", | | 1049 | "I217 V Ethernet Connection", |
1050 | WM_T_PCH_LPT, WMP_F_1000T }, | | 1050 | WM_T_PCH_LPT, WMP_F_1000T }, |
1051 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I217_LM, | | 1051 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I217_LM, |
1052 | "I217 LM Ethernet Connection", | | 1052 | "I217 LM Ethernet Connection", |
1053 | WM_T_PCH_LPT, WMP_F_1000T }, | | 1053 | WM_T_PCH_LPT, WMP_F_1000T }, |
1054 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I218_V, | | 1054 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I218_V, |
1055 | "I218 V Ethernet Connection", | | 1055 | "I218 V Ethernet Connection", |
1056 | WM_T_PCH_LPT, WMP_F_1000T }, | | 1056 | WM_T_PCH_LPT, WMP_F_1000T }, |
1057 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I218_LM, | | 1057 | { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I218_LM, |
1058 | "I218 LM Ethernet Connection", | | 1058 | "I218 LM Ethernet Connection", |
1059 | WM_T_PCH_LPT, WMP_F_1000T }, | | 1059 | WM_T_PCH_LPT, WMP_F_1000T }, |
1060 | { 0, 0, | | 1060 | { 0, 0, |
1061 | NULL, | | 1061 | NULL, |
1062 | 0, 0 }, | | 1062 | 0, 0 }, |
1063 | }; | | 1063 | }; |
1064 | | | 1064 | |
1065 | #ifdef WM_EVENT_COUNTERS | | 1065 | #ifdef WM_EVENT_COUNTERS |
1066 | static char wm_txseg_evcnt_names[WM_NTXSEGS][sizeof("txsegXXX")]; | | 1066 | static char wm_txseg_evcnt_names[WM_NTXSEGS][sizeof("txsegXXX")]; |
1067 | #endif /* WM_EVENT_COUNTERS */ | | 1067 | #endif /* WM_EVENT_COUNTERS */ |
1068 | | | 1068 | |
1069 | #if 0 /* Not currently used */ | | 1069 | #if 0 /* Not currently used */ |
1070 | static inline uint32_t | | 1070 | static inline uint32_t |
1071 | wm_io_read(struct wm_softc *sc, int reg) | | 1071 | wm_io_read(struct wm_softc *sc, int reg) |
1072 | { | | 1072 | { |
1073 | | | 1073 | |
1074 | bus_space_write_4(sc->sc_iot, sc->sc_ioh, 0, reg); | | 1074 | bus_space_write_4(sc->sc_iot, sc->sc_ioh, 0, reg); |
1075 | return (bus_space_read_4(sc->sc_iot, sc->sc_ioh, 4)); | | 1075 | return (bus_space_read_4(sc->sc_iot, sc->sc_ioh, 4)); |
1076 | } | | 1076 | } |
1077 | #endif | | 1077 | #endif |
1078 | | | 1078 | |
| @@ -5346,1999 +5346,2000 @@ wm_validate_eeprom_checksum(struct wm_so | | | @@ -5346,1999 +5346,2000 @@ wm_validate_eeprom_checksum(struct wm_so |
5346 | | | 5346 | |
5347 | /* Don't check for I211 */ | | 5347 | /* Don't check for I211 */ |
5348 | if (sc->sc_type == WM_T_I211) | | 5348 | if (sc->sc_type == WM_T_I211) |
5349 | return 0; | | 5349 | return 0; |
5350 | | | 5350 | |
5351 | if (sc->sc_type == WM_T_PCH_LPT) { | | 5351 | if (sc->sc_type == WM_T_PCH_LPT) { |
5352 | csum_wordaddr = NVM_COMPAT; | | 5352 | csum_wordaddr = NVM_COMPAT; |
5353 | valid_checksum = NVM_COMPAT_VALID_CHECKSUM; | | 5353 | valid_checksum = NVM_COMPAT_VALID_CHECKSUM; |
5354 | } else { | | 5354 | } else { |
5355 | csum_wordaddr = NVM_FUTURE_INIT_WORD1; | | 5355 | csum_wordaddr = NVM_FUTURE_INIT_WORD1; |
5356 | valid_checksum = NVM_FUTURE_INIT_WORD1_VALID_CHECKSUM; | | 5356 | valid_checksum = NVM_FUTURE_INIT_WORD1_VALID_CHECKSUM; |
5357 | } | | 5357 | } |
5358 | | | 5358 | |
5359 | #ifdef WM_DEBUG | | 5359 | #ifdef WM_DEBUG |
5360 | /* Dump EEPROM image for debug */ | | 5360 | /* Dump EEPROM image for debug */ |
5361 | if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9) | | 5361 | if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9) |
5362 | || (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH) | | 5362 | || (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH) |
5363 | || (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT)) { | | 5363 | || (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT)) { |
5364 | wm_read_eeprom(sc, csum_wordaddr, 1, &eeprom_data); | | 5364 | wm_read_eeprom(sc, csum_wordaddr, 1, &eeprom_data); |
5365 | if ((eeprom_data & valid_checksum) == 0) { | | 5365 | if ((eeprom_data & valid_checksum) == 0) { |
5366 | DPRINTF(WM_DEBUG_NVM, | | 5366 | DPRINTF(WM_DEBUG_NVM, |
5367 | ("%s: NVM need to be updated (%04x != %04x)\n", | | 5367 | ("%s: NVM need to be updated (%04x != %04x)\n", |
5368 | device_xname(sc->sc_dev), eeprom_data, | | 5368 | device_xname(sc->sc_dev), eeprom_data, |
5369 | valid_checksum)); | | 5369 | valid_checksum)); |
5370 | } | | 5370 | } |
5371 | } | | 5371 | } |
5372 | | | 5372 | |
5373 | if ((wm_debug & WM_DEBUG_NVM) != 0) { | | 5373 | if ((wm_debug & WM_DEBUG_NVM) != 0) { |
5374 | printf("%s: NVM dump:\n", device_xname(sc->sc_dev)); | | 5374 | printf("%s: NVM dump:\n", device_xname(sc->sc_dev)); |
5375 | for (i = 0; i < EEPROM_SIZE; i++) { | | 5375 | for (i = 0; i < EEPROM_SIZE; i++) { |
5376 | if (wm_read_eeprom(sc, i, 1, &eeprom_data)) | | 5376 | if (wm_read_eeprom(sc, i, 1, &eeprom_data)) |
5377 | printf("XX "); | | 5377 | printf("XX "); |
5378 | else | | 5378 | else |
5379 | printf("%04x ", eeprom_data); | | 5379 | printf("%04x ", eeprom_data); |
5380 | if (i % 8 == 7) | | 5380 | if (i % 8 == 7) |
5381 | printf("\n"); | | 5381 | printf("\n"); |
5382 | } | | 5382 | } |
5383 | } | | 5383 | } |
5384 | | | 5384 | |
5385 | #endif /* WM_DEBUG */ | | 5385 | #endif /* WM_DEBUG */ |
5386 | | | 5386 | |
5387 | for (i = 0; i < EEPROM_SIZE; i++) { | | 5387 | for (i = 0; i < EEPROM_SIZE; i++) { |
5388 | if (wm_read_eeprom(sc, i, 1, &eeprom_data)) | | 5388 | if (wm_read_eeprom(sc, i, 1, &eeprom_data)) |
5389 | return 1; | | 5389 | return 1; |
5390 | checksum += eeprom_data; | | 5390 | checksum += eeprom_data; |
5391 | } | | 5391 | } |
5392 | | | 5392 | |
5393 | if (checksum != (uint16_t) NVM_CHECKSUM) { | | 5393 | if (checksum != (uint16_t) NVM_CHECKSUM) { |
5394 | #ifdef WM_DEBUG | | 5394 | #ifdef WM_DEBUG |
5395 | printf("%s: NVM checksum mismatch (%04x != %04x)\n", | | 5395 | printf("%s: NVM checksum mismatch (%04x != %04x)\n", |
5396 | device_xname(sc->sc_dev), checksum, NVM_CHECKSUM); | | 5396 | device_xname(sc->sc_dev), checksum, NVM_CHECKSUM); |
5397 | #endif | | 5397 | #endif |
5398 | } | | 5398 | } |
5399 | | | 5399 | |
5400 | return 0; | | 5400 | return 0; |
5401 | } | | 5401 | } |
5402 | | | 5402 | |
5403 | /* | | 5403 | /* |
5404 | * wm_read_eeprom: | | 5404 | * wm_read_eeprom: |
5405 | * | | 5405 | * |
5406 | * Read data from the serial EEPROM. | | 5406 | * Read data from the serial EEPROM. |
5407 | */ | | 5407 | */ |
5408 | static int | | 5408 | static int |
5409 | wm_read_eeprom(struct wm_softc *sc, int word, int wordcnt, uint16_t *data) | | 5409 | wm_read_eeprom(struct wm_softc *sc, int word, int wordcnt, uint16_t *data) |
5410 | { | | 5410 | { |
5411 | int rv; | | 5411 | int rv; |
5412 | | | 5412 | |
5413 | if (sc->sc_flags & WM_F_EEPROM_INVALID) | | 5413 | if (sc->sc_flags & WM_F_EEPROM_INVALID) |
5414 | return 1; | | 5414 | return 1; |
5415 | | | 5415 | |
5416 | if (wm_acquire_eeprom(sc)) | | 5416 | if (wm_acquire_eeprom(sc)) |
5417 | return 1; | | 5417 | return 1; |
5418 | | | 5418 | |
5419 | if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9) | | 5419 | if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9) |
5420 | || (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH) | | 5420 | || (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH) |
5421 | || (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT)) | | 5421 | || (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT)) |
5422 | rv = wm_read_eeprom_ich8(sc, word, wordcnt, data); | | 5422 | rv = wm_read_eeprom_ich8(sc, word, wordcnt, data); |
5423 | else if (sc->sc_flags & WM_F_EEPROM_EERDEEWR) | | 5423 | else if (sc->sc_flags & WM_F_EEPROM_EERDEEWR) |
5424 | rv = wm_read_eeprom_eerd(sc, word, wordcnt, data); | | 5424 | rv = wm_read_eeprom_eerd(sc, word, wordcnt, data); |
5425 | else if (sc->sc_flags & WM_F_EEPROM_SPI) | | 5425 | else if (sc->sc_flags & WM_F_EEPROM_SPI) |
5426 | rv = wm_read_eeprom_spi(sc, word, wordcnt, data); | | 5426 | rv = wm_read_eeprom_spi(sc, word, wordcnt, data); |
5427 | else | | 5427 | else |
5428 | rv = wm_read_eeprom_uwire(sc, word, wordcnt, data); | | 5428 | rv = wm_read_eeprom_uwire(sc, word, wordcnt, data); |
5429 | | | 5429 | |
5430 | wm_release_eeprom(sc); | | 5430 | wm_release_eeprom(sc); |
5431 | return rv; | | 5431 | return rv; |
5432 | } | | 5432 | } |
5433 | | | 5433 | |
5434 | static int | | 5434 | static int |
5435 | wm_read_eeprom_eerd(struct wm_softc *sc, int offset, int wordcnt, | | 5435 | wm_read_eeprom_eerd(struct wm_softc *sc, int offset, int wordcnt, |
5436 | uint16_t *data) | | 5436 | uint16_t *data) |
5437 | { | | 5437 | { |
5438 | int i, eerd = 0; | | 5438 | int i, eerd = 0; |
5439 | int error = 0; | | 5439 | int error = 0; |
5440 | | | 5440 | |
5441 | for (i = 0; i < wordcnt; i++) { | | 5441 | for (i = 0; i < wordcnt; i++) { |
5442 | eerd = ((offset + i) << EERD_ADDR_SHIFT) | EERD_START; | | 5442 | eerd = ((offset + i) << EERD_ADDR_SHIFT) | EERD_START; |
5443 | | | 5443 | |
5444 | CSR_WRITE(sc, WMREG_EERD, eerd); | | 5444 | CSR_WRITE(sc, WMREG_EERD, eerd); |
5445 | error = wm_poll_eerd_eewr_done(sc, WMREG_EERD); | | 5445 | error = wm_poll_eerd_eewr_done(sc, WMREG_EERD); |
5446 | if (error != 0) | | 5446 | if (error != 0) |
5447 | break; | | 5447 | break; |
5448 | | | 5448 | |
5449 | data[i] = (CSR_READ(sc, WMREG_EERD) >> EERD_DATA_SHIFT); | | 5449 | data[i] = (CSR_READ(sc, WMREG_EERD) >> EERD_DATA_SHIFT); |
5450 | } | | 5450 | } |
5451 | | | 5451 | |
5452 | return error; | | 5452 | return error; |
5453 | } | | 5453 | } |
5454 | | | 5454 | |
5455 | static int | | 5455 | static int |
5456 | wm_poll_eerd_eewr_done(struct wm_softc *sc, int rw) | | 5456 | wm_poll_eerd_eewr_done(struct wm_softc *sc, int rw) |
5457 | { | | 5457 | { |
5458 | uint32_t attempts = 100000; | | 5458 | uint32_t attempts = 100000; |
5459 | uint32_t i, reg = 0; | | 5459 | uint32_t i, reg = 0; |
5460 | int32_t done = -1; | | 5460 | int32_t done = -1; |
5461 | | | 5461 | |
5462 | for (i = 0; i < attempts; i++) { | | 5462 | for (i = 0; i < attempts; i++) { |
5463 | reg = CSR_READ(sc, rw); | | 5463 | reg = CSR_READ(sc, rw); |
5464 | | | 5464 | |
5465 | if (reg & EERD_DONE) { | | 5465 | if (reg & EERD_DONE) { |
5466 | done = 0; | | 5466 | done = 0; |
5467 | break; | | 5467 | break; |
5468 | } | | 5468 | } |
5469 | delay(5); | | 5469 | delay(5); |
5470 | } | | 5470 | } |
5471 | | | 5471 | |
5472 | return done; | | 5472 | return done; |
5473 | } | | 5473 | } |
5474 | | | 5474 | |
5475 | static int | | 5475 | static int |
5476 | wm_check_alt_mac_addr(struct wm_softc *sc) | | 5476 | wm_check_alt_mac_addr(struct wm_softc *sc) |
5477 | { | | 5477 | { |
5478 | uint16_t myea[ETHER_ADDR_LEN / 2]; | | 5478 | uint16_t myea[ETHER_ADDR_LEN / 2]; |
5479 | uint16_t offset = EEPROM_OFF_MACADDR; | | 5479 | uint16_t offset = EEPROM_OFF_MACADDR; |
5480 | | | 5480 | |
5481 | /* Try to read alternative MAC address pointer */ | | 5481 | /* Try to read alternative MAC address pointer */ |
5482 | if (wm_read_eeprom(sc, EEPROM_ALT_MAC_ADDR_PTR, 1, &offset) != 0) | | 5482 | if (wm_read_eeprom(sc, EEPROM_ALT_MAC_ADDR_PTR, 1, &offset) != 0) |
5483 | return -1; | | 5483 | return -1; |
5484 | | | 5484 | |
5485 | /* Check pointer */ | | 5485 | /* Check pointer */ |
5486 | if (offset == 0xffff) | | 5486 | if (offset == 0xffff) |
5487 | return -1; | | 5487 | return -1; |
5488 | | | 5488 | |
5489 | /* | | 5489 | /* |
5490 | * Check whether alternative MAC address is valid or not. | | 5490 | * Check whether alternative MAC address is valid or not. |
5491 | * Some cards have non 0xffff pointer but those don't use | | 5491 | * Some cards have non 0xffff pointer but those don't use |
5492 | * alternative MAC address in reality. | | 5492 | * alternative MAC address in reality. |
5493 | * | | 5493 | * |
5494 | * Check whether the broadcast bit is set or not. | | 5494 | * Check whether the broadcast bit is set or not. |
5495 | */ | | 5495 | */ |
5496 | if (wm_read_eeprom(sc, offset, 1, myea) == 0) | | 5496 | if (wm_read_eeprom(sc, offset, 1, myea) == 0) |
5497 | if (((myea[0] & 0xff) & 0x01) == 0) | | 5497 | if (((myea[0] & 0xff) & 0x01) == 0) |
5498 | return 0; /* found! */ | | 5498 | return 0; /* found! */ |
5499 | | | 5499 | |
5500 | /* not found */ | | 5500 | /* not found */ |
5501 | return -1; | | 5501 | return -1; |
5502 | } | | 5502 | } |
5503 | | | 5503 | |
5504 | static int | | 5504 | static int |
5505 | wm_read_mac_addr(struct wm_softc *sc, uint8_t *enaddr) | | 5505 | wm_read_mac_addr(struct wm_softc *sc, uint8_t *enaddr) |
5506 | { | | 5506 | { |
5507 | uint16_t myea[ETHER_ADDR_LEN / 2]; | | 5507 | uint16_t myea[ETHER_ADDR_LEN / 2]; |
5508 | uint16_t offset = EEPROM_OFF_MACADDR; | | 5508 | uint16_t offset = EEPROM_OFF_MACADDR; |
5509 | int do_invert = 0; | | 5509 | int do_invert = 0; |
5510 | | | 5510 | |
5511 | switch (sc->sc_type) { | | 5511 | switch (sc->sc_type) { |
5512 | case WM_T_82580: | | 5512 | case WM_T_82580: |
5513 | case WM_T_82580ER: | | 5513 | case WM_T_82580ER: |
5514 | case WM_T_I350: | | 5514 | case WM_T_I350: |
5515 | switch (sc->sc_funcid) { | | 5515 | switch (sc->sc_funcid) { |
5516 | case 0: | | 5516 | case 0: |
5517 | /* default value (== EEPROM_OFF_MACADDR) */ | | 5517 | /* default value (== EEPROM_OFF_MACADDR) */ |
5518 | break; | | 5518 | break; |
5519 | case 1: | | 5519 | case 1: |
5520 | offset = EEPROM_OFF_LAN1; | | 5520 | offset = EEPROM_OFF_LAN1; |
5521 | break; | | 5521 | break; |
5522 | case 2: | | 5522 | case 2: |
5523 | offset = EEPROM_OFF_LAN2; | | 5523 | offset = EEPROM_OFF_LAN2; |
5524 | break; | | 5524 | break; |
5525 | case 3: | | 5525 | case 3: |
5526 | offset = EEPROM_OFF_LAN3; | | 5526 | offset = EEPROM_OFF_LAN3; |
5527 | break; | | 5527 | break; |
5528 | default: | | 5528 | default: |
5529 | goto bad; | | 5529 | goto bad; |
5530 | /* NOTREACHED */ | | 5530 | /* NOTREACHED */ |
5531 | break; | | 5531 | break; |
5532 | } | | 5532 | } |
5533 | break; | | 5533 | break; |
5534 | case WM_T_82571: | | 5534 | case WM_T_82571: |
5535 | case WM_T_82575: | | 5535 | case WM_T_82575: |
5536 | case WM_T_82576: | | 5536 | case WM_T_82576: |
5537 | case WM_T_80003: | | 5537 | case WM_T_80003: |
5538 | case WM_T_I210: | | 5538 | case WM_T_I210: |
5539 | case WM_T_I211: | | 5539 | case WM_T_I211: |
5540 | if (wm_check_alt_mac_addr(sc) != 0) { | | 5540 | if (wm_check_alt_mac_addr(sc) != 0) { |
5541 | /* reset the offset to LAN0 */ | | 5541 | /* reset the offset to LAN0 */ |
5542 | offset = EEPROM_OFF_MACADDR; | | 5542 | offset = EEPROM_OFF_MACADDR; |
5543 | if ((sc->sc_funcid & 0x01) == 1) | | 5543 | if ((sc->sc_funcid & 0x01) == 1) |
5544 | do_invert = 1; | | 5544 | do_invert = 1; |
5545 | goto do_read; | | 5545 | goto do_read; |
5546 | } | | 5546 | } |
5547 | switch (sc->sc_funcid) { | | 5547 | switch (sc->sc_funcid) { |
5548 | case 0: | | 5548 | case 0: |
5549 | /* | | 5549 | /* |
5550 | * The offset is the value in EEPROM_ALT_MAC_ADDR_PTR | | 5550 | * The offset is the value in EEPROM_ALT_MAC_ADDR_PTR |
5551 | * itself. | | 5551 | * itself. |
5552 | */ | | 5552 | */ |
5553 | break; | | 5553 | break; |
5554 | case 1: | | 5554 | case 1: |
5555 | offset += EEPROM_OFF_MACADDR_LAN1; | | 5555 | offset += EEPROM_OFF_MACADDR_LAN1; |
5556 | break; | | 5556 | break; |
5557 | case 2: | | 5557 | case 2: |
5558 | offset += EEPROM_OFF_MACADDR_LAN2; | | 5558 | offset += EEPROM_OFF_MACADDR_LAN2; |
5559 | break; | | 5559 | break; |
5560 | case 3: | | 5560 | case 3: |
5561 | offset += EEPROM_OFF_MACADDR_LAN3; | | 5561 | offset += EEPROM_OFF_MACADDR_LAN3; |
5562 | break; | | 5562 | break; |
5563 | default: | | 5563 | default: |
5564 | goto bad; | | 5564 | goto bad; |
5565 | /* NOTREACHED */ | | 5565 | /* NOTREACHED */ |
5566 | break; | | 5566 | break; |
5567 | } | | 5567 | } |
5568 | break; | | 5568 | break; |
5569 | default: | | 5569 | default: |
5570 | if ((sc->sc_funcid & 0x01) == 1) | | 5570 | if ((sc->sc_funcid & 0x01) == 1) |
5571 | do_invert = 1; | | 5571 | do_invert = 1; |
5572 | break; | | 5572 | break; |
5573 | } | | 5573 | } |
5574 | | | 5574 | |
5575 | do_read: | | 5575 | do_read: |
5576 | if (wm_read_eeprom(sc, offset, sizeof(myea) / sizeof(myea[0]), | | 5576 | if (wm_read_eeprom(sc, offset, sizeof(myea) / sizeof(myea[0]), |
5577 | myea) != 0) { | | 5577 | myea) != 0) { |
5578 | goto bad; | | 5578 | goto bad; |
5579 | } | | 5579 | } |
5580 | | | 5580 | |
5581 | enaddr[0] = myea[0] & 0xff; | | 5581 | enaddr[0] = myea[0] & 0xff; |
5582 | enaddr[1] = myea[0] >> 8; | | 5582 | enaddr[1] = myea[0] >> 8; |
5583 | enaddr[2] = myea[1] & 0xff; | | 5583 | enaddr[2] = myea[1] & 0xff; |
5584 | enaddr[3] = myea[1] >> 8; | | 5584 | enaddr[3] = myea[1] >> 8; |
5585 | enaddr[4] = myea[2] & 0xff; | | 5585 | enaddr[4] = myea[2] & 0xff; |
5586 | enaddr[5] = myea[2] >> 8; | | 5586 | enaddr[5] = myea[2] >> 8; |
5587 | | | 5587 | |
5588 | /* | | 5588 | /* |
5589 | * Toggle the LSB of the MAC address on the second port | | 5589 | * Toggle the LSB of the MAC address on the second port |
5590 | * of some dual port cards. | | 5590 | * of some dual port cards. |
5591 | */ | | 5591 | */ |
5592 | if (do_invert != 0) | | 5592 | if (do_invert != 0) |
5593 | enaddr[5] ^= 1; | | 5593 | enaddr[5] ^= 1; |
5594 | | | 5594 | |
5595 | return 0; | | 5595 | return 0; |
5596 | | | 5596 | |
5597 | bad: | | 5597 | bad: |
5598 | aprint_error_dev(sc->sc_dev, "unable to read Ethernet address\n"); | | 5598 | aprint_error_dev(sc->sc_dev, "unable to read Ethernet address\n"); |
5599 | | | 5599 | |
5600 | return -1; | | 5600 | return -1; |
5601 | } | | 5601 | } |
5602 | | | 5602 | |
5603 | /* | | 5603 | /* |
5604 | * wm_add_rxbuf: | | 5604 | * wm_add_rxbuf: |
5605 | * | | 5605 | * |
5606 | * Add a receive buffer to the indiciated descriptor. | | 5606 | * Add a receive buffer to the indiciated descriptor. |
5607 | */ | | 5607 | */ |
5608 | static int | | 5608 | static int |
5609 | wm_add_rxbuf(struct wm_softc *sc, int idx) | | 5609 | wm_add_rxbuf(struct wm_softc *sc, int idx) |
5610 | { | | 5610 | { |
5611 | struct wm_rxsoft *rxs = &sc->sc_rxsoft[idx]; | | 5611 | struct wm_rxsoft *rxs = &sc->sc_rxsoft[idx]; |
5612 | struct mbuf *m; | | 5612 | struct mbuf *m; |
5613 | int error; | | 5613 | int error; |
5614 | | | 5614 | |
5615 | MGETHDR(m, M_DONTWAIT, MT_DATA); | | 5615 | MGETHDR(m, M_DONTWAIT, MT_DATA); |
5616 | if (m == NULL) | | 5616 | if (m == NULL) |
5617 | return ENOBUFS; | | 5617 | return ENOBUFS; |
5618 | | | 5618 | |
5619 | MCLGET(m, M_DONTWAIT); | | 5619 | MCLGET(m, M_DONTWAIT); |
5620 | if ((m->m_flags & M_EXT) == 0) { | | 5620 | if ((m->m_flags & M_EXT) == 0) { |
5621 | m_freem(m); | | 5621 | m_freem(m); |
5622 | return ENOBUFS; | | 5622 | return ENOBUFS; |
5623 | } | | 5623 | } |
5624 | | | 5624 | |
5625 | if (rxs->rxs_mbuf != NULL) | | 5625 | if (rxs->rxs_mbuf != NULL) |
5626 | bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap); | | 5626 | bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap); |
5627 | | | 5627 | |
5628 | rxs->rxs_mbuf = m; | | 5628 | rxs->rxs_mbuf = m; |
5629 | | | 5629 | |
5630 | m->m_len = m->m_pkthdr.len = m->m_ext.ext_size; | | 5630 | m->m_len = m->m_pkthdr.len = m->m_ext.ext_size; |
5631 | error = bus_dmamap_load_mbuf(sc->sc_dmat, rxs->rxs_dmamap, m, | | 5631 | error = bus_dmamap_load_mbuf(sc->sc_dmat, rxs->rxs_dmamap, m, |
5632 | BUS_DMA_READ|BUS_DMA_NOWAIT); | | 5632 | BUS_DMA_READ|BUS_DMA_NOWAIT); |
5633 | if (error) { | | 5633 | if (error) { |
5634 | /* XXX XXX XXX */ | | 5634 | /* XXX XXX XXX */ |
5635 | aprint_error_dev(sc->sc_dev, | | 5635 | aprint_error_dev(sc->sc_dev, |
5636 | "unable to load rx DMA map %d, error = %d\n", | | 5636 | "unable to load rx DMA map %d, error = %d\n", |
5637 | idx, error); | | 5637 | idx, error); |
5638 | panic("wm_add_rxbuf"); | | 5638 | panic("wm_add_rxbuf"); |
5639 | } | | 5639 | } |
5640 | | | 5640 | |
5641 | bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0, | | 5641 | bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0, |
5642 | rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD); | | 5642 | rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD); |
5643 | | | 5643 | |
5644 | if ((sc->sc_flags & WM_F_NEWQUEUE) != 0) { | | 5644 | if ((sc->sc_flags & WM_F_NEWQUEUE) != 0) { |
5645 | if ((sc->sc_rctl & RCTL_EN) != 0) | | 5645 | if ((sc->sc_rctl & RCTL_EN) != 0) |
5646 | WM_INIT_RXDESC(sc, idx); | | 5646 | WM_INIT_RXDESC(sc, idx); |
5647 | } else | | 5647 | } else |
5648 | WM_INIT_RXDESC(sc, idx); | | 5648 | WM_INIT_RXDESC(sc, idx); |
5649 | | | 5649 | |
5650 | return 0; | | 5650 | return 0; |
5651 | } | | 5651 | } |
5652 | | | 5652 | |
5653 | /* | | 5653 | /* |
5654 | * wm_set_ral: | | 5654 | * wm_set_ral: |
5655 | * | | 5655 | * |
5656 | * Set an entery in the receive address list. | | 5656 | * Set an entery in the receive address list. |
5657 | */ | | 5657 | */ |
5658 | static void | | 5658 | static void |
5659 | wm_set_ral(struct wm_softc *sc, const uint8_t *enaddr, int idx) | | 5659 | wm_set_ral(struct wm_softc *sc, const uint8_t *enaddr, int idx) |
5660 | { | | 5660 | { |
5661 | uint32_t ral_lo, ral_hi; | | 5661 | uint32_t ral_lo, ral_hi; |
5662 | | | 5662 | |
5663 | if (enaddr != NULL) { | | 5663 | if (enaddr != NULL) { |
5664 | ral_lo = enaddr[0] | (enaddr[1] << 8) | (enaddr[2] << 16) | | | 5664 | ral_lo = enaddr[0] | (enaddr[1] << 8) | (enaddr[2] << 16) | |
5665 | (enaddr[3] << 24); | | 5665 | (enaddr[3] << 24); |
5666 | ral_hi = enaddr[4] | (enaddr[5] << 8); | | 5666 | ral_hi = enaddr[4] | (enaddr[5] << 8); |
5667 | ral_hi |= RAL_AV; | | 5667 | ral_hi |= RAL_AV; |
5668 | } else { | | 5668 | } else { |
5669 | ral_lo = 0; | | 5669 | ral_lo = 0; |
5670 | ral_hi = 0; | | 5670 | ral_hi = 0; |
5671 | } | | 5671 | } |
5672 | | | 5672 | |
5673 | if (sc->sc_type >= WM_T_82544) { | | 5673 | if (sc->sc_type >= WM_T_82544) { |
5674 | CSR_WRITE(sc, WMREG_RAL_LO(WMREG_CORDOVA_RAL_BASE, idx), | | 5674 | CSR_WRITE(sc, WMREG_RAL_LO(WMREG_CORDOVA_RAL_BASE, idx), |
5675 | ral_lo); | | 5675 | ral_lo); |
5676 | CSR_WRITE(sc, WMREG_RAL_HI(WMREG_CORDOVA_RAL_BASE, idx), | | 5676 | CSR_WRITE(sc, WMREG_RAL_HI(WMREG_CORDOVA_RAL_BASE, idx), |
5677 | ral_hi); | | 5677 | ral_hi); |
5678 | } else { | | 5678 | } else { |
5679 | CSR_WRITE(sc, WMREG_RAL_LO(WMREG_RAL_BASE, idx), ral_lo); | | 5679 | CSR_WRITE(sc, WMREG_RAL_LO(WMREG_RAL_BASE, idx), ral_lo); |
5680 | CSR_WRITE(sc, WMREG_RAL_HI(WMREG_RAL_BASE, idx), ral_hi); | | 5680 | CSR_WRITE(sc, WMREG_RAL_HI(WMREG_RAL_BASE, idx), ral_hi); |
5681 | } | | 5681 | } |
5682 | } | | 5682 | } |
5683 | | | 5683 | |
5684 | /* | | 5684 | /* |
5685 | * wm_mchash: | | 5685 | * wm_mchash: |
5686 | * | | 5686 | * |
5687 | * Compute the hash of the multicast address for the 4096-bit | | 5687 | * Compute the hash of the multicast address for the 4096-bit |
5688 | * multicast filter. | | 5688 | * multicast filter. |
5689 | */ | | 5689 | */ |
5690 | static uint32_t | | 5690 | static uint32_t |
5691 | wm_mchash(struct wm_softc *sc, const uint8_t *enaddr) | | 5691 | wm_mchash(struct wm_softc *sc, const uint8_t *enaddr) |
5692 | { | | 5692 | { |
5693 | static const int lo_shift[4] = { 4, 3, 2, 0 }; | | 5693 | static const int lo_shift[4] = { 4, 3, 2, 0 }; |
5694 | static const int hi_shift[4] = { 4, 5, 6, 8 }; | | 5694 | static const int hi_shift[4] = { 4, 5, 6, 8 }; |
5695 | static const int ich8_lo_shift[4] = { 6, 5, 4, 2 }; | | 5695 | static const int ich8_lo_shift[4] = { 6, 5, 4, 2 }; |
5696 | static const int ich8_hi_shift[4] = { 2, 3, 4, 6 }; | | 5696 | static const int ich8_hi_shift[4] = { 2, 3, 4, 6 }; |
5697 | uint32_t hash; | | 5697 | uint32_t hash; |
5698 | | | 5698 | |
5699 | if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9) | | 5699 | if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9) |
5700 | || (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH) | | 5700 | || (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH) |
5701 | || (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT)) { | | 5701 | || (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT)) { |
5702 | hash = (enaddr[4] >> ich8_lo_shift[sc->sc_mchash_type]) | | | 5702 | hash = (enaddr[4] >> ich8_lo_shift[sc->sc_mchash_type]) | |
5703 | (((uint16_t) enaddr[5]) << ich8_hi_shift[sc->sc_mchash_type]); | | 5703 | (((uint16_t) enaddr[5]) << ich8_hi_shift[sc->sc_mchash_type]); |
5704 | return (hash & 0x3ff); | | 5704 | return (hash & 0x3ff); |
5705 | } | | 5705 | } |
5706 | hash = (enaddr[4] >> lo_shift[sc->sc_mchash_type]) | | | 5706 | hash = (enaddr[4] >> lo_shift[sc->sc_mchash_type]) | |
5707 | (((uint16_t) enaddr[5]) << hi_shift[sc->sc_mchash_type]); | | 5707 | (((uint16_t) enaddr[5]) << hi_shift[sc->sc_mchash_type]); |
5708 | | | 5708 | |
5709 | return (hash & 0xfff); | | 5709 | return (hash & 0xfff); |
5710 | } | | 5710 | } |
5711 | | | 5711 | |
5712 | /* | | 5712 | /* |
5713 | * wm_set_filter: | | 5713 | * wm_set_filter: |
5714 | * | | 5714 | * |
5715 | * Set up the receive filter. | | 5715 | * Set up the receive filter. |
5716 | */ | | 5716 | */ |
5717 | static void | | 5717 | static void |
5718 | wm_set_filter(struct wm_softc *sc) | | 5718 | wm_set_filter(struct wm_softc *sc) |
5719 | { | | 5719 | { |
5720 | struct ethercom *ec = &sc->sc_ethercom; | | 5720 | struct ethercom *ec = &sc->sc_ethercom; |
5721 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; | | 5721 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
5722 | struct ether_multi *enm; | | 5722 | struct ether_multi *enm; |
5723 | struct ether_multistep step; | | 5723 | struct ether_multistep step; |
5724 | bus_addr_t mta_reg; | | 5724 | bus_addr_t mta_reg; |
5725 | uint32_t hash, reg, bit; | | 5725 | uint32_t hash, reg, bit; |
5726 | int i, size; | | 5726 | int i, size; |
5727 | | | 5727 | |
5728 | if (sc->sc_type >= WM_T_82544) | | 5728 | if (sc->sc_type >= WM_T_82544) |
5729 | mta_reg = WMREG_CORDOVA_MTA; | | 5729 | mta_reg = WMREG_CORDOVA_MTA; |
5730 | else | | 5730 | else |
5731 | mta_reg = WMREG_MTA; | | 5731 | mta_reg = WMREG_MTA; |
5732 | | | 5732 | |
5733 | sc->sc_rctl &= ~(RCTL_BAM | RCTL_UPE | RCTL_MPE); | | 5733 | sc->sc_rctl &= ~(RCTL_BAM | RCTL_UPE | RCTL_MPE); |
5734 | | | 5734 | |
5735 | if (ifp->if_flags & IFF_BROADCAST) | | 5735 | if (ifp->if_flags & IFF_BROADCAST) |
5736 | sc->sc_rctl |= RCTL_BAM; | | 5736 | sc->sc_rctl |= RCTL_BAM; |
5737 | if (ifp->if_flags & IFF_PROMISC) { | | 5737 | if (ifp->if_flags & IFF_PROMISC) { |
5738 | sc->sc_rctl |= RCTL_UPE; | | 5738 | sc->sc_rctl |= RCTL_UPE; |
5739 | goto allmulti; | | 5739 | goto allmulti; |
5740 | } | | 5740 | } |
5741 | | | 5741 | |
5742 | /* | | 5742 | /* |
5743 | * Set the station address in the first RAL slot, and | | 5743 | * Set the station address in the first RAL slot, and |
5744 | * clear the remaining slots. | | 5744 | * clear the remaining slots. |
5745 | */ | | 5745 | */ |
5746 | if (sc->sc_type == WM_T_ICH8) | | 5746 | if (sc->sc_type == WM_T_ICH8) |
5747 | size = WM_RAL_TABSIZE_ICH8 -1; | | 5747 | size = WM_RAL_TABSIZE_ICH8 -1; |
5748 | else if ((sc->sc_type == WM_T_ICH9) || (sc->sc_type == WM_T_ICH10) | | 5748 | else if ((sc->sc_type == WM_T_ICH9) || (sc->sc_type == WM_T_ICH10) |
5749 | || (sc->sc_type == WM_T_PCH) || (sc->sc_type == WM_T_PCH2) | | 5749 | || (sc->sc_type == WM_T_PCH) || (sc->sc_type == WM_T_PCH2) |
5750 | || (sc->sc_type == WM_T_PCH_LPT)) | | 5750 | || (sc->sc_type == WM_T_PCH_LPT)) |
5751 | size = WM_RAL_TABSIZE_ICH8; | | 5751 | size = WM_RAL_TABSIZE_ICH8; |
5752 | else if (sc->sc_type == WM_T_82575) | | 5752 | else if (sc->sc_type == WM_T_82575) |
5753 | size = WM_RAL_TABSIZE_82575; | | 5753 | size = WM_RAL_TABSIZE_82575; |
5754 | else if ((sc->sc_type == WM_T_82576) || (sc->sc_type == WM_T_82580)) | | 5754 | else if ((sc->sc_type == WM_T_82576) || (sc->sc_type == WM_T_82580)) |
5755 | size = WM_RAL_TABSIZE_82576; | | 5755 | size = WM_RAL_TABSIZE_82576; |
5756 | else if (sc->sc_type == WM_T_I350) | | 5756 | else if (sc->sc_type == WM_T_I350) |
5757 | size = WM_RAL_TABSIZE_I350; | | 5757 | size = WM_RAL_TABSIZE_I350; |
5758 | else | | 5758 | else |
5759 | size = WM_RAL_TABSIZE; | | 5759 | size = WM_RAL_TABSIZE; |
5760 | wm_set_ral(sc, CLLADDR(ifp->if_sadl), 0); | | 5760 | wm_set_ral(sc, CLLADDR(ifp->if_sadl), 0); |
5761 | for (i = 1; i < size; i++) | | 5761 | for (i = 1; i < size; i++) |
5762 | wm_set_ral(sc, NULL, i); | | 5762 | wm_set_ral(sc, NULL, i); |
5763 | | | 5763 | |
5764 | if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9) | | 5764 | if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9) |
5765 | || (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH) | | 5765 | || (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH) |
5766 | || (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT)) | | 5766 | || (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT)) |
5767 | size = WM_ICH8_MC_TABSIZE; | | 5767 | size = WM_ICH8_MC_TABSIZE; |
5768 | else | | 5768 | else |
5769 | size = WM_MC_TABSIZE; | | 5769 | size = WM_MC_TABSIZE; |
5770 | /* Clear out the multicast table. */ | | 5770 | /* Clear out the multicast table. */ |
5771 | for (i = 0; i < size; i++) | | 5771 | for (i = 0; i < size; i++) |
5772 | CSR_WRITE(sc, mta_reg + (i << 2), 0); | | 5772 | CSR_WRITE(sc, mta_reg + (i << 2), 0); |
5773 | | | 5773 | |
5774 | ETHER_FIRST_MULTI(step, ec, enm); | | 5774 | ETHER_FIRST_MULTI(step, ec, enm); |
5775 | while (enm != NULL) { | | 5775 | while (enm != NULL) { |
5776 | if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { | | 5776 | if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { |
5777 | /* | | 5777 | /* |
5778 | * We must listen to a range of multicast addresses. | | 5778 | * We must listen to a range of multicast addresses. |
5779 | * For now, just accept all multicasts, rather than | | 5779 | * For now, just accept all multicasts, rather than |
5780 | * trying to set only those filter bits needed to match | | 5780 | * trying to set only those filter bits needed to match |
5781 | * the range. (At this time, the only use of address | | 5781 | * the range. (At this time, the only use of address |
5782 | * ranges is for IP multicast routing, for which the | | 5782 | * ranges is for IP multicast routing, for which the |
5783 | * range is big enough to require all bits set.) | | 5783 | * range is big enough to require all bits set.) |
5784 | */ | | 5784 | */ |
5785 | goto allmulti; | | 5785 | goto allmulti; |
5786 | } | | 5786 | } |
5787 | | | 5787 | |
5788 | hash = wm_mchash(sc, enm->enm_addrlo); | | 5788 | hash = wm_mchash(sc, enm->enm_addrlo); |
5789 | | | 5789 | |
5790 | reg = (hash >> 5); | | 5790 | reg = (hash >> 5); |
5791 | if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9) | | 5791 | if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9) |
5792 | || (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH) | | 5792 | || (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH) |
5793 | || (sc->sc_type == WM_T_PCH2) | | 5793 | || (sc->sc_type == WM_T_PCH2) |
5794 | || (sc->sc_type == WM_T_PCH_LPT)) | | 5794 | || (sc->sc_type == WM_T_PCH_LPT)) |
5795 | reg &= 0x1f; | | 5795 | reg &= 0x1f; |
5796 | else | | 5796 | else |
5797 | reg &= 0x7f; | | 5797 | reg &= 0x7f; |
5798 | bit = hash & 0x1f; | | 5798 | bit = hash & 0x1f; |
5799 | | | 5799 | |
5800 | hash = CSR_READ(sc, mta_reg + (reg << 2)); | | 5800 | hash = CSR_READ(sc, mta_reg + (reg << 2)); |
5801 | hash |= 1U << bit; | | 5801 | hash |= 1U << bit; |
5802 | | | 5802 | |
5803 | /* XXX Hardware bug?? */ | | 5803 | /* XXX Hardware bug?? */ |
5804 | if (sc->sc_type == WM_T_82544 && (reg & 0xe) == 1) { | | 5804 | if (sc->sc_type == WM_T_82544 && (reg & 0xe) == 1) { |
5805 | bit = CSR_READ(sc, mta_reg + ((reg - 1) << 2)); | | 5805 | bit = CSR_READ(sc, mta_reg + ((reg - 1) << 2)); |
5806 | CSR_WRITE(sc, mta_reg + (reg << 2), hash); | | 5806 | CSR_WRITE(sc, mta_reg + (reg << 2), hash); |
5807 | CSR_WRITE(sc, mta_reg + ((reg - 1) << 2), bit); | | 5807 | CSR_WRITE(sc, mta_reg + ((reg - 1) << 2), bit); |
5808 | } else | | 5808 | } else |
5809 | CSR_WRITE(sc, mta_reg + (reg << 2), hash); | | 5809 | CSR_WRITE(sc, mta_reg + (reg << 2), hash); |
5810 | | | 5810 | |
5811 | ETHER_NEXT_MULTI(step, enm); | | 5811 | ETHER_NEXT_MULTI(step, enm); |
5812 | } | | 5812 | } |
5813 | | | 5813 | |
5814 | ifp->if_flags &= ~IFF_ALLMULTI; | | 5814 | ifp->if_flags &= ~IFF_ALLMULTI; |
5815 | goto setit; | | 5815 | goto setit; |
5816 | | | 5816 | |
5817 | allmulti: | | 5817 | allmulti: |
5818 | ifp->if_flags |= IFF_ALLMULTI; | | 5818 | ifp->if_flags |= IFF_ALLMULTI; |
5819 | sc->sc_rctl |= RCTL_MPE; | | 5819 | sc->sc_rctl |= RCTL_MPE; |
5820 | | | 5820 | |
5821 | setit: | | 5821 | setit: |
5822 | CSR_WRITE(sc, WMREG_RCTL, sc->sc_rctl); | | 5822 | CSR_WRITE(sc, WMREG_RCTL, sc->sc_rctl); |
5823 | } | | 5823 | } |
5824 | | | 5824 | |
5825 | /* | | 5825 | /* |
5826 | * wm_tbi_mediainit: | | 5826 | * wm_tbi_mediainit: |
5827 | * | | 5827 | * |
5828 | * Initialize media for use on 1000BASE-X devices. | | 5828 | * Initialize media for use on 1000BASE-X devices. |
5829 | */ | | 5829 | */ |
5830 | static void | | 5830 | static void |
5831 | wm_tbi_mediainit(struct wm_softc *sc) | | 5831 | wm_tbi_mediainit(struct wm_softc *sc) |
5832 | { | | 5832 | { |
5833 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; | | 5833 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
5834 | const char *sep = ""; | | 5834 | const char *sep = ""; |
5835 | | | 5835 | |
5836 | if (sc->sc_type < WM_T_82543) | | 5836 | if (sc->sc_type < WM_T_82543) |
5837 | sc->sc_tipg = TIPG_WM_DFLT; | | 5837 | sc->sc_tipg = TIPG_WM_DFLT; |
5838 | else | | 5838 | else |
5839 | sc->sc_tipg = TIPG_LG_DFLT; | | 5839 | sc->sc_tipg = TIPG_LG_DFLT; |
5840 | | | 5840 | |
5841 | sc->sc_tbi_anegticks = 5; | | 5841 | sc->sc_tbi_anegticks = 5; |
5842 | | | 5842 | |
5843 | /* Initialize our media structures */ | | 5843 | /* Initialize our media structures */ |
5844 | sc->sc_mii.mii_ifp = ifp; | | 5844 | sc->sc_mii.mii_ifp = ifp; |
5845 | | | 5845 | |
5846 | sc->sc_ethercom.ec_mii = &sc->sc_mii; | | 5846 | sc->sc_ethercom.ec_mii = &sc->sc_mii; |
5847 | ifmedia_init(&sc->sc_mii.mii_media, IFM_IMASK, wm_tbi_mediachange, | | 5847 | ifmedia_init(&sc->sc_mii.mii_media, IFM_IMASK, wm_tbi_mediachange, |
5848 | wm_tbi_mediastatus); | | 5848 | wm_tbi_mediastatus); |
5849 | | | 5849 | |
5850 | /* | | 5850 | /* |
5851 | * SWD Pins: | | 5851 | * SWD Pins: |
5852 | * | | 5852 | * |
5853 | * 0 = Link LED (output) | | 5853 | * 0 = Link LED (output) |
5854 | * 1 = Loss Of Signal (input) | | 5854 | * 1 = Loss Of Signal (input) |
5855 | */ | | 5855 | */ |
5856 | sc->sc_ctrl |= CTRL_SWDPIO(0); | | 5856 | sc->sc_ctrl |= CTRL_SWDPIO(0); |
5857 | sc->sc_ctrl &= ~CTRL_SWDPIO(1); | | 5857 | sc->sc_ctrl &= ~CTRL_SWDPIO(1); |
5858 | | | 5858 | |
5859 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); | | 5859 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); |
5860 | | | 5860 | |
5861 | #define ADD(ss, mm, dd) \ | | 5861 | #define ADD(ss, mm, dd) \ |
5862 | do { \ | | 5862 | do { \ |
5863 | aprint_normal("%s%s", sep, ss); \ | | 5863 | aprint_normal("%s%s", sep, ss); \ |
5864 | ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|(mm), (dd), NULL); \ | | 5864 | ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|(mm), (dd), NULL); \ |
5865 | sep = ", "; \ | | 5865 | sep = ", "; \ |
5866 | } while (/*CONSTCOND*/0) | | 5866 | } while (/*CONSTCOND*/0) |
5867 | | | 5867 | |
5868 | aprint_normal_dev(sc->sc_dev, ""); | | 5868 | aprint_normal_dev(sc->sc_dev, ""); |
5869 | ADD("1000baseSX", IFM_1000_SX, ANAR_X_HD); | | 5869 | ADD("1000baseSX", IFM_1000_SX, ANAR_X_HD); |
5870 | ADD("1000baseSX-FDX", IFM_1000_SX|IFM_FDX, ANAR_X_FD); | | 5870 | ADD("1000baseSX-FDX", IFM_1000_SX|IFM_FDX, ANAR_X_FD); |
5871 | ADD("auto", IFM_AUTO, ANAR_X_FD|ANAR_X_HD); | | 5871 | ADD("auto", IFM_AUTO, ANAR_X_FD|ANAR_X_HD); |
5872 | aprint_normal("\n"); | | 5872 | aprint_normal("\n"); |
5873 | | | 5873 | |
5874 | #undef ADD | | 5874 | #undef ADD |
5875 | | | 5875 | |
5876 | ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO); | | 5876 | ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO); |
5877 | } | | 5877 | } |
5878 | | | 5878 | |
5879 | /* | | 5879 | /* |
5880 | * wm_tbi_mediastatus: [ifmedia interface function] | | 5880 | * wm_tbi_mediastatus: [ifmedia interface function] |
5881 | * | | 5881 | * |
5882 | * Get the current interface media status on a 1000BASE-X device. | | 5882 | * Get the current interface media status on a 1000BASE-X device. |
5883 | */ | | 5883 | */ |
5884 | static void | | 5884 | static void |
5885 | wm_tbi_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) | | 5885 | wm_tbi_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) |
5886 | { | | 5886 | { |
5887 | struct wm_softc *sc = ifp->if_softc; | | 5887 | struct wm_softc *sc = ifp->if_softc; |
5888 | uint32_t ctrl, status; | | 5888 | uint32_t ctrl, status; |
5889 | | | 5889 | |
5890 | ifmr->ifm_status = IFM_AVALID; | | 5890 | ifmr->ifm_status = IFM_AVALID; |
5891 | ifmr->ifm_active = IFM_ETHER; | | 5891 | ifmr->ifm_active = IFM_ETHER; |
5892 | | | 5892 | |
5893 | status = CSR_READ(sc, WMREG_STATUS); | | 5893 | status = CSR_READ(sc, WMREG_STATUS); |
5894 | if ((status & STATUS_LU) == 0) { | | 5894 | if ((status & STATUS_LU) == 0) { |
5895 | ifmr->ifm_active |= IFM_NONE; | | 5895 | ifmr->ifm_active |= IFM_NONE; |
5896 | return; | | 5896 | return; |
5897 | } | | 5897 | } |
5898 | | | 5898 | |
5899 | ifmr->ifm_status |= IFM_ACTIVE; | | 5899 | ifmr->ifm_status |= IFM_ACTIVE; |
5900 | ifmr->ifm_active |= IFM_1000_SX; | | 5900 | ifmr->ifm_active |= IFM_1000_SX; |
5901 | if (CSR_READ(sc, WMREG_STATUS) & STATUS_FD) | | 5901 | if (CSR_READ(sc, WMREG_STATUS) & STATUS_FD) |
5902 | ifmr->ifm_active |= IFM_FDX; | | 5902 | ifmr->ifm_active |= IFM_FDX; |
5903 | ctrl = CSR_READ(sc, WMREG_CTRL); | | 5903 | ctrl = CSR_READ(sc, WMREG_CTRL); |
5904 | if (ctrl & CTRL_RFCE) | | 5904 | if (ctrl & CTRL_RFCE) |
5905 | ifmr->ifm_active |= IFM_FLOW | IFM_ETH_RXPAUSE; | | 5905 | ifmr->ifm_active |= IFM_FLOW | IFM_ETH_RXPAUSE; |
5906 | if (ctrl & CTRL_TFCE) | | 5906 | if (ctrl & CTRL_TFCE) |
5907 | ifmr->ifm_active |= IFM_FLOW | IFM_ETH_TXPAUSE; | | 5907 | ifmr->ifm_active |= IFM_FLOW | IFM_ETH_TXPAUSE; |
5908 | } | | 5908 | } |
5909 | | | 5909 | |
5910 | /* | | 5910 | /* |
5911 | * wm_tbi_mediachange: [ifmedia interface function] | | 5911 | * wm_tbi_mediachange: [ifmedia interface function] |
5912 | * | | 5912 | * |
5913 | * Set hardware to newly-selected media on a 1000BASE-X device. | | 5913 | * Set hardware to newly-selected media on a 1000BASE-X device. |
5914 | */ | | 5914 | */ |
5915 | static int | | 5915 | static int |
5916 | wm_tbi_mediachange(struct ifnet *ifp) | | 5916 | wm_tbi_mediachange(struct ifnet *ifp) |
5917 | { | | 5917 | { |
5918 | struct wm_softc *sc = ifp->if_softc; | | 5918 | struct wm_softc *sc = ifp->if_softc; |
5919 | struct ifmedia_entry *ife = sc->sc_mii.mii_media.ifm_cur; | | 5919 | struct ifmedia_entry *ife = sc->sc_mii.mii_media.ifm_cur; |
5920 | uint32_t status; | | 5920 | uint32_t status; |
5921 | int i; | | 5921 | int i; |
5922 | | | 5922 | |
5923 | sc->sc_txcw = 0; | | 5923 | sc->sc_txcw = 0; |
5924 | if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO || | | 5924 | if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO || |
5925 | (sc->sc_mii.mii_media.ifm_media & IFM_FLOW) != 0) | | 5925 | (sc->sc_mii.mii_media.ifm_media & IFM_FLOW) != 0) |
5926 | sc->sc_txcw |= TXCW_SYM_PAUSE | TXCW_ASYM_PAUSE; | | 5926 | sc->sc_txcw |= TXCW_SYM_PAUSE | TXCW_ASYM_PAUSE; |
5927 | if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) { | | 5927 | if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) { |
5928 | sc->sc_txcw |= TXCW_ANE; | | 5928 | sc->sc_txcw |= TXCW_ANE; |
5929 | } else { | | 5929 | } else { |
5930 | /* | | 5930 | /* |
5931 | * If autonegotiation is turned off, force link up and turn on | | 5931 | * If autonegotiation is turned off, force link up and turn on |
5932 | * full duplex | | 5932 | * full duplex |
5933 | */ | | 5933 | */ |
5934 | sc->sc_txcw &= ~TXCW_ANE; | | 5934 | sc->sc_txcw &= ~TXCW_ANE; |
5935 | sc->sc_ctrl |= CTRL_SLU | CTRL_FD; | | 5935 | sc->sc_ctrl |= CTRL_SLU | CTRL_FD; |
5936 | sc->sc_ctrl &= ~(CTRL_TFCE | CTRL_RFCE); | | 5936 | sc->sc_ctrl &= ~(CTRL_TFCE | CTRL_RFCE); |
5937 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); | | 5937 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); |
5938 | delay(1000); | | 5938 | delay(1000); |
5939 | } | | 5939 | } |
5940 | | | 5940 | |
5941 | DPRINTF(WM_DEBUG_LINK,("%s: sc_txcw = 0x%x after autoneg check\n", | | 5941 | DPRINTF(WM_DEBUG_LINK,("%s: sc_txcw = 0x%x after autoneg check\n", |
5942 | device_xname(sc->sc_dev),sc->sc_txcw)); | | 5942 | device_xname(sc->sc_dev),sc->sc_txcw)); |
5943 | CSR_WRITE(sc, WMREG_TXCW, sc->sc_txcw); | | 5943 | CSR_WRITE(sc, WMREG_TXCW, sc->sc_txcw); |
5944 | delay(10000); | | 5944 | delay(10000); |
5945 | | | 5945 | |
5946 | i = CSR_READ(sc, WMREG_CTRL) & CTRL_SWDPIN(1); | | 5946 | i = CSR_READ(sc, WMREG_CTRL) & CTRL_SWDPIN(1); |
5947 | DPRINTF(WM_DEBUG_LINK,("%s: i = 0x%x\n", device_xname(sc->sc_dev),i)); | | 5947 | DPRINTF(WM_DEBUG_LINK,("%s: i = 0x%x\n", device_xname(sc->sc_dev),i)); |
5948 | | | 5948 | |
5949 | /* | | 5949 | /* |
5950 | * On 82544 chips and later, the CTRL_SWDPIN(1) bit will be set if the | | 5950 | * On 82544 chips and later, the CTRL_SWDPIN(1) bit will be set if the |
5951 | * optics detect a signal, 0 if they don't. | | 5951 | * optics detect a signal, 0 if they don't. |
5952 | */ | | 5952 | */ |
5953 | if (((i != 0) && (sc->sc_type > WM_T_82544)) || (i == 0)) { | | 5953 | if (((i != 0) && (sc->sc_type > WM_T_82544)) || (i == 0)) { |
5954 | /* Have signal; wait for the link to come up. */ | | 5954 | /* Have signal; wait for the link to come up. */ |
5955 | | | 5955 | |
5956 | if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) { | | 5956 | if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) { |
5957 | /* | | 5957 | /* |
5958 | * Reset the link, and let autonegotiation do its thing | | 5958 | * Reset the link, and let autonegotiation do its thing |
5959 | */ | | 5959 | */ |
5960 | sc->sc_ctrl |= CTRL_LRST; | | 5960 | sc->sc_ctrl |= CTRL_LRST; |
5961 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); | | 5961 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); |
5962 | delay(1000); | | 5962 | delay(1000); |
5963 | sc->sc_ctrl &= ~CTRL_LRST; | | 5963 | sc->sc_ctrl &= ~CTRL_LRST; |
5964 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); | | 5964 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); |
5965 | delay(1000); | | 5965 | delay(1000); |
5966 | } | | 5966 | } |
5967 | | | 5967 | |
5968 | for (i = 0; i < WM_LINKUP_TIMEOUT; i++) { | | 5968 | for (i = 0; i < WM_LINKUP_TIMEOUT; i++) { |
5969 | delay(10000); | | 5969 | delay(10000); |
5970 | if (CSR_READ(sc, WMREG_STATUS) & STATUS_LU) | | 5970 | if (CSR_READ(sc, WMREG_STATUS) & STATUS_LU) |
5971 | break; | | 5971 | break; |
5972 | } | | 5972 | } |
5973 | | | 5973 | |
5974 | DPRINTF(WM_DEBUG_LINK,("%s: i = %d after waiting for link\n", | | 5974 | DPRINTF(WM_DEBUG_LINK,("%s: i = %d after waiting for link\n", |
5975 | device_xname(sc->sc_dev),i)); | | 5975 | device_xname(sc->sc_dev),i)); |
5976 | | | 5976 | |
5977 | status = CSR_READ(sc, WMREG_STATUS); | | 5977 | status = CSR_READ(sc, WMREG_STATUS); |
5978 | DPRINTF(WM_DEBUG_LINK, | | 5978 | DPRINTF(WM_DEBUG_LINK, |
5979 | ("%s: status after final read = 0x%x, STATUS_LU = 0x%x\n", | | 5979 | ("%s: status after final read = 0x%x, STATUS_LU = 0x%x\n", |
5980 | device_xname(sc->sc_dev),status, STATUS_LU)); | | 5980 | device_xname(sc->sc_dev),status, STATUS_LU)); |
5981 | if (status & STATUS_LU) { | | 5981 | if (status & STATUS_LU) { |
5982 | /* Link is up. */ | | 5982 | /* Link is up. */ |
5983 | DPRINTF(WM_DEBUG_LINK, | | 5983 | DPRINTF(WM_DEBUG_LINK, |
5984 | ("%s: LINK: set media -> link up %s\n", | | 5984 | ("%s: LINK: set media -> link up %s\n", |
5985 | device_xname(sc->sc_dev), | | 5985 | device_xname(sc->sc_dev), |
5986 | (status & STATUS_FD) ? "FDX" : "HDX")); | | 5986 | (status & STATUS_FD) ? "FDX" : "HDX")); |
5987 | | | 5987 | |
5988 | /* | | 5988 | /* |
5989 | * NOTE: CTRL will update TFCE and RFCE automatically, | | 5989 | * NOTE: CTRL will update TFCE and RFCE automatically, |
5990 | * so we should update sc->sc_ctrl | | 5990 | * so we should update sc->sc_ctrl |
5991 | */ | | 5991 | */ |
5992 | sc->sc_ctrl = CSR_READ(sc, WMREG_CTRL); | | 5992 | sc->sc_ctrl = CSR_READ(sc, WMREG_CTRL); |
5993 | sc->sc_tctl &= ~TCTL_COLD(0x3ff); | | 5993 | sc->sc_tctl &= ~TCTL_COLD(0x3ff); |
5994 | sc->sc_fcrtl &= ~FCRTL_XONE; | | 5994 | sc->sc_fcrtl &= ~FCRTL_XONE; |
5995 | if (status & STATUS_FD) | | 5995 | if (status & STATUS_FD) |
5996 | sc->sc_tctl |= | | 5996 | sc->sc_tctl |= |
5997 | TCTL_COLD(TX_COLLISION_DISTANCE_FDX); | | 5997 | TCTL_COLD(TX_COLLISION_DISTANCE_FDX); |
5998 | else | | 5998 | else |
5999 | sc->sc_tctl |= | | 5999 | sc->sc_tctl |= |
6000 | TCTL_COLD(TX_COLLISION_DISTANCE_HDX); | | 6000 | TCTL_COLD(TX_COLLISION_DISTANCE_HDX); |
6001 | if (CSR_READ(sc, WMREG_CTRL) & CTRL_TFCE) | | 6001 | if (CSR_READ(sc, WMREG_CTRL) & CTRL_TFCE) |
6002 | sc->sc_fcrtl |= FCRTL_XONE; | | 6002 | sc->sc_fcrtl |= FCRTL_XONE; |
6003 | CSR_WRITE(sc, WMREG_TCTL, sc->sc_tctl); | | 6003 | CSR_WRITE(sc, WMREG_TCTL, sc->sc_tctl); |
6004 | CSR_WRITE(sc, (sc->sc_type < WM_T_82543) ? | | 6004 | CSR_WRITE(sc, (sc->sc_type < WM_T_82543) ? |
6005 | WMREG_OLD_FCRTL : WMREG_FCRTL, | | 6005 | WMREG_OLD_FCRTL : WMREG_FCRTL, |
6006 | sc->sc_fcrtl); | | 6006 | sc->sc_fcrtl); |
6007 | sc->sc_tbi_linkup = 1; | | 6007 | sc->sc_tbi_linkup = 1; |
6008 | } else { | | 6008 | } else { |
6009 | if (i == WM_LINKUP_TIMEOUT) | | 6009 | if (i == WM_LINKUP_TIMEOUT) |
6010 | wm_check_for_link(sc); | | 6010 | wm_check_for_link(sc); |
6011 | /* Link is down. */ | | 6011 | /* Link is down. */ |
6012 | DPRINTF(WM_DEBUG_LINK, | | 6012 | DPRINTF(WM_DEBUG_LINK, |
6013 | ("%s: LINK: set media -> link down\n", | | 6013 | ("%s: LINK: set media -> link down\n", |
6014 | device_xname(sc->sc_dev))); | | 6014 | device_xname(sc->sc_dev))); |
6015 | sc->sc_tbi_linkup = 0; | | 6015 | sc->sc_tbi_linkup = 0; |
6016 | } | | 6016 | } |
6017 | } else { | | 6017 | } else { |
6018 | DPRINTF(WM_DEBUG_LINK, ("%s: LINK: set media -> no signal\n", | | 6018 | DPRINTF(WM_DEBUG_LINK, ("%s: LINK: set media -> no signal\n", |
6019 | device_xname(sc->sc_dev))); | | 6019 | device_xname(sc->sc_dev))); |
6020 | sc->sc_tbi_linkup = 0; | | 6020 | sc->sc_tbi_linkup = 0; |
6021 | } | | 6021 | } |
6022 | | | 6022 | |
6023 | wm_tbi_set_linkled(sc); | | 6023 | wm_tbi_set_linkled(sc); |
6024 | | | 6024 | |
6025 | return 0; | | 6025 | return 0; |
6026 | } | | 6026 | } |
6027 | | | 6027 | |
6028 | /* | | 6028 | /* |
6029 | * wm_tbi_set_linkled: | | 6029 | * wm_tbi_set_linkled: |
6030 | * | | 6030 | * |
6031 | * Update the link LED on 1000BASE-X devices. | | 6031 | * Update the link LED on 1000BASE-X devices. |
6032 | */ | | 6032 | */ |
6033 | static void | | 6033 | static void |
6034 | wm_tbi_set_linkled(struct wm_softc *sc) | | 6034 | wm_tbi_set_linkled(struct wm_softc *sc) |
6035 | { | | 6035 | { |
6036 | | | 6036 | |
6037 | if (sc->sc_tbi_linkup) | | 6037 | if (sc->sc_tbi_linkup) |
6038 | sc->sc_ctrl |= CTRL_SWDPIN(0); | | 6038 | sc->sc_ctrl |= CTRL_SWDPIN(0); |
6039 | else | | 6039 | else |
6040 | sc->sc_ctrl &= ~CTRL_SWDPIN(0); | | 6040 | sc->sc_ctrl &= ~CTRL_SWDPIN(0); |
6041 | | | 6041 | |
6042 | /* 82540 or newer devices are active low */ | | 6042 | /* 82540 or newer devices are active low */ |
6043 | sc->sc_ctrl ^= (sc->sc_type >= WM_T_82540) ? CTRL_SWDPIN(0) : 0; | | 6043 | sc->sc_ctrl ^= (sc->sc_type >= WM_T_82540) ? CTRL_SWDPIN(0) : 0; |
6044 | | | 6044 | |
6045 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); | | 6045 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); |
6046 | } | | 6046 | } |
6047 | | | 6047 | |
6048 | /* | | 6048 | /* |
6049 | * wm_tbi_check_link: | | 6049 | * wm_tbi_check_link: |
6050 | * | | 6050 | * |
6051 | * Check the link on 1000BASE-X devices. | | 6051 | * Check the link on 1000BASE-X devices. |
6052 | */ | | 6052 | */ |
6053 | static void | | 6053 | static void |
6054 | wm_tbi_check_link(struct wm_softc *sc) | | 6054 | wm_tbi_check_link(struct wm_softc *sc) |
6055 | { | | 6055 | { |
6056 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; | | 6056 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
6057 | struct ifmedia_entry *ife = sc->sc_mii.mii_media.ifm_cur; | | 6057 | struct ifmedia_entry *ife = sc->sc_mii.mii_media.ifm_cur; |
6058 | uint32_t rxcw, ctrl, status; | | 6058 | uint32_t rxcw, ctrl, status; |
6059 | | | 6059 | |
6060 | status = CSR_READ(sc, WMREG_STATUS); | | 6060 | status = CSR_READ(sc, WMREG_STATUS); |
6061 | | | 6061 | |
6062 | rxcw = CSR_READ(sc, WMREG_RXCW); | | 6062 | rxcw = CSR_READ(sc, WMREG_RXCW); |
6063 | ctrl = CSR_READ(sc, WMREG_CTRL); | | 6063 | ctrl = CSR_READ(sc, WMREG_CTRL); |
6064 | | | 6064 | |
6065 | /* set link status */ | | 6065 | /* set link status */ |
6066 | if ((status & STATUS_LU) == 0) { | | 6066 | if ((status & STATUS_LU) == 0) { |
6067 | DPRINTF(WM_DEBUG_LINK, | | 6067 | DPRINTF(WM_DEBUG_LINK, |
6068 | ("%s: LINK: checklink -> down\n", device_xname(sc->sc_dev))); | | 6068 | ("%s: LINK: checklink -> down\n", device_xname(sc->sc_dev))); |
6069 | sc->sc_tbi_linkup = 0; | | 6069 | sc->sc_tbi_linkup = 0; |
6070 | } else if (sc->sc_tbi_linkup == 0) { | | 6070 | } else if (sc->sc_tbi_linkup == 0) { |
6071 | DPRINTF(WM_DEBUG_LINK, | | 6071 | DPRINTF(WM_DEBUG_LINK, |
6072 | ("%s: LINK: checklink -> up %s\n", device_xname(sc->sc_dev), | | 6072 | ("%s: LINK: checklink -> up %s\n", device_xname(sc->sc_dev), |
6073 | (status & STATUS_FD) ? "FDX" : "HDX")); | | 6073 | (status & STATUS_FD) ? "FDX" : "HDX")); |
6074 | sc->sc_tbi_linkup = 1; | | 6074 | sc->sc_tbi_linkup = 1; |
6075 | } | | 6075 | } |
6076 | | | 6076 | |
6077 | if ((sc->sc_ethercom.ec_if.if_flags & IFF_UP) | | 6077 | if ((sc->sc_ethercom.ec_if.if_flags & IFF_UP) |
6078 | && ((status & STATUS_LU) == 0)) { | | 6078 | && ((status & STATUS_LU) == 0)) { |
6079 | sc->sc_tbi_linkup = 0; | | 6079 | sc->sc_tbi_linkup = 0; |
6080 | if (sc->sc_tbi_nrxcfg - sc->sc_tbi_lastnrxcfg > 100) { | | 6080 | if (sc->sc_tbi_nrxcfg - sc->sc_tbi_lastnrxcfg > 100) { |
6081 | /* RXCFG storm! */ | | 6081 | /* RXCFG storm! */ |
6082 | DPRINTF(WM_DEBUG_LINK, ("RXCFG storm! (%d)\n", | | 6082 | DPRINTF(WM_DEBUG_LINK, ("RXCFG storm! (%d)\n", |
6083 | sc->sc_tbi_nrxcfg - sc->sc_tbi_lastnrxcfg)); | | 6083 | sc->sc_tbi_nrxcfg - sc->sc_tbi_lastnrxcfg)); |
6084 | wm_init(ifp); | | 6084 | wm_init(ifp); |
6085 | ifp->if_start(ifp); | | 6085 | ifp->if_start(ifp); |
6086 | } else if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) { | | 6086 | } else if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) { |
6087 | /* If the timer expired, retry autonegotiation */ | | 6087 | /* If the timer expired, retry autonegotiation */ |
6088 | if (++sc->sc_tbi_ticks >= sc->sc_tbi_anegticks) { | | 6088 | if (++sc->sc_tbi_ticks >= sc->sc_tbi_anegticks) { |
6089 | DPRINTF(WM_DEBUG_LINK, ("EXPIRE\n")); | | 6089 | DPRINTF(WM_DEBUG_LINK, ("EXPIRE\n")); |
6090 | sc->sc_tbi_ticks = 0; | | 6090 | sc->sc_tbi_ticks = 0; |
6091 | /* | | 6091 | /* |
6092 | * Reset the link, and let autonegotiation do | | 6092 | * Reset the link, and let autonegotiation do |
6093 | * its thing | | 6093 | * its thing |
6094 | */ | | 6094 | */ |
6095 | sc->sc_ctrl |= CTRL_LRST; | | 6095 | sc->sc_ctrl |= CTRL_LRST; |
6096 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); | | 6096 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); |
6097 | delay(1000); | | 6097 | delay(1000); |
6098 | sc->sc_ctrl &= ~CTRL_LRST; | | 6098 | sc->sc_ctrl &= ~CTRL_LRST; |
6099 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); | | 6099 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); |
6100 | delay(1000); | | 6100 | delay(1000); |
6101 | CSR_WRITE(sc, WMREG_TXCW, | | 6101 | CSR_WRITE(sc, WMREG_TXCW, |
6102 | sc->sc_txcw & ~TXCW_ANE); | | 6102 | sc->sc_txcw & ~TXCW_ANE); |
6103 | CSR_WRITE(sc, WMREG_TXCW, sc->sc_txcw); | | 6103 | CSR_WRITE(sc, WMREG_TXCW, sc->sc_txcw); |
6104 | } | | 6104 | } |
6105 | } | | 6105 | } |
6106 | } | | 6106 | } |
6107 | | | 6107 | |
6108 | wm_tbi_set_linkled(sc); | | 6108 | wm_tbi_set_linkled(sc); |
6109 | } | | 6109 | } |
6110 | | | 6110 | |
6111 | /* | | 6111 | /* |
6112 | * wm_gmii_reset: | | 6112 | * wm_gmii_reset: |
6113 | * | | 6113 | * |
6114 | * Reset the PHY. | | 6114 | * Reset the PHY. |
6115 | */ | | 6115 | */ |
6116 | static void | | 6116 | static void |
6117 | wm_gmii_reset(struct wm_softc *sc) | | 6117 | wm_gmii_reset(struct wm_softc *sc) |
6118 | { | | 6118 | { |
6119 | uint32_t reg; | | 6119 | uint32_t reg; |
6120 | int rv; | | 6120 | int rv; |
6121 | | | 6121 | |
6122 | /* get phy semaphore */ | | 6122 | /* get phy semaphore */ |
6123 | switch (sc->sc_type) { | | 6123 | switch (sc->sc_type) { |
6124 | case WM_T_82571: | | 6124 | case WM_T_82571: |
6125 | case WM_T_82572: | | 6125 | case WM_T_82572: |
6126 | case WM_T_82573: | | 6126 | case WM_T_82573: |
6127 | case WM_T_82574: | | 6127 | case WM_T_82574: |
6128 | case WM_T_82583: | | 6128 | case WM_T_82583: |
6129 | /* XXX should get sw semaphore, too */ | | 6129 | /* XXX should get sw semaphore, too */ |
6130 | rv = wm_get_swsm_semaphore(sc); | | 6130 | rv = wm_get_swsm_semaphore(sc); |
6131 | break; | | 6131 | break; |
6132 | case WM_T_82575: | | 6132 | case WM_T_82575: |
6133 | case WM_T_82576: | | 6133 | case WM_T_82576: |
6134 | case WM_T_82580: | | 6134 | case WM_T_82580: |
6135 | case WM_T_82580ER: | | 6135 | case WM_T_82580ER: |
6136 | case WM_T_I350: | | 6136 | case WM_T_I350: |
6137 | case WM_T_I210: | | 6137 | case WM_T_I210: |
6138 | case WM_T_I211: | | 6138 | case WM_T_I211: |
6139 | case WM_T_80003: | | 6139 | case WM_T_80003: |
6140 | rv = wm_get_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]); | | 6140 | rv = wm_get_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]); |
6141 | break; | | 6141 | break; |
6142 | case WM_T_ICH8: | | 6142 | case WM_T_ICH8: |
6143 | case WM_T_ICH9: | | 6143 | case WM_T_ICH9: |
6144 | case WM_T_ICH10: | | 6144 | case WM_T_ICH10: |
6145 | case WM_T_PCH: | | 6145 | case WM_T_PCH: |
6146 | case WM_T_PCH2: | | 6146 | case WM_T_PCH2: |
6147 | case WM_T_PCH_LPT: | | 6147 | case WM_T_PCH_LPT: |
6148 | rv = wm_get_swfwhw_semaphore(sc); | | 6148 | rv = wm_get_swfwhw_semaphore(sc); |
6149 | break; | | 6149 | break; |
6150 | default: | | 6150 | default: |
6151 | /* nothing to do*/ | | 6151 | /* nothing to do*/ |
6152 | rv = 0; | | 6152 | rv = 0; |
6153 | break; | | 6153 | break; |
6154 | } | | 6154 | } |
6155 | if (rv != 0) { | | 6155 | if (rv != 0) { |
6156 | aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", | | 6156 | aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", |
6157 | __func__); | | 6157 | __func__); |
6158 | return; | | 6158 | return; |
6159 | } | | 6159 | } |
6160 | | | 6160 | |
6161 | switch (sc->sc_type) { | | 6161 | switch (sc->sc_type) { |
6162 | case WM_T_82542_2_0: | | 6162 | case WM_T_82542_2_0: |
6163 | case WM_T_82542_2_1: | | 6163 | case WM_T_82542_2_1: |
6164 | /* null */ | | 6164 | /* null */ |
6165 | break; | | 6165 | break; |
6166 | case WM_T_82543: | | 6166 | case WM_T_82543: |
6167 | /* | | 6167 | /* |
6168 | * With 82543, we need to force speed and duplex on the MAC | | 6168 | * With 82543, we need to force speed and duplex on the MAC |
6169 | * equal to what the PHY speed and duplex configuration is. | | 6169 | * equal to what the PHY speed and duplex configuration is. |
6170 | * In addition, we need to perform a hardware reset on the PHY | | 6170 | * In addition, we need to perform a hardware reset on the PHY |
6171 | * to take it out of reset. | | 6171 | * to take it out of reset. |
6172 | */ | | 6172 | */ |
6173 | sc->sc_ctrl |= CTRL_FRCSPD | CTRL_FRCFDX; | | 6173 | sc->sc_ctrl |= CTRL_FRCSPD | CTRL_FRCFDX; |
6174 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); | | 6174 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); |
6175 | | | 6175 | |
6176 | /* The PHY reset pin is active-low. */ | | 6176 | /* The PHY reset pin is active-low. */ |
6177 | reg = CSR_READ(sc, WMREG_CTRL_EXT); | | 6177 | reg = CSR_READ(sc, WMREG_CTRL_EXT); |
6178 | reg &= ~((CTRL_EXT_SWDPIO_MASK << CTRL_EXT_SWDPIO_SHIFT) | | | 6178 | reg &= ~((CTRL_EXT_SWDPIO_MASK << CTRL_EXT_SWDPIO_SHIFT) | |
6179 | CTRL_EXT_SWDPIN(4)); | | 6179 | CTRL_EXT_SWDPIN(4)); |
6180 | reg |= CTRL_EXT_SWDPIO(4); | | 6180 | reg |= CTRL_EXT_SWDPIO(4); |
6181 | | | 6181 | |
6182 | CSR_WRITE(sc, WMREG_CTRL_EXT, reg); | | 6182 | CSR_WRITE(sc, WMREG_CTRL_EXT, reg); |
6183 | delay(10*1000); | | 6183 | delay(10*1000); |
6184 | | | 6184 | |
6185 | CSR_WRITE(sc, WMREG_CTRL_EXT, reg | CTRL_EXT_SWDPIN(4)); | | 6185 | CSR_WRITE(sc, WMREG_CTRL_EXT, reg | CTRL_EXT_SWDPIN(4)); |
6186 | delay(150); | | 6186 | delay(150); |
6187 | #if 0 | | 6187 | #if 0 |
6188 | sc->sc_ctrl_ext = reg | CTRL_EXT_SWDPIN(4); | | 6188 | sc->sc_ctrl_ext = reg | CTRL_EXT_SWDPIN(4); |
6189 | #endif | | 6189 | #endif |
6190 | delay(20*1000); /* XXX extra delay to get PHY ID? */ | | 6190 | delay(20*1000); /* XXX extra delay to get PHY ID? */ |
6191 | break; | | 6191 | break; |
6192 | case WM_T_82544: /* reset 10000us */ | | 6192 | case WM_T_82544: /* reset 10000us */ |
6193 | case WM_T_82540: | | 6193 | case WM_T_82540: |
6194 | case WM_T_82545: | | 6194 | case WM_T_82545: |
6195 | case WM_T_82545_3: | | 6195 | case WM_T_82545_3: |
6196 | case WM_T_82546: | | 6196 | case WM_T_82546: |
6197 | case WM_T_82546_3: | | 6197 | case WM_T_82546_3: |
6198 | case WM_T_82541: | | 6198 | case WM_T_82541: |
6199 | case WM_T_82541_2: | | 6199 | case WM_T_82541_2: |
6200 | case WM_T_82547: | | 6200 | case WM_T_82547: |
6201 | case WM_T_82547_2: | | 6201 | case WM_T_82547_2: |
6202 | case WM_T_82571: /* reset 100us */ | | 6202 | case WM_T_82571: /* reset 100us */ |
6203 | case WM_T_82572: | | 6203 | case WM_T_82572: |
6204 | case WM_T_82573: | | 6204 | case WM_T_82573: |
6205 | case WM_T_82574: | | 6205 | case WM_T_82574: |
6206 | case WM_T_82575: | | 6206 | case WM_T_82575: |
6207 | case WM_T_82576: | | 6207 | case WM_T_82576: |
6208 | case WM_T_82580: | | 6208 | case WM_T_82580: |
6209 | case WM_T_82580ER: | | 6209 | case WM_T_82580ER: |
6210 | case WM_T_I350: | | 6210 | case WM_T_I350: |
6211 | case WM_T_I210: | | 6211 | case WM_T_I210: |
6212 | case WM_T_I211: | | 6212 | case WM_T_I211: |
6213 | case WM_T_82583: | | 6213 | case WM_T_82583: |
6214 | case WM_T_80003: | | 6214 | case WM_T_80003: |
6215 | /* generic reset */ | | 6215 | /* generic reset */ |
6216 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl | CTRL_PHY_RESET); | | 6216 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl | CTRL_PHY_RESET); |
6217 | delay(20000); | | 6217 | delay(20000); |
6218 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); | | 6218 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); |
6219 | delay(20000); | | 6219 | delay(20000); |
6220 | | | 6220 | |
6221 | if ((sc->sc_type == WM_T_82541) | | 6221 | if ((sc->sc_type == WM_T_82541) |
6222 | || (sc->sc_type == WM_T_82541_2) | | 6222 | || (sc->sc_type == WM_T_82541_2) |
6223 | || (sc->sc_type == WM_T_82547) | | 6223 | || (sc->sc_type == WM_T_82547) |
6224 | || (sc->sc_type == WM_T_82547_2)) { | | 6224 | || (sc->sc_type == WM_T_82547_2)) { |
6225 | /* workaround for igp are done in igp_reset() */ | | 6225 | /* workaround for igp are done in igp_reset() */ |
6226 | /* XXX add code to set LED after phy reset */ | | 6226 | /* XXX add code to set LED after phy reset */ |
6227 | } | | 6227 | } |
6228 | break; | | 6228 | break; |
6229 | case WM_T_ICH8: | | 6229 | case WM_T_ICH8: |
6230 | case WM_T_ICH9: | | 6230 | case WM_T_ICH9: |
6231 | case WM_T_ICH10: | | 6231 | case WM_T_ICH10: |
6232 | case WM_T_PCH: | | 6232 | case WM_T_PCH: |
6233 | case WM_T_PCH2: | | 6233 | case WM_T_PCH2: |
6234 | case WM_T_PCH_LPT: | | 6234 | case WM_T_PCH_LPT: |
6235 | /* generic reset */ | | 6235 | /* generic reset */ |
6236 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl | CTRL_PHY_RESET); | | 6236 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl | CTRL_PHY_RESET); |
6237 | delay(100); | | 6237 | delay(100); |
6238 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); | | 6238 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); |
6239 | delay(150); | | 6239 | delay(150); |
6240 | break; | | 6240 | break; |
6241 | default: | | 6241 | default: |
6242 | panic("%s: %s: unknown type\n", device_xname(sc->sc_dev), | | 6242 | panic("%s: %s: unknown type\n", device_xname(sc->sc_dev), |
6243 | __func__); | | 6243 | __func__); |
6244 | break; | | 6244 | break; |
6245 | } | | 6245 | } |
6246 | | | 6246 | |
6247 | /* release PHY semaphore */ | | 6247 | /* release PHY semaphore */ |
6248 | switch (sc->sc_type) { | | 6248 | switch (sc->sc_type) { |
6249 | case WM_T_82571: | | 6249 | case WM_T_82571: |
6250 | case WM_T_82572: | | 6250 | case WM_T_82572: |
6251 | case WM_T_82573: | | 6251 | case WM_T_82573: |
6252 | case WM_T_82574: | | 6252 | case WM_T_82574: |
6253 | case WM_T_82583: | | 6253 | case WM_T_82583: |
6254 | /* XXX should put sw semaphore, too */ | | 6254 | /* XXX should put sw semaphore, too */ |
6255 | wm_put_swsm_semaphore(sc); | | 6255 | wm_put_swsm_semaphore(sc); |
6256 | break; | | 6256 | break; |
6257 | case WM_T_82575: | | 6257 | case WM_T_82575: |
6258 | case WM_T_82576: | | 6258 | case WM_T_82576: |
6259 | case WM_T_82580: | | 6259 | case WM_T_82580: |
6260 | case WM_T_82580ER: | | 6260 | case WM_T_82580ER: |
6261 | case WM_T_I350: | | 6261 | case WM_T_I350: |
6262 | case WM_T_I210: | | 6262 | case WM_T_I210: |
6263 | case WM_T_I211: | | 6263 | case WM_T_I211: |
6264 | case WM_T_80003: | | 6264 | case WM_T_80003: |
6265 | wm_put_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]); | | 6265 | wm_put_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]); |
6266 | break; | | 6266 | break; |
6267 | case WM_T_ICH8: | | 6267 | case WM_T_ICH8: |
6268 | case WM_T_ICH9: | | 6268 | case WM_T_ICH9: |
6269 | case WM_T_ICH10: | | 6269 | case WM_T_ICH10: |
6270 | case WM_T_PCH: | | 6270 | case WM_T_PCH: |
6271 | case WM_T_PCH2: | | 6271 | case WM_T_PCH2: |
6272 | case WM_T_PCH_LPT: | | 6272 | case WM_T_PCH_LPT: |
6273 | wm_put_swfwhw_semaphore(sc); | | 6273 | wm_put_swfwhw_semaphore(sc); |
6274 | break; | | 6274 | break; |
6275 | default: | | 6275 | default: |
6276 | /* nothing to do*/ | | 6276 | /* nothing to do*/ |
6277 | rv = 0; | | 6277 | rv = 0; |
6278 | break; | | 6278 | break; |
6279 | } | | 6279 | } |
6280 | | | 6280 | |
6281 | /* get_cfg_done */ | | 6281 | /* get_cfg_done */ |
6282 | wm_get_cfg_done(sc); | | 6282 | wm_get_cfg_done(sc); |
6283 | | | 6283 | |
6284 | /* extra setup */ | | 6284 | /* extra setup */ |
6285 | switch (sc->sc_type) { | | 6285 | switch (sc->sc_type) { |
6286 | case WM_T_82542_2_0: | | 6286 | case WM_T_82542_2_0: |
6287 | case WM_T_82542_2_1: | | 6287 | case WM_T_82542_2_1: |
6288 | case WM_T_82543: | | 6288 | case WM_T_82543: |
6289 | case WM_T_82544: | | 6289 | case WM_T_82544: |
6290 | case WM_T_82540: | | 6290 | case WM_T_82540: |
6291 | case WM_T_82545: | | 6291 | case WM_T_82545: |
6292 | case WM_T_82545_3: | | 6292 | case WM_T_82545_3: |
6293 | case WM_T_82546: | | 6293 | case WM_T_82546: |
6294 | case WM_T_82546_3: | | 6294 | case WM_T_82546_3: |
6295 | case WM_T_82541_2: | | 6295 | case WM_T_82541_2: |
6296 | case WM_T_82547_2: | | 6296 | case WM_T_82547_2: |
6297 | case WM_T_82571: | | 6297 | case WM_T_82571: |
6298 | case WM_T_82572: | | 6298 | case WM_T_82572: |
6299 | case WM_T_82573: | | 6299 | case WM_T_82573: |
6300 | case WM_T_82574: | | 6300 | case WM_T_82574: |
6301 | case WM_T_82575: | | 6301 | case WM_T_82575: |
6302 | case WM_T_82576: | | 6302 | case WM_T_82576: |
6303 | case WM_T_82580: | | 6303 | case WM_T_82580: |
6304 | case WM_T_82580ER: | | 6304 | case WM_T_82580ER: |
6305 | case WM_T_I350: | | 6305 | case WM_T_I350: |
6306 | case WM_T_I210: | | 6306 | case WM_T_I210: |
6307 | case WM_T_I211: | | 6307 | case WM_T_I211: |
6308 | case WM_T_82583: | | 6308 | case WM_T_82583: |
6309 | case WM_T_80003: | | 6309 | case WM_T_80003: |
6310 | /* null */ | | 6310 | /* null */ |
6311 | break; | | 6311 | break; |
6312 | case WM_T_82541: | | 6312 | case WM_T_82541: |
6313 | case WM_T_82547: | | 6313 | case WM_T_82547: |
6314 | /* XXX Configure actively LED after PHY reset */ | | 6314 | /* XXX Configure actively LED after PHY reset */ |
6315 | break; | | 6315 | break; |
6316 | case WM_T_ICH8: | | 6316 | case WM_T_ICH8: |
6317 | case WM_T_ICH9: | | 6317 | case WM_T_ICH9: |
6318 | case WM_T_ICH10: | | 6318 | case WM_T_ICH10: |
6319 | case WM_T_PCH: | | 6319 | case WM_T_PCH: |
6320 | case WM_T_PCH2: | | 6320 | case WM_T_PCH2: |
6321 | case WM_T_PCH_LPT: | | 6321 | case WM_T_PCH_LPT: |
6322 | /* Allow time for h/w to get to a quiescent state afer reset */ | | 6322 | /* Allow time for h/w to get to a quiescent state afer reset */ |
6323 | delay(10*1000); | | 6323 | delay(10*1000); |
6324 | | | 6324 | |
6325 | if (sc->sc_type == WM_T_PCH) | | 6325 | if (sc->sc_type == WM_T_PCH) |
6326 | wm_hv_phy_workaround_ich8lan(sc); | | 6326 | wm_hv_phy_workaround_ich8lan(sc); |
6327 | | | 6327 | |
6328 | if (sc->sc_type == WM_T_PCH2) | | 6328 | if (sc->sc_type == WM_T_PCH2) |
6329 | wm_lv_phy_workaround_ich8lan(sc); | | 6329 | wm_lv_phy_workaround_ich8lan(sc); |
6330 | | | 6330 | |
6331 | if ((sc->sc_type == WM_T_PCH) || (sc->sc_type == WM_T_PCH2)) { | | 6331 | if ((sc->sc_type == WM_T_PCH) || (sc->sc_type == WM_T_PCH2)) { |
6332 | /* | | 6332 | /* |
6333 | * dummy read to clear the phy wakeup bit after lcd | | 6333 | * dummy read to clear the phy wakeup bit after lcd |
6334 | * reset | | 6334 | * reset |
6335 | */ | | 6335 | */ |
6336 | reg = wm_gmii_hv_readreg(sc->sc_dev, 1, BM_WUC); | | 6336 | reg = wm_gmii_hv_readreg(sc->sc_dev, 1, BM_WUC); |
6337 | } | | 6337 | } |
6338 | | | 6338 | |
6339 | /* | | 6339 | /* |
6340 | * XXX Configure the LCD with th extended configuration region | | 6340 | * XXX Configure the LCD with th extended configuration region |
6341 | * in NVM | | 6341 | * in NVM |
6342 | */ | | 6342 | */ |
6343 | | | 6343 | |
6344 | /* Configure the LCD with the OEM bits in NVM */ | | 6344 | /* Configure the LCD with the OEM bits in NVM */ |
6345 | if ((sc->sc_type == WM_T_PCH) || (sc->sc_type == WM_T_PCH2)) { | | 6345 | if ((sc->sc_type == WM_T_PCH) || (sc->sc_type == WM_T_PCH2) |
| | | 6346 | || (sc->sc_type == WM_T_PCH_LPT)) { |
6346 | /* | | 6347 | /* |
6347 | * Disable LPLU. | | 6348 | * Disable LPLU. |
6348 | * XXX It seems that 82567 has LPLU, too. | | 6349 | * XXX It seems that 82567 has LPLU, too. |
6349 | */ | | 6350 | */ |
6350 | reg = wm_gmii_hv_readreg(sc->sc_dev, 1, HV_OEM_BITS); | | 6351 | reg = wm_gmii_hv_readreg(sc->sc_dev, 1, HV_OEM_BITS); |
6351 | reg &= ~(HV_OEM_BITS_A1KDIS| HV_OEM_BITS_LPLU); | | 6352 | reg &= ~(HV_OEM_BITS_A1KDIS| HV_OEM_BITS_LPLU); |
6352 | reg |= HV_OEM_BITS_ANEGNOW; | | 6353 | reg |= HV_OEM_BITS_ANEGNOW; |
6353 | wm_gmii_hv_writereg(sc->sc_dev, 1, HV_OEM_BITS, reg); | | 6354 | wm_gmii_hv_writereg(sc->sc_dev, 1, HV_OEM_BITS, reg); |
6354 | } | | 6355 | } |
6355 | break; | | 6356 | break; |
6356 | default: | | 6357 | default: |
6357 | panic("%s: unknown type\n", __func__); | | 6358 | panic("%s: unknown type\n", __func__); |
6358 | break; | | 6359 | break; |
6359 | } | | 6360 | } |
6360 | } | | 6361 | } |
6361 | | | 6362 | |
6362 | /* | | 6363 | /* |
6363 | * wm_gmii_mediainit: | | 6364 | * wm_gmii_mediainit: |
6364 | * | | 6365 | * |
6365 | * Initialize media for use on 1000BASE-T devices. | | 6366 | * Initialize media for use on 1000BASE-T devices. |
6366 | */ | | 6367 | */ |
6367 | static void | | 6368 | static void |
6368 | wm_gmii_mediainit(struct wm_softc *sc, pci_product_id_t prodid) | | 6369 | wm_gmii_mediainit(struct wm_softc *sc, pci_product_id_t prodid) |
6369 | { | | 6370 | { |
6370 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; | | 6371 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
6371 | struct mii_data *mii = &sc->sc_mii; | | 6372 | struct mii_data *mii = &sc->sc_mii; |
6372 | | | 6373 | |
6373 | /* We have MII. */ | | 6374 | /* We have MII. */ |
6374 | sc->sc_flags |= WM_F_HAS_MII; | | 6375 | sc->sc_flags |= WM_F_HAS_MII; |
6375 | | | 6376 | |
6376 | if (sc->sc_type == WM_T_80003) | | 6377 | if (sc->sc_type == WM_T_80003) |
6377 | sc->sc_tipg = TIPG_1000T_80003_DFLT; | | 6378 | sc->sc_tipg = TIPG_1000T_80003_DFLT; |
6378 | else | | 6379 | else |
6379 | sc->sc_tipg = TIPG_1000T_DFLT; | | 6380 | sc->sc_tipg = TIPG_1000T_DFLT; |
6380 | | | 6381 | |
6381 | /* | | 6382 | /* |
6382 | * Let the chip set speed/duplex on its own based on | | 6383 | * Let the chip set speed/duplex on its own based on |
6383 | * signals from the PHY. | | 6384 | * signals from the PHY. |
6384 | * XXXbouyer - I'm not sure this is right for the 80003, | | 6385 | * XXXbouyer - I'm not sure this is right for the 80003, |
6385 | * the em driver only sets CTRL_SLU here - but it seems to work. | | 6386 | * the em driver only sets CTRL_SLU here - but it seems to work. |
6386 | */ | | 6387 | */ |
6387 | sc->sc_ctrl |= CTRL_SLU; | | 6388 | sc->sc_ctrl |= CTRL_SLU; |
6388 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); | | 6389 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); |
6389 | | | 6390 | |
6390 | /* Initialize our media structures and probe the GMII. */ | | 6391 | /* Initialize our media structures and probe the GMII. */ |
6391 | mii->mii_ifp = ifp; | | 6392 | mii->mii_ifp = ifp; |
6392 | | | 6393 | |
6393 | /* | | 6394 | /* |
6394 | * Determine the PHY access method. | | 6395 | * Determine the PHY access method. |
6395 | * | | 6396 | * |
6396 | * For SGMII, use SGMII specific method. | | 6397 | * For SGMII, use SGMII specific method. |
6397 | * | | 6398 | * |
6398 | * For some devices, we can determine the PHY access method | | 6399 | * For some devices, we can determine the PHY access method |
6399 | * from sc_type. | | 6400 | * from sc_type. |
6400 | * | | 6401 | * |
6401 | * For ICH8 variants, it's difficult to detemine the PHY access | | 6402 | * For ICH8 variants, it's difficult to detemine the PHY access |
6402 | * method by sc_type, so use the PCI product ID for some devices. | | 6403 | * method by sc_type, so use the PCI product ID for some devices. |
6403 | * For other ICH8 variants, try to use igp's method. If the PHY | | 6404 | * For other ICH8 variants, try to use igp's method. If the PHY |
6404 | * can't detect, then use bm's method. | | 6405 | * can't detect, then use bm's method. |
6405 | */ | | 6406 | */ |
6406 | switch (prodid) { | | 6407 | switch (prodid) { |
6407 | case PCI_PRODUCT_INTEL_PCH_M_LM: | | 6408 | case PCI_PRODUCT_INTEL_PCH_M_LM: |
6408 | case PCI_PRODUCT_INTEL_PCH_M_LC: | | 6409 | case PCI_PRODUCT_INTEL_PCH_M_LC: |
6409 | /* 82577 */ | | 6410 | /* 82577 */ |
6410 | sc->sc_phytype = WMPHY_82577; | | 6411 | sc->sc_phytype = WMPHY_82577; |
6411 | mii->mii_readreg = wm_gmii_hv_readreg; | | 6412 | mii->mii_readreg = wm_gmii_hv_readreg; |
6412 | mii->mii_writereg = wm_gmii_hv_writereg; | | 6413 | mii->mii_writereg = wm_gmii_hv_writereg; |
6413 | break; | | 6414 | break; |
6414 | case PCI_PRODUCT_INTEL_PCH_D_DM: | | 6415 | case PCI_PRODUCT_INTEL_PCH_D_DM: |
6415 | case PCI_PRODUCT_INTEL_PCH_D_DC: | | 6416 | case PCI_PRODUCT_INTEL_PCH_D_DC: |
6416 | /* 82578 */ | | 6417 | /* 82578 */ |
6417 | sc->sc_phytype = WMPHY_82578; | | 6418 | sc->sc_phytype = WMPHY_82578; |
6418 | mii->mii_readreg = wm_gmii_hv_readreg; | | 6419 | mii->mii_readreg = wm_gmii_hv_readreg; |
6419 | mii->mii_writereg = wm_gmii_hv_writereg; | | 6420 | mii->mii_writereg = wm_gmii_hv_writereg; |
6420 | break; | | 6421 | break; |
6421 | case PCI_PRODUCT_INTEL_PCH2_LV_LM: | | 6422 | case PCI_PRODUCT_INTEL_PCH2_LV_LM: |
6422 | case PCI_PRODUCT_INTEL_PCH2_LV_V: | | 6423 | case PCI_PRODUCT_INTEL_PCH2_LV_V: |
6423 | /* 82579 */ | | 6424 | /* 82579 */ |
6424 | sc->sc_phytype = WMPHY_82579; | | 6425 | sc->sc_phytype = WMPHY_82579; |
6425 | mii->mii_readreg = wm_gmii_hv_readreg; | | 6426 | mii->mii_readreg = wm_gmii_hv_readreg; |
6426 | mii->mii_writereg = wm_gmii_hv_writereg; | | 6427 | mii->mii_writereg = wm_gmii_hv_writereg; |
6427 | break; | | 6428 | break; |
6428 | case PCI_PRODUCT_INTEL_I217_LM: | | 6429 | case PCI_PRODUCT_INTEL_I217_LM: |
6429 | case PCI_PRODUCT_INTEL_I217_V: | | 6430 | case PCI_PRODUCT_INTEL_I217_V: |
6430 | case PCI_PRODUCT_INTEL_I218_LM: | | 6431 | case PCI_PRODUCT_INTEL_I218_LM: |
6431 | case PCI_PRODUCT_INTEL_I218_V: | | 6432 | case PCI_PRODUCT_INTEL_I218_V: |
6432 | /* I21[78] */ | | 6433 | /* I21[78] */ |
6433 | mii->mii_readreg = wm_gmii_hv_readreg; | | 6434 | mii->mii_readreg = wm_gmii_hv_readreg; |
6434 | mii->mii_writereg = wm_gmii_hv_writereg; | | 6435 | mii->mii_writereg = wm_gmii_hv_writereg; |
6435 | break; | | 6436 | break; |
6436 | case PCI_PRODUCT_INTEL_82801I_BM: | | 6437 | case PCI_PRODUCT_INTEL_82801I_BM: |
6437 | case PCI_PRODUCT_INTEL_82801J_R_BM_LM: | | 6438 | case PCI_PRODUCT_INTEL_82801J_R_BM_LM: |
6438 | case PCI_PRODUCT_INTEL_82801J_R_BM_LF: | | 6439 | case PCI_PRODUCT_INTEL_82801J_R_BM_LF: |
6439 | case PCI_PRODUCT_INTEL_82801J_D_BM_LM: | | 6440 | case PCI_PRODUCT_INTEL_82801J_D_BM_LM: |
6440 | case PCI_PRODUCT_INTEL_82801J_D_BM_LF: | | 6441 | case PCI_PRODUCT_INTEL_82801J_D_BM_LF: |
6441 | case PCI_PRODUCT_INTEL_82801J_R_BM_V: | | 6442 | case PCI_PRODUCT_INTEL_82801J_R_BM_V: |
6442 | /* 82567 */ | | 6443 | /* 82567 */ |
6443 | sc->sc_phytype = WMPHY_BM; | | 6444 | sc->sc_phytype = WMPHY_BM; |
6444 | mii->mii_readreg = wm_gmii_bm_readreg; | | 6445 | mii->mii_readreg = wm_gmii_bm_readreg; |
6445 | mii->mii_writereg = wm_gmii_bm_writereg; | | 6446 | mii->mii_writereg = wm_gmii_bm_writereg; |
6446 | break; | | 6447 | break; |
6447 | default: | | 6448 | default: |
6448 | if ((sc->sc_flags & WM_F_SGMII) != 0) { | | 6449 | if ((sc->sc_flags & WM_F_SGMII) != 0) { |
6449 | mii->mii_readreg = wm_sgmii_readreg; | | 6450 | mii->mii_readreg = wm_sgmii_readreg; |
6450 | mii->mii_writereg = wm_sgmii_writereg; | | 6451 | mii->mii_writereg = wm_sgmii_writereg; |
6451 | } else if (sc->sc_type >= WM_T_80003) { | | 6452 | } else if (sc->sc_type >= WM_T_80003) { |
6452 | mii->mii_readreg = wm_gmii_i80003_readreg; | | 6453 | mii->mii_readreg = wm_gmii_i80003_readreg; |
6453 | mii->mii_writereg = wm_gmii_i80003_writereg; | | 6454 | mii->mii_writereg = wm_gmii_i80003_writereg; |
6454 | } else if (sc->sc_type >= WM_T_I210) { | | 6455 | } else if (sc->sc_type >= WM_T_I210) { |
6455 | mii->mii_readreg = wm_gmii_i82544_readreg; | | 6456 | mii->mii_readreg = wm_gmii_i82544_readreg; |
6456 | mii->mii_writereg = wm_gmii_i82544_writereg; | | 6457 | mii->mii_writereg = wm_gmii_i82544_writereg; |
6457 | } else if (sc->sc_type >= WM_T_82580) { | | 6458 | } else if (sc->sc_type >= WM_T_82580) { |
6458 | sc->sc_phytype = WMPHY_82580; | | 6459 | sc->sc_phytype = WMPHY_82580; |
6459 | mii->mii_readreg = wm_gmii_82580_readreg; | | 6460 | mii->mii_readreg = wm_gmii_82580_readreg; |
6460 | mii->mii_writereg = wm_gmii_82580_writereg; | | 6461 | mii->mii_writereg = wm_gmii_82580_writereg; |
6461 | } else if (sc->sc_type >= WM_T_82544) { | | 6462 | } else if (sc->sc_type >= WM_T_82544) { |
6462 | mii->mii_readreg = wm_gmii_i82544_readreg; | | 6463 | mii->mii_readreg = wm_gmii_i82544_readreg; |
6463 | mii->mii_writereg = wm_gmii_i82544_writereg; | | 6464 | mii->mii_writereg = wm_gmii_i82544_writereg; |
6464 | } else { | | 6465 | } else { |
6465 | mii->mii_readreg = wm_gmii_i82543_readreg; | | 6466 | mii->mii_readreg = wm_gmii_i82543_readreg; |
6466 | mii->mii_writereg = wm_gmii_i82543_writereg; | | 6467 | mii->mii_writereg = wm_gmii_i82543_writereg; |
6467 | } | | 6468 | } |
6468 | break; | | 6469 | break; |
6469 | } | | 6470 | } |
6470 | mii->mii_statchg = wm_gmii_statchg; | | 6471 | mii->mii_statchg = wm_gmii_statchg; |
6471 | | | 6472 | |
6472 | wm_gmii_reset(sc); | | 6473 | wm_gmii_reset(sc); |
6473 | | | 6474 | |
6474 | sc->sc_ethercom.ec_mii = &sc->sc_mii; | | 6475 | sc->sc_ethercom.ec_mii = &sc->sc_mii; |
6475 | ifmedia_init(&mii->mii_media, IFM_IMASK, wm_gmii_mediachange, | | 6476 | ifmedia_init(&mii->mii_media, IFM_IMASK, wm_gmii_mediachange, |
6476 | wm_gmii_mediastatus); | | 6477 | wm_gmii_mediastatus); |
6477 | | | 6478 | |
6478 | if ((sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576) | | 6479 | if ((sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576) |
6479 | || (sc->sc_type == WM_T_82580) || (sc->sc_type == WM_T_82580ER) | | 6480 | || (sc->sc_type == WM_T_82580) || (sc->sc_type == WM_T_82580ER) |
6480 | || (sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I210) | | 6481 | || (sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I210) |
6481 | || (sc->sc_type == WM_T_I211)) { | | 6482 | || (sc->sc_type == WM_T_I211)) { |
6482 | if ((sc->sc_flags & WM_F_SGMII) == 0) { | | 6483 | if ((sc->sc_flags & WM_F_SGMII) == 0) { |
6483 | /* Attach only one port */ | | 6484 | /* Attach only one port */ |
6484 | mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, 1, | | 6485 | mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, 1, |
6485 | MII_OFFSET_ANY, MIIF_DOPAUSE); | | 6486 | MII_OFFSET_ANY, MIIF_DOPAUSE); |
6486 | } else { | | 6487 | } else { |
6487 | int i; | | 6488 | int i; |
6488 | uint32_t ctrl_ext; | | 6489 | uint32_t ctrl_ext; |
6489 | | | 6490 | |
6490 | /* Power on sgmii phy if it is disabled */ | | 6491 | /* Power on sgmii phy if it is disabled */ |
6491 | ctrl_ext = CSR_READ(sc, WMREG_CTRL_EXT); | | 6492 | ctrl_ext = CSR_READ(sc, WMREG_CTRL_EXT); |
6492 | CSR_WRITE(sc, WMREG_CTRL_EXT, | | 6493 | CSR_WRITE(sc, WMREG_CTRL_EXT, |
6493 | ctrl_ext &~ CTRL_EXT_SWDPIN(3)); | | 6494 | ctrl_ext &~ CTRL_EXT_SWDPIN(3)); |
6494 | CSR_WRITE_FLUSH(sc); | | 6495 | CSR_WRITE_FLUSH(sc); |
6495 | delay(300*1000); /* XXX too long */ | | 6496 | delay(300*1000); /* XXX too long */ |
6496 | | | 6497 | |
6497 | /* from 1 to 8 */ | | 6498 | /* from 1 to 8 */ |
6498 | for (i = 1; i < 8; i++) | | 6499 | for (i = 1; i < 8; i++) |
6499 | mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, | | 6500 | mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, |
6500 | i, MII_OFFSET_ANY, MIIF_DOPAUSE); | | 6501 | i, MII_OFFSET_ANY, MIIF_DOPAUSE); |
6501 | | | 6502 | |
6502 | /* restore previous sfp cage power state */ | | 6503 | /* restore previous sfp cage power state */ |
6503 | CSR_WRITE(sc, WMREG_CTRL_EXT, ctrl_ext); | | 6504 | CSR_WRITE(sc, WMREG_CTRL_EXT, ctrl_ext); |
6504 | } | | 6505 | } |
6505 | } else { | | 6506 | } else { |
6506 | mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, | | 6507 | mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, |
6507 | MII_OFFSET_ANY, MIIF_DOPAUSE); | | 6508 | MII_OFFSET_ANY, MIIF_DOPAUSE); |
6508 | } | | 6509 | } |
6509 | | | 6510 | |
6510 | /* | | 6511 | /* |
6511 | * If the MAC is PCH2 or PCH_LPT and failed to detect MII PHY, call | | 6512 | * If the MAC is PCH2 or PCH_LPT and failed to detect MII PHY, call |
6512 | * wm_set_mdio_slow_mode_hv() for a workaround and retry. | | 6513 | * wm_set_mdio_slow_mode_hv() for a workaround and retry. |
6513 | */ | | 6514 | */ |
6514 | if (((sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT)) && | | 6515 | if (((sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT)) && |
6515 | (LIST_FIRST(&mii->mii_phys) == NULL)) { | | 6516 | (LIST_FIRST(&mii->mii_phys) == NULL)) { |
6516 | wm_set_mdio_slow_mode_hv(sc); | | 6517 | wm_set_mdio_slow_mode_hv(sc); |
6517 | mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, | | 6518 | mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, |
6518 | MII_OFFSET_ANY, MIIF_DOPAUSE); | | 6519 | MII_OFFSET_ANY, MIIF_DOPAUSE); |
6519 | } | | 6520 | } |
6520 | | | 6521 | |
6521 | /* | | 6522 | /* |
6522 | * (For ICH8 variants) | | 6523 | * (For ICH8 variants) |
6523 | * If PHY detection failed, use BM's r/w function and retry. | | 6524 | * If PHY detection failed, use BM's r/w function and retry. |
6524 | */ | | 6525 | */ |
6525 | if (LIST_FIRST(&mii->mii_phys) == NULL) { | | 6526 | if (LIST_FIRST(&mii->mii_phys) == NULL) { |
6526 | /* if failed, retry with *_bm_* */ | | 6527 | /* if failed, retry with *_bm_* */ |
6527 | mii->mii_readreg = wm_gmii_bm_readreg; | | 6528 | mii->mii_readreg = wm_gmii_bm_readreg; |
6528 | mii->mii_writereg = wm_gmii_bm_writereg; | | 6529 | mii->mii_writereg = wm_gmii_bm_writereg; |
6529 | | | 6530 | |
6530 | mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, | | 6531 | mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, |
6531 | MII_OFFSET_ANY, MIIF_DOPAUSE); | | 6532 | MII_OFFSET_ANY, MIIF_DOPAUSE); |
6532 | } | | 6533 | } |
6533 | | | 6534 | |
6534 | if (LIST_FIRST(&mii->mii_phys) == NULL) { | | 6535 | if (LIST_FIRST(&mii->mii_phys) == NULL) { |
6535 | /* Any PHY wasn't find */ | | 6536 | /* Any PHY wasn't find */ |
6536 | ifmedia_add(&mii->mii_media, IFM_ETHER|IFM_NONE, 0, NULL); | | 6537 | ifmedia_add(&mii->mii_media, IFM_ETHER|IFM_NONE, 0, NULL); |
6537 | ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_NONE); | | 6538 | ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_NONE); |
6538 | sc->sc_phytype = WMPHY_NONE; | | 6539 | sc->sc_phytype = WMPHY_NONE; |
6539 | } else { | | 6540 | } else { |
6540 | /* | | 6541 | /* |
6541 | * PHY Found! | | 6542 | * PHY Found! |
6542 | * Check PHY type. | | 6543 | * Check PHY type. |
6543 | */ | | 6544 | */ |
6544 | uint32_t model; | | 6545 | uint32_t model; |
6545 | struct mii_softc *child; | | 6546 | struct mii_softc *child; |
6546 | | | 6547 | |
6547 | child = LIST_FIRST(&mii->mii_phys); | | 6548 | child = LIST_FIRST(&mii->mii_phys); |
6548 | if (device_is_a(child->mii_dev, "igphy")) { | | 6549 | if (device_is_a(child->mii_dev, "igphy")) { |
6549 | struct igphy_softc *isc = (struct igphy_softc *)child; | | 6550 | struct igphy_softc *isc = (struct igphy_softc *)child; |
6550 | | | 6551 | |
6551 | model = isc->sc_mii.mii_mpd_model; | | 6552 | model = isc->sc_mii.mii_mpd_model; |
6552 | if (model == MII_MODEL_yyINTEL_I82566) | | 6553 | if (model == MII_MODEL_yyINTEL_I82566) |
6553 | sc->sc_phytype = WMPHY_IGP_3; | | 6554 | sc->sc_phytype = WMPHY_IGP_3; |
6554 | } | | 6555 | } |
6555 | | | 6556 | |
6556 | ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); | | 6557 | ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); |
6557 | } | | 6558 | } |
6558 | } | | 6559 | } |
6559 | | | 6560 | |
6560 | /* | | 6561 | /* |
6561 | * wm_gmii_mediastatus: [ifmedia interface function] | | 6562 | * wm_gmii_mediastatus: [ifmedia interface function] |
6562 | * | | 6563 | * |
6563 | * Get the current interface media status on a 1000BASE-T device. | | 6564 | * Get the current interface media status on a 1000BASE-T device. |
6564 | */ | | 6565 | */ |
6565 | static void | | 6566 | static void |
6566 | wm_gmii_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) | | 6567 | wm_gmii_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) |
6567 | { | | 6568 | { |
6568 | struct wm_softc *sc = ifp->if_softc; | | 6569 | struct wm_softc *sc = ifp->if_softc; |
6569 | | | 6570 | |
6570 | ether_mediastatus(ifp, ifmr); | | 6571 | ether_mediastatus(ifp, ifmr); |
6571 | ifmr->ifm_active = (ifmr->ifm_active & ~IFM_ETH_FMASK) | | 6572 | ifmr->ifm_active = (ifmr->ifm_active & ~IFM_ETH_FMASK) |
6572 | | sc->sc_flowflags; | | 6573 | | sc->sc_flowflags; |
6573 | } | | 6574 | } |
6574 | | | 6575 | |
6575 | /* | | 6576 | /* |
6576 | * wm_gmii_mediachange: [ifmedia interface function] | | 6577 | * wm_gmii_mediachange: [ifmedia interface function] |
6577 | * | | 6578 | * |
6578 | * Set hardware to newly-selected media on a 1000BASE-T device. | | 6579 | * Set hardware to newly-selected media on a 1000BASE-T device. |
6579 | */ | | 6580 | */ |
6580 | static int | | 6581 | static int |
6581 | wm_gmii_mediachange(struct ifnet *ifp) | | 6582 | wm_gmii_mediachange(struct ifnet *ifp) |
6582 | { | | 6583 | { |
6583 | struct wm_softc *sc = ifp->if_softc; | | 6584 | struct wm_softc *sc = ifp->if_softc; |
6584 | struct ifmedia_entry *ife = sc->sc_mii.mii_media.ifm_cur; | | 6585 | struct ifmedia_entry *ife = sc->sc_mii.mii_media.ifm_cur; |
6585 | int rc; | | 6586 | int rc; |
6586 | | | 6587 | |
6587 | if ((ifp->if_flags & IFF_UP) == 0) | | 6588 | if ((ifp->if_flags & IFF_UP) == 0) |
6588 | return 0; | | 6589 | return 0; |
6589 | | | 6590 | |
6590 | sc->sc_ctrl &= ~(CTRL_SPEED_MASK | CTRL_FD); | | 6591 | sc->sc_ctrl &= ~(CTRL_SPEED_MASK | CTRL_FD); |
6591 | sc->sc_ctrl |= CTRL_SLU; | | 6592 | sc->sc_ctrl |= CTRL_SLU; |
6592 | if ((IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) | | 6593 | if ((IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) |
6593 | || (sc->sc_type > WM_T_82543)) { | | 6594 | || (sc->sc_type > WM_T_82543)) { |
6594 | sc->sc_ctrl &= ~(CTRL_FRCSPD | CTRL_FRCFDX); | | 6595 | sc->sc_ctrl &= ~(CTRL_FRCSPD | CTRL_FRCFDX); |
6595 | } else { | | 6596 | } else { |
6596 | sc->sc_ctrl &= ~CTRL_ASDE; | | 6597 | sc->sc_ctrl &= ~CTRL_ASDE; |
6597 | sc->sc_ctrl |= CTRL_FRCSPD | CTRL_FRCFDX; | | 6598 | sc->sc_ctrl |= CTRL_FRCSPD | CTRL_FRCFDX; |
6598 | if (ife->ifm_media & IFM_FDX) | | 6599 | if (ife->ifm_media & IFM_FDX) |
6599 | sc->sc_ctrl |= CTRL_FD; | | 6600 | sc->sc_ctrl |= CTRL_FD; |
6600 | switch (IFM_SUBTYPE(ife->ifm_media)) { | | 6601 | switch (IFM_SUBTYPE(ife->ifm_media)) { |
6601 | case IFM_10_T: | | 6602 | case IFM_10_T: |
6602 | sc->sc_ctrl |= CTRL_SPEED_10; | | 6603 | sc->sc_ctrl |= CTRL_SPEED_10; |
6603 | break; | | 6604 | break; |
6604 | case IFM_100_TX: | | 6605 | case IFM_100_TX: |
6605 | sc->sc_ctrl |= CTRL_SPEED_100; | | 6606 | sc->sc_ctrl |= CTRL_SPEED_100; |
6606 | break; | | 6607 | break; |
6607 | case IFM_1000_T: | | 6608 | case IFM_1000_T: |
6608 | sc->sc_ctrl |= CTRL_SPEED_1000; | | 6609 | sc->sc_ctrl |= CTRL_SPEED_1000; |
6609 | break; | | 6610 | break; |
6610 | default: | | 6611 | default: |
6611 | panic("wm_gmii_mediachange: bad media 0x%x", | | 6612 | panic("wm_gmii_mediachange: bad media 0x%x", |
6612 | ife->ifm_media); | | 6613 | ife->ifm_media); |
6613 | } | | 6614 | } |
6614 | } | | 6615 | } |
6615 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); | | 6616 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); |
6616 | if (sc->sc_type <= WM_T_82543) | | 6617 | if (sc->sc_type <= WM_T_82543) |
6617 | wm_gmii_reset(sc); | | 6618 | wm_gmii_reset(sc); |
6618 | | | 6619 | |
6619 | if ((rc = mii_mediachg(&sc->sc_mii)) == ENXIO) | | 6620 | if ((rc = mii_mediachg(&sc->sc_mii)) == ENXIO) |
6620 | return 0; | | 6621 | return 0; |
6621 | return rc; | | 6622 | return rc; |
6622 | } | | 6623 | } |
6623 | | | 6624 | |
6624 | #define MDI_IO CTRL_SWDPIN(2) | | 6625 | #define MDI_IO CTRL_SWDPIN(2) |
6625 | #define MDI_DIR CTRL_SWDPIO(2) /* host -> PHY */ | | 6626 | #define MDI_DIR CTRL_SWDPIO(2) /* host -> PHY */ |
6626 | #define MDI_CLK CTRL_SWDPIN(3) | | 6627 | #define MDI_CLK CTRL_SWDPIN(3) |
6627 | | | 6628 | |
6628 | static void | | 6629 | static void |
6629 | i82543_mii_sendbits(struct wm_softc *sc, uint32_t data, int nbits) | | 6630 | i82543_mii_sendbits(struct wm_softc *sc, uint32_t data, int nbits) |
6630 | { | | 6631 | { |
6631 | uint32_t i, v; | | 6632 | uint32_t i, v; |
6632 | | | 6633 | |
6633 | v = CSR_READ(sc, WMREG_CTRL); | | 6634 | v = CSR_READ(sc, WMREG_CTRL); |
6634 | v &= ~(MDI_IO|MDI_CLK|(CTRL_SWDPIO_MASK << CTRL_SWDPIO_SHIFT)); | | 6635 | v &= ~(MDI_IO|MDI_CLK|(CTRL_SWDPIO_MASK << CTRL_SWDPIO_SHIFT)); |
6635 | v |= MDI_DIR | CTRL_SWDPIO(3); | | 6636 | v |= MDI_DIR | CTRL_SWDPIO(3); |
6636 | | | 6637 | |
6637 | for (i = 1 << (nbits - 1); i != 0; i >>= 1) { | | 6638 | for (i = 1 << (nbits - 1); i != 0; i >>= 1) { |
6638 | if (data & i) | | 6639 | if (data & i) |
6639 | v |= MDI_IO; | | 6640 | v |= MDI_IO; |
6640 | else | | 6641 | else |
6641 | v &= ~MDI_IO; | | 6642 | v &= ~MDI_IO; |
6642 | CSR_WRITE(sc, WMREG_CTRL, v); | | 6643 | CSR_WRITE(sc, WMREG_CTRL, v); |
6643 | delay(10); | | 6644 | delay(10); |
6644 | CSR_WRITE(sc, WMREG_CTRL, v | MDI_CLK); | | 6645 | CSR_WRITE(sc, WMREG_CTRL, v | MDI_CLK); |
6645 | delay(10); | | 6646 | delay(10); |
6646 | CSR_WRITE(sc, WMREG_CTRL, v); | | 6647 | CSR_WRITE(sc, WMREG_CTRL, v); |
6647 | delay(10); | | 6648 | delay(10); |
6648 | } | | 6649 | } |
6649 | } | | 6650 | } |
6650 | | | 6651 | |
6651 | static uint32_t | | 6652 | static uint32_t |
6652 | i82543_mii_recvbits(struct wm_softc *sc) | | 6653 | i82543_mii_recvbits(struct wm_softc *sc) |
6653 | { | | 6654 | { |
6654 | uint32_t v, i, data = 0; | | 6655 | uint32_t v, i, data = 0; |
6655 | | | 6656 | |
6656 | v = CSR_READ(sc, WMREG_CTRL); | | 6657 | v = CSR_READ(sc, WMREG_CTRL); |
6657 | v &= ~(MDI_IO|MDI_CLK|(CTRL_SWDPIO_MASK << CTRL_SWDPIO_SHIFT)); | | 6658 | v &= ~(MDI_IO|MDI_CLK|(CTRL_SWDPIO_MASK << CTRL_SWDPIO_SHIFT)); |
6658 | v |= CTRL_SWDPIO(3); | | 6659 | v |= CTRL_SWDPIO(3); |
6659 | | | 6660 | |
6660 | CSR_WRITE(sc, WMREG_CTRL, v); | | 6661 | CSR_WRITE(sc, WMREG_CTRL, v); |
6661 | delay(10); | | 6662 | delay(10); |
6662 | CSR_WRITE(sc, WMREG_CTRL, v | MDI_CLK); | | 6663 | CSR_WRITE(sc, WMREG_CTRL, v | MDI_CLK); |
6663 | delay(10); | | 6664 | delay(10); |
6664 | CSR_WRITE(sc, WMREG_CTRL, v); | | 6665 | CSR_WRITE(sc, WMREG_CTRL, v); |
6665 | delay(10); | | 6666 | delay(10); |
6666 | | | 6667 | |
6667 | for (i = 0; i < 16; i++) { | | 6668 | for (i = 0; i < 16; i++) { |
6668 | data <<= 1; | | 6669 | data <<= 1; |
6669 | CSR_WRITE(sc, WMREG_CTRL, v | MDI_CLK); | | 6670 | CSR_WRITE(sc, WMREG_CTRL, v | MDI_CLK); |
6670 | delay(10); | | 6671 | delay(10); |
6671 | if (CSR_READ(sc, WMREG_CTRL) & MDI_IO) | | 6672 | if (CSR_READ(sc, WMREG_CTRL) & MDI_IO) |
6672 | data |= 1; | | 6673 | data |= 1; |
6673 | CSR_WRITE(sc, WMREG_CTRL, v); | | 6674 | CSR_WRITE(sc, WMREG_CTRL, v); |
6674 | delay(10); | | 6675 | delay(10); |
6675 | } | | 6676 | } |
6676 | | | 6677 | |
6677 | CSR_WRITE(sc, WMREG_CTRL, v | MDI_CLK); | | 6678 | CSR_WRITE(sc, WMREG_CTRL, v | MDI_CLK); |
6678 | delay(10); | | 6679 | delay(10); |
6679 | CSR_WRITE(sc, WMREG_CTRL, v); | | 6680 | CSR_WRITE(sc, WMREG_CTRL, v); |
6680 | delay(10); | | 6681 | delay(10); |
6681 | | | 6682 | |
6682 | return data; | | 6683 | return data; |
6683 | } | | 6684 | } |
6684 | | | 6685 | |
6685 | #undef MDI_IO | | 6686 | #undef MDI_IO |
6686 | #undef MDI_DIR | | 6687 | #undef MDI_DIR |
6687 | #undef MDI_CLK | | 6688 | #undef MDI_CLK |
6688 | | | 6689 | |
6689 | /* | | 6690 | /* |
6690 | * wm_gmii_i82543_readreg: [mii interface function] | | 6691 | * wm_gmii_i82543_readreg: [mii interface function] |
6691 | * | | 6692 | * |
6692 | * Read a PHY register on the GMII (i82543 version). | | 6693 | * Read a PHY register on the GMII (i82543 version). |
6693 | */ | | 6694 | */ |
6694 | static int | | 6695 | static int |
6695 | wm_gmii_i82543_readreg(device_t self, int phy, int reg) | | 6696 | wm_gmii_i82543_readreg(device_t self, int phy, int reg) |
6696 | { | | 6697 | { |
6697 | struct wm_softc *sc = device_private(self); | | 6698 | struct wm_softc *sc = device_private(self); |
6698 | int rv; | | 6699 | int rv; |
6699 | | | 6700 | |
6700 | i82543_mii_sendbits(sc, 0xffffffffU, 32); | | 6701 | i82543_mii_sendbits(sc, 0xffffffffU, 32); |
6701 | i82543_mii_sendbits(sc, reg | (phy << 5) | | | 6702 | i82543_mii_sendbits(sc, reg | (phy << 5) | |
6702 | (MII_COMMAND_READ << 10) | (MII_COMMAND_START << 12), 14); | | 6703 | (MII_COMMAND_READ << 10) | (MII_COMMAND_START << 12), 14); |
6703 | rv = i82543_mii_recvbits(sc) & 0xffff; | | 6704 | rv = i82543_mii_recvbits(sc) & 0xffff; |
6704 | | | 6705 | |
6705 | DPRINTF(WM_DEBUG_GMII, | | 6706 | DPRINTF(WM_DEBUG_GMII, |
6706 | ("%s: GMII: read phy %d reg %d -> 0x%04x\n", | | 6707 | ("%s: GMII: read phy %d reg %d -> 0x%04x\n", |
6707 | device_xname(sc->sc_dev), phy, reg, rv)); | | 6708 | device_xname(sc->sc_dev), phy, reg, rv)); |
6708 | | | 6709 | |
6709 | return rv; | | 6710 | return rv; |
6710 | } | | 6711 | } |
6711 | | | 6712 | |
6712 | /* | | 6713 | /* |
6713 | * wm_gmii_i82543_writereg: [mii interface function] | | 6714 | * wm_gmii_i82543_writereg: [mii interface function] |
6714 | * | | 6715 | * |
6715 | * Write a PHY register on the GMII (i82543 version). | | 6716 | * Write a PHY register on the GMII (i82543 version). |
6716 | */ | | 6717 | */ |
6717 | static void | | 6718 | static void |
6718 | wm_gmii_i82543_writereg(device_t self, int phy, int reg, int val) | | 6719 | wm_gmii_i82543_writereg(device_t self, int phy, int reg, int val) |
6719 | { | | 6720 | { |
6720 | struct wm_softc *sc = device_private(self); | | 6721 | struct wm_softc *sc = device_private(self); |
6721 | | | 6722 | |
6722 | i82543_mii_sendbits(sc, 0xffffffffU, 32); | | 6723 | i82543_mii_sendbits(sc, 0xffffffffU, 32); |
6723 | i82543_mii_sendbits(sc, val | (MII_COMMAND_ACK << 16) | | | 6724 | i82543_mii_sendbits(sc, val | (MII_COMMAND_ACK << 16) | |
6724 | (reg << 18) | (phy << 23) | (MII_COMMAND_WRITE << 28) | | | 6725 | (reg << 18) | (phy << 23) | (MII_COMMAND_WRITE << 28) | |
6725 | (MII_COMMAND_START << 30), 32); | | 6726 | (MII_COMMAND_START << 30), 32); |
6726 | } | | 6727 | } |
6727 | | | 6728 | |
6728 | /* | | 6729 | /* |
6729 | * wm_gmii_i82544_readreg: [mii interface function] | | 6730 | * wm_gmii_i82544_readreg: [mii interface function] |
6730 | * | | 6731 | * |
6731 | * Read a PHY register on the GMII. | | 6732 | * Read a PHY register on the GMII. |
6732 | */ | | 6733 | */ |
6733 | static int | | 6734 | static int |
6734 | wm_gmii_i82544_readreg(device_t self, int phy, int reg) | | 6735 | wm_gmii_i82544_readreg(device_t self, int phy, int reg) |
6735 | { | | 6736 | { |
6736 | struct wm_softc *sc = device_private(self); | | 6737 | struct wm_softc *sc = device_private(self); |
6737 | uint32_t mdic = 0; | | 6738 | uint32_t mdic = 0; |
6738 | int i, rv; | | 6739 | int i, rv; |
6739 | | | 6740 | |
6740 | CSR_WRITE(sc, WMREG_MDIC, MDIC_OP_READ | MDIC_PHYADD(phy) | | | 6741 | CSR_WRITE(sc, WMREG_MDIC, MDIC_OP_READ | MDIC_PHYADD(phy) | |
6741 | MDIC_REGADD(reg)); | | 6742 | MDIC_REGADD(reg)); |
6742 | | | 6743 | |
6743 | for (i = 0; i < WM_GEN_POLL_TIMEOUT * 3; i++) { | | 6744 | for (i = 0; i < WM_GEN_POLL_TIMEOUT * 3; i++) { |
6744 | mdic = CSR_READ(sc, WMREG_MDIC); | | 6745 | mdic = CSR_READ(sc, WMREG_MDIC); |
6745 | if (mdic & MDIC_READY) | | 6746 | if (mdic & MDIC_READY) |
6746 | break; | | 6747 | break; |
6747 | delay(50); | | 6748 | delay(50); |
6748 | } | | 6749 | } |
6749 | | | 6750 | |
6750 | if ((mdic & MDIC_READY) == 0) { | | 6751 | if ((mdic & MDIC_READY) == 0) { |
6751 | log(LOG_WARNING, "%s: MDIC read timed out: phy %d reg %d\n", | | 6752 | log(LOG_WARNING, "%s: MDIC read timed out: phy %d reg %d\n", |
6752 | device_xname(sc->sc_dev), phy, reg); | | 6753 | device_xname(sc->sc_dev), phy, reg); |
6753 | rv = 0; | | 6754 | rv = 0; |
6754 | } else if (mdic & MDIC_E) { | | 6755 | } else if (mdic & MDIC_E) { |
6755 | #if 0 /* This is normal if no PHY is present. */ | | 6756 | #if 0 /* This is normal if no PHY is present. */ |
6756 | log(LOG_WARNING, "%s: MDIC read error: phy %d reg %d\n", | | 6757 | log(LOG_WARNING, "%s: MDIC read error: phy %d reg %d\n", |
6757 | device_xname(sc->sc_dev), phy, reg); | | 6758 | device_xname(sc->sc_dev), phy, reg); |
6758 | #endif | | 6759 | #endif |
6759 | rv = 0; | | 6760 | rv = 0; |
6760 | } else { | | 6761 | } else { |
6761 | rv = MDIC_DATA(mdic); | | 6762 | rv = MDIC_DATA(mdic); |
6762 | if (rv == 0xffff) | | 6763 | if (rv == 0xffff) |
6763 | rv = 0; | | 6764 | rv = 0; |
6764 | } | | 6765 | } |
6765 | | | 6766 | |
6766 | return rv; | | 6767 | return rv; |
6767 | } | | 6768 | } |
6768 | | | 6769 | |
6769 | /* | | 6770 | /* |
6770 | * wm_gmii_i82544_writereg: [mii interface function] | | 6771 | * wm_gmii_i82544_writereg: [mii interface function] |
6771 | * | | 6772 | * |
6772 | * Write a PHY register on the GMII. | | 6773 | * Write a PHY register on the GMII. |
6773 | */ | | 6774 | */ |
6774 | static void | | 6775 | static void |
6775 | wm_gmii_i82544_writereg(device_t self, int phy, int reg, int val) | | 6776 | wm_gmii_i82544_writereg(device_t self, int phy, int reg, int val) |
6776 | { | | 6777 | { |
6777 | struct wm_softc *sc = device_private(self); | | 6778 | struct wm_softc *sc = device_private(self); |
6778 | uint32_t mdic = 0; | | 6779 | uint32_t mdic = 0; |
6779 | int i; | | 6780 | int i; |
6780 | | | 6781 | |
6781 | CSR_WRITE(sc, WMREG_MDIC, MDIC_OP_WRITE | MDIC_PHYADD(phy) | | | 6782 | CSR_WRITE(sc, WMREG_MDIC, MDIC_OP_WRITE | MDIC_PHYADD(phy) | |
6782 | MDIC_REGADD(reg) | MDIC_DATA(val)); | | 6783 | MDIC_REGADD(reg) | MDIC_DATA(val)); |
6783 | | | 6784 | |
6784 | for (i = 0; i < WM_GEN_POLL_TIMEOUT * 3; i++) { | | 6785 | for (i = 0; i < WM_GEN_POLL_TIMEOUT * 3; i++) { |
6785 | mdic = CSR_READ(sc, WMREG_MDIC); | | 6786 | mdic = CSR_READ(sc, WMREG_MDIC); |
6786 | if (mdic & MDIC_READY) | | 6787 | if (mdic & MDIC_READY) |
6787 | break; | | 6788 | break; |
6788 | delay(50); | | 6789 | delay(50); |
6789 | } | | 6790 | } |
6790 | | | 6791 | |
6791 | if ((mdic & MDIC_READY) == 0) | | 6792 | if ((mdic & MDIC_READY) == 0) |
6792 | log(LOG_WARNING, "%s: MDIC write timed out: phy %d reg %d\n", | | 6793 | log(LOG_WARNING, "%s: MDIC write timed out: phy %d reg %d\n", |
6793 | device_xname(sc->sc_dev), phy, reg); | | 6794 | device_xname(sc->sc_dev), phy, reg); |
6794 | else if (mdic & MDIC_E) | | 6795 | else if (mdic & MDIC_E) |
6795 | log(LOG_WARNING, "%s: MDIC write error: phy %d reg %d\n", | | 6796 | log(LOG_WARNING, "%s: MDIC write error: phy %d reg %d\n", |
6796 | device_xname(sc->sc_dev), phy, reg); | | 6797 | device_xname(sc->sc_dev), phy, reg); |
6797 | } | | 6798 | } |
6798 | | | 6799 | |
6799 | /* | | 6800 | /* |
6800 | * wm_gmii_i80003_readreg: [mii interface function] | | 6801 | * wm_gmii_i80003_readreg: [mii interface function] |
6801 | * | | 6802 | * |
6802 | * Read a PHY register on the kumeran | | 6803 | * Read a PHY register on the kumeran |
6803 | * This could be handled by the PHY layer if we didn't have to lock the | | 6804 | * This could be handled by the PHY layer if we didn't have to lock the |
6804 | * ressource ... | | 6805 | * ressource ... |
6805 | */ | | 6806 | */ |
6806 | static int | | 6807 | static int |
6807 | wm_gmii_i80003_readreg(device_t self, int phy, int reg) | | 6808 | wm_gmii_i80003_readreg(device_t self, int phy, int reg) |
6808 | { | | 6809 | { |
6809 | struct wm_softc *sc = device_private(self); | | 6810 | struct wm_softc *sc = device_private(self); |
6810 | int sem; | | 6811 | int sem; |
6811 | int rv; | | 6812 | int rv; |
6812 | | | 6813 | |
6813 | if (phy != 1) /* only one PHY on kumeran bus */ | | 6814 | if (phy != 1) /* only one PHY on kumeran bus */ |
6814 | return 0; | | 6815 | return 0; |
6815 | | | 6816 | |
6816 | sem = swfwphysem[sc->sc_funcid]; | | 6817 | sem = swfwphysem[sc->sc_funcid]; |
6817 | if (wm_get_swfw_semaphore(sc, sem)) { | | 6818 | if (wm_get_swfw_semaphore(sc, sem)) { |
6818 | aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", | | 6819 | aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", |
6819 | __func__); | | 6820 | __func__); |
6820 | return 0; | | 6821 | return 0; |
6821 | } | | 6822 | } |
6822 | | | 6823 | |
6823 | if ((reg & GG82563_MAX_REG_ADDRESS) < GG82563_MIN_ALT_REG) { | | 6824 | if ((reg & GG82563_MAX_REG_ADDRESS) < GG82563_MIN_ALT_REG) { |
6824 | wm_gmii_i82544_writereg(self, phy, GG82563_PHY_PAGE_SELECT, | | 6825 | wm_gmii_i82544_writereg(self, phy, GG82563_PHY_PAGE_SELECT, |
6825 | reg >> GG82563_PAGE_SHIFT); | | 6826 | reg >> GG82563_PAGE_SHIFT); |
6826 | } else { | | 6827 | } else { |
6827 | wm_gmii_i82544_writereg(self, phy, GG82563_PHY_PAGE_SELECT_ALT, | | 6828 | wm_gmii_i82544_writereg(self, phy, GG82563_PHY_PAGE_SELECT_ALT, |
6828 | reg >> GG82563_PAGE_SHIFT); | | 6829 | reg >> GG82563_PAGE_SHIFT); |
6829 | } | | 6830 | } |
6830 | /* Wait more 200us for a bug of the ready bit in the MDIC register */ | | 6831 | /* Wait more 200us for a bug of the ready bit in the MDIC register */ |
6831 | delay(200); | | 6832 | delay(200); |
6832 | rv = wm_gmii_i82544_readreg(self, phy, reg & GG82563_MAX_REG_ADDRESS); | | 6833 | rv = wm_gmii_i82544_readreg(self, phy, reg & GG82563_MAX_REG_ADDRESS); |
6833 | delay(200); | | 6834 | delay(200); |
6834 | | | 6835 | |
6835 | wm_put_swfw_semaphore(sc, sem); | | 6836 | wm_put_swfw_semaphore(sc, sem); |
6836 | return rv; | | 6837 | return rv; |
6837 | } | | 6838 | } |
6838 | | | 6839 | |
6839 | /* | | 6840 | /* |
6840 | * wm_gmii_i80003_writereg: [mii interface function] | | 6841 | * wm_gmii_i80003_writereg: [mii interface function] |
6841 | * | | 6842 | * |
6842 | * Write a PHY register on the kumeran. | | 6843 | * Write a PHY register on the kumeran. |
6843 | * This could be handled by the PHY layer if we didn't have to lock the | | 6844 | * This could be handled by the PHY layer if we didn't have to lock the |
6844 | * ressource ... | | 6845 | * ressource ... |
6845 | */ | | 6846 | */ |
6846 | static void | | 6847 | static void |
6847 | wm_gmii_i80003_writereg(device_t self, int phy, int reg, int val) | | 6848 | wm_gmii_i80003_writereg(device_t self, int phy, int reg, int val) |
6848 | { | | 6849 | { |
6849 | struct wm_softc *sc = device_private(self); | | 6850 | struct wm_softc *sc = device_private(self); |
6850 | int sem; | | 6851 | int sem; |
6851 | | | 6852 | |
6852 | if (phy != 1) /* only one PHY on kumeran bus */ | | 6853 | if (phy != 1) /* only one PHY on kumeran bus */ |
6853 | return; | | 6854 | return; |
6854 | | | 6855 | |
6855 | sem = swfwphysem[sc->sc_funcid]; | | 6856 | sem = swfwphysem[sc->sc_funcid]; |
6856 | if (wm_get_swfw_semaphore(sc, sem)) { | | 6857 | if (wm_get_swfw_semaphore(sc, sem)) { |
6857 | aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", | | 6858 | aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", |
6858 | __func__); | | 6859 | __func__); |
6859 | return; | | 6860 | return; |
6860 | } | | 6861 | } |
6861 | | | 6862 | |
6862 | if ((reg & GG82563_MAX_REG_ADDRESS) < GG82563_MIN_ALT_REG) { | | 6863 | if ((reg & GG82563_MAX_REG_ADDRESS) < GG82563_MIN_ALT_REG) { |
6863 | wm_gmii_i82544_writereg(self, phy, GG82563_PHY_PAGE_SELECT, | | 6864 | wm_gmii_i82544_writereg(self, phy, GG82563_PHY_PAGE_SELECT, |
6864 | reg >> GG82563_PAGE_SHIFT); | | 6865 | reg >> GG82563_PAGE_SHIFT); |
6865 | } else { | | 6866 | } else { |
6866 | wm_gmii_i82544_writereg(self, phy, GG82563_PHY_PAGE_SELECT_ALT, | | 6867 | wm_gmii_i82544_writereg(self, phy, GG82563_PHY_PAGE_SELECT_ALT, |
6867 | reg >> GG82563_PAGE_SHIFT); | | 6868 | reg >> GG82563_PAGE_SHIFT); |
6868 | } | | 6869 | } |
6869 | /* Wait more 200us for a bug of the ready bit in the MDIC register */ | | 6870 | /* Wait more 200us for a bug of the ready bit in the MDIC register */ |
6870 | delay(200); | | 6871 | delay(200); |
6871 | wm_gmii_i82544_writereg(self, phy, reg & GG82563_MAX_REG_ADDRESS, val); | | 6872 | wm_gmii_i82544_writereg(self, phy, reg & GG82563_MAX_REG_ADDRESS, val); |
6872 | delay(200); | | 6873 | delay(200); |
6873 | | | 6874 | |
6874 | wm_put_swfw_semaphore(sc, sem); | | 6875 | wm_put_swfw_semaphore(sc, sem); |
6875 | } | | 6876 | } |
6876 | | | 6877 | |
6877 | /* | | 6878 | /* |
6878 | * wm_gmii_bm_readreg: [mii interface function] | | 6879 | * wm_gmii_bm_readreg: [mii interface function] |
6879 | * | | 6880 | * |
6880 | * Read a PHY register on the kumeran | | 6881 | * Read a PHY register on the kumeran |
6881 | * This could be handled by the PHY layer if we didn't have to lock the | | 6882 | * This could be handled by the PHY layer if we didn't have to lock the |
6882 | * ressource ... | | 6883 | * ressource ... |
6883 | */ | | 6884 | */ |
6884 | static int | | 6885 | static int |
6885 | wm_gmii_bm_readreg(device_t self, int phy, int reg) | | 6886 | wm_gmii_bm_readreg(device_t self, int phy, int reg) |
6886 | { | | 6887 | { |
6887 | struct wm_softc *sc = device_private(self); | | 6888 | struct wm_softc *sc = device_private(self); |
6888 | int sem; | | 6889 | int sem; |
6889 | int rv; | | 6890 | int rv; |
6890 | | | 6891 | |
6891 | sem = swfwphysem[sc->sc_funcid]; | | 6892 | sem = swfwphysem[sc->sc_funcid]; |
6892 | if (wm_get_swfw_semaphore(sc, sem)) { | | 6893 | if (wm_get_swfw_semaphore(sc, sem)) { |
6893 | aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", | | 6894 | aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", |
6894 | __func__); | | 6895 | __func__); |
6895 | return 0; | | 6896 | return 0; |
6896 | } | | 6897 | } |
6897 | | | 6898 | |
6898 | if (reg > BME1000_MAX_MULTI_PAGE_REG) { | | 6899 | if (reg > BME1000_MAX_MULTI_PAGE_REG) { |
6899 | if (phy == 1) | | 6900 | if (phy == 1) |
6900 | wm_gmii_i82544_writereg(self, phy, MII_IGPHY_PAGE_SELECT, | | 6901 | wm_gmii_i82544_writereg(self, phy, MII_IGPHY_PAGE_SELECT, |
6901 | reg); | | 6902 | reg); |
6902 | else | | 6903 | else |
6903 | wm_gmii_i82544_writereg(self, phy, | | 6904 | wm_gmii_i82544_writereg(self, phy, |
6904 | GG82563_PHY_PAGE_SELECT, | | 6905 | GG82563_PHY_PAGE_SELECT, |
6905 | reg >> GG82563_PAGE_SHIFT); | | 6906 | reg >> GG82563_PAGE_SHIFT); |
6906 | } | | 6907 | } |
6907 | | | 6908 | |
6908 | rv = wm_gmii_i82544_readreg(self, phy, reg & GG82563_MAX_REG_ADDRESS); | | 6909 | rv = wm_gmii_i82544_readreg(self, phy, reg & GG82563_MAX_REG_ADDRESS); |
6909 | wm_put_swfw_semaphore(sc, sem); | | 6910 | wm_put_swfw_semaphore(sc, sem); |
6910 | return rv; | | 6911 | return rv; |
6911 | } | | 6912 | } |
6912 | | | 6913 | |
6913 | /* | | 6914 | /* |
6914 | * wm_gmii_bm_writereg: [mii interface function] | | 6915 | * wm_gmii_bm_writereg: [mii interface function] |
6915 | * | | 6916 | * |
6916 | * Write a PHY register on the kumeran. | | 6917 | * Write a PHY register on the kumeran. |
6917 | * This could be handled by the PHY layer if we didn't have to lock the | | 6918 | * This could be handled by the PHY layer if we didn't have to lock the |
6918 | * ressource ... | | 6919 | * ressource ... |
6919 | */ | | 6920 | */ |
6920 | static void | | 6921 | static void |
6921 | wm_gmii_bm_writereg(device_t self, int phy, int reg, int val) | | 6922 | wm_gmii_bm_writereg(device_t self, int phy, int reg, int val) |
6922 | { | | 6923 | { |
6923 | struct wm_softc *sc = device_private(self); | | 6924 | struct wm_softc *sc = device_private(self); |
6924 | int sem; | | 6925 | int sem; |
6925 | | | 6926 | |
6926 | sem = swfwphysem[sc->sc_funcid]; | | 6927 | sem = swfwphysem[sc->sc_funcid]; |
6927 | if (wm_get_swfw_semaphore(sc, sem)) { | | 6928 | if (wm_get_swfw_semaphore(sc, sem)) { |
6928 | aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", | | 6929 | aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", |
6929 | __func__); | | 6930 | __func__); |
6930 | return; | | 6931 | return; |
6931 | } | | 6932 | } |
6932 | | | 6933 | |
6933 | if (reg > BME1000_MAX_MULTI_PAGE_REG) { | | 6934 | if (reg > BME1000_MAX_MULTI_PAGE_REG) { |
6934 | if (phy == 1) | | 6935 | if (phy == 1) |
6935 | wm_gmii_i82544_writereg(self, phy, MII_IGPHY_PAGE_SELECT, | | 6936 | wm_gmii_i82544_writereg(self, phy, MII_IGPHY_PAGE_SELECT, |
6936 | reg); | | 6937 | reg); |
6937 | else | | 6938 | else |
6938 | wm_gmii_i82544_writereg(self, phy, | | 6939 | wm_gmii_i82544_writereg(self, phy, |
6939 | GG82563_PHY_PAGE_SELECT, | | 6940 | GG82563_PHY_PAGE_SELECT, |
6940 | reg >> GG82563_PAGE_SHIFT); | | 6941 | reg >> GG82563_PAGE_SHIFT); |
6941 | } | | 6942 | } |
6942 | | | 6943 | |
6943 | wm_gmii_i82544_writereg(self, phy, reg & GG82563_MAX_REG_ADDRESS, val); | | 6944 | wm_gmii_i82544_writereg(self, phy, reg & GG82563_MAX_REG_ADDRESS, val); |
6944 | wm_put_swfw_semaphore(sc, sem); | | 6945 | wm_put_swfw_semaphore(sc, sem); |
6945 | } | | 6946 | } |
6946 | | | 6947 | |
6947 | static void | | 6948 | static void |
6948 | wm_access_phy_wakeup_reg_bm(device_t self, int offset, int16_t *val, int rd) | | 6949 | wm_access_phy_wakeup_reg_bm(device_t self, int offset, int16_t *val, int rd) |
6949 | { | | 6950 | { |
6950 | struct wm_softc *sc = device_private(self); | | 6951 | struct wm_softc *sc = device_private(self); |
6951 | uint16_t regnum = BM_PHY_REG_NUM(offset); | | 6952 | uint16_t regnum = BM_PHY_REG_NUM(offset); |
6952 | uint16_t wuce; | | 6953 | uint16_t wuce; |
6953 | | | 6954 | |
6954 | /* XXX Gig must be disabled for MDIO accesses to page 800 */ | | 6955 | /* XXX Gig must be disabled for MDIO accesses to page 800 */ |
6955 | if (sc->sc_type == WM_T_PCH) { | | 6956 | if (sc->sc_type == WM_T_PCH) { |
6956 | /* XXX e1000 driver do nothing... why? */ | | 6957 | /* XXX e1000 driver do nothing... why? */ |
6957 | } | | 6958 | } |
6958 | | | 6959 | |
6959 | /* Set page 769 */ | | 6960 | /* Set page 769 */ |
6960 | wm_gmii_i82544_writereg(self, 1, MII_IGPHY_PAGE_SELECT, | | 6961 | wm_gmii_i82544_writereg(self, 1, MII_IGPHY_PAGE_SELECT, |
6961 | BM_WUC_ENABLE_PAGE << BME1000_PAGE_SHIFT); | | 6962 | BM_WUC_ENABLE_PAGE << BME1000_PAGE_SHIFT); |
6962 | | | 6963 | |
6963 | wuce = wm_gmii_i82544_readreg(self, 1, BM_WUC_ENABLE_REG); | | 6964 | wuce = wm_gmii_i82544_readreg(self, 1, BM_WUC_ENABLE_REG); |
6964 | | | 6965 | |
6965 | wuce &= ~BM_WUC_HOST_WU_BIT; | | 6966 | wuce &= ~BM_WUC_HOST_WU_BIT; |
6966 | wm_gmii_i82544_writereg(self, 1, BM_WUC_ENABLE_REG, | | 6967 | wm_gmii_i82544_writereg(self, 1, BM_WUC_ENABLE_REG, |
6967 | wuce | BM_WUC_ENABLE_BIT); | | 6968 | wuce | BM_WUC_ENABLE_BIT); |
6968 | | | 6969 | |
6969 | /* Select page 800 */ | | 6970 | /* Select page 800 */ |
6970 | wm_gmii_i82544_writereg(self, 1, MII_IGPHY_PAGE_SELECT, | | 6971 | wm_gmii_i82544_writereg(self, 1, MII_IGPHY_PAGE_SELECT, |
6971 | BM_WUC_PAGE << BME1000_PAGE_SHIFT); | | 6972 | BM_WUC_PAGE << BME1000_PAGE_SHIFT); |
6972 | | | 6973 | |
6973 | /* Write page 800 */ | | 6974 | /* Write page 800 */ |
6974 | wm_gmii_i82544_writereg(self, 1, BM_WUC_ADDRESS_OPCODE, regnum); | | 6975 | wm_gmii_i82544_writereg(self, 1, BM_WUC_ADDRESS_OPCODE, regnum); |
6975 | | | 6976 | |
6976 | if (rd) | | 6977 | if (rd) |
6977 | *val = wm_gmii_i82544_readreg(self, 1, BM_WUC_DATA_OPCODE); | | 6978 | *val = wm_gmii_i82544_readreg(self, 1, BM_WUC_DATA_OPCODE); |
6978 | else | | 6979 | else |
6979 | wm_gmii_i82544_writereg(self, 1, BM_WUC_DATA_OPCODE, *val); | | 6980 | wm_gmii_i82544_writereg(self, 1, BM_WUC_DATA_OPCODE, *val); |
6980 | | | 6981 | |
6981 | /* Set page 769 */ | | 6982 | /* Set page 769 */ |
6982 | wm_gmii_i82544_writereg(self, 1, MII_IGPHY_PAGE_SELECT, | | 6983 | wm_gmii_i82544_writereg(self, 1, MII_IGPHY_PAGE_SELECT, |
6983 | BM_WUC_ENABLE_PAGE << BME1000_PAGE_SHIFT); | | 6984 | BM_WUC_ENABLE_PAGE << BME1000_PAGE_SHIFT); |
6984 | | | 6985 | |
6985 | wm_gmii_i82544_writereg(self, 1, BM_WUC_ENABLE_REG, wuce); | | 6986 | wm_gmii_i82544_writereg(self, 1, BM_WUC_ENABLE_REG, wuce); |
6986 | } | | 6987 | } |
6987 | | | 6988 | |
6988 | /* | | 6989 | /* |
6989 | * wm_gmii_hv_readreg: [mii interface function] | | 6990 | * wm_gmii_hv_readreg: [mii interface function] |
6990 | * | | 6991 | * |
6991 | * Read a PHY register on the kumeran | | 6992 | * Read a PHY register on the kumeran |
6992 | * This could be handled by the PHY layer if we didn't have to lock the | | 6993 | * This could be handled by the PHY layer if we didn't have to lock the |
6993 | * ressource ... | | 6994 | * ressource ... |
6994 | */ | | 6995 | */ |
6995 | static int | | 6996 | static int |
6996 | wm_gmii_hv_readreg(device_t self, int phy, int reg) | | 6997 | wm_gmii_hv_readreg(device_t self, int phy, int reg) |
6997 | { | | 6998 | { |
6998 | struct wm_softc *sc = device_private(self); | | 6999 | struct wm_softc *sc = device_private(self); |
6999 | uint16_t page = BM_PHY_REG_PAGE(reg); | | 7000 | uint16_t page = BM_PHY_REG_PAGE(reg); |
7000 | uint16_t regnum = BM_PHY_REG_NUM(reg); | | 7001 | uint16_t regnum = BM_PHY_REG_NUM(reg); |
7001 | uint16_t val; | | 7002 | uint16_t val; |
7002 | int rv; | | 7003 | int rv; |
7003 | | | 7004 | |
7004 | if (wm_get_swfw_semaphore(sc, SWFW_PHY0_SM)) { | | 7005 | if (wm_get_swfw_semaphore(sc, SWFW_PHY0_SM)) { |
7005 | aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", | | 7006 | aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", |
7006 | __func__); | | 7007 | __func__); |
7007 | return 0; | | 7008 | return 0; |
7008 | } | | 7009 | } |
7009 | | | 7010 | |
7010 | /* XXX Workaround failure in MDIO access while cable is disconnected */ | | 7011 | /* XXX Workaround failure in MDIO access while cable is disconnected */ |
7011 | if (sc->sc_phytype == WMPHY_82577) { | | 7012 | if (sc->sc_phytype == WMPHY_82577) { |
7012 | /* XXX must write */ | | 7013 | /* XXX must write */ |
7013 | } | | 7014 | } |
7014 | | | 7015 | |
7015 | /* Page 800 works differently than the rest so it has its own func */ | | 7016 | /* Page 800 works differently than the rest so it has its own func */ |
7016 | if (page == BM_WUC_PAGE) { | | 7017 | if (page == BM_WUC_PAGE) { |
7017 | wm_access_phy_wakeup_reg_bm(self, reg, &val, 1); | | 7018 | wm_access_phy_wakeup_reg_bm(self, reg, &val, 1); |
7018 | return val; | | 7019 | return val; |
7019 | } | | 7020 | } |
7020 | | | 7021 | |
7021 | /* | | 7022 | /* |
7022 | * Lower than page 768 works differently than the rest so it has its | | 7023 | * Lower than page 768 works differently than the rest so it has its |
7023 | * own func | | 7024 | * own func |
7024 | */ | | 7025 | */ |
7025 | if ((page > 0) && (page < HV_INTC_FC_PAGE_START)) { | | 7026 | if ((page > 0) && (page < HV_INTC_FC_PAGE_START)) { |
7026 | printf("gmii_hv_readreg!!!\n"); | | 7027 | printf("gmii_hv_readreg!!!\n"); |
7027 | return 0; | | 7028 | return 0; |
7028 | } | | 7029 | } |
7029 | | | 7030 | |
7030 | if (regnum > BME1000_MAX_MULTI_PAGE_REG) { | | 7031 | if (regnum > BME1000_MAX_MULTI_PAGE_REG) { |
7031 | wm_gmii_i82544_writereg(self, 1, MII_IGPHY_PAGE_SELECT, | | 7032 | wm_gmii_i82544_writereg(self, 1, MII_IGPHY_PAGE_SELECT, |
7032 | page << BME1000_PAGE_SHIFT); | | 7033 | page << BME1000_PAGE_SHIFT); |
7033 | } | | 7034 | } |
7034 | | | 7035 | |
7035 | rv = wm_gmii_i82544_readreg(self, phy, regnum & IGPHY_MAXREGADDR); | | 7036 | rv = wm_gmii_i82544_readreg(self, phy, regnum & IGPHY_MAXREGADDR); |
7036 | wm_put_swfw_semaphore(sc, SWFW_PHY0_SM); | | 7037 | wm_put_swfw_semaphore(sc, SWFW_PHY0_SM); |
7037 | return rv; | | 7038 | return rv; |
7038 | } | | 7039 | } |
7039 | | | 7040 | |
7040 | /* | | 7041 | /* |
7041 | * wm_gmii_hv_writereg: [mii interface function] | | 7042 | * wm_gmii_hv_writereg: [mii interface function] |
7042 | * | | 7043 | * |
7043 | * Write a PHY register on the kumeran. | | 7044 | * Write a PHY register on the kumeran. |
7044 | * This could be handled by the PHY layer if we didn't have to lock the | | 7045 | * This could be handled by the PHY layer if we didn't have to lock the |
7045 | * ressource ... | | 7046 | * ressource ... |
7046 | */ | | 7047 | */ |
7047 | static void | | 7048 | static void |
7048 | wm_gmii_hv_writereg(device_t self, int phy, int reg, int val) | | 7049 | wm_gmii_hv_writereg(device_t self, int phy, int reg, int val) |
7049 | { | | 7050 | { |
7050 | struct wm_softc *sc = device_private(self); | | 7051 | struct wm_softc *sc = device_private(self); |
7051 | uint16_t page = BM_PHY_REG_PAGE(reg); | | 7052 | uint16_t page = BM_PHY_REG_PAGE(reg); |
7052 | uint16_t regnum = BM_PHY_REG_NUM(reg); | | 7053 | uint16_t regnum = BM_PHY_REG_NUM(reg); |
7053 | | | 7054 | |
7054 | if (wm_get_swfw_semaphore(sc, SWFW_PHY0_SM)) { | | 7055 | if (wm_get_swfw_semaphore(sc, SWFW_PHY0_SM)) { |
7055 | aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", | | 7056 | aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", |
7056 | __func__); | | 7057 | __func__); |
7057 | return; | | 7058 | return; |
7058 | } | | 7059 | } |
7059 | | | 7060 | |
7060 | /* XXX Workaround failure in MDIO access while cable is disconnected */ | | 7061 | /* XXX Workaround failure in MDIO access while cable is disconnected */ |
7061 | | | 7062 | |
7062 | /* Page 800 works differently than the rest so it has its own func */ | | 7063 | /* Page 800 works differently than the rest so it has its own func */ |
7063 | if (page == BM_WUC_PAGE) { | | 7064 | if (page == BM_WUC_PAGE) { |
7064 | uint16_t tmp; | | 7065 | uint16_t tmp; |
7065 | | | 7066 | |
7066 | tmp = val; | | 7067 | tmp = val; |
7067 | wm_access_phy_wakeup_reg_bm(self, reg, &tmp, 0); | | 7068 | wm_access_phy_wakeup_reg_bm(self, reg, &tmp, 0); |
7068 | return; | | 7069 | return; |
7069 | } | | 7070 | } |
7070 | | | 7071 | |
7071 | /* | | 7072 | /* |
7072 | * Lower than page 768 works differently than the rest so it has its | | 7073 | * Lower than page 768 works differently than the rest so it has its |
7073 | * own func | | 7074 | * own func |
7074 | */ | | 7075 | */ |
7075 | if ((page > 0) && (page < HV_INTC_FC_PAGE_START)) { | | 7076 | if ((page > 0) && (page < HV_INTC_FC_PAGE_START)) { |
7076 | printf("gmii_hv_writereg!!!\n"); | | 7077 | printf("gmii_hv_writereg!!!\n"); |
7077 | return; | | 7078 | return; |
7078 | } | | 7079 | } |
7079 | | | 7080 | |
7080 | /* | | 7081 | /* |
7081 | * XXX Workaround MDIO accesses being disabled after entering IEEE | | 7082 | * XXX Workaround MDIO accesses being disabled after entering IEEE |
7082 | * Power Down (whenever bit 11 of the PHY control register is set) | | 7083 | * Power Down (whenever bit 11 of the PHY control register is set) |
7083 | */ | | 7084 | */ |
7084 | | | 7085 | |
7085 | if (regnum > BME1000_MAX_MULTI_PAGE_REG) { | | 7086 | if (regnum > BME1000_MAX_MULTI_PAGE_REG) { |
7086 | wm_gmii_i82544_writereg(self, 1, MII_IGPHY_PAGE_SELECT, | | 7087 | wm_gmii_i82544_writereg(self, 1, MII_IGPHY_PAGE_SELECT, |
7087 | page << BME1000_PAGE_SHIFT); | | 7088 | page << BME1000_PAGE_SHIFT); |
7088 | } | | 7089 | } |
7089 | | | 7090 | |
7090 | wm_gmii_i82544_writereg(self, phy, regnum & IGPHY_MAXREGADDR, val); | | 7091 | wm_gmii_i82544_writereg(self, phy, regnum & IGPHY_MAXREGADDR, val); |
7091 | wm_put_swfw_semaphore(sc, SWFW_PHY0_SM); | | 7092 | wm_put_swfw_semaphore(sc, SWFW_PHY0_SM); |
7092 | } | | 7093 | } |
7093 | | | 7094 | |
7094 | /* | | 7095 | /* |
7095 | * wm_sgmii_readreg: [mii interface function] | | 7096 | * wm_sgmii_readreg: [mii interface function] |
7096 | * | | 7097 | * |
7097 | * Read a PHY register on the SGMII | | 7098 | * Read a PHY register on the SGMII |
7098 | * This could be handled by the PHY layer if we didn't have to lock the | | 7099 | * This could be handled by the PHY layer if we didn't have to lock the |
7099 | * ressource ... | | 7100 | * ressource ... |
7100 | */ | | 7101 | */ |
7101 | static int | | 7102 | static int |
7102 | wm_sgmii_readreg(device_t self, int phy, int reg) | | 7103 | wm_sgmii_readreg(device_t self, int phy, int reg) |
7103 | { | | 7104 | { |
7104 | struct wm_softc *sc = device_private(self); | | 7105 | struct wm_softc *sc = device_private(self); |
7105 | uint32_t i2ccmd; | | 7106 | uint32_t i2ccmd; |
7106 | int i, rv; | | 7107 | int i, rv; |
7107 | | | 7108 | |
7108 | if (wm_get_swfw_semaphore(sc, swfwphysem[sc->sc_funcid])) { | | 7109 | if (wm_get_swfw_semaphore(sc, swfwphysem[sc->sc_funcid])) { |
7109 | aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", | | 7110 | aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", |
7110 | __func__); | | 7111 | __func__); |
7111 | return 0; | | 7112 | return 0; |
7112 | } | | 7113 | } |
7113 | | | 7114 | |
7114 | i2ccmd = (reg << I2CCMD_REG_ADDR_SHIFT) | | 7115 | i2ccmd = (reg << I2CCMD_REG_ADDR_SHIFT) |
7115 | | (phy << I2CCMD_PHY_ADDR_SHIFT) | | 7116 | | (phy << I2CCMD_PHY_ADDR_SHIFT) |
7116 | | I2CCMD_OPCODE_READ; | | 7117 | | I2CCMD_OPCODE_READ; |
7117 | CSR_WRITE(sc, WMREG_I2CCMD, i2ccmd); | | 7118 | CSR_WRITE(sc, WMREG_I2CCMD, i2ccmd); |
7118 | | | 7119 | |
7119 | /* Poll the ready bit */ | | 7120 | /* Poll the ready bit */ |
7120 | for (i = 0; i < I2CCMD_PHY_TIMEOUT; i++) { | | 7121 | for (i = 0; i < I2CCMD_PHY_TIMEOUT; i++) { |
7121 | delay(50); | | 7122 | delay(50); |
7122 | i2ccmd = CSR_READ(sc, WMREG_I2CCMD); | | 7123 | i2ccmd = CSR_READ(sc, WMREG_I2CCMD); |
7123 | if (i2ccmd & I2CCMD_READY) | | 7124 | if (i2ccmd & I2CCMD_READY) |
7124 | break; | | 7125 | break; |
7125 | } | | 7126 | } |
7126 | if ((i2ccmd & I2CCMD_READY) == 0) | | 7127 | if ((i2ccmd & I2CCMD_READY) == 0) |
7127 | aprint_error_dev(sc->sc_dev, "I2CCMD Read did not complete\n"); | | 7128 | aprint_error_dev(sc->sc_dev, "I2CCMD Read did not complete\n"); |
7128 | if ((i2ccmd & I2CCMD_ERROR) != 0) | | 7129 | if ((i2ccmd & I2CCMD_ERROR) != 0) |
7129 | aprint_error_dev(sc->sc_dev, "I2CCMD Error bit set\n"); | | 7130 | aprint_error_dev(sc->sc_dev, "I2CCMD Error bit set\n"); |
7130 | | | 7131 | |
7131 | rv = ((i2ccmd >> 8) & 0x00ff) | ((i2ccmd << 8) & 0xff00); | | 7132 | rv = ((i2ccmd >> 8) & 0x00ff) | ((i2ccmd << 8) & 0xff00); |
7132 | | | 7133 | |
7133 | wm_put_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]); | | 7134 | wm_put_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]); |
7134 | return rv; | | 7135 | return rv; |
7135 | } | | 7136 | } |
7136 | | | 7137 | |
7137 | /* | | 7138 | /* |
7138 | * wm_sgmii_writereg: [mii interface function] | | 7139 | * wm_sgmii_writereg: [mii interface function] |
7139 | * | | 7140 | * |
7140 | * Write a PHY register on the SGMII. | | 7141 | * Write a PHY register on the SGMII. |
7141 | * This could be handled by the PHY layer if we didn't have to lock the | | 7142 | * This could be handled by the PHY layer if we didn't have to lock the |
7142 | * ressource ... | | 7143 | * ressource ... |
7143 | */ | | 7144 | */ |
7144 | static void | | 7145 | static void |
7145 | wm_sgmii_writereg(device_t self, int phy, int reg, int val) | | 7146 | wm_sgmii_writereg(device_t self, int phy, int reg, int val) |
7146 | { | | 7147 | { |
7147 | struct wm_softc *sc = device_private(self); | | 7148 | struct wm_softc *sc = device_private(self); |
7148 | uint32_t i2ccmd; | | 7149 | uint32_t i2ccmd; |
7149 | int i; | | 7150 | int i; |
7150 | | | 7151 | |
7151 | if (wm_get_swfw_semaphore(sc, swfwphysem[sc->sc_funcid])) { | | 7152 | if (wm_get_swfw_semaphore(sc, swfwphysem[sc->sc_funcid])) { |
7152 | aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", | | 7153 | aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", |
7153 | __func__); | | 7154 | __func__); |
7154 | return; | | 7155 | return; |
7155 | } | | 7156 | } |
7156 | | | 7157 | |
7157 | i2ccmd = (reg << I2CCMD_REG_ADDR_SHIFT) | | 7158 | i2ccmd = (reg << I2CCMD_REG_ADDR_SHIFT) |
7158 | | (phy << I2CCMD_PHY_ADDR_SHIFT) | | 7159 | | (phy << I2CCMD_PHY_ADDR_SHIFT) |
7159 | | I2CCMD_OPCODE_WRITE; | | 7160 | | I2CCMD_OPCODE_WRITE; |
7160 | CSR_WRITE(sc, WMREG_I2CCMD, i2ccmd); | | 7161 | CSR_WRITE(sc, WMREG_I2CCMD, i2ccmd); |
7161 | | | 7162 | |
7162 | /* Poll the ready bit */ | | 7163 | /* Poll the ready bit */ |
7163 | for (i = 0; i < I2CCMD_PHY_TIMEOUT; i++) { | | 7164 | for (i = 0; i < I2CCMD_PHY_TIMEOUT; i++) { |
7164 | delay(50); | | 7165 | delay(50); |
7165 | i2ccmd = CSR_READ(sc, WMREG_I2CCMD); | | 7166 | i2ccmd = CSR_READ(sc, WMREG_I2CCMD); |
7166 | if (i2ccmd & I2CCMD_READY) | | 7167 | if (i2ccmd & I2CCMD_READY) |
7167 | break; | | 7168 | break; |
7168 | } | | 7169 | } |
7169 | if ((i2ccmd & I2CCMD_READY) == 0) | | 7170 | if ((i2ccmd & I2CCMD_READY) == 0) |
7170 | aprint_error_dev(sc->sc_dev, "I2CCMD Write did not complete\n"); | | 7171 | aprint_error_dev(sc->sc_dev, "I2CCMD Write did not complete\n"); |
7171 | if ((i2ccmd & I2CCMD_ERROR) != 0) | | 7172 | if ((i2ccmd & I2CCMD_ERROR) != 0) |
7172 | aprint_error_dev(sc->sc_dev, "I2CCMD Error bit set\n"); | | 7173 | aprint_error_dev(sc->sc_dev, "I2CCMD Error bit set\n"); |
7173 | | | 7174 | |
7174 | wm_put_swfw_semaphore(sc, SWFW_PHY0_SM); | | 7175 | wm_put_swfw_semaphore(sc, SWFW_PHY0_SM); |
7175 | } | | 7176 | } |
7176 | | | 7177 | |
7177 | /* | | 7178 | /* |
7178 | * wm_gmii_82580_readreg: [mii interface function] | | 7179 | * wm_gmii_82580_readreg: [mii interface function] |
7179 | * | | 7180 | * |
7180 | * Read a PHY register on the 82580 and I350. | | 7181 | * Read a PHY register on the 82580 and I350. |
7181 | * This could be handled by the PHY layer if we didn't have to lock the | | 7182 | * This could be handled by the PHY layer if we didn't have to lock the |
7182 | * ressource ... | | 7183 | * ressource ... |
7183 | */ | | 7184 | */ |
7184 | static int | | 7185 | static int |
7185 | wm_gmii_82580_readreg(device_t self, int phy, int reg) | | 7186 | wm_gmii_82580_readreg(device_t self, int phy, int reg) |
7186 | { | | 7187 | { |
7187 | struct wm_softc *sc = device_private(self); | | 7188 | struct wm_softc *sc = device_private(self); |
7188 | int sem; | | 7189 | int sem; |
7189 | int rv; | | 7190 | int rv; |
7190 | | | 7191 | |
7191 | sem = swfwphysem[sc->sc_funcid]; | | 7192 | sem = swfwphysem[sc->sc_funcid]; |
7192 | if (wm_get_swfw_semaphore(sc, sem)) { | | 7193 | if (wm_get_swfw_semaphore(sc, sem)) { |
7193 | aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", | | 7194 | aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", |
7194 | __func__); | | 7195 | __func__); |
7195 | return 0; | | 7196 | return 0; |
7196 | } | | 7197 | } |
7197 | | | 7198 | |
7198 | rv = wm_gmii_i82544_readreg(self, phy, reg); | | 7199 | rv = wm_gmii_i82544_readreg(self, phy, reg); |
7199 | | | 7200 | |
7200 | wm_put_swfw_semaphore(sc, sem); | | 7201 | wm_put_swfw_semaphore(sc, sem); |
7201 | return rv; | | 7202 | return rv; |
7202 | } | | 7203 | } |
7203 | | | 7204 | |
7204 | /* | | 7205 | /* |
7205 | * wm_gmii_82580_writereg: [mii interface function] | | 7206 | * wm_gmii_82580_writereg: [mii interface function] |
7206 | * | | 7207 | * |
7207 | * Write a PHY register on the 82580 and I350. | | 7208 | * Write a PHY register on the 82580 and I350. |
7208 | * This could be handled by the PHY layer if we didn't have to lock the | | 7209 | * This could be handled by the PHY layer if we didn't have to lock the |
7209 | * ressource ... | | 7210 | * ressource ... |
7210 | */ | | 7211 | */ |
7211 | static void | | 7212 | static void |
7212 | wm_gmii_82580_writereg(device_t self, int phy, int reg, int val) | | 7213 | wm_gmii_82580_writereg(device_t self, int phy, int reg, int val) |
7213 | { | | 7214 | { |
7214 | struct wm_softc *sc = device_private(self); | | 7215 | struct wm_softc *sc = device_private(self); |
7215 | int sem; | | 7216 | int sem; |
7216 | | | 7217 | |
7217 | sem = swfwphysem[sc->sc_funcid]; | | 7218 | sem = swfwphysem[sc->sc_funcid]; |
7218 | if (wm_get_swfw_semaphore(sc, sem)) { | | 7219 | if (wm_get_swfw_semaphore(sc, sem)) { |
7219 | aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", | | 7220 | aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", |
7220 | __func__); | | 7221 | __func__); |
7221 | return; | | 7222 | return; |
7222 | } | | 7223 | } |
7223 | | | 7224 | |
7224 | wm_gmii_i82544_writereg(self, phy, reg, val); | | 7225 | wm_gmii_i82544_writereg(self, phy, reg, val); |
7225 | | | 7226 | |
7226 | wm_put_swfw_semaphore(sc, sem); | | 7227 | wm_put_swfw_semaphore(sc, sem); |
7227 | } | | 7228 | } |
7228 | | | 7229 | |
7229 | /* | | 7230 | /* |
7230 | * wm_gmii_statchg: [mii interface function] | | 7231 | * wm_gmii_statchg: [mii interface function] |
7231 | * | | 7232 | * |
7232 | * Callback from MII layer when media changes. | | 7233 | * Callback from MII layer when media changes. |
7233 | */ | | 7234 | */ |
7234 | static void | | 7235 | static void |
7235 | wm_gmii_statchg(struct ifnet *ifp) | | 7236 | wm_gmii_statchg(struct ifnet *ifp) |
7236 | { | | 7237 | { |
7237 | struct wm_softc *sc = ifp->if_softc; | | 7238 | struct wm_softc *sc = ifp->if_softc; |
7238 | struct mii_data *mii = &sc->sc_mii; | | 7239 | struct mii_data *mii = &sc->sc_mii; |
7239 | | | 7240 | |
7240 | sc->sc_ctrl &= ~(CTRL_TFCE | CTRL_RFCE); | | 7241 | sc->sc_ctrl &= ~(CTRL_TFCE | CTRL_RFCE); |
7241 | sc->sc_tctl &= ~TCTL_COLD(0x3ff); | | 7242 | sc->sc_tctl &= ~TCTL_COLD(0x3ff); |
7242 | sc->sc_fcrtl &= ~FCRTL_XONE; | | 7243 | sc->sc_fcrtl &= ~FCRTL_XONE; |
7243 | | | 7244 | |
7244 | /* | | 7245 | /* |
7245 | * Get flow control negotiation result. | | 7246 | * Get flow control negotiation result. |
7246 | */ | | 7247 | */ |
7247 | if (IFM_SUBTYPE(mii->mii_media.ifm_cur->ifm_media) == IFM_AUTO && | | 7248 | if (IFM_SUBTYPE(mii->mii_media.ifm_cur->ifm_media) == IFM_AUTO && |
7248 | (mii->mii_media_active & IFM_ETH_FMASK) != sc->sc_flowflags) { | | 7249 | (mii->mii_media_active & IFM_ETH_FMASK) != sc->sc_flowflags) { |
7249 | sc->sc_flowflags = mii->mii_media_active & IFM_ETH_FMASK; | | 7250 | sc->sc_flowflags = mii->mii_media_active & IFM_ETH_FMASK; |
7250 | mii->mii_media_active &= ~IFM_ETH_FMASK; | | 7251 | mii->mii_media_active &= ~IFM_ETH_FMASK; |
7251 | } | | 7252 | } |
7252 | | | 7253 | |
7253 | if (sc->sc_flowflags & IFM_FLOW) { | | 7254 | if (sc->sc_flowflags & IFM_FLOW) { |
7254 | if (sc->sc_flowflags & IFM_ETH_TXPAUSE) { | | 7255 | if (sc->sc_flowflags & IFM_ETH_TXPAUSE) { |
7255 | sc->sc_ctrl |= CTRL_TFCE; | | 7256 | sc->sc_ctrl |= CTRL_TFCE; |
7256 | sc->sc_fcrtl |= FCRTL_XONE; | | 7257 | sc->sc_fcrtl |= FCRTL_XONE; |
7257 | } | | 7258 | } |
7258 | if (sc->sc_flowflags & IFM_ETH_RXPAUSE) | | 7259 | if (sc->sc_flowflags & IFM_ETH_RXPAUSE) |
7259 | sc->sc_ctrl |= CTRL_RFCE; | | 7260 | sc->sc_ctrl |= CTRL_RFCE; |
7260 | } | | 7261 | } |
7261 | | | 7262 | |
7262 | if (sc->sc_mii.mii_media_active & IFM_FDX) { | | 7263 | if (sc->sc_mii.mii_media_active & IFM_FDX) { |
7263 | DPRINTF(WM_DEBUG_LINK, | | 7264 | DPRINTF(WM_DEBUG_LINK, |
7264 | ("%s: LINK: statchg: FDX\n", ifp->if_xname)); | | 7265 | ("%s: LINK: statchg: FDX\n", ifp->if_xname)); |
7265 | sc->sc_tctl |= TCTL_COLD(TX_COLLISION_DISTANCE_FDX); | | 7266 | sc->sc_tctl |= TCTL_COLD(TX_COLLISION_DISTANCE_FDX); |
7266 | } else { | | 7267 | } else { |
7267 | DPRINTF(WM_DEBUG_LINK, | | 7268 | DPRINTF(WM_DEBUG_LINK, |
7268 | ("%s: LINK: statchg: HDX\n", ifp->if_xname)); | | 7269 | ("%s: LINK: statchg: HDX\n", ifp->if_xname)); |
7269 | sc->sc_tctl |= TCTL_COLD(TX_COLLISION_DISTANCE_HDX); | | 7270 | sc->sc_tctl |= TCTL_COLD(TX_COLLISION_DISTANCE_HDX); |
7270 | } | | 7271 | } |
7271 | | | 7272 | |
7272 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); | | 7273 | CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); |
7273 | CSR_WRITE(sc, WMREG_TCTL, sc->sc_tctl); | | 7274 | CSR_WRITE(sc, WMREG_TCTL, sc->sc_tctl); |
7274 | CSR_WRITE(sc, (sc->sc_type < WM_T_82543) ? WMREG_OLD_FCRTL | | 7275 | CSR_WRITE(sc, (sc->sc_type < WM_T_82543) ? WMREG_OLD_FCRTL |
7275 | : WMREG_FCRTL, sc->sc_fcrtl); | | 7276 | : WMREG_FCRTL, sc->sc_fcrtl); |
7276 | if (sc->sc_type == WM_T_80003) { | | 7277 | if (sc->sc_type == WM_T_80003) { |
7277 | switch (IFM_SUBTYPE(sc->sc_mii.mii_media_active)) { | | 7278 | switch (IFM_SUBTYPE(sc->sc_mii.mii_media_active)) { |
7278 | case IFM_1000_T: | | 7279 | case IFM_1000_T: |
7279 | wm_kmrn_writereg(sc, KUMCTRLSTA_OFFSET_HD_CTRL, | | 7280 | wm_kmrn_writereg(sc, KUMCTRLSTA_OFFSET_HD_CTRL, |
7280 | KUMCTRLSTA_HD_CTRL_1000_DEFAULT); | | 7281 | KUMCTRLSTA_HD_CTRL_1000_DEFAULT); |
7281 | sc->sc_tipg = TIPG_1000T_80003_DFLT; | | 7282 | sc->sc_tipg = TIPG_1000T_80003_DFLT; |
7282 | break; | | 7283 | break; |
7283 | default: | | 7284 | default: |
7284 | wm_kmrn_writereg(sc, KUMCTRLSTA_OFFSET_HD_CTRL, | | 7285 | wm_kmrn_writereg(sc, KUMCTRLSTA_OFFSET_HD_CTRL, |
7285 | KUMCTRLSTA_HD_CTRL_10_100_DEFAULT); | | 7286 | KUMCTRLSTA_HD_CTRL_10_100_DEFAULT); |
7286 | sc->sc_tipg = TIPG_10_100_80003_DFLT; | | 7287 | sc->sc_tipg = TIPG_10_100_80003_DFLT; |
7287 | break; | | 7288 | break; |
7288 | } | | 7289 | } |
7289 | CSR_WRITE(sc, WMREG_TIPG, sc->sc_tipg); | | 7290 | CSR_WRITE(sc, WMREG_TIPG, sc->sc_tipg); |
7290 | } | | 7291 | } |
7291 | } | | 7292 | } |
7292 | | | 7293 | |
7293 | /* | | 7294 | /* |
7294 | * wm_kmrn_readreg: | | 7295 | * wm_kmrn_readreg: |
7295 | * | | 7296 | * |
7296 | * Read a kumeran register | | 7297 | * Read a kumeran register |
7297 | */ | | 7298 | */ |
7298 | static int | | 7299 | static int |
7299 | wm_kmrn_readreg(struct wm_softc *sc, int reg) | | 7300 | wm_kmrn_readreg(struct wm_softc *sc, int reg) |
7300 | { | | 7301 | { |
7301 | int rv; | | 7302 | int rv; |
7302 | | | 7303 | |
7303 | if (sc->sc_flags == WM_F_SWFW_SYNC) { | | 7304 | if (sc->sc_flags == WM_F_SWFW_SYNC) { |
7304 | if (wm_get_swfw_semaphore(sc, SWFW_MAC_CSR_SM)) { | | 7305 | if (wm_get_swfw_semaphore(sc, SWFW_MAC_CSR_SM)) { |
7305 | aprint_error_dev(sc->sc_dev, | | 7306 | aprint_error_dev(sc->sc_dev, |
7306 | "%s: failed to get semaphore\n", __func__); | | 7307 | "%s: failed to get semaphore\n", __func__); |
7307 | return 0; | | 7308 | return 0; |
7308 | } | | 7309 | } |
7309 | } else if (sc->sc_flags == WM_F_SWFWHW_SYNC) { | | 7310 | } else if (sc->sc_flags == WM_F_SWFWHW_SYNC) { |
7310 | if (wm_get_swfwhw_semaphore(sc)) { | | 7311 | if (wm_get_swfwhw_semaphore(sc)) { |
7311 | aprint_error_dev(sc->sc_dev, | | 7312 | aprint_error_dev(sc->sc_dev, |
7312 | "%s: failed to get semaphore\n", __func__); | | 7313 | "%s: failed to get semaphore\n", __func__); |
7313 | return 0; | | 7314 | return 0; |
7314 | } | | 7315 | } |
7315 | } | | 7316 | } |
7316 | | | 7317 | |
7317 | CSR_WRITE(sc, WMREG_KUMCTRLSTA, | | 7318 | CSR_WRITE(sc, WMREG_KUMCTRLSTA, |
7318 | ((reg << KUMCTRLSTA_OFFSET_SHIFT) & KUMCTRLSTA_OFFSET) | | | 7319 | ((reg << KUMCTRLSTA_OFFSET_SHIFT) & KUMCTRLSTA_OFFSET) | |
7319 | KUMCTRLSTA_REN); | | 7320 | KUMCTRLSTA_REN); |
7320 | delay(2); | | 7321 | delay(2); |
7321 | | | 7322 | |
7322 | rv = CSR_READ(sc, WMREG_KUMCTRLSTA) & KUMCTRLSTA_MASK; | | 7323 | rv = CSR_READ(sc, WMREG_KUMCTRLSTA) & KUMCTRLSTA_MASK; |
7323 | | | 7324 | |
7324 | if (sc->sc_flags == WM_F_SWFW_SYNC) | | 7325 | if (sc->sc_flags == WM_F_SWFW_SYNC) |
7325 | wm_put_swfw_semaphore(sc, SWFW_MAC_CSR_SM); | | 7326 | wm_put_swfw_semaphore(sc, SWFW_MAC_CSR_SM); |
7326 | else if (sc->sc_flags == WM_F_SWFWHW_SYNC) | | 7327 | else if (sc->sc_flags == WM_F_SWFWHW_SYNC) |
7327 | wm_put_swfwhw_semaphore(sc); | | 7328 | wm_put_swfwhw_semaphore(sc); |
7328 | | | 7329 | |
7329 | return rv; | | 7330 | return rv; |
7330 | } | | 7331 | } |
7331 | | | 7332 | |
7332 | /* | | 7333 | /* |
7333 | * wm_kmrn_writereg: | | 7334 | * wm_kmrn_writereg: |
7334 | * | | 7335 | * |
7335 | * Write a kumeran register | | 7336 | * Write a kumeran register |
7336 | */ | | 7337 | */ |
7337 | static void | | 7338 | static void |
7338 | wm_kmrn_writereg(struct wm_softc *sc, int reg, int val) | | 7339 | wm_kmrn_writereg(struct wm_softc *sc, int reg, int val) |
7339 | { | | 7340 | { |
7340 | | | 7341 | |
7341 | if (sc->sc_flags == WM_F_SWFW_SYNC) { | | 7342 | if (sc->sc_flags == WM_F_SWFW_SYNC) { |
7342 | if (wm_get_swfw_semaphore(sc, SWFW_MAC_CSR_SM)) { | | 7343 | if (wm_get_swfw_semaphore(sc, SWFW_MAC_CSR_SM)) { |
7343 | aprint_error_dev(sc->sc_dev, | | 7344 | aprint_error_dev(sc->sc_dev, |
7344 | "%s: failed to get semaphore\n", __func__); | | 7345 | "%s: failed to get semaphore\n", __func__); |