]>
Commit | Line | Data |
---|---|---|
cfb739b4 GKH |
1 | /* |
2 | * Agere Systems Inc. | |
3 | * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs | |
4 | * | |
64f93036 | 5 | * Copyright © 2005 Agere Systems Inc. |
cfb739b4 GKH |
6 | * All rights reserved. |
7 | * http://www.agere.com | |
8 | * | |
9 | *------------------------------------------------------------------------------ | |
10 | * | |
11 | * et1310_mac.c - All code and routines pertaining to the MAC | |
12 | * | |
13 | *------------------------------------------------------------------------------ | |
14 | * | |
15 | * SOFTWARE LICENSE | |
16 | * | |
17 | * This software is provided subject to the following terms and conditions, | |
18 | * which you should read carefully before using the software. Using this | |
19 | * software indicates your acceptance of these terms and conditions. If you do | |
20 | * not agree with these terms and conditions, do not use the software. | |
21 | * | |
64f93036 | 22 | * Copyright © 2005 Agere Systems Inc. |
cfb739b4 GKH |
23 | * All rights reserved. |
24 | * | |
25 | * Redistribution and use in source or binary forms, with or without | |
26 | * modifications, are permitted provided that the following conditions are met: | |
27 | * | |
28 | * . Redistributions of source code must retain the above copyright notice, this | |
29 | * list of conditions and the following Disclaimer as comments in the code as | |
30 | * well as in the documentation and/or other materials provided with the | |
31 | * distribution. | |
32 | * | |
33 | * . Redistributions in binary form must reproduce the above copyright notice, | |
34 | * this list of conditions and the following Disclaimer in the documentation | |
35 | * and/or other materials provided with the distribution. | |
36 | * | |
37 | * . Neither the name of Agere Systems Inc. nor the names of the contributors | |
38 | * may be used to endorse or promote products derived from this software | |
39 | * without specific prior written permission. | |
40 | * | |
41 | * Disclaimer | |
42 | * | |
64f93036 | 43 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, |
cfb739b4 GKH |
44 | * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF |
45 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY | |
46 | * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN | |
47 | * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY | |
48 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
49 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
50 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
51 | * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT | |
52 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |
53 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH | |
54 | * DAMAGE. | |
55 | * | |
56 | */ | |
57 | ||
58 | #include "et131x_version.h" | |
cfb739b4 GKH |
59 | #include "et131x_defs.h" |
60 | ||
61 | #include <linux/init.h> | |
62 | #include <linux/module.h> | |
63 | #include <linux/types.h> | |
64 | #include <linux/kernel.h> | |
65 | ||
66 | #include <linux/sched.h> | |
67 | #include <linux/ptrace.h> | |
cfb739b4 GKH |
68 | #include <linux/ctype.h> |
69 | #include <linux/string.h> | |
70 | #include <linux/timer.h> | |
71 | #include <linux/interrupt.h> | |
72 | #include <linux/in.h> | |
73 | #include <linux/delay.h> | |
64f93036 AC |
74 | #include <linux/io.h> |
75 | #include <linux/bitops.h> | |
15700039 | 76 | #include <linux/pci.h> |
cfb739b4 | 77 | #include <asm/system.h> |
cfb739b4 GKH |
78 | |
79 | #include <linux/netdevice.h> | |
80 | #include <linux/etherdevice.h> | |
81 | #include <linux/skbuff.h> | |
82 | #include <linux/if_arp.h> | |
83 | #include <linux/ioport.h> | |
84 | #include <linux/crc32.h> | |
85 | ||
86 | #include "et1310_phy.h" | |
cfb739b4 | 87 | #include "et131x_adapter.h" |
69ea5fcb AC |
88 | #include "et131x.h" |
89 | ||
90 | ||
91 | #define COUNTER_WRAP_28_BIT 0x10000000 | |
92 | #define COUNTER_WRAP_22_BIT 0x400000 | |
93 | #define COUNTER_WRAP_16_BIT 0x10000 | |
94 | #define COUNTER_WRAP_12_BIT 0x1000 | |
95 | ||
96 | #define COUNTER_MASK_28_BIT (COUNTER_WRAP_28_BIT - 1) | |
97 | #define COUNTER_MASK_22_BIT (COUNTER_WRAP_22_BIT - 1) | |
98 | #define COUNTER_MASK_16_BIT (COUNTER_WRAP_16_BIT - 1) | |
99 | #define COUNTER_MASK_12_BIT (COUNTER_WRAP_12_BIT - 1) | |
cfb739b4 | 100 | |
cfb739b4 GKH |
101 | /** |
102 | * ConfigMacRegs1 - Initialize the first part of MAC regs | |
103 | * @pAdpater: pointer to our adapter structure | |
104 | */ | |
25ad00bb | 105 | void ConfigMACRegs1(struct et131x_adapter *etdev) |
cfb739b4 | 106 | { |
f3f415a3 | 107 | struct _MAC_t __iomem *pMac = &etdev->regs->mac; |
cfb739b4 GKH |
108 | MAC_STATION_ADDR1_t station1; |
109 | MAC_STATION_ADDR2_t station2; | |
308e93e0 | 110 | u32 ipg; |
cfb739b4 | 111 | |
cfb739b4 GKH |
112 | /* First we need to reset everything. Write to MAC configuration |
113 | * register 1 to perform reset. | |
114 | */ | |
c9835d97 | 115 | writel(0xC00F0000, &pMac->cfg1); |
cfb739b4 GKH |
116 | |
117 | /* Next lets configure the MAC Inter-packet gap register */ | |
308e93e0 AC |
118 | ipg = 0x38005860; /* IPG1 0x38 IPG2 0x58 B2B 0x60 */ |
119 | ipg |= 0x50 << 8; /* ifg enforce 0x50 */ | |
120 | writel(ipg, &pMac->ipg); | |
cfb739b4 GKH |
121 | |
122 | /* Next lets configure the MAC Half Duplex register */ | |
c2f6118a AC |
123 | /* BEB trunc 0xA, Ex Defer, Rexmit 0xF Coll 0x37 */ |
124 | writel(0x00A1F037, &pMac->hfdp); | |
cfb739b4 GKH |
125 | |
126 | /* Next lets configure the MAC Interface Control register */ | |
b491f147 | 127 | writel(0, &pMac->if_ctrl); |
cfb739b4 | 128 | |
658ce9d6 | 129 | /* Let's move on to setting up the mii management configuration */ |
eccdd88f | 130 | writel(0x07, &pMac->mii_mgmt_cfg); /* Clock reset 0x7 */ |
cfb739b4 GKH |
131 | |
132 | /* Next lets configure the MAC Station Address register. These | |
133 | * values are read from the EEPROM during initialization and stored | |
134 | * in the adapter structure. We write what is stored in the adapter | |
135 | * structure to the MAC Station Address registers high and low. This | |
136 | * station address is used for generating and checking pause control | |
137 | * packets. | |
138 | */ | |
25ad00bb AC |
139 | station2.bits.Octet1 = etdev->CurrentAddress[0]; |
140 | station2.bits.Octet2 = etdev->CurrentAddress[1]; | |
141 | station1.bits.Octet3 = etdev->CurrentAddress[2]; | |
142 | station1.bits.Octet4 = etdev->CurrentAddress[3]; | |
143 | station1.bits.Octet5 = etdev->CurrentAddress[4]; | |
144 | station1.bits.Octet6 = etdev->CurrentAddress[5]; | |
cfb739b4 GKH |
145 | writel(station1.value, &pMac->station_addr_1.value); |
146 | writel(station2.value, &pMac->station_addr_2.value); | |
147 | ||
148 | /* Max ethernet packet in bytes that will passed by the mac without | |
149 | * being truncated. Allow the MAC to pass 4 more than our max packet | |
150 | * size. This is 4 for the Ethernet CRC. | |
151 | * | |
152 | * Packets larger than (RegistryJumboPacket) that do not contain a | |
153 | * VLAN ID will be dropped by the Rx function. | |
154 | */ | |
cc5dc29c | 155 | writel(etdev->RegistryJumboPacket + 4, &pMac->max_fm_len); |
cfb739b4 GKH |
156 | |
157 | /* clear out MAC config reset */ | |
c9835d97 | 158 | writel(0, &pMac->cfg1); |
cfb739b4 GKH |
159 | } |
160 | ||
161 | /** | |
162 | * ConfigMacRegs2 - Initialize the second part of MAC regs | |
163 | * @pAdpater: pointer to our adapter structure | |
164 | */ | |
25ad00bb | 165 | void ConfigMACRegs2(struct et131x_adapter *etdev) |
cfb739b4 GKH |
166 | { |
167 | int32_t delay = 0; | |
f3f415a3 | 168 | struct _MAC_t __iomem *pMac = &etdev->regs->mac; |
c9835d97 AC |
169 | u32 cfg1; |
170 | u32 cfg2; | |
b491f147 | 171 | u32 ifctrl; |
6720949d | 172 | u32 ctl; |
cfb739b4 | 173 | |
6720949d | 174 | ctl = readl(&etdev->regs->txmac.ctl); |
c9835d97 AC |
175 | cfg1 = readl(&pMac->cfg1); |
176 | cfg2 = readl(&pMac->cfg2); | |
b491f147 | 177 | ifctrl = readl(&pMac->if_ctrl); |
cfb739b4 | 178 | |
c9835d97 AC |
179 | /* Set up the if mode bits */ |
180 | cfg2 &= ~0x300; | |
9fa81099 | 181 | if (etdev->linkspeed == TRUEPHY_SPEED_1000MBPS) { |
c9835d97 | 182 | cfg2 |= 0x200; |
b491f147 AC |
183 | /* Phy mode bit */ |
184 | ifctrl &= ~(1 << 24); | |
cfb739b4 | 185 | } else { |
c9835d97 | 186 | cfg2 |= 0x100; |
b491f147 | 187 | ifctrl |= (1 << 24); |
cfb739b4 GKH |
188 | } |
189 | ||
190 | /* We need to enable Rx/Tx */ | |
c9835d97 | 191 | cfg1 |= CFG1_RX_ENABLE|CFG1_TX_ENABLE|CFG1_TX_FLOW; |
cfb739b4 | 192 | /* Initialize loop back to off */ |
c9835d97 AC |
193 | cfg1 &= ~(CFG1_LOOPBACK|CFG1_RX_FLOW); |
194 | if (etdev->FlowControl == RxOnly || etdev->FlowControl == Both) | |
195 | cfg1 |= CFG1_RX_FLOW; | |
196 | writel(cfg1, &pMac->cfg1); | |
cfb739b4 GKH |
197 | |
198 | /* Now we need to initialize the MAC Configuration 2 register */ | |
c9835d97 AC |
199 | /* preamble 7, check length, huge frame off, pad crc, crc enable |
200 | full duplex off */ | |
201 | cfg2 |= 0x7016; | |
202 | cfg2 &= ~0x0021; | |
cfb739b4 | 203 | |
c9835d97 AC |
204 | /* Turn on duplex if needed */ |
205 | if (etdev->duplex_mode) | |
206 | cfg2 |= 0x01; | |
cfb739b4 | 207 | |
b491f147 AC |
208 | ifctrl &= ~(1 << 26); |
209 | if (!etdev->duplex_mode) | |
210 | ifctrl |= (1<<26); /* Enable ghd */ | |
cfb739b4 | 211 | |
b491f147 | 212 | writel(ifctrl, &pMac->if_ctrl); |
c9835d97 | 213 | writel(cfg2, &pMac->cfg2); |
cfb739b4 GKH |
214 | |
215 | do { | |
216 | udelay(10); | |
217 | delay++; | |
c9835d97 AC |
218 | cfg1 = readl(&pMac->cfg1); |
219 | } while ((cfg1 & CFG1_WAIT) != CFG1_WAIT && delay < 100); | |
cfb739b4 GKH |
220 | |
221 | if (delay == 100) { | |
15700039 | 222 | dev_warn(&etdev->pdev->dev, |
64f93036 | 223 | "Syncd bits did not respond correctly cfg1 word 0x%08x\n", |
c9835d97 | 224 | cfg1); |
cfb739b4 GKH |
225 | } |
226 | ||
cfb739b4 | 227 | /* Enable TXMAC */ |
05ad62a5 | 228 | ctl |= 0x09; /* TX mac enable, FC disable */ |
6720949d | 229 | writel(ctl, &etdev->regs->txmac.ctl); |
cfb739b4 GKH |
230 | |
231 | /* Ready to start the RXDMA/TXDMA engine */ | |
f6b35d66 | 232 | if (etdev->Flags & fMP_ADAPTER_LOWER_POWER) { |
25ad00bb AC |
233 | et131x_rx_dma_enable(etdev); |
234 | et131x_tx_dma_enable(etdev); | |
cfb739b4 | 235 | } |
cfb739b4 GKH |
236 | } |
237 | ||
25ad00bb | 238 | void ConfigRxMacRegs(struct et131x_adapter *etdev) |
cfb739b4 | 239 | { |
f3f415a3 | 240 | struct _RXMAC_t __iomem *pRxMac = &etdev->regs->rxmac; |
cfb739b4 GKH |
241 | RXMAC_WOL_SA_LO_t sa_lo; |
242 | RXMAC_WOL_SA_HI_t sa_hi; | |
b186f331 | 243 | u32 pf_ctrl = 0; |
cfb739b4 | 244 | |
cfb739b4 | 245 | /* Disable the MAC while it is being configured (also disable WOL) */ |
bd03d0d5 | 246 | writel(0x8, &pRxMac->ctrl); |
cfb739b4 GKH |
247 | |
248 | /* Initialize WOL to disabled. */ | |
70a29a24 AC |
249 | writel(0, &pRxMac->crc0); |
250 | writel(0, &pRxMac->crc12); | |
251 | writel(0, &pRxMac->crc34); | |
cfb739b4 GKH |
252 | |
253 | /* We need to set the WOL mask0 - mask4 next. We initialize it to | |
254 | * its default Values of 0x00000000 because there are not WOL masks | |
255 | * as of this time. | |
256 | */ | |
257 | writel(0, &pRxMac->mask0_word0); | |
258 | writel(0, &pRxMac->mask0_word1); | |
259 | writel(0, &pRxMac->mask0_word2); | |
260 | writel(0, &pRxMac->mask0_word3); | |
261 | ||
262 | writel(0, &pRxMac->mask1_word0); | |
263 | writel(0, &pRxMac->mask1_word1); | |
264 | writel(0, &pRxMac->mask1_word2); | |
265 | writel(0, &pRxMac->mask1_word3); | |
266 | ||
267 | writel(0, &pRxMac->mask2_word0); | |
268 | writel(0, &pRxMac->mask2_word1); | |
269 | writel(0, &pRxMac->mask2_word2); | |
270 | writel(0, &pRxMac->mask2_word3); | |
271 | ||
272 | writel(0, &pRxMac->mask3_word0); | |
273 | writel(0, &pRxMac->mask3_word1); | |
274 | writel(0, &pRxMac->mask3_word2); | |
275 | writel(0, &pRxMac->mask3_word3); | |
276 | ||
277 | writel(0, &pRxMac->mask4_word0); | |
278 | writel(0, &pRxMac->mask4_word1); | |
279 | writel(0, &pRxMac->mask4_word2); | |
280 | writel(0, &pRxMac->mask4_word3); | |
281 | ||
282 | /* Lets setup the WOL Source Address */ | |
25ad00bb AC |
283 | sa_lo.bits.sa3 = etdev->CurrentAddress[2]; |
284 | sa_lo.bits.sa4 = etdev->CurrentAddress[3]; | |
285 | sa_lo.bits.sa5 = etdev->CurrentAddress[4]; | |
286 | sa_lo.bits.sa6 = etdev->CurrentAddress[5]; | |
cfb739b4 GKH |
287 | writel(sa_lo.value, &pRxMac->sa_lo.value); |
288 | ||
25ad00bb AC |
289 | sa_hi.bits.sa1 = etdev->CurrentAddress[0]; |
290 | sa_hi.bits.sa2 = etdev->CurrentAddress[1]; | |
cfb739b4 GKH |
291 | writel(sa_hi.value, &pRxMac->sa_hi.value); |
292 | ||
293 | /* Disable all Packet Filtering */ | |
b186f331 | 294 | writel(0, &pRxMac->pf_ctrl); |
cfb739b4 GKH |
295 | |
296 | /* Let's initialize the Unicast Packet filtering address */ | |
25ad00bb AC |
297 | if (etdev->PacketFilter & ET131X_PACKET_TYPE_DIRECTED) { |
298 | SetupDeviceForUnicast(etdev); | |
b186f331 | 299 | pf_ctrl |= 4; /* Unicast filter */ |
cfb739b4 GKH |
300 | } else { |
301 | writel(0, &pRxMac->uni_pf_addr1.value); | |
302 | writel(0, &pRxMac->uni_pf_addr2.value); | |
303 | writel(0, &pRxMac->uni_pf_addr3.value); | |
304 | } | |
305 | ||
306 | /* Let's initialize the Multicast hash */ | |
b186f331 AC |
307 | if (!(etdev->PacketFilter & ET131X_PACKET_TYPE_ALL_MULTICAST)) { |
308 | pf_ctrl |= 2; /* Multicast filter */ | |
25ad00bb | 309 | SetupDeviceForMulticast(etdev); |
cfb739b4 GKH |
310 | } |
311 | ||
312 | /* Runt packet filtering. Didn't work in version A silicon. */ | |
b186f331 AC |
313 | pf_ctrl |= (NIC_MIN_PACKET_SIZE + 4) << 16; |
314 | pf_ctrl |= 8; /* Fragment filter */ | |
cfb739b4 | 315 | |
287acb63 | 316 | if (etdev->RegistryJumboPacket > 8192) |
cfb739b4 GKH |
317 | /* In order to transmit jumbo packets greater than 8k, the |
318 | * FIFO between RxMAC and RxDMA needs to be reduced in size | |
319 | * to (16k - Jumbo packet size). In order to implement this, | |
320 | * we must use "cut through" mode in the RxMAC, which chops | |
321 | * packets down into segments which are (max_size * 16). In | |
322 | * this case we selected 256 bytes, since this is the size of | |
323 | * the PCI-Express TLP's that the 1310 uses. | |
287acb63 AC |
324 | * |
325 | * seg_en on, fc_en off, size 0x10 | |
cfb739b4 | 326 | */ |
287acb63 AC |
327 | writel(0x41, &pRxMac->mcif_ctrl_max_seg); |
328 | else | |
329 | writel(0, &pRxMac->mcif_ctrl_max_seg); | |
cfb739b4 GKH |
330 | |
331 | /* Initialize the MCIF water marks */ | |
287acb63 | 332 | writel(0, &pRxMac->mcif_water_mark); |
cfb739b4 GKH |
333 | |
334 | /* Initialize the MIF control */ | |
dcb0789b | 335 | writel(0, &pRxMac->mif_ctrl); |
cfb739b4 GKH |
336 | |
337 | /* Initialize the Space Available Register */ | |
370d52ac | 338 | writel(0, &pRxMac->space_avail); |
cfb739b4 GKH |
339 | |
340 | /* Initialize the the mif_ctrl register | |
341 | * bit 3: Receive code error. One or more nibbles were signaled as | |
342 | * errors during the reception of the packet. Clear this | |
343 | * bit in Gigabit, set it in 100Mbit. This was derived | |
344 | * experimentally at UNH. | |
345 | * bit 4: Receive CRC error. The packet's CRC did not match the | |
346 | * internally generated CRC. | |
347 | * bit 5: Receive length check error. Indicates that frame length | |
348 | * field value in the packet does not match the actual data | |
349 | * byte length and is not a type field. | |
350 | * bit 16: Receive frame truncated. | |
351 | * bit 17: Drop packet enable | |
352 | */ | |
9fa81099 | 353 | if (etdev->linkspeed == TRUEPHY_SPEED_100MBPS) |
dcb0789b | 354 | writel(0x30038, &pRxMac->mif_ctrl); |
64f93036 | 355 | else |
dcb0789b | 356 | writel(0x30030, &pRxMac->mif_ctrl); |
cfb739b4 GKH |
357 | |
358 | /* Finally we initialize RxMac to be enabled & WOL disabled. Packet | |
359 | * filter is always enabled since it is where the runt packets are | |
360 | * supposed to be dropped. For version A silicon, runt packet | |
361 | * dropping doesn't work, so it is disabled in the pf_ctrl register, | |
362 | * but we still leave the packet filter on. | |
363 | */ | |
b186f331 | 364 | writel(pf_ctrl, &pRxMac->pf_ctrl); |
bd03d0d5 | 365 | writel(0x9, &pRxMac->ctrl); |
cfb739b4 GKH |
366 | } |
367 | ||
25ad00bb | 368 | void ConfigTxMacRegs(struct et131x_adapter *etdev) |
cfb739b4 | 369 | { |
afa7e5ec | 370 | struct txmac_regs *txmac = &etdev->regs->txmac; |
cfb739b4 | 371 | |
cfb739b4 GKH |
372 | /* We need to update the Control Frame Parameters |
373 | * cfpt - control frame pause timer set to 64 (0x40) | |
374 | * cfep - control frame extended pause timer set to 0x0 | |
375 | */ | |
f838cabd | 376 | if (etdev->FlowControl == None) |
afa7e5ec | 377 | writel(0, &txmac->cf_param); |
f838cabd | 378 | else |
afa7e5ec | 379 | writel(0x40, &txmac->cf_param); |
cfb739b4 GKH |
380 | } |
381 | ||
25ad00bb | 382 | void ConfigMacStatRegs(struct et131x_adapter *etdev) |
cfb739b4 | 383 | { |
dc26ffc7 AC |
384 | struct macstat_regs __iomem *macstat = |
385 | &etdev->regs->macstat; | |
cfb739b4 | 386 | |
cfb739b4 GKH |
387 | /* Next we need to initialize all the MAC_STAT registers to zero on |
388 | * the device. | |
389 | */ | |
74f38633 AC |
390 | writel(0, &macstat->RFcs); |
391 | writel(0, &macstat->RAln); | |
392 | writel(0, &macstat->RFlr); | |
393 | writel(0, &macstat->RDrp); | |
394 | writel(0, &macstat->RCde); | |
395 | writel(0, &macstat->ROvr); | |
396 | writel(0, &macstat->RFrg); | |
397 | ||
398 | writel(0, &macstat->TScl); | |
399 | writel(0, &macstat->TDfr); | |
400 | writel(0, &macstat->TMcl); | |
401 | writel(0, &macstat->TLcl); | |
402 | writel(0, &macstat->TNcl); | |
403 | writel(0, &macstat->TOvr); | |
404 | writel(0, &macstat->TUnd); | |
cfb739b4 GKH |
405 | |
406 | /* Unmask any counters that we want to track the overflow of. | |
407 | * Initially this will be all counters. It may become clear later | |
408 | * that we do not need to track all counters. | |
409 | */ | |
74f38633 AC |
410 | writel(0xFFFFBE32, &macstat->Carry1M); |
411 | writel(0xFFFE7E8B, &macstat->Carry2M); | |
cfb739b4 GKH |
412 | } |
413 | ||
25ad00bb | 414 | void ConfigFlowControl(struct et131x_adapter *etdev) |
cfb739b4 | 415 | { |
9fa81099 | 416 | if (etdev->duplex_mode == 0) { |
25ad00bb | 417 | etdev->FlowControl = None; |
cfb739b4 | 418 | } else { |
74f38633 | 419 | char remote_pause, remote_async_pause; |
cfb739b4 | 420 | |
25ad00bb | 421 | ET1310_PhyAccessMiBit(etdev, |
74f38633 | 422 | TRUEPHY_BIT_READ, 5, 10, &remote_pause); |
25ad00bb | 423 | ET1310_PhyAccessMiBit(etdev, |
cfb739b4 | 424 | TRUEPHY_BIT_READ, 5, 11, |
74f38633 | 425 | &remote_async_pause); |
cfb739b4 | 426 | |
74f38633 AC |
427 | if ((remote_pause == TRUEPHY_BIT_SET) && |
428 | (remote_async_pause == TRUEPHY_BIT_SET)) { | |
25ad00bb | 429 | etdev->FlowControl = etdev->RegistryFlowControl; |
74f38633 AC |
430 | } else if ((remote_pause == TRUEPHY_BIT_SET) && |
431 | (remote_async_pause == TRUEPHY_BIT_CLEAR)) { | |
25ad00bb AC |
432 | if (etdev->RegistryFlowControl == Both) |
433 | etdev->FlowControl = Both; | |
64f93036 | 434 | else |
25ad00bb | 435 | etdev->FlowControl = None; |
74f38633 AC |
436 | } else if ((remote_pause == TRUEPHY_BIT_CLEAR) && |
437 | (remote_async_pause == TRUEPHY_BIT_CLEAR)) { | |
25ad00bb | 438 | etdev->FlowControl = None; |
74f38633 AC |
439 | } else {/* if (remote_pause == TRUEPHY_CLEAR_BIT && |
440 | remote_async_pause == TRUEPHY_SET_BIT) */ | |
25ad00bb AC |
441 | if (etdev->RegistryFlowControl == Both) |
442 | etdev->FlowControl = RxOnly; | |
64f93036 | 443 | else |
25ad00bb | 444 | etdev->FlowControl = None; |
cfb739b4 GKH |
445 | } |
446 | } | |
447 | } | |
448 | ||
449 | /** | |
450 | * UpdateMacStatHostCounters - Update the local copy of the statistics | |
25ad00bb | 451 | * @etdev: pointer to the adapter structure |
cfb739b4 | 452 | */ |
25ad00bb | 453 | void UpdateMacStatHostCounters(struct et131x_adapter *etdev) |
cfb739b4 | 454 | { |
25ad00bb | 455 | struct _ce_stats_t *stats = &etdev->Stats; |
dc26ffc7 AC |
456 | struct macstat_regs __iomem *macstat = |
457 | &etdev->regs->macstat; | |
cfb739b4 | 458 | |
74f38633 AC |
459 | stats->collisions += readl(&macstat->TNcl); |
460 | stats->first_collision += readl(&macstat->TScl); | |
461 | stats->tx_deferred += readl(&macstat->TDfr); | |
462 | stats->excessive_collisions += readl(&macstat->TMcl); | |
463 | stats->late_collisions += readl(&macstat->TLcl); | |
464 | stats->tx_uflo += readl(&macstat->TUnd); | |
465 | stats->max_pkt_error += readl(&macstat->TOvr); | |
466 | ||
467 | stats->alignment_err += readl(&macstat->RAln); | |
468 | stats->crc_err += readl(&macstat->RCde); | |
469 | stats->norcvbuf += readl(&macstat->RDrp); | |
470 | stats->rx_ov_flow += readl(&macstat->ROvr); | |
471 | stats->code_violations += readl(&macstat->RFcs); | |
472 | stats->length_err += readl(&macstat->RFlr); | |
473 | ||
474 | stats->other_errors += readl(&macstat->RFrg); | |
cfb739b4 GKH |
475 | } |
476 | ||
477 | /** | |
478 | * HandleMacStatInterrupt | |
25ad00bb | 479 | * @etdev: pointer to the adapter structure |
cfb739b4 GKH |
480 | * |
481 | * One of the MACSTAT counters has wrapped. Update the local copy of | |
482 | * the statistics held in the adapter structure, checking the "wrap" | |
483 | * bit for each counter. | |
484 | */ | |
25ad00bb | 485 | void HandleMacStatInterrupt(struct et131x_adapter *etdev) |
cfb739b4 | 486 | { |
ae8d9d84 AC |
487 | u32 Carry1; |
488 | u32 Carry2; | |
cfb739b4 | 489 | |
cfb739b4 GKH |
490 | /* Read the interrupt bits from the register(s). These are Clear On |
491 | * Write. | |
492 | */ | |
dc26ffc7 AC |
493 | Carry1 = readl(&etdev->regs->macstat.Carry1); |
494 | Carry2 = readl(&etdev->regs->macstat.Carry2); | |
cfb739b4 | 495 | |
dc26ffc7 AC |
496 | writel(Carry1, &etdev->regs->macstat.Carry1); |
497 | writel(Carry2, &etdev->regs->macstat.Carry2); | |
cfb739b4 GKH |
498 | |
499 | /* We need to do update the host copy of all the MAC_STAT counters. | |
500 | * For each counter, check it's overflow bit. If the overflow bit is | |
501 | * set, then increment the host version of the count by one complete | |
502 | * revolution of the counter. This routine is called when the counter | |
503 | * block indicates that one of the counters has wrapped. | |
504 | */ | |
ae8d9d84 | 505 | if (Carry1 & (1 << 14)) |
25ad00bb | 506 | etdev->Stats.code_violations += COUNTER_WRAP_16_BIT; |
ae8d9d84 | 507 | if (Carry1 & (1 << 8)) |
25ad00bb | 508 | etdev->Stats.alignment_err += COUNTER_WRAP_12_BIT; |
ae8d9d84 | 509 | if (Carry1 & (1 << 7)) |
25ad00bb | 510 | etdev->Stats.length_err += COUNTER_WRAP_16_BIT; |
ae8d9d84 | 511 | if (Carry1 & (1 << 2)) |
25ad00bb | 512 | etdev->Stats.other_errors += COUNTER_WRAP_16_BIT; |
ae8d9d84 | 513 | if (Carry1 & (1 << 6)) |
25ad00bb | 514 | etdev->Stats.crc_err += COUNTER_WRAP_16_BIT; |
ae8d9d84 | 515 | if (Carry1 & (1 << 3)) |
25ad00bb | 516 | etdev->Stats.rx_ov_flow += COUNTER_WRAP_16_BIT; |
ae8d9d84 | 517 | if (Carry1 & (1 << 0)) |
25ad00bb | 518 | etdev->Stats.norcvbuf += COUNTER_WRAP_16_BIT; |
ae8d9d84 | 519 | if (Carry2 & (1 << 16)) |
25ad00bb | 520 | etdev->Stats.max_pkt_error += COUNTER_WRAP_12_BIT; |
ae8d9d84 | 521 | if (Carry2 & (1 << 15)) |
25ad00bb | 522 | etdev->Stats.tx_uflo += COUNTER_WRAP_12_BIT; |
ae8d9d84 | 523 | if (Carry2 & (1 << 6)) |
25ad00bb | 524 | etdev->Stats.first_collision += COUNTER_WRAP_12_BIT; |
ae8d9d84 | 525 | if (Carry2 & (1 << 8)) |
25ad00bb | 526 | etdev->Stats.tx_deferred += COUNTER_WRAP_12_BIT; |
ae8d9d84 | 527 | if (Carry2 & (1 << 5)) |
25ad00bb | 528 | etdev->Stats.excessive_collisions += COUNTER_WRAP_12_BIT; |
ae8d9d84 | 529 | if (Carry2 & (1 << 4)) |
25ad00bb | 530 | etdev->Stats.late_collisions += COUNTER_WRAP_12_BIT; |
ae8d9d84 | 531 | if (Carry2 & (1 << 2)) |
25ad00bb | 532 | etdev->Stats.collisions += COUNTER_WRAP_12_BIT; |
cfb739b4 GKH |
533 | } |
534 | ||
25ad00bb | 535 | void SetupDeviceForMulticast(struct et131x_adapter *etdev) |
cfb739b4 | 536 | { |
f3f415a3 | 537 | struct _RXMAC_t __iomem *rxmac = &etdev->regs->rxmac; |
cfb739b4 GKH |
538 | uint32_t nIndex; |
539 | uint32_t result; | |
540 | uint32_t hash1 = 0; | |
541 | uint32_t hash2 = 0; | |
542 | uint32_t hash3 = 0; | |
543 | uint32_t hash4 = 0; | |
f2c98d27 | 544 | u32 pm_csr; |
cfb739b4 | 545 | |
cfb739b4 GKH |
546 | /* If ET131X_PACKET_TYPE_MULTICAST is specified, then we provision |
547 | * the multi-cast LIST. If it is NOT specified, (and "ALL" is not | |
548 | * specified) then we should pass NO multi-cast addresses to the | |
549 | * driver. | |
550 | */ | |
25ad00bb | 551 | if (etdev->PacketFilter & ET131X_PACKET_TYPE_MULTICAST) { |
cfb739b4 | 552 | /* Loop through our multicast array and set up the device */ |
25ad00bb | 553 | for (nIndex = 0; nIndex < etdev->MCAddressCount; nIndex++) { |
25ad00bb | 554 | result = ether_crc(6, etdev->MCList[nIndex]); |
cfb739b4 GKH |
555 | |
556 | result = (result & 0x3F800000) >> 23; | |
557 | ||
558 | if (result < 32) { | |
559 | hash1 |= (1 << result); | |
560 | } else if ((31 < result) && (result < 64)) { | |
561 | result -= 32; | |
562 | hash2 |= (1 << result); | |
563 | } else if ((63 < result) && (result < 96)) { | |
564 | result -= 64; | |
565 | hash3 |= (1 << result); | |
566 | } else { | |
567 | result -= 96; | |
568 | hash4 |= (1 << result); | |
569 | } | |
570 | } | |
571 | } | |
572 | ||
573 | /* Write out the new hash to the device */ | |
f2c98d27 AC |
574 | pm_csr = readl(&etdev->regs->global.pm_csr); |
575 | if ((pm_csr & ET_PM_PHY_SW_COMA) == 0) { | |
cfb739b4 GKH |
576 | writel(hash1, &rxmac->multi_hash1); |
577 | writel(hash2, &rxmac->multi_hash2); | |
578 | writel(hash3, &rxmac->multi_hash3); | |
579 | writel(hash4, &rxmac->multi_hash4); | |
580 | } | |
cfb739b4 GKH |
581 | } |
582 | ||
25ad00bb | 583 | void SetupDeviceForUnicast(struct et131x_adapter *etdev) |
cfb739b4 | 584 | { |
f3f415a3 | 585 | struct _RXMAC_t __iomem *rxmac = &etdev->regs->rxmac; |
cfb739b4 GKH |
586 | RXMAC_UNI_PF_ADDR1_t uni_pf1; |
587 | RXMAC_UNI_PF_ADDR2_t uni_pf2; | |
588 | RXMAC_UNI_PF_ADDR3_t uni_pf3; | |
f2c98d27 | 589 | u32 pm_csr; |
cfb739b4 | 590 | |
cfb739b4 GKH |
591 | /* Set up unicast packet filter reg 3 to be the first two octets of |
592 | * the MAC address for both address | |
593 | * | |
594 | * Set up unicast packet filter reg 2 to be the octets 2 - 5 of the | |
595 | * MAC address for second address | |
596 | * | |
597 | * Set up unicast packet filter reg 3 to be the octets 2 - 5 of the | |
598 | * MAC address for first address | |
599 | */ | |
25ad00bb AC |
600 | uni_pf3.bits.addr1_1 = etdev->CurrentAddress[0]; |
601 | uni_pf3.bits.addr1_2 = etdev->CurrentAddress[1]; | |
602 | uni_pf3.bits.addr2_1 = etdev->CurrentAddress[0]; | |
603 | uni_pf3.bits.addr2_2 = etdev->CurrentAddress[1]; | |
604 | ||
605 | uni_pf2.bits.addr2_3 = etdev->CurrentAddress[2]; | |
606 | uni_pf2.bits.addr2_4 = etdev->CurrentAddress[3]; | |
607 | uni_pf2.bits.addr2_5 = etdev->CurrentAddress[4]; | |
608 | uni_pf2.bits.addr2_6 = etdev->CurrentAddress[5]; | |
609 | ||
610 | uni_pf1.bits.addr1_3 = etdev->CurrentAddress[2]; | |
611 | uni_pf1.bits.addr1_4 = etdev->CurrentAddress[3]; | |
612 | uni_pf1.bits.addr1_5 = etdev->CurrentAddress[4]; | |
613 | uni_pf1.bits.addr1_6 = etdev->CurrentAddress[5]; | |
614 | ||
f2c98d27 AC |
615 | pm_csr = readl(&etdev->regs->global.pm_csr); |
616 | if ((pm_csr & ET_PM_PHY_SW_COMA) == 0) { | |
cfb739b4 GKH |
617 | writel(uni_pf1.value, &rxmac->uni_pf_addr1.value); |
618 | writel(uni_pf2.value, &rxmac->uni_pf_addr2.value); | |
619 | writel(uni_pf3.value, &rxmac->uni_pf_addr3.value); | |
620 | } | |
cfb739b4 | 621 | } |