]>
Commit | Line | Data |
---|---|---|
c609719b WD |
1 | /******************************************************************************/ |
2 | /* */ | |
3 | /* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ | |
4 | /* Corporation. */ | |
5 | /* All rights reserved. */ | |
6 | /* */ | |
7 | /* This program is free software; you can redistribute it and/or modify */ | |
8 | /* it under the terms of the GNU General Public License as published by */ | |
9 | /* the Free Software Foundation, located in the file LICENSE. */ | |
10 | /* */ | |
11 | /* History: */ | |
12 | /******************************************************************************/ | |
13 | #include <common.h> | |
c609719b | 14 | #include <asm/types.h> |
3b904ccb | 15 | |
c609719b WD |
16 | #ifdef CONFIG_BMW |
17 | #include <mpc824x.h> | |
18 | #endif | |
19 | #include <malloc.h> | |
20 | #include <linux/byteorder/big_endian.h> | |
6069ff26 | 21 | #include "bcm570x_mm.h" |
c609719b WD |
22 | |
23 | #define EMBEDDED 1 | |
24 | /******************************************************************************/ | |
25 | /* Local functions. */ | |
26 | /******************************************************************************/ | |
27 | ||
f539edc0 VB |
28 | LM_STATUS LM_Abort (PLM_DEVICE_BLOCK pDevice); |
29 | LM_STATUS LM_QueueRxPackets (PLM_DEVICE_BLOCK pDevice); | |
30 | ||
31 | static LM_STATUS LM_TranslateRequestedMediaType (LM_REQUESTED_MEDIA_TYPE | |
32 | RequestedMediaType, | |
33 | PLM_MEDIA_TYPE pMediaType, | |
34 | PLM_LINE_SPEED pLineSpeed, | |
35 | PLM_DUPLEX_MODE pDuplexMode); | |
36 | ||
37 | static LM_STATUS LM_InitBcm540xPhy (PLM_DEVICE_BLOCK pDevice); | |
38 | ||
39 | __inline static LM_VOID LM_ServiceRxInterrupt (PLM_DEVICE_BLOCK pDevice); | |
40 | __inline static LM_VOID LM_ServiceTxInterrupt (PLM_DEVICE_BLOCK pDevice); | |
41 | ||
42 | static LM_STATUS LM_ForceAutoNegBcm540xPhy (PLM_DEVICE_BLOCK pDevice, | |
43 | LM_REQUESTED_MEDIA_TYPE | |
44 | RequestedMediaType); | |
45 | static LM_STATUS LM_ForceAutoNeg (PLM_DEVICE_BLOCK pDevice, | |
46 | LM_REQUESTED_MEDIA_TYPE RequestedMediaType); | |
47 | static LM_UINT32 GetPhyAdFlowCntrlSettings (PLM_DEVICE_BLOCK pDevice); | |
48 | STATIC LM_STATUS LM_SetFlowControl (PLM_DEVICE_BLOCK pDevice, | |
49 | LM_UINT32 LocalPhyAd, | |
50 | LM_UINT32 RemotePhyAd); | |
c609719b | 51 | #if INCLUDE_TBI_SUPPORT |
f539edc0 VB |
52 | STATIC LM_STATUS LM_SetupFiberPhy (PLM_DEVICE_BLOCK pDevice); |
53 | STATIC LM_STATUS LM_InitBcm800xPhy (PLM_DEVICE_BLOCK pDevice); | |
c609719b | 54 | #endif |
f539edc0 VB |
55 | STATIC LM_STATUS LM_SetupCopperPhy (PLM_DEVICE_BLOCK pDevice); |
56 | STATIC PLM_ADAPTER_INFO LM_GetAdapterInfoBySsid (LM_UINT16 Svid, | |
57 | LM_UINT16 Ssid); | |
58 | STATIC LM_STATUS LM_DmaTest (PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pBufferVirt, | |
59 | LM_PHYSICAL_ADDRESS BufferPhy, | |
60 | LM_UINT32 BufferSize); | |
61 | STATIC LM_STATUS LM_HaltCpu (PLM_DEVICE_BLOCK pDevice, LM_UINT32 cpu_number); | |
62 | STATIC LM_STATUS LM_ResetChip (PLM_DEVICE_BLOCK pDevice); | |
63 | STATIC LM_STATUS LM_Test4GBoundary (PLM_DEVICE_BLOCK pDevice, | |
64 | PLM_PACKET pPacket, PT3_SND_BD pSendBd); | |
c609719b WD |
65 | |
66 | /******************************************************************************/ | |
67 | /* External functions. */ | |
68 | /******************************************************************************/ | |
69 | ||
f539edc0 | 70 | LM_STATUS LM_LoadRlsFirmware (PLM_DEVICE_BLOCK pDevice); |
c609719b WD |
71 | |
72 | /******************************************************************************/ | |
73 | /* Description: */ | |
74 | /* */ | |
75 | /* Return: */ | |
76 | /******************************************************************************/ | |
f539edc0 VB |
77 | LM_UINT32 LM_RegRdInd (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register) |
78 | { | |
79 | LM_UINT32 Value32; | |
c609719b WD |
80 | |
81 | #if PCIX_TARGET_WORKAROUND | |
f539edc0 | 82 | MM_ACQUIRE_UNDI_LOCK (pDevice); |
c609719b | 83 | #endif |
f539edc0 VB |
84 | MM_WriteConfig32 (pDevice, T3_PCI_REG_ADDR_REG, Register); |
85 | MM_ReadConfig32 (pDevice, T3_PCI_REG_DATA_REG, &Value32); | |
c609719b | 86 | #if PCIX_TARGET_WORKAROUND |
f539edc0 | 87 | MM_RELEASE_UNDI_LOCK (pDevice); |
c609719b WD |
88 | #endif |
89 | ||
f539edc0 VB |
90 | return Value32; |
91 | } /* LM_RegRdInd */ | |
c609719b | 92 | |
c609719b WD |
93 | /******************************************************************************/ |
94 | /* Description: */ | |
95 | /* */ | |
96 | /* Return: */ | |
97 | /******************************************************************************/ | |
98 | LM_VOID | |
f539edc0 VB |
99 | LM_RegWrInd (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register, LM_UINT32 Value32) |
100 | { | |
c609719b WD |
101 | |
102 | #if PCIX_TARGET_WORKAROUND | |
f539edc0 | 103 | MM_ACQUIRE_UNDI_LOCK (pDevice); |
c609719b | 104 | #endif |
f539edc0 VB |
105 | MM_WriteConfig32 (pDevice, T3_PCI_REG_ADDR_REG, Register); |
106 | MM_WriteConfig32 (pDevice, T3_PCI_REG_DATA_REG, Value32); | |
c609719b | 107 | #if PCIX_TARGET_WORKAROUND |
f539edc0 | 108 | MM_RELEASE_UNDI_LOCK (pDevice); |
c609719b | 109 | #endif |
f539edc0 | 110 | } /* LM_RegWrInd */ |
c609719b | 111 | |
c609719b WD |
112 | /******************************************************************************/ |
113 | /* Description: */ | |
114 | /* */ | |
115 | /* Return: */ | |
116 | /******************************************************************************/ | |
f539edc0 VB |
117 | LM_UINT32 LM_MemRdInd (PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr) |
118 | { | |
119 | LM_UINT32 Value32; | |
c609719b | 120 | |
f539edc0 | 121 | MM_ACQUIRE_UNDI_LOCK (pDevice); |
c609719b | 122 | #ifdef BIG_ENDIAN_HOST |
f539edc0 VB |
123 | MM_WriteConfig32 (pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr); |
124 | Value32 = REG_RD (pDevice, PciCfg.MemWindowData); | |
125 | /* Value32 = REG_RD(pDevice,uIntMem.Mbuf[(MemAddr & 0x7fff)/4]); */ | |
c609719b | 126 | #else |
f539edc0 VB |
127 | MM_WriteConfig32 (pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr); |
128 | MM_ReadConfig32 (pDevice, T3_PCI_MEM_WIN_DATA_REG, &Value32); | |
c609719b | 129 | #endif |
f539edc0 | 130 | MM_RELEASE_UNDI_LOCK (pDevice); |
c609719b | 131 | |
f539edc0 VB |
132 | return Value32; |
133 | } /* LM_MemRdInd */ | |
c609719b | 134 | |
c609719b WD |
135 | /******************************************************************************/ |
136 | /* Description: */ | |
137 | /* */ | |
138 | /* Return: */ | |
139 | /******************************************************************************/ | |
140 | LM_VOID | |
f539edc0 VB |
141 | LM_MemWrInd (PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr, LM_UINT32 Value32) |
142 | { | |
143 | MM_ACQUIRE_UNDI_LOCK (pDevice); | |
c609719b | 144 | #ifdef BIG_ENDIAN_HOST |
f539edc0 VB |
145 | REG_WR (pDevice, PciCfg.MemWindowBaseAddr, MemAddr); |
146 | REG_WR (pDevice, uIntMem.Mbuf[(MemAddr & 0x7fff) / 4], Value32); | |
c609719b | 147 | #else |
f539edc0 VB |
148 | MM_WriteConfig32 (pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr); |
149 | MM_WriteConfig32 (pDevice, T3_PCI_MEM_WIN_DATA_REG, Value32); | |
c609719b | 150 | #endif |
f539edc0 VB |
151 | MM_RELEASE_UNDI_LOCK (pDevice); |
152 | } /* LM_MemWrInd */ | |
c609719b | 153 | |
c609719b WD |
154 | /******************************************************************************/ |
155 | /* Description: */ | |
156 | /* */ | |
157 | /* Return: */ | |
158 | /******************************************************************************/ | |
f539edc0 VB |
159 | LM_STATUS LM_QueueRxPackets (PLM_DEVICE_BLOCK pDevice) |
160 | { | |
161 | LM_STATUS Lmstatus; | |
162 | PLM_PACKET pPacket; | |
163 | PT3_RCV_BD pRcvBd; | |
164 | LM_UINT32 StdBdAdded = 0; | |
c609719b | 165 | #if T3_JUMBO_RCV_RCB_ENTRY_COUNT |
f539edc0 VB |
166 | LM_UINT32 JumboBdAdded = 0; |
167 | #endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ | |
c609719b | 168 | |
f539edc0 | 169 | Lmstatus = LM_STATUS_SUCCESS; |
c609719b | 170 | |
f539edc0 VB |
171 | pPacket = (PLM_PACKET) QQ_PopHead (&pDevice->RxPacketFreeQ.Container); |
172 | while (pPacket) { | |
173 | switch (pPacket->u.Rx.RcvProdRing) { | |
c609719b | 174 | #if T3_JUMBO_RCV_RCB_ENTRY_COUNT |
f539edc0 VB |
175 | case T3_JUMBO_RCV_PROD_RING: /* Jumbo Receive Ring. */ |
176 | /* Initialize the buffer descriptor. */ | |
177 | pRcvBd = | |
178 | &pDevice->pRxJumboBdVirt[pDevice->RxJumboProdIdx]; | |
179 | pRcvBd->Flags = | |
180 | RCV_BD_FLAG_END | RCV_BD_FLAG_JUMBO_RING; | |
181 | pRcvBd->Len = (LM_UINT16) pDevice->RxJumboBufferSize; | |
182 | ||
183 | /* Initialize the receive buffer pointer */ | |
184 | #if 0 /* Jimmy, deleted in new */ | |
185 | pRcvBd->HostAddr.Low = pPacket->u.Rx.RxBufferPhy.Low; | |
186 | pRcvBd->HostAddr.High = pPacket->u.Rx.RxBufferPhy.High; | |
c609719b | 187 | #endif |
f539edc0 | 188 | MM_MapRxDma (pDevice, pPacket, &pRcvBd->HostAddr); |
c609719b | 189 | |
f539edc0 VB |
190 | /* The opaque field may point to an offset from a fix addr. */ |
191 | pRcvBd->Opaque = (LM_UINT32) (MM_UINT_PTR (pPacket) - | |
192 | MM_UINT_PTR (pDevice-> | |
193 | pPacketDescBase)); | |
c609719b | 194 | |
f539edc0 VB |
195 | /* Update the producer index. */ |
196 | pDevice->RxJumboProdIdx = | |
197 | (pDevice->RxJumboProdIdx + | |
198 | 1) & T3_JUMBO_RCV_RCB_ENTRY_COUNT_MASK; | |
c609719b | 199 | |
f539edc0 VB |
200 | JumboBdAdded++; |
201 | break; | |
202 | #endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ | |
203 | ||
204 | case T3_STD_RCV_PROD_RING: /* Standard Receive Ring. */ | |
205 | /* Initialize the buffer descriptor. */ | |
206 | pRcvBd = &pDevice->pRxStdBdVirt[pDevice->RxStdProdIdx]; | |
207 | pRcvBd->Flags = RCV_BD_FLAG_END; | |
208 | pRcvBd->Len = MAX_STD_RCV_BUFFER_SIZE; | |
209 | ||
210 | /* Initialize the receive buffer pointer */ | |
211 | #if 0 /* Jimmy, deleted in new replaced with MM_MapRxDma */ | |
212 | pRcvBd->HostAddr.Low = pPacket->u.Rx.RxBufferPhy.Low; | |
213 | pRcvBd->HostAddr.High = pPacket->u.Rx.RxBufferPhy.High; | |
c609719b | 214 | #endif |
f539edc0 | 215 | MM_MapRxDma (pDevice, pPacket, &pRcvBd->HostAddr); |
c609719b | 216 | |
f539edc0 VB |
217 | /* The opaque field may point to an offset from a fix addr. */ |
218 | pRcvBd->Opaque = (LM_UINT32) (MM_UINT_PTR (pPacket) - | |
219 | MM_UINT_PTR (pDevice-> | |
220 | pPacketDescBase)); | |
c609719b | 221 | |
f539edc0 VB |
222 | /* Update the producer index. */ |
223 | pDevice->RxStdProdIdx = (pDevice->RxStdProdIdx + 1) & | |
224 | T3_STD_RCV_RCB_ENTRY_COUNT_MASK; | |
c609719b | 225 | |
f539edc0 VB |
226 | StdBdAdded++; |
227 | break; | |
c609719b | 228 | |
f539edc0 VB |
229 | case T3_UNKNOWN_RCV_PROD_RING: |
230 | default: | |
231 | Lmstatus = LM_STATUS_FAILURE; | |
232 | break; | |
233 | } /* switch */ | |
c609719b | 234 | |
f539edc0 VB |
235 | /* Bail out if there is any error. */ |
236 | if (Lmstatus != LM_STATUS_SUCCESS) { | |
237 | break; | |
238 | } | |
c609719b | 239 | |
f539edc0 VB |
240 | pPacket = |
241 | (PLM_PACKET) QQ_PopHead (&pDevice->RxPacketFreeQ.Container); | |
242 | } /* while */ | |
c609719b | 243 | |
f539edc0 VB |
244 | wmb (); |
245 | /* Update the procedure index. */ | |
246 | if (StdBdAdded) { | |
247 | MB_REG_WR (pDevice, Mailbox.RcvStdProdIdx.Low, | |
248 | pDevice->RxStdProdIdx); | |
249 | } | |
c609719b | 250 | #if T3_JUMBO_RCV_RCB_ENTRY_COUNT |
f539edc0 VB |
251 | if (JumboBdAdded) { |
252 | MB_REG_WR (pDevice, Mailbox.RcvJumboProdIdx.Low, | |
253 | pDevice->RxJumboProdIdx); | |
254 | } | |
255 | #endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ | |
c609719b | 256 | |
f539edc0 VB |
257 | return Lmstatus; |
258 | } /* LM_QueueRxPackets */ | |
c609719b WD |
259 | |
260 | /******************************************************************************/ | |
261 | /* Description: */ | |
262 | /* */ | |
263 | /* Return: */ | |
264 | /******************************************************************************/ | |
f539edc0 | 265 | STATIC LM_VOID LM_NvramInit (PLM_DEVICE_BLOCK pDevice) |
c609719b | 266 | { |
f539edc0 VB |
267 | LM_UINT32 Value32; |
268 | LM_UINT32 j; | |
c609719b | 269 | |
f539edc0 VB |
270 | /* Intialize clock period and state machine. */ |
271 | Value32 = SEEPROM_ADDR_CLK_PERD (SEEPROM_CLOCK_PERIOD) | | |
272 | SEEPROM_ADDR_FSM_RESET; | |
273 | REG_WR (pDevice, Grc.EepromAddr, Value32); | |
274 | ||
275 | for (j = 0; j < 100; j++) { | |
276 | MM_Wait (10); | |
8bde7f77 | 277 | } |
c609719b | 278 | |
f539edc0 VB |
279 | /* Serial eeprom access using the Grc.EepromAddr/EepromData registers. */ |
280 | Value32 = REG_RD (pDevice, Grc.LocalCtrl); | |
281 | REG_WR (pDevice, Grc.LocalCtrl, | |
282 | Value32 | GRC_MISC_LOCAL_CTRL_AUTO_SEEPROM); | |
283 | ||
284 | /* Set the 5701 compatibility mode if we are using EEPROM. */ | |
285 | if (T3_ASIC_REV (pDevice->ChipRevId) != T3_ASIC_REV_5700 && | |
286 | T3_ASIC_REV (pDevice->ChipRevId) != T3_ASIC_REV_5701) { | |
287 | Value32 = REG_RD (pDevice, Nvram.Config1); | |
288 | if ((Value32 & FLASH_INTERFACE_ENABLE) == 0) { | |
289 | /* Use the new interface to read EEPROM. */ | |
290 | Value32 &= ~FLASH_COMPAT_BYPASS; | |
291 | ||
292 | REG_WR (pDevice, Nvram.Config1, Value32); | |
293 | } | |
294 | } | |
295 | } /* LM_NvRamInit */ | |
c609719b WD |
296 | |
297 | /******************************************************************************/ | |
298 | /* Description: */ | |
299 | /* */ | |
300 | /* Return: */ | |
301 | /******************************************************************************/ | |
302 | STATIC LM_STATUS | |
f539edc0 | 303 | LM_EepromRead (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, LM_UINT32 * pData) |
c609719b | 304 | { |
f539edc0 VB |
305 | LM_UINT32 Value32; |
306 | LM_UINT32 Addr; | |
307 | LM_UINT32 Dev; | |
308 | LM_UINT32 j; | |
c609719b | 309 | |
f539edc0 VB |
310 | if (Offset > SEEPROM_CHIP_SIZE) { |
311 | return LM_STATUS_FAILURE; | |
312 | } | |
c609719b | 313 | |
f539edc0 VB |
314 | Dev = Offset / SEEPROM_CHIP_SIZE; |
315 | Addr = Offset % SEEPROM_CHIP_SIZE; | |
c609719b | 316 | |
f539edc0 VB |
317 | Value32 = REG_RD (pDevice, Grc.EepromAddr); |
318 | Value32 &= ~(SEEPROM_ADDR_ADDRESS_MASK | SEEPROM_ADDR_DEV_ID_MASK | | |
319 | SEEPROM_ADDR_RW_MASK); | |
320 | REG_WR (pDevice, Grc.EepromAddr, Value32 | SEEPROM_ADDR_DEV_ID (Dev) | | |
321 | SEEPROM_ADDR_ADDRESS (Addr) | SEEPROM_ADDR_START | | |
322 | SEEPROM_ADDR_READ); | |
c609719b | 323 | |
f539edc0 VB |
324 | for (j = 0; j < 1000; j++) { |
325 | Value32 = REG_RD (pDevice, Grc.EepromAddr); | |
326 | if (Value32 & SEEPROM_ADDR_COMPLETE) { | |
327 | break; | |
328 | } | |
329 | MM_Wait (10); | |
8bde7f77 | 330 | } |
c609719b | 331 | |
f539edc0 VB |
332 | if (Value32 & SEEPROM_ADDR_COMPLETE) { |
333 | Value32 = REG_RD (pDevice, Grc.EepromData); | |
334 | *pData = Value32; | |
c609719b | 335 | |
f539edc0 VB |
336 | return LM_STATUS_SUCCESS; |
337 | } | |
c609719b | 338 | |
f539edc0 VB |
339 | return LM_STATUS_FAILURE; |
340 | } /* LM_EepromRead */ | |
c609719b | 341 | |
c609719b WD |
342 | /******************************************************************************/ |
343 | /* Description: */ | |
344 | /* */ | |
345 | /* Return: */ | |
346 | /******************************************************************************/ | |
347 | STATIC LM_STATUS | |
f539edc0 | 348 | LM_NvramRead (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, LM_UINT32 * pData) |
c609719b | 349 | { |
f539edc0 VB |
350 | LM_UINT32 Value32; |
351 | LM_STATUS Status; | |
352 | LM_UINT32 j; | |
353 | ||
354 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || | |
355 | T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { | |
356 | Status = LM_EepromRead (pDevice, Offset, pData); | |
357 | } else { | |
358 | /* Determine if we have flash or EEPROM. */ | |
359 | Value32 = REG_RD (pDevice, Nvram.Config1); | |
360 | if (Value32 & FLASH_INTERFACE_ENABLE) { | |
361 | if (Value32 & FLASH_SSRAM_BUFFERRED_MODE) { | |
362 | Offset = ((Offset / BUFFERED_FLASH_PAGE_SIZE) << | |
363 | BUFFERED_FLASH_PAGE_POS) + | |
364 | (Offset % BUFFERED_FLASH_PAGE_SIZE); | |
365 | } | |
366 | } | |
8bde7f77 | 367 | |
f539edc0 VB |
368 | REG_WR (pDevice, Nvram.SwArb, SW_ARB_REQ_SET1); |
369 | for (j = 0; j < 1000; j++) { | |
370 | if (REG_RD (pDevice, Nvram.SwArb) & SW_ARB_GNT1) { | |
371 | break; | |
372 | } | |
373 | MM_Wait (20); | |
374 | } | |
375 | if (j == 1000) { | |
376 | return LM_STATUS_FAILURE; | |
377 | } | |
8bde7f77 | 378 | |
f539edc0 VB |
379 | /* Read from flash or EEPROM with the new 5703/02 interface. */ |
380 | REG_WR (pDevice, Nvram.Addr, Offset & NVRAM_ADDRESS_MASK); | |
8bde7f77 | 381 | |
f539edc0 VB |
382 | REG_WR (pDevice, Nvram.Cmd, NVRAM_CMD_RD | NVRAM_CMD_DO_IT | |
383 | NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE); | |
8bde7f77 | 384 | |
f539edc0 VB |
385 | /* Wait for the done bit to clear. */ |
386 | for (j = 0; j < 500; j++) { | |
387 | MM_Wait (10); | |
8bde7f77 | 388 | |
f539edc0 VB |
389 | Value32 = REG_RD (pDevice, Nvram.Cmd); |
390 | if (!(Value32 & NVRAM_CMD_DONE)) { | |
391 | break; | |
392 | } | |
393 | } | |
8bde7f77 | 394 | |
f539edc0 VB |
395 | /* Wait for the done bit. */ |
396 | if (!(Value32 & NVRAM_CMD_DONE)) { | |
397 | for (j = 0; j < 500; j++) { | |
398 | MM_Wait (10); | |
8bde7f77 | 399 | |
f539edc0 VB |
400 | Value32 = REG_RD (pDevice, Nvram.Cmd); |
401 | if (Value32 & NVRAM_CMD_DONE) { | |
402 | MM_Wait (10); | |
8bde7f77 | 403 | |
f539edc0 VB |
404 | *pData = |
405 | REG_RD (pDevice, Nvram.ReadData); | |
8bde7f77 | 406 | |
f539edc0 VB |
407 | /* Change the endianess. */ |
408 | *pData = | |
409 | ((*pData & 0xff) << 24) | | |
410 | ((*pData & 0xff00) << 8) | | |
411 | ((*pData & 0xff0000) >> 8) | | |
412 | ((*pData >> 24) & 0xff); | |
8bde7f77 | 413 | |
f539edc0 VB |
414 | break; |
415 | } | |
416 | } | |
8bde7f77 | 417 | } |
8bde7f77 | 418 | |
f539edc0 VB |
419 | REG_WR (pDevice, Nvram.SwArb, SW_ARB_REQ_CLR1); |
420 | if (Value32 & NVRAM_CMD_DONE) { | |
421 | Status = LM_STATUS_SUCCESS; | |
422 | } else { | |
423 | Status = LM_STATUS_FAILURE; | |
424 | } | |
8bde7f77 | 425 | } |
c609719b | 426 | |
f539edc0 VB |
427 | return Status; |
428 | } /* LM_NvramRead */ | |
c609719b | 429 | |
f539edc0 | 430 | STATIC void LM_ReadVPD (PLM_DEVICE_BLOCK pDevice) |
c609719b | 431 | { |
f539edc0 VB |
432 | LM_UINT32 Vpd_arr[256 / 4]; |
433 | LM_UINT8 *Vpd = (LM_UINT8 *) & Vpd_arr[0]; | |
434 | LM_UINT32 *Vpd_dptr = &Vpd_arr[0]; | |
435 | LM_UINT32 Value32; | |
436 | unsigned int j; | |
437 | ||
438 | /* Read PN from VPD */ | |
439 | for (j = 0; j < 256; j += 4, Vpd_dptr++) { | |
440 | if (LM_NvramRead (pDevice, 0x100 + j, &Value32) != | |
441 | LM_STATUS_SUCCESS) { | |
442 | printf ("BCM570x: LM_ReadVPD: VPD read failed" | |
443 | " (no EEPROM onboard)\n"); | |
444 | return; | |
8bde7f77 | 445 | } |
f539edc0 VB |
446 | *Vpd_dptr = cpu_to_le32 (Value32); |
447 | } | |
448 | for (j = 0; j < 256;) { | |
449 | unsigned int Vpd_r_len; | |
450 | unsigned int Vpd_r_end; | |
451 | ||
452 | if ((Vpd[j] == 0x82) || (Vpd[j] == 0x91)) { | |
453 | j = j + 3 + Vpd[j + 1] + (Vpd[j + 2] << 8); | |
454 | } else if (Vpd[j] == 0x90) { | |
455 | Vpd_r_len = Vpd[j + 1] + (Vpd[j + 2] << 8); | |
456 | j += 3; | |
457 | Vpd_r_end = Vpd_r_len + j; | |
458 | while (j < Vpd_r_end) { | |
459 | if ((Vpd[j] == 'P') && (Vpd[j + 1] == 'N')) { | |
460 | unsigned int len = Vpd[j + 2]; | |
461 | ||
462 | if (len <= 24) { | |
463 | memcpy (pDevice->PartNo, | |
464 | &Vpd[j + 3], len); | |
465 | } | |
466 | break; | |
467 | } else { | |
468 | if (Vpd[j + 2] == 0) { | |
469 | break; | |
470 | } | |
471 | j = j + Vpd[j + 2]; | |
472 | } | |
473 | } | |
474 | break; | |
475 | } else { | |
8bde7f77 | 476 | break; |
8bde7f77 | 477 | } |
8bde7f77 | 478 | } |
c609719b WD |
479 | } |
480 | ||
f539edc0 | 481 | STATIC void LM_ReadBootCodeVersion (PLM_DEVICE_BLOCK pDevice) |
c609719b | 482 | { |
f539edc0 VB |
483 | LM_UINT32 Value32, offset, ver_offset; |
484 | int i; | |
485 | ||
486 | if (LM_NvramRead (pDevice, 0x0, &Value32) != LM_STATUS_SUCCESS) | |
8bde7f77 | 487 | return; |
f539edc0 VB |
488 | if (Value32 != 0xaa559966) |
489 | return; | |
490 | if (LM_NvramRead (pDevice, 0xc, &offset) != LM_STATUS_SUCCESS) | |
491 | return; | |
492 | ||
493 | offset = ((offset & 0xff) << 24) | ((offset & 0xff00) << 8) | | |
494 | ((offset & 0xff0000) >> 8) | ((offset >> 24) & 0xff); | |
495 | if (LM_NvramRead (pDevice, offset, &Value32) != LM_STATUS_SUCCESS) | |
496 | return; | |
497 | if ((Value32 == 0x0300000e) && | |
498 | (LM_NvramRead (pDevice, offset + 4, &Value32) == LM_STATUS_SUCCESS) | |
499 | && (Value32 == 0)) { | |
500 | ||
501 | if (LM_NvramRead (pDevice, offset + 8, &ver_offset) != | |
502 | LM_STATUS_SUCCESS) | |
503 | return; | |
504 | ver_offset = ((ver_offset & 0xff0000) >> 8) | | |
505 | ((ver_offset >> 24) & 0xff); | |
506 | for (i = 0; i < 16; i += 4) { | |
507 | if (LM_NvramRead | |
508 | (pDevice, offset + ver_offset + i, | |
509 | &Value32) != LM_STATUS_SUCCESS) { | |
510 | return; | |
511 | } | |
512 | *((LM_UINT32 *) & pDevice->BootCodeVer[i]) = | |
513 | cpu_to_le32 (Value32); | |
514 | } | |
515 | } else { | |
516 | char c; | |
8bde7f77 | 517 | |
f539edc0 VB |
518 | if (LM_NvramRead (pDevice, 0x94, &Value32) != LM_STATUS_SUCCESS) |
519 | return; | |
8bde7f77 | 520 | |
f539edc0 VB |
521 | i = 0; |
522 | c = ((Value32 & 0xff0000) >> 16); | |
8bde7f77 | 523 | |
f539edc0 VB |
524 | if (c < 10) { |
525 | pDevice->BootCodeVer[i++] = c + '0'; | |
526 | } else { | |
527 | pDevice->BootCodeVer[i++] = (c / 10) + '0'; | |
528 | pDevice->BootCodeVer[i++] = (c % 10) + '0'; | |
529 | } | |
530 | pDevice->BootCodeVer[i++] = '.'; | |
531 | c = (Value32 & 0xff000000) >> 24; | |
532 | if (c < 10) { | |
533 | pDevice->BootCodeVer[i++] = c + '0'; | |
534 | } else { | |
535 | pDevice->BootCodeVer[i++] = (c / 10) + '0'; | |
536 | pDevice->BootCodeVer[i++] = (c % 10) + '0'; | |
537 | } | |
538 | pDevice->BootCodeVer[i] = 0; | |
8bde7f77 | 539 | } |
c609719b WD |
540 | } |
541 | ||
f539edc0 | 542 | STATIC void LM_GetBusSpeed (PLM_DEVICE_BLOCK pDevice) |
c609719b | 543 | { |
f539edc0 VB |
544 | LM_UINT32 PciState = pDevice->PciState; |
545 | LM_UINT32 ClockCtrl; | |
546 | char *SpeedStr = ""; | |
547 | ||
548 | if (PciState & T3_PCI_STATE_32BIT_PCI_BUS) { | |
549 | strcpy (pDevice->BusSpeedStr, "32-bit "); | |
550 | } else { | |
551 | strcpy (pDevice->BusSpeedStr, "64-bit "); | |
552 | } | |
553 | if (PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) { | |
554 | strcat (pDevice->BusSpeedStr, "PCI "); | |
555 | if (PciState & T3_PCI_STATE_HIGH_BUS_SPEED) { | |
556 | SpeedStr = "66MHz"; | |
557 | } else { | |
558 | SpeedStr = "33MHz"; | |
559 | } | |
560 | } else { | |
561 | strcat (pDevice->BusSpeedStr, "PCIX "); | |
562 | if (pDevice->BondId == GRC_MISC_BD_ID_5704CIOBE) { | |
563 | SpeedStr = "133MHz"; | |
564 | } else { | |
565 | ClockCtrl = REG_RD (pDevice, PciCfg.ClockCtrl) & 0x1f; | |
566 | switch (ClockCtrl) { | |
567 | case 0: | |
568 | SpeedStr = "33MHz"; | |
569 | break; | |
570 | ||
571 | case 2: | |
572 | SpeedStr = "50MHz"; | |
573 | break; | |
574 | ||
575 | case 4: | |
576 | SpeedStr = "66MHz"; | |
577 | break; | |
578 | ||
579 | case 6: | |
580 | SpeedStr = "100MHz"; | |
581 | break; | |
582 | ||
583 | case 7: | |
584 | SpeedStr = "133MHz"; | |
585 | break; | |
586 | } | |
587 | } | |
8bde7f77 | 588 | } |
f539edc0 | 589 | strcat (pDevice->BusSpeedStr, SpeedStr); |
c609719b WD |
590 | } |
591 | ||
592 | /******************************************************************************/ | |
593 | /* Description: */ | |
594 | /* This routine initializes default parameters and reads the PCI */ | |
595 | /* configurations. */ | |
596 | /* */ | |
597 | /* Return: */ | |
598 | /* LM_STATUS_SUCCESS */ | |
599 | /******************************************************************************/ | |
f539edc0 | 600 | LM_STATUS LM_GetAdapterInfo (PLM_DEVICE_BLOCK pDevice) |
c609719b | 601 | { |
f539edc0 VB |
602 | PLM_ADAPTER_INFO pAdapterInfo; |
603 | LM_UINT32 Value32; | |
604 | LM_STATUS Status; | |
605 | LM_UINT32 j; | |
606 | LM_UINT32 EeSigFound; | |
607 | LM_UINT32 EePhyTypeSerdes = 0; | |
608 | LM_UINT32 EePhyLedMode = 0; | |
609 | LM_UINT32 EePhyId = 0; | |
610 | ||
611 | /* Get Device Id and Vendor Id */ | |
612 | Status = MM_ReadConfig32 (pDevice, PCI_VENDOR_ID_REG, &Value32); | |
613 | if (Status != LM_STATUS_SUCCESS) { | |
614 | return Status; | |
615 | } | |
616 | pDevice->PciVendorId = (LM_UINT16) Value32; | |
617 | pDevice->PciDeviceId = (LM_UINT16) (Value32 >> 16); | |
618 | ||
619 | /* If we are not getting the write adapter, exit. */ | |
620 | if ((Value32 != T3_PCI_ID_BCM5700) && | |
621 | (Value32 != T3_PCI_ID_BCM5701) && | |
622 | (Value32 != T3_PCI_ID_BCM5702) && | |
623 | (Value32 != T3_PCI_ID_BCM5702x) && | |
624 | (Value32 != T3_PCI_ID_BCM5702FE) && | |
625 | (Value32 != T3_PCI_ID_BCM5703) && | |
626 | (Value32 != T3_PCI_ID_BCM5703x) && (Value32 != T3_PCI_ID_BCM5704)) { | |
627 | return LM_STATUS_FAILURE; | |
628 | } | |
c609719b | 629 | |
f539edc0 VB |
630 | Status = MM_ReadConfig32 (pDevice, PCI_REV_ID_REG, &Value32); |
631 | if (Status != LM_STATUS_SUCCESS) { | |
632 | return Status; | |
633 | } | |
634 | pDevice->PciRevId = (LM_UINT8) Value32; | |
c609719b | 635 | |
f539edc0 VB |
636 | /* Get IRQ. */ |
637 | Status = MM_ReadConfig32 (pDevice, PCI_INT_LINE_REG, &Value32); | |
638 | if (Status != LM_STATUS_SUCCESS) { | |
639 | return Status; | |
640 | } | |
641 | pDevice->Irq = (LM_UINT8) Value32; | |
c609719b | 642 | |
f539edc0 VB |
643 | /* Get interrupt pin. */ |
644 | pDevice->IntPin = (LM_UINT8) (Value32 >> 8); | |
c609719b | 645 | |
f539edc0 VB |
646 | /* Get chip revision id. */ |
647 | Status = MM_ReadConfig32 (pDevice, T3_PCI_MISC_HOST_CTRL_REG, &Value32); | |
648 | pDevice->ChipRevId = Value32 >> 16; | |
c609719b | 649 | |
f539edc0 VB |
650 | /* Get subsystem vendor. */ |
651 | Status = | |
652 | MM_ReadConfig32 (pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG, &Value32); | |
653 | if (Status != LM_STATUS_SUCCESS) { | |
654 | return Status; | |
655 | } | |
656 | pDevice->SubsystemVendorId = (LM_UINT16) Value32; | |
c609719b | 657 | |
f539edc0 VB |
658 | /* Get PCI subsystem id. */ |
659 | pDevice->SubsystemId = (LM_UINT16) (Value32 >> 16); | |
c609719b | 660 | |
f539edc0 VB |
661 | /* Get the cache line size. */ |
662 | MM_ReadConfig32 (pDevice, PCI_CACHE_LINE_SIZE_REG, &Value32); | |
663 | pDevice->CacheLineSize = (LM_UINT8) Value32; | |
664 | pDevice->SavedCacheLineReg = Value32; | |
c609719b | 665 | |
f539edc0 VB |
666 | if (pDevice->ChipRevId != T3_CHIP_ID_5703_A1 && |
667 | pDevice->ChipRevId != T3_CHIP_ID_5703_A2 && | |
668 | pDevice->ChipRevId != T3_CHIP_ID_5704_A0) { | |
669 | pDevice->UndiFix = FALSE; | |
670 | } | |
c609719b | 671 | #if !PCIX_TARGET_WORKAROUND |
f539edc0 | 672 | pDevice->UndiFix = FALSE; |
c609719b | 673 | #endif |
f539edc0 VB |
674 | /* Map the memory base to system address space. */ |
675 | if (!pDevice->UndiFix) { | |
676 | Status = MM_MapMemBase (pDevice); | |
677 | if (Status != LM_STATUS_SUCCESS) { | |
678 | return Status; | |
679 | } | |
680 | /* Initialize the memory view pointer. */ | |
681 | pDevice->pMemView = (PT3_STD_MEM_MAP) pDevice->pMappedMemBase; | |
8bde7f77 | 682 | } |
c609719b | 683 | #if PCIX_TARGET_WORKAROUND |
f539edc0 VB |
684 | /* store whether we are in PCI are PCI-X mode */ |
685 | pDevice->EnablePciXFix = FALSE; | |
686 | ||
687 | MM_ReadConfig32 (pDevice, T3_PCI_STATE_REG, &Value32); | |
688 | if ((Value32 & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) == 0) { | |
689 | /* Enable PCI-X workaround only if we are running on 5700 BX. */ | |
690 | if (T3_CHIP_REV (pDevice->ChipRevId) == T3_CHIP_REV_5700_BX) { | |
691 | pDevice->EnablePciXFix = TRUE; | |
692 | } | |
693 | } | |
694 | if (pDevice->UndiFix) { | |
695 | pDevice->EnablePciXFix = TRUE; | |
8bde7f77 | 696 | } |
c609719b | 697 | #endif |
f539edc0 VB |
698 | /* Bx bug: due to the "byte_enable bug" in PCI-X mode, the power */ |
699 | /* management register may be clobbered which may cause the */ | |
700 | /* BCM5700 to go into D3 state. While in this state, we will */ | |
701 | /* not have memory mapped register access. As a workaround, we */ | |
702 | /* need to restore the device to D0 state. */ | |
703 | MM_ReadConfig32 (pDevice, T3_PCI_PM_STATUS_CTRL_REG, &Value32); | |
704 | Value32 |= T3_PM_PME_ASSERTED; | |
705 | Value32 &= ~T3_PM_POWER_STATE_MASK; | |
706 | Value32 |= T3_PM_POWER_STATE_D0; | |
707 | MM_WriteConfig32 (pDevice, T3_PCI_PM_STATUS_CTRL_REG, Value32); | |
708 | ||
709 | /* read the current PCI command word */ | |
710 | MM_ReadConfig32 (pDevice, PCI_COMMAND_REG, &Value32); | |
711 | ||
712 | /* Make sure bus-mastering is enabled. */ | |
713 | Value32 |= PCI_BUSMASTER_ENABLE; | |
c609719b WD |
714 | |
715 | #if PCIX_TARGET_WORKAROUND | |
f539edc0 VB |
716 | /* if we are in PCI-X mode, also make sure mem-mapping and SERR#/PERR# |
717 | are enabled */ | |
718 | if (pDevice->EnablePciXFix == TRUE) { | |
719 | Value32 |= (PCI_MEM_SPACE_ENABLE | PCI_SYSTEM_ERROR_ENABLE | | |
720 | PCI_PARITY_ERROR_ENABLE); | |
721 | } | |
722 | if (pDevice->UndiFix) { | |
723 | Value32 &= ~PCI_MEM_SPACE_ENABLE; | |
724 | } | |
c609719b WD |
725 | #endif |
726 | ||
f539edc0 VB |
727 | if (pDevice->EnableMWI) { |
728 | Value32 |= PCI_MEMORY_WRITE_INVALIDATE; | |
729 | } else { | |
730 | Value32 &= (~PCI_MEMORY_WRITE_INVALIDATE); | |
731 | } | |
732 | ||
733 | /* Error out if mem-mapping is NOT enabled for PCI systems */ | |
734 | if (!(Value32 | PCI_MEM_SPACE_ENABLE)) { | |
735 | return LM_STATUS_FAILURE; | |
736 | } | |
c609719b | 737 | |
f539edc0 VB |
738 | /* save the value we are going to write into the PCI command word */ |
739 | pDevice->PciCommandStatusWords = Value32; | |
c609719b | 740 | |
f539edc0 VB |
741 | Status = MM_WriteConfig32 (pDevice, PCI_COMMAND_REG, Value32); |
742 | if (Status != LM_STATUS_SUCCESS) { | |
743 | return Status; | |
744 | } | |
c609719b | 745 | |
f539edc0 VB |
746 | /* Set power state to D0. */ |
747 | LM_SetPowerState (pDevice, LM_POWER_STATE_D0); | |
c609719b WD |
748 | |
749 | #ifdef BIG_ENDIAN_PCI | |
f539edc0 VB |
750 | pDevice->MiscHostCtrl = |
751 | MISC_HOST_CTRL_MASK_PCI_INT | | |
752 | MISC_HOST_CTRL_ENABLE_INDIRECT_ACCESS | | |
753 | MISC_HOST_CTRL_ENABLE_ENDIAN_WORD_SWAP | | |
754 | MISC_HOST_CTRL_ENABLE_PCI_STATE_REG_RW; | |
755 | #else /* No CPU Swap modes for PCI IO */ | |
756 | ||
757 | /* Setup the mode registers. */ | |
758 | pDevice->MiscHostCtrl = | |
759 | MISC_HOST_CTRL_MASK_PCI_INT | | |
760 | MISC_HOST_CTRL_ENABLE_ENDIAN_WORD_SWAP | | |
c609719b | 761 | #ifdef BIG_ENDIAN_HOST |
f539edc0 VB |
762 | MISC_HOST_CTRL_ENABLE_ENDIAN_BYTE_SWAP | |
763 | #endif /* BIG_ENDIAN_HOST */ | |
764 | MISC_HOST_CTRL_ENABLE_INDIRECT_ACCESS | | |
765 | MISC_HOST_CTRL_ENABLE_PCI_STATE_REG_RW; | |
766 | #endif /* !BIG_ENDIAN_PCI */ | |
c609719b | 767 | |
f539edc0 VB |
768 | /* write to PCI misc host ctr first in order to enable indirect accesses */ |
769 | MM_WriteConfig32 (pDevice, T3_PCI_MISC_HOST_CTRL_REG, | |
770 | pDevice->MiscHostCtrl); | |
c609719b | 771 | |
f539edc0 | 772 | REG_WR (pDevice, PciCfg.MiscHostCtrl, pDevice->MiscHostCtrl); |
c609719b WD |
773 | |
774 | #ifdef BIG_ENDIAN_PCI | |
f539edc0 | 775 | Value32 = GRC_MODE_WORD_SWAP_DATA | GRC_MODE_WORD_SWAP_NON_FRAME_DATA; |
c609719b WD |
776 | #else |
777 | /* No CPU Swap modes for PCI IO */ | |
778 | #ifdef BIG_ENDIAN_HOST | |
f539edc0 VB |
779 | Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | |
780 | GRC_MODE_WORD_SWAP_NON_FRAME_DATA; | |
c609719b | 781 | #else |
f539edc0 | 782 | Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | GRC_MODE_BYTE_SWAP_DATA; |
c609719b | 783 | #endif |
f539edc0 VB |
784 | #endif /* !BIG_ENDIAN_PCI */ |
785 | ||
786 | REG_WR (pDevice, Grc.Mode, Value32); | |
787 | ||
788 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { | |
789 | REG_WR (pDevice, Grc.LocalCtrl, | |
790 | GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 | | |
791 | GRC_MISC_LOCAL_CTRL_GPIO_OE1); | |
792 | } | |
793 | MM_Wait (40); | |
794 | ||
795 | /* Enable indirect memory access */ | |
796 | REG_WR (pDevice, MemArbiter.Mode, T3_MEM_ARBITER_MODE_ENABLE); | |
797 | ||
798 | if (REG_RD (pDevice, PciCfg.ClockCtrl) & T3_PCI_44MHZ_CORE_CLOCK) { | |
799 | REG_WR (pDevice, PciCfg.ClockCtrl, T3_PCI_44MHZ_CORE_CLOCK | | |
800 | T3_PCI_SELECT_ALTERNATE_CLOCK); | |
801 | REG_WR (pDevice, PciCfg.ClockCtrl, | |
802 | T3_PCI_SELECT_ALTERNATE_CLOCK); | |
803 | MM_Wait (40); /* required delay is 27usec */ | |
804 | } | |
805 | REG_WR (pDevice, PciCfg.ClockCtrl, 0); | |
806 | REG_WR (pDevice, PciCfg.MemWindowBaseAddr, 0); | |
c609719b WD |
807 | |
808 | #if PCIX_TARGET_WORKAROUND | |
f539edc0 VB |
809 | MM_ReadConfig32 (pDevice, T3_PCI_STATE_REG, &Value32); |
810 | if ((pDevice->EnablePciXFix == FALSE) && | |
811 | ((Value32 & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) == 0)) { | |
812 | if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 || | |
813 | pDevice->ChipRevId == T3_CHIP_ID_5701_B0 || | |
814 | pDevice->ChipRevId == T3_CHIP_ID_5701_B2 || | |
815 | pDevice->ChipRevId == T3_CHIP_ID_5701_B5) { | |
816 | __raw_writel (0, | |
817 | &(pDevice->pMemView->uIntMem. | |
818 | MemBlock32K[0x300])); | |
819 | __raw_writel (0, | |
820 | &(pDevice->pMemView->uIntMem. | |
821 | MemBlock32K[0x301])); | |
822 | __raw_writel (0xffffffff, | |
823 | &(pDevice->pMemView->uIntMem. | |
824 | MemBlock32K[0x301])); | |
825 | if (__raw_readl | |
826 | (&(pDevice->pMemView->uIntMem.MemBlock32K[0x300]))) | |
827 | { | |
828 | pDevice->EnablePciXFix = TRUE; | |
829 | } | |
830 | } | |
8bde7f77 | 831 | } |
c609719b WD |
832 | #endif |
833 | #if 1 | |
f539edc0 VB |
834 | /* |
835 | * This code was at the beginning of else block below, but that's | |
836 | * a bug if node address in shared memory. | |
837 | */ | |
838 | MM_Wait (50); | |
839 | LM_NvramInit (pDevice); | |
c609719b | 840 | #endif |
f539edc0 VB |
841 | /* Get the node address. First try to get in from the shared memory. */ |
842 | /* If the signature is not present, then get it from the NVRAM. */ | |
843 | Value32 = MEM_RD_OFFSET (pDevice, T3_MAC_ADDR_HIGH_MAILBOX); | |
844 | if ((Value32 >> 16) == 0x484b) { | |
845 | ||
846 | pDevice->NodeAddress[0] = (LM_UINT8) (Value32 >> 8); | |
847 | pDevice->NodeAddress[1] = (LM_UINT8) Value32; | |
848 | ||
849 | Value32 = MEM_RD_OFFSET (pDevice, T3_MAC_ADDR_LOW_MAILBOX); | |
850 | ||
851 | pDevice->NodeAddress[2] = (LM_UINT8) (Value32 >> 24); | |
852 | pDevice->NodeAddress[3] = (LM_UINT8) (Value32 >> 16); | |
853 | pDevice->NodeAddress[4] = (LM_UINT8) (Value32 >> 8); | |
854 | pDevice->NodeAddress[5] = (LM_UINT8) Value32; | |
855 | ||
856 | Status = LM_STATUS_SUCCESS; | |
857 | } else { | |
858 | Status = LM_NvramRead (pDevice, 0x7c, &Value32); | |
859 | if (Status == LM_STATUS_SUCCESS) { | |
860 | pDevice->NodeAddress[0] = (LM_UINT8) (Value32 >> 16); | |
861 | pDevice->NodeAddress[1] = (LM_UINT8) (Value32 >> 24); | |
862 | ||
863 | Status = LM_NvramRead (pDevice, 0x80, &Value32); | |
864 | ||
865 | pDevice->NodeAddress[2] = (LM_UINT8) Value32; | |
866 | pDevice->NodeAddress[3] = (LM_UINT8) (Value32 >> 8); | |
867 | pDevice->NodeAddress[4] = (LM_UINT8) (Value32 >> 16); | |
868 | pDevice->NodeAddress[5] = (LM_UINT8) (Value32 >> 24); | |
869 | } | |
8bde7f77 | 870 | } |
c609719b | 871 | |
f539edc0 VB |
872 | /* Assign a default address. */ |
873 | if (Status != LM_STATUS_SUCCESS) { | |
c609719b | 874 | #ifndef EMBEDDED |
f539edc0 VB |
875 | printk (KERN_ERR |
876 | "Cannot get MAC addr from NVRAM. Using default.\n"); | |
c609719b | 877 | #endif |
f539edc0 VB |
878 | pDevice->NodeAddress[0] = 0x00; |
879 | pDevice->NodeAddress[1] = 0x10; | |
880 | pDevice->NodeAddress[2] = 0x18; | |
881 | pDevice->NodeAddress[3] = 0x68; | |
882 | pDevice->NodeAddress[4] = 0x61; | |
883 | pDevice->NodeAddress[5] = 0x76; | |
884 | } | |
885 | ||
886 | pDevice->PermanentNodeAddress[0] = pDevice->NodeAddress[0]; | |
887 | pDevice->PermanentNodeAddress[1] = pDevice->NodeAddress[1]; | |
888 | pDevice->PermanentNodeAddress[2] = pDevice->NodeAddress[2]; | |
889 | pDevice->PermanentNodeAddress[3] = pDevice->NodeAddress[3]; | |
890 | pDevice->PermanentNodeAddress[4] = pDevice->NodeAddress[4]; | |
891 | pDevice->PermanentNodeAddress[5] = pDevice->NodeAddress[5]; | |
892 | ||
893 | /* Initialize the default values. */ | |
894 | pDevice->NoTxPseudoHdrChksum = FALSE; | |
895 | pDevice->NoRxPseudoHdrChksum = FALSE; | |
896 | pDevice->NicSendBd = FALSE; | |
897 | pDevice->TxPacketDescCnt = DEFAULT_TX_PACKET_DESC_COUNT; | |
898 | pDevice->RxStdDescCnt = DEFAULT_STD_RCV_DESC_COUNT; | |
899 | pDevice->RxCoalescingTicks = DEFAULT_RX_COALESCING_TICKS; | |
900 | pDevice->TxCoalescingTicks = DEFAULT_TX_COALESCING_TICKS; | |
901 | pDevice->RxMaxCoalescedFrames = DEFAULT_RX_MAX_COALESCED_FRAMES; | |
902 | pDevice->TxMaxCoalescedFrames = DEFAULT_TX_MAX_COALESCED_FRAMES; | |
903 | pDevice->RxCoalescingTicksDuringInt = BAD_DEFAULT_VALUE; | |
904 | pDevice->TxCoalescingTicksDuringInt = BAD_DEFAULT_VALUE; | |
905 | pDevice->RxMaxCoalescedFramesDuringInt = BAD_DEFAULT_VALUE; | |
906 | pDevice->TxMaxCoalescedFramesDuringInt = BAD_DEFAULT_VALUE; | |
907 | pDevice->StatsCoalescingTicks = DEFAULT_STATS_COALESCING_TICKS; | |
908 | pDevice->EnableMWI = FALSE; | |
909 | pDevice->TxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC; | |
910 | pDevice->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC; | |
911 | pDevice->DisableAutoNeg = FALSE; | |
912 | pDevice->PhyIntMode = T3_PHY_INT_MODE_AUTO; | |
913 | pDevice->LinkChngMode = T3_LINK_CHNG_MODE_AUTO; | |
914 | pDevice->LedMode = LED_MODE_AUTO; | |
915 | pDevice->ResetPhyOnInit = TRUE; | |
916 | pDevice->DelayPciGrant = TRUE; | |
917 | pDevice->UseTaggedStatus = FALSE; | |
918 | pDevice->OneDmaAtOnce = BAD_DEFAULT_VALUE; | |
c609719b | 919 | |
f539edc0 VB |
920 | pDevice->DmaMbufLowMark = T3_DEF_DMA_MBUF_LOW_WMARK_JUMBO; |
921 | pDevice->RxMacMbufLowMark = T3_DEF_RX_MAC_MBUF_LOW_WMARK_JUMBO; | |
922 | pDevice->MbufHighMark = T3_DEF_MBUF_HIGH_WMARK_JUMBO; | |
c609719b | 923 | |
f539edc0 VB |
924 | pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_AUTO; |
925 | pDevice->TaskOffloadCap = LM_TASK_OFFLOAD_NONE; | |
926 | pDevice->FlowControlCap = LM_FLOW_CONTROL_AUTO_PAUSE; | |
927 | pDevice->EnableTbi = FALSE; | |
928 | #if INCLUDE_TBI_SUPPORT | |
929 | pDevice->PollTbiLink = BAD_DEFAULT_VALUE; | |
930 | #endif | |
8bde7f77 | 931 | |
f539edc0 VB |
932 | switch (T3_ASIC_REV (pDevice->ChipRevId)) { |
933 | case T3_ASIC_REV_5704: | |
934 | pDevice->MbufBase = T3_NIC_MBUF_POOL_ADDR; | |
935 | pDevice->MbufSize = T3_NIC_MBUF_POOL_SIZE64; | |
8bde7f77 | 936 | break; |
f539edc0 VB |
937 | default: |
938 | pDevice->MbufBase = T3_NIC_MBUF_POOL_ADDR; | |
939 | pDevice->MbufSize = T3_NIC_MBUF_POOL_SIZE96; | |
8bde7f77 WD |
940 | break; |
941 | } | |
942 | ||
f539edc0 VB |
943 | pDevice->LinkStatus = LM_STATUS_LINK_DOWN; |
944 | pDevice->QueueRxPackets = TRUE; | |
8bde7f77 | 945 | |
f539edc0 | 946 | pDevice->EnableWireSpeed = TRUE; |
8bde7f77 | 947 | |
f539edc0 VB |
948 | #if T3_JUMBO_RCV_RCB_ENTRY_COUNT |
949 | pDevice->RxJumboDescCnt = DEFAULT_JUMBO_RCV_DESC_COUNT; | |
950 | #endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ | |
951 | ||
952 | /* Make this is a known adapter. */ | |
953 | pAdapterInfo = LM_GetAdapterInfoBySsid (pDevice->SubsystemVendorId, | |
954 | pDevice->SubsystemId); | |
955 | ||
956 | pDevice->BondId = REG_RD (pDevice, Grc.MiscCfg) & GRC_MISC_BD_ID_MASK; | |
957 | if (pDevice->BondId != GRC_MISC_BD_ID_5700 && | |
958 | pDevice->BondId != GRC_MISC_BD_ID_5701 && | |
959 | pDevice->BondId != GRC_MISC_BD_ID_5702FE && | |
960 | pDevice->BondId != GRC_MISC_BD_ID_5703 && | |
961 | pDevice->BondId != GRC_MISC_BD_ID_5703S && | |
962 | pDevice->BondId != GRC_MISC_BD_ID_5704 && | |
963 | pDevice->BondId != GRC_MISC_BD_ID_5704CIOBE) { | |
964 | return LM_STATUS_UNKNOWN_ADAPTER; | |
965 | } | |
966 | ||
967 | pDevice->SplitModeEnable = SPLIT_MODE_DISABLE; | |
968 | if ((pDevice->ChipRevId == T3_CHIP_ID_5704_A0) && | |
969 | (pDevice->BondId == GRC_MISC_BD_ID_5704CIOBE)) { | |
970 | pDevice->SplitModeEnable = SPLIT_MODE_ENABLE; | |
971 | pDevice->SplitModeMaxReq = SPLIT_MODE_5704_MAX_REQ; | |
972 | } | |
973 | ||
974 | /* Get Eeprom info. */ | |
975 | Value32 = MEM_RD_OFFSET (pDevice, T3_NIC_DATA_SIG_ADDR); | |
976 | if (Value32 == T3_NIC_DATA_SIG) { | |
977 | EeSigFound = TRUE; | |
978 | Value32 = MEM_RD_OFFSET (pDevice, T3_NIC_DATA_NIC_CFG_ADDR); | |
979 | ||
980 | /* Determine PHY type. */ | |
981 | switch (Value32 & T3_NIC_CFG_PHY_TYPE_MASK) { | |
982 | case T3_NIC_CFG_PHY_TYPE_COPPER: | |
983 | EePhyTypeSerdes = FALSE; | |
984 | break; | |
8bde7f77 | 985 | |
f539edc0 VB |
986 | case T3_NIC_CFG_PHY_TYPE_FIBER: |
987 | EePhyTypeSerdes = TRUE; | |
988 | break; | |
8bde7f77 WD |
989 | |
990 | default: | |
f539edc0 VB |
991 | EePhyTypeSerdes = FALSE; |
992 | break; | |
993 | } | |
8bde7f77 | 994 | |
f539edc0 VB |
995 | /* Determine PHY led mode. */ |
996 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || | |
997 | T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { | |
998 | switch (Value32 & T3_NIC_CFG_LED_MODE_MASK) { | |
999 | case T3_NIC_CFG_LED_MODE_TRIPLE_SPEED: | |
1000 | EePhyLedMode = LED_MODE_THREE_LINK; | |
1001 | break; | |
1002 | ||
1003 | case T3_NIC_CFG_LED_MODE_LINK_SPEED: | |
1004 | EePhyLedMode = LED_MODE_LINK10; | |
1005 | break; | |
1006 | ||
1007 | default: | |
1008 | EePhyLedMode = LED_MODE_AUTO; | |
1009 | break; | |
1010 | } | |
1011 | } else { | |
1012 | switch (Value32 & T3_NIC_CFG_LED_MODE_MASK) { | |
1013 | case T3_NIC_CFG_LED_MODE_OPEN_DRAIN: | |
1014 | EePhyLedMode = LED_MODE_OPEN_DRAIN; | |
1015 | break; | |
1016 | ||
1017 | case T3_NIC_CFG_LED_MODE_OUTPUT: | |
1018 | EePhyLedMode = LED_MODE_OUTPUT; | |
1019 | break; | |
1020 | ||
1021 | default: | |
1022 | EePhyLedMode = LED_MODE_AUTO; | |
1023 | break; | |
1024 | } | |
1025 | } | |
1026 | if (pDevice->ChipRevId == T3_CHIP_ID_5703_A1 || | |
1027 | pDevice->ChipRevId == T3_CHIP_ID_5703_A2) { | |
1028 | /* Enable EEPROM write protection. */ | |
1029 | if (Value32 & T3_NIC_EEPROM_WP) { | |
1030 | pDevice->EepromWp = TRUE; | |
1031 | } | |
1032 | } | |
8bde7f77 | 1033 | |
f539edc0 VB |
1034 | /* Get the PHY Id. */ |
1035 | Value32 = MEM_RD_OFFSET (pDevice, T3_NIC_DATA_PHY_ID_ADDR); | |
1036 | if (Value32) { | |
1037 | EePhyId = (((Value32 & T3_NIC_PHY_ID1_MASK) >> 16) & | |
1038 | PHY_ID1_OUI_MASK) << 10; | |
8bde7f77 | 1039 | |
f539edc0 VB |
1040 | Value32 = Value32 & T3_NIC_PHY_ID2_MASK; |
1041 | ||
1042 | EePhyId |= ((Value32 & PHY_ID2_OUI_MASK) << 16) | | |
1043 | (Value32 & PHY_ID2_MODEL_MASK) | (Value32 & | |
1044 | PHY_ID2_REV_MASK); | |
1045 | } else { | |
1046 | EePhyId = 0; | |
1047 | } | |
1048 | } else { | |
1049 | EeSigFound = FALSE; | |
8bde7f77 | 1050 | } |
c609719b | 1051 | |
f539edc0 VB |
1052 | /* Set the PHY address. */ |
1053 | pDevice->PhyAddr = PHY_DEVICE_ID; | |
c609719b | 1054 | |
f539edc0 VB |
1055 | /* Disable auto polling. */ |
1056 | pDevice->MiMode = 0xc0000; | |
1057 | REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode); | |
1058 | MM_Wait (40); | |
c609719b | 1059 | |
f539edc0 VB |
1060 | /* Get the PHY id. */ |
1061 | LM_ReadPhy (pDevice, PHY_ID1_REG, &Value32); | |
1062 | pDevice->PhyId = (Value32 & PHY_ID1_OUI_MASK) << 10; | |
c609719b | 1063 | |
f539edc0 VB |
1064 | LM_ReadPhy (pDevice, PHY_ID2_REG, &Value32); |
1065 | pDevice->PhyId |= ((Value32 & PHY_ID2_OUI_MASK) << 16) | | |
1066 | (Value32 & PHY_ID2_MODEL_MASK) | (Value32 & PHY_ID2_REV_MASK); | |
c609719b | 1067 | |
f539edc0 VB |
1068 | /* Set the EnableTbi flag to false if we have a copper PHY. */ |
1069 | switch (pDevice->PhyId & PHY_ID_MASK) { | |
8bde7f77 | 1070 | case PHY_BCM5400_PHY_ID: |
f539edc0 VB |
1071 | pDevice->EnableTbi = FALSE; |
1072 | break; | |
c609719b | 1073 | |
8bde7f77 | 1074 | case PHY_BCM5401_PHY_ID: |
f539edc0 VB |
1075 | pDevice->EnableTbi = FALSE; |
1076 | break; | |
c609719b | 1077 | |
8bde7f77 | 1078 | case PHY_BCM5411_PHY_ID: |
f539edc0 VB |
1079 | pDevice->EnableTbi = FALSE; |
1080 | break; | |
c609719b | 1081 | |
8bde7f77 | 1082 | case PHY_BCM5701_PHY_ID: |
f539edc0 VB |
1083 | pDevice->EnableTbi = FALSE; |
1084 | break; | |
c609719b | 1085 | |
8bde7f77 | 1086 | case PHY_BCM5703_PHY_ID: |
f539edc0 VB |
1087 | pDevice->EnableTbi = FALSE; |
1088 | break; | |
c609719b | 1089 | |
8bde7f77 | 1090 | case PHY_BCM5704_PHY_ID: |
f539edc0 VB |
1091 | pDevice->EnableTbi = FALSE; |
1092 | break; | |
c609719b | 1093 | |
8bde7f77 | 1094 | case PHY_BCM8002_PHY_ID: |
f539edc0 VB |
1095 | pDevice->EnableTbi = TRUE; |
1096 | break; | |
c609719b | 1097 | |
8bde7f77 | 1098 | default: |
c609719b | 1099 | |
f539edc0 VB |
1100 | if (pAdapterInfo) { |
1101 | pDevice->PhyId = pAdapterInfo->PhyId; | |
1102 | pDevice->EnableTbi = pAdapterInfo->Serdes; | |
1103 | } else if (EeSigFound) { | |
1104 | pDevice->PhyId = EePhyId; | |
1105 | pDevice->EnableTbi = EePhyTypeSerdes; | |
1106 | } | |
1107 | break; | |
1108 | } | |
c609719b | 1109 | |
f539edc0 VB |
1110 | /* Bail out if we don't know the copper PHY id. */ |
1111 | if (UNKNOWN_PHY_ID (pDevice->PhyId) && !pDevice->EnableTbi) { | |
1112 | return LM_STATUS_FAILURE; | |
1113 | } | |
c609719b | 1114 | |
f539edc0 VB |
1115 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5703) { |
1116 | if ((pDevice->SavedCacheLineReg & 0xff00) < 0x4000) { | |
1117 | pDevice->SavedCacheLineReg &= 0xffff00ff; | |
1118 | pDevice->SavedCacheLineReg |= 0x4000; | |
1119 | } | |
1120 | } | |
1121 | /* Change driver parameters. */ | |
1122 | Status = MM_GetConfig (pDevice); | |
1123 | if (Status != LM_STATUS_SUCCESS) { | |
1124 | return Status; | |
1125 | } | |
c609719b | 1126 | #if INCLUDE_5701_AX_FIX |
f539edc0 VB |
1127 | if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 || |
1128 | pDevice->ChipRevId == T3_CHIP_ID_5701_B0) { | |
1129 | pDevice->ResetPhyOnInit = TRUE; | |
1130 | } | |
c609719b WD |
1131 | #endif |
1132 | ||
f539edc0 VB |
1133 | /* Save the current phy link status. */ |
1134 | if (!pDevice->EnableTbi) { | |
1135 | LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); | |
1136 | LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); | |
c609719b | 1137 | |
f539edc0 VB |
1138 | /* If we don't have link reset the PHY. */ |
1139 | if (!(Value32 & PHY_STATUS_LINK_PASS) | |
1140 | || pDevice->ResetPhyOnInit) { | |
c609719b | 1141 | |
f539edc0 | 1142 | LM_WritePhy (pDevice, PHY_CTRL_REG, PHY_CTRL_PHY_RESET); |
c609719b | 1143 | |
f539edc0 VB |
1144 | for (j = 0; j < 100; j++) { |
1145 | MM_Wait (10); | |
c609719b | 1146 | |
f539edc0 VB |
1147 | LM_ReadPhy (pDevice, PHY_CTRL_REG, &Value32); |
1148 | if (Value32 && !(Value32 & PHY_CTRL_PHY_RESET)) { | |
1149 | MM_Wait (40); | |
1150 | break; | |
1151 | } | |
1152 | } | |
c609719b WD |
1153 | |
1154 | #if INCLUDE_5701_AX_FIX | |
f539edc0 VB |
1155 | /* 5701_AX_BX bug: only advertises 10mb speed. */ |
1156 | if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 || | |
1157 | pDevice->ChipRevId == T3_CHIP_ID_5701_B0) { | |
1158 | ||
1159 | Value32 = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD | | |
1160 | PHY_AN_AD_10BASET_HALF | | |
1161 | PHY_AN_AD_10BASET_FULL | | |
1162 | PHY_AN_AD_100BASETX_FULL | | |
1163 | PHY_AN_AD_100BASETX_HALF; | |
1164 | Value32 |= GetPhyAdFlowCntrlSettings (pDevice); | |
1165 | LM_WritePhy (pDevice, PHY_AN_AD_REG, Value32); | |
1166 | pDevice->advertising = Value32; | |
1167 | ||
1168 | Value32 = BCM540X_AN_AD_1000BASET_HALF | | |
1169 | BCM540X_AN_AD_1000BASET_FULL | | |
1170 | BCM540X_CONFIG_AS_MASTER | | |
1171 | BCM540X_ENABLE_CONFIG_AS_MASTER; | |
1172 | LM_WritePhy (pDevice, | |
1173 | BCM540X_1000BASET_CTRL_REG, | |
1174 | Value32); | |
1175 | pDevice->advertising1000 = Value32; | |
1176 | ||
1177 | LM_WritePhy (pDevice, PHY_CTRL_REG, | |
1178 | PHY_CTRL_AUTO_NEG_ENABLE | | |
1179 | PHY_CTRL_RESTART_AUTO_NEG); | |
1180 | } | |
c609719b | 1181 | #endif |
f539edc0 VB |
1182 | if (T3_ASIC_REV (pDevice->ChipRevId) == |
1183 | T3_ASIC_REV_5703) { | |
1184 | LM_WritePhy (pDevice, 0x18, 0x0c00); | |
1185 | LM_WritePhy (pDevice, 0x17, 0x201f); | |
1186 | LM_WritePhy (pDevice, 0x15, 0x2aaa); | |
1187 | } | |
1188 | if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0) { | |
1189 | LM_WritePhy (pDevice, 0x1c, 0x8d68); | |
1190 | LM_WritePhy (pDevice, 0x1c, 0x8d68); | |
1191 | } | |
1192 | /* Enable Ethernet@WireSpeed. */ | |
1193 | if (pDevice->EnableWireSpeed) { | |
1194 | LM_WritePhy (pDevice, 0x18, 0x7007); | |
1195 | LM_ReadPhy (pDevice, 0x18, &Value32); | |
1196 | LM_WritePhy (pDevice, 0x18, | |
1197 | Value32 | BIT_15 | BIT_4); | |
1198 | } | |
1199 | } | |
1200 | } | |
c609719b | 1201 | |
f539edc0 VB |
1202 | /* Turn off tap power management. */ |
1203 | if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID) { | |
1204 | LM_WritePhy (pDevice, BCM5401_AUX_CTRL, 0x0c20); | |
1205 | LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x0012); | |
1206 | LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x1804); | |
1207 | LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x0013); | |
1208 | LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x1204); | |
1209 | LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006); | |
1210 | LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x0132); | |
1211 | LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006); | |
1212 | LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x0232); | |
1213 | LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x201f); | |
1214 | LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x0a20); | |
c609719b | 1215 | |
f539edc0 | 1216 | MM_Wait (40); |
8bde7f77 | 1217 | } |
f539edc0 VB |
1218 | #if INCLUDE_TBI_SUPPORT |
1219 | pDevice->IgnoreTbiLinkChange = FALSE; | |
1220 | ||
1221 | if (pDevice->EnableTbi) { | |
1222 | pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_NONE; | |
1223 | pDevice->PhyIntMode = T3_PHY_INT_MODE_LINK_READY; | |
1224 | if ((pDevice->PollTbiLink == BAD_DEFAULT_VALUE) || | |
1225 | pDevice->DisableAutoNeg) { | |
1226 | pDevice->PollTbiLink = FALSE; | |
1227 | } | |
1228 | } else { | |
1229 | pDevice->PollTbiLink = FALSE; | |
8bde7f77 | 1230 | } |
f539edc0 | 1231 | #endif /* INCLUDE_TBI_SUPPORT */ |
8bde7f77 | 1232 | |
f539edc0 VB |
1233 | /* UseTaggedStatus is only valid for 5701 and later. */ |
1234 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { | |
1235 | pDevice->UseTaggedStatus = FALSE; | |
8bde7f77 | 1236 | |
f539edc0 VB |
1237 | pDevice->CoalesceMode = 0; |
1238 | } else { | |
1239 | pDevice->CoalesceMode = | |
1240 | HOST_COALESCE_CLEAR_TICKS_ON_RX_BD_EVENT | | |
1241 | HOST_COALESCE_CLEAR_TICKS_ON_TX_BD_EVENT; | |
8bde7f77 | 1242 | } |
c609719b | 1243 | |
f539edc0 VB |
1244 | /* Set the status block size. */ |
1245 | if (T3_CHIP_REV (pDevice->ChipRevId) != T3_CHIP_REV_5700_AX && | |
1246 | T3_CHIP_REV (pDevice->ChipRevId) != T3_CHIP_REV_5700_BX) { | |
1247 | pDevice->CoalesceMode |= HOST_COALESCE_32_BYTE_STATUS_MODE; | |
8bde7f77 | 1248 | } |
c609719b | 1249 | |
f539edc0 VB |
1250 | /* Check the DURING_INT coalescing ticks parameters. */ |
1251 | if (pDevice->UseTaggedStatus) { | |
1252 | if (pDevice->RxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE) { | |
1253 | pDevice->RxCoalescingTicksDuringInt = | |
1254 | DEFAULT_RX_COALESCING_TICKS_DURING_INT; | |
1255 | } | |
c609719b | 1256 | |
f539edc0 VB |
1257 | if (pDevice->TxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE) { |
1258 | pDevice->TxCoalescingTicksDuringInt = | |
1259 | DEFAULT_TX_COALESCING_TICKS_DURING_INT; | |
1260 | } | |
c609719b | 1261 | |
f539edc0 VB |
1262 | if (pDevice->RxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE) { |
1263 | pDevice->RxMaxCoalescedFramesDuringInt = | |
1264 | DEFAULT_RX_MAX_COALESCED_FRAMES_DURING_INT; | |
1265 | } | |
c609719b | 1266 | |
f539edc0 VB |
1267 | if (pDevice->TxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE) { |
1268 | pDevice->TxMaxCoalescedFramesDuringInt = | |
1269 | DEFAULT_TX_MAX_COALESCED_FRAMES_DURING_INT; | |
1270 | } | |
1271 | } else { | |
1272 | if (pDevice->RxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE) { | |
1273 | pDevice->RxCoalescingTicksDuringInt = 0; | |
1274 | } | |
c609719b | 1275 | |
f539edc0 VB |
1276 | if (pDevice->TxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE) { |
1277 | pDevice->TxCoalescingTicksDuringInt = 0; | |
1278 | } | |
1279 | ||
1280 | if (pDevice->RxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE) { | |
1281 | pDevice->RxMaxCoalescedFramesDuringInt = 0; | |
1282 | } | |
1283 | ||
1284 | if (pDevice->TxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE) { | |
1285 | pDevice->TxMaxCoalescedFramesDuringInt = 0; | |
1286 | } | |
1287 | } | |
c609719b | 1288 | |
c609719b | 1289 | #if T3_JUMBO_RCV_RCB_ENTRY_COUNT |
f539edc0 VB |
1290 | if (pDevice->RxMtu <= (MAX_STD_RCV_BUFFER_SIZE - 8 /* CRC */ )) { |
1291 | pDevice->RxJumboDescCnt = 0; | |
1292 | if (pDevice->RxMtu <= MAX_ETHERNET_PACKET_SIZE_NO_CRC) { | |
1293 | pDevice->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC; | |
1294 | } | |
1295 | } else { | |
1296 | pDevice->RxJumboBufferSize = | |
1297 | (pDevice->RxMtu + 8 /* CRC + VLAN */ + | |
1298 | COMMON_CACHE_LINE_SIZE - 1) & ~COMMON_CACHE_LINE_MASK; | |
1299 | ||
1300 | if (pDevice->RxJumboBufferSize > MAX_JUMBO_RCV_BUFFER_SIZE) { | |
1301 | pDevice->RxJumboBufferSize = | |
1302 | DEFAULT_JUMBO_RCV_BUFFER_SIZE; | |
1303 | pDevice->RxMtu = | |
1304 | pDevice->RxJumboBufferSize - 8 /* CRC + VLAN */ ; | |
1305 | } | |
1306 | pDevice->TxMtu = pDevice->RxMtu; | |
c609719b | 1307 | |
f539edc0 VB |
1308 | } |
1309 | #else | |
1310 | pDevice->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC; | |
1311 | #endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ | |
c609719b | 1312 | |
f539edc0 VB |
1313 | pDevice->RxPacketDescCnt = |
1314 | #if T3_JUMBO_RCV_RCB_ENTRY_COUNT | |
1315 | pDevice->RxJumboDescCnt + | |
1316 | #endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ | |
1317 | pDevice->RxStdDescCnt; | |
c609719b | 1318 | |
f539edc0 VB |
1319 | if (pDevice->TxMtu < MAX_ETHERNET_PACKET_SIZE_NO_CRC) { |
1320 | pDevice->TxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC; | |
8bde7f77 | 1321 | } |
f539edc0 VB |
1322 | |
1323 | if (pDevice->TxMtu > MAX_JUMBO_TX_BUFFER_SIZE) { | |
1324 | pDevice->TxMtu = MAX_JUMBO_TX_BUFFER_SIZE; | |
8bde7f77 | 1325 | } |
f539edc0 VB |
1326 | |
1327 | /* Configure the proper ways to get link change interrupt. */ | |
1328 | if (pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO) { | |
1329 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { | |
1330 | pDevice->PhyIntMode = T3_PHY_INT_MODE_MI_INTERRUPT; | |
1331 | } else { | |
1332 | pDevice->PhyIntMode = T3_PHY_INT_MODE_LINK_READY; | |
1333 | } | |
1334 | } else if (pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING) { | |
1335 | /* Auto-polling does not work on 5700_AX and 5700_BX. */ | |
1336 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { | |
1337 | pDevice->PhyIntMode = T3_PHY_INT_MODE_MI_INTERRUPT; | |
1338 | } | |
8bde7f77 | 1339 | } |
c609719b | 1340 | |
f539edc0 VB |
1341 | /* Determine the method to get link change status. */ |
1342 | if (pDevice->LinkChngMode == T3_LINK_CHNG_MODE_AUTO) { | |
1343 | /* The link status bit in the status block does not work on 5700_AX */ | |
1344 | /* and 5700_BX chips. */ | |
1345 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { | |
1346 | pDevice->LinkChngMode = | |
1347 | T3_LINK_CHNG_MODE_USE_STATUS_REG; | |
1348 | } else { | |
1349 | pDevice->LinkChngMode = | |
1350 | T3_LINK_CHNG_MODE_USE_STATUS_BLOCK; | |
1351 | } | |
8bde7f77 | 1352 | } |
f539edc0 VB |
1353 | |
1354 | if (pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT || | |
1355 | T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { | |
1356 | pDevice->LinkChngMode = T3_LINK_CHNG_MODE_USE_STATUS_REG; | |
8bde7f77 | 1357 | } |
c609719b | 1358 | |
f539edc0 VB |
1359 | /* Configure PHY led mode. */ |
1360 | if (pDevice->LedMode == LED_MODE_AUTO) { | |
1361 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || | |
1362 | T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { | |
1363 | if (pDevice->SubsystemVendorId == T3_SVID_DELL) { | |
1364 | pDevice->LedMode = LED_MODE_LINK10; | |
1365 | } else { | |
1366 | pDevice->LedMode = LED_MODE_THREE_LINK; | |
c609719b | 1367 | |
f539edc0 VB |
1368 | if (EeSigFound && EePhyLedMode != LED_MODE_AUTO) { |
1369 | pDevice->LedMode = EePhyLedMode; | |
1370 | } | |
1371 | } | |
1372 | ||
1373 | /* bug? 5701 in LINK10 mode does not seem to work when */ | |
1374 | /* PhyIntMode is LINK_READY. */ | |
1375 | if (T3_ASIC_REV (pDevice->ChipRevId) != T3_ASIC_REV_5700 | |
1376 | && | |
c609719b | 1377 | #if INCLUDE_TBI_SUPPORT |
f539edc0 | 1378 | pDevice->EnableTbi == FALSE && |
c609719b | 1379 | #endif |
f539edc0 VB |
1380 | pDevice->LedMode == LED_MODE_LINK10) { |
1381 | pDevice->PhyIntMode = | |
1382 | T3_PHY_INT_MODE_MI_INTERRUPT; | |
1383 | pDevice->LinkChngMode = | |
1384 | T3_LINK_CHNG_MODE_USE_STATUS_REG; | |
1385 | } | |
1386 | ||
1387 | if (pDevice->EnableTbi) { | |
1388 | pDevice->LedMode = LED_MODE_THREE_LINK; | |
1389 | } | |
1390 | } else { | |
1391 | if (EeSigFound && EePhyLedMode != LED_MODE_AUTO) { | |
1392 | pDevice->LedMode = EePhyLedMode; | |
1393 | } else { | |
1394 | pDevice->LedMode = LED_MODE_OPEN_DRAIN; | |
1395 | } | |
1396 | } | |
1397 | } | |
8bde7f77 | 1398 | |
f539edc0 VB |
1399 | /* Enable OneDmaAtOnce. */ |
1400 | if (pDevice->OneDmaAtOnce == BAD_DEFAULT_VALUE) { | |
1401 | pDevice->OneDmaAtOnce = FALSE; | |
8bde7f77 | 1402 | } |
f539edc0 VB |
1403 | |
1404 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || | |
1405 | pDevice->ChipRevId == T3_CHIP_ID_5701_A0 || | |
1406 | pDevice->ChipRevId == T3_CHIP_ID_5701_B0 || | |
1407 | pDevice->ChipRevId == T3_CHIP_ID_5701_B2) { | |
1408 | pDevice->WolSpeed = WOL_SPEED_10MB; | |
1409 | } else { | |
1410 | pDevice->WolSpeed = WOL_SPEED_100MB; | |
1411 | } | |
1412 | ||
1413 | /* Offloadings. */ | |
1414 | pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE; | |
1415 | ||
1416 | /* Turn off task offloading on Ax. */ | |
1417 | if (pDevice->ChipRevId == T3_CHIP_ID_5700_B0) { | |
1418 | pDevice->TaskOffloadCap &= ~(LM_TASK_OFFLOAD_TX_TCP_CHECKSUM | | |
1419 | LM_TASK_OFFLOAD_TX_UDP_CHECKSUM); | |
1420 | } | |
1421 | pDevice->PciState = REG_RD (pDevice, PciCfg.PciState); | |
1422 | LM_ReadVPD (pDevice); | |
1423 | LM_ReadBootCodeVersion (pDevice); | |
1424 | LM_GetBusSpeed (pDevice); | |
1425 | ||
1426 | return LM_STATUS_SUCCESS; | |
1427 | } /* LM_GetAdapterInfo */ | |
1428 | ||
1429 | STATIC PLM_ADAPTER_INFO LM_GetAdapterInfoBySsid (LM_UINT16 Svid, LM_UINT16 Ssid) | |
c609719b | 1430 | { |
f539edc0 VB |
1431 | static LM_ADAPTER_INFO AdapterArr[] = { |
1432 | {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95700A6, | |
1433 | PHY_BCM5401_PHY_ID, 0}, | |
1434 | {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A5, | |
1435 | PHY_BCM5701_PHY_ID, 0}, | |
1436 | {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95700T6, | |
1437 | PHY_BCM8002_PHY_ID, 1}, | |
1438 | {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95700A9, 0, 1}, | |
1439 | {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701T1, | |
1440 | PHY_BCM5701_PHY_ID, 0}, | |
1441 | {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701T8, | |
1442 | PHY_BCM5701_PHY_ID, 0}, | |
1443 | {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A7, 0, 1}, | |
1444 | {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A10, | |
1445 | PHY_BCM5701_PHY_ID, 0}, | |
1446 | {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A12, | |
1447 | PHY_BCM5701_PHY_ID, 0}, | |
1448 | {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95703Ax1, | |
1449 | PHY_BCM5701_PHY_ID, 0}, | |
1450 | {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95703Ax2, | |
1451 | PHY_BCM5701_PHY_ID, 0}, | |
1452 | ||
1453 | {T3_SVID_3COM, T3_SSID_3COM_3C996T, PHY_BCM5401_PHY_ID, 0}, | |
1454 | {T3_SVID_3COM, T3_SSID_3COM_3C996BT, PHY_BCM5701_PHY_ID, 0}, | |
1455 | {T3_SVID_3COM, T3_SSID_3COM_3C996SX, 0, 1}, | |
1456 | {T3_SVID_3COM, T3_SSID_3COM_3C1000T, PHY_BCM5701_PHY_ID, 0}, | |
1457 | {T3_SVID_3COM, T3_SSID_3COM_3C940BR01, PHY_BCM5701_PHY_ID, 0}, | |
1458 | ||
1459 | {T3_SVID_DELL, T3_SSID_DELL_VIPER, PHY_BCM5401_PHY_ID, 0}, | |
1460 | {T3_SVID_DELL, T3_SSID_DELL_JAGUAR, PHY_BCM5401_PHY_ID, 0}, | |
1461 | {T3_SVID_DELL, T3_SSID_DELL_MERLOT, PHY_BCM5411_PHY_ID, 0}, | |
1462 | {T3_SVID_DELL, T3_SSID_DELL_SLIM_MERLOT, PHY_BCM5411_PHY_ID, 0}, | |
1463 | ||
1464 | {T3_SVID_COMPAQ, T3_SSID_COMPAQ_BANSHEE, PHY_BCM5701_PHY_ID, 0}, | |
1465 | {T3_SVID_COMPAQ, T3_SSID_COMPAQ_BANSHEE_2, PHY_BCM5701_PHY_ID, | |
1466 | 0}, | |
1467 | {T3_SVID_COMPAQ, T3_SSID_COMPAQ_CHANGELING, 0, 1}, | |
1468 | {T3_SVID_COMPAQ, T3_SSID_COMPAQ_NC7780, PHY_BCM5701_PHY_ID, 0}, | |
1469 | {T3_SVID_COMPAQ, T3_SSID_COMPAQ_NC7780_2, PHY_BCM5701_PHY_ID, | |
1470 | 0}, | |
1471 | ||
1472 | }; | |
1473 | LM_UINT32 j; | |
1474 | ||
1475 | for (j = 0; j < sizeof (AdapterArr) / sizeof (LM_ADAPTER_INFO); j++) { | |
1476 | if (AdapterArr[j].Svid == Svid && AdapterArr[j].Ssid == Ssid) { | |
1477 | return &AdapterArr[j]; | |
1478 | } | |
8bde7f77 | 1479 | } |
c609719b | 1480 | |
f539edc0 | 1481 | return NULL; |
c609719b WD |
1482 | } |
1483 | ||
c609719b WD |
1484 | /******************************************************************************/ |
1485 | /* Description: */ | |
1486 | /* This routine sets up receive/transmit buffer descriptions queues. */ | |
1487 | /* */ | |
1488 | /* Return: */ | |
1489 | /* LM_STATUS_SUCCESS */ | |
1490 | /******************************************************************************/ | |
f539edc0 | 1491 | LM_STATUS LM_InitializeAdapter (PLM_DEVICE_BLOCK pDevice) |
c609719b | 1492 | { |
f539edc0 VB |
1493 | LM_PHYSICAL_ADDRESS MemPhy; |
1494 | PLM_UINT8 pMemVirt; | |
1495 | PLM_PACKET pPacket; | |
1496 | LM_STATUS Status; | |
1497 | LM_UINT32 Size; | |
1498 | LM_UINT32 j; | |
1499 | ||
1500 | /* Set power state to D0. */ | |
1501 | LM_SetPowerState (pDevice, LM_POWER_STATE_D0); | |
1502 | ||
1503 | /* Intialize the queues. */ | |
1504 | QQ_InitQueue (&pDevice->RxPacketReceivedQ.Container, | |
1505 | MAX_RX_PACKET_DESC_COUNT); | |
1506 | QQ_InitQueue (&pDevice->RxPacketFreeQ.Container, | |
1507 | MAX_RX_PACKET_DESC_COUNT); | |
1508 | ||
1509 | QQ_InitQueue (&pDevice->TxPacketFreeQ.Container, | |
1510 | MAX_TX_PACKET_DESC_COUNT); | |
1511 | QQ_InitQueue (&pDevice->TxPacketActiveQ.Container, | |
1512 | MAX_TX_PACKET_DESC_COUNT); | |
1513 | QQ_InitQueue (&pDevice->TxPacketXmittedQ.Container, | |
1514 | MAX_TX_PACKET_DESC_COUNT); | |
1515 | ||
1516 | /* Allocate shared memory for: status block, the buffers for receive */ | |
1517 | /* rings -- standard, mini, jumbo, and return rings. */ | |
1518 | Size = T3_STATUS_BLOCK_SIZE + sizeof (T3_STATS_BLOCK) + | |
1519 | T3_STD_RCV_RCB_ENTRY_COUNT * sizeof (T3_RCV_BD) + | |
c609719b | 1520 | #if T3_JUMBO_RCV_RCB_ENTRY_COUNT |
f539edc0 VB |
1521 | T3_JUMBO_RCV_RCB_ENTRY_COUNT * sizeof (T3_RCV_BD) + |
1522 | #endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ | |
1523 | T3_RCV_RETURN_RCB_ENTRY_COUNT * sizeof (T3_RCV_BD); | |
1524 | ||
1525 | /* Memory for host based Send BD. */ | |
1526 | if (pDevice->NicSendBd == FALSE) { | |
1527 | Size += sizeof (T3_SND_BD) * T3_SEND_RCB_ENTRY_COUNT; | |
1528 | } | |
1529 | ||
1530 | /* Allocate the memory block. */ | |
1531 | Status = | |
1532 | MM_AllocateSharedMemory (pDevice, Size, (PLM_VOID) & pMemVirt, | |
1533 | &MemPhy, FALSE); | |
1534 | if (Status != LM_STATUS_SUCCESS) { | |
1535 | return Status; | |
1536 | } | |
1537 | ||
1538 | /* Program DMA Read/Write */ | |
1539 | if (pDevice->PciState & T3_PCI_STATE_NOT_PCI_X_BUS) { | |
1540 | pDevice->DmaReadWriteCtrl = 0x763f000f; | |
1541 | } else { | |
1542 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5704) { | |
1543 | pDevice->DmaReadWriteCtrl = 0x761f0000; | |
1544 | } else { | |
1545 | pDevice->DmaReadWriteCtrl = 0x761b000f; | |
1546 | } | |
1547 | if (pDevice->ChipRevId == T3_CHIP_ID_5703_A1 || | |
1548 | pDevice->ChipRevId == T3_CHIP_ID_5703_A2) { | |
1549 | pDevice->OneDmaAtOnce = TRUE; | |
1550 | } | |
8bde7f77 | 1551 | } |
f539edc0 VB |
1552 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5703) { |
1553 | pDevice->DmaReadWriteCtrl &= 0xfffffff0; | |
1554 | } | |
1555 | ||
1556 | if (pDevice->OneDmaAtOnce) { | |
1557 | pDevice->DmaReadWriteCtrl |= DMA_CTRL_WRITE_ONE_DMA_AT_ONCE; | |
1558 | } | |
1559 | REG_WR (pDevice, PciCfg.DmaReadWriteCtrl, pDevice->DmaReadWriteCtrl); | |
1560 | ||
1561 | if (LM_DmaTest (pDevice, pMemVirt, MemPhy, 0x400) != LM_STATUS_SUCCESS) { | |
1562 | return LM_STATUS_FAILURE; | |
8bde7f77 | 1563 | } |
c609719b | 1564 | |
f539edc0 VB |
1565 | /* Status block. */ |
1566 | pDevice->pStatusBlkVirt = (PT3_STATUS_BLOCK) pMemVirt; | |
1567 | pDevice->StatusBlkPhy = MemPhy; | |
1568 | pMemVirt += T3_STATUS_BLOCK_SIZE; | |
1569 | LM_INC_PHYSICAL_ADDRESS (&MemPhy, T3_STATUS_BLOCK_SIZE); | |
c609719b | 1570 | |
f539edc0 VB |
1571 | /* Statistics block. */ |
1572 | pDevice->pStatsBlkVirt = (PT3_STATS_BLOCK) pMemVirt; | |
1573 | pDevice->StatsBlkPhy = MemPhy; | |
1574 | pMemVirt += sizeof (T3_STATS_BLOCK); | |
1575 | LM_INC_PHYSICAL_ADDRESS (&MemPhy, sizeof (T3_STATS_BLOCK)); | |
c609719b | 1576 | |
f539edc0 VB |
1577 | /* Receive standard BD buffer. */ |
1578 | pDevice->pRxStdBdVirt = (PT3_RCV_BD) pMemVirt; | |
1579 | pDevice->RxStdBdPhy = MemPhy; | |
c609719b | 1580 | |
f539edc0 VB |
1581 | pMemVirt += T3_STD_RCV_RCB_ENTRY_COUNT * sizeof (T3_RCV_BD); |
1582 | LM_INC_PHYSICAL_ADDRESS (&MemPhy, | |
1583 | T3_STD_RCV_RCB_ENTRY_COUNT * | |
1584 | sizeof (T3_RCV_BD)); | |
c609719b WD |
1585 | |
1586 | #if T3_JUMBO_RCV_RCB_ENTRY_COUNT | |
f539edc0 VB |
1587 | /* Receive jumbo BD buffer. */ |
1588 | pDevice->pRxJumboBdVirt = (PT3_RCV_BD) pMemVirt; | |
1589 | pDevice->RxJumboBdPhy = MemPhy; | |
1590 | ||
1591 | pMemVirt += T3_JUMBO_RCV_RCB_ENTRY_COUNT * sizeof (T3_RCV_BD); | |
1592 | LM_INC_PHYSICAL_ADDRESS (&MemPhy, | |
1593 | T3_JUMBO_RCV_RCB_ENTRY_COUNT * | |
1594 | sizeof (T3_RCV_BD)); | |
1595 | #endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ | |
1596 | ||
1597 | /* Receive return BD buffer. */ | |
1598 | pDevice->pRcvRetBdVirt = (PT3_RCV_BD) pMemVirt; | |
1599 | pDevice->RcvRetBdPhy = MemPhy; | |
1600 | ||
1601 | pMemVirt += T3_RCV_RETURN_RCB_ENTRY_COUNT * sizeof (T3_RCV_BD); | |
1602 | LM_INC_PHYSICAL_ADDRESS (&MemPhy, | |
1603 | T3_RCV_RETURN_RCB_ENTRY_COUNT * | |
1604 | sizeof (T3_RCV_BD)); | |
1605 | ||
1606 | /* Set up Send BD. */ | |
1607 | if (pDevice->NicSendBd == FALSE) { | |
1608 | pDevice->pSendBdVirt = (PT3_SND_BD) pMemVirt; | |
1609 | pDevice->SendBdPhy = MemPhy; | |
1610 | ||
1611 | pMemVirt += sizeof (T3_SND_BD) * T3_SEND_RCB_ENTRY_COUNT; | |
1612 | LM_INC_PHYSICAL_ADDRESS (&MemPhy, | |
1613 | sizeof (T3_SND_BD) * | |
1614 | T3_SEND_RCB_ENTRY_COUNT); | |
1615 | } else { | |
1616 | pDevice->pSendBdVirt = (PT3_SND_BD) | |
1617 | pDevice->pMemView->uIntMem.First32k.BufferDesc; | |
1618 | pDevice->SendBdPhy.High = 0; | |
1619 | pDevice->SendBdPhy.Low = T3_NIC_SND_BUFFER_DESC_ADDR; | |
1620 | } | |
1621 | ||
1622 | /* Allocate memory for packet descriptors. */ | |
1623 | Size = (pDevice->RxPacketDescCnt + | |
1624 | pDevice->TxPacketDescCnt) * MM_PACKET_DESC_SIZE; | |
1625 | Status = MM_AllocateMemory (pDevice, Size, (PLM_VOID *) & pPacket); | |
1626 | if (Status != LM_STATUS_SUCCESS) { | |
1627 | return Status; | |
1628 | } | |
1629 | pDevice->pPacketDescBase = (PLM_VOID) pPacket; | |
1630 | ||
1631 | /* Create transmit packet descriptors from the memory block and add them */ | |
1632 | /* to the TxPacketFreeQ for each send ring. */ | |
1633 | for (j = 0; j < pDevice->TxPacketDescCnt; j++) { | |
1634 | /* Ring index. */ | |
1635 | pPacket->Flags = 0; | |
1636 | ||
1637 | /* Queue the descriptor in the TxPacketFreeQ of the 'k' ring. */ | |
1638 | QQ_PushTail (&pDevice->TxPacketFreeQ.Container, pPacket); | |
1639 | ||
1640 | /* Get the pointer to the next descriptor. MM_PACKET_DESC_SIZE */ | |
1641 | /* is the total size of the packet descriptor including the */ | |
1642 | /* os-specific extensions in the UM_PACKET structure. */ | |
1643 | pPacket = | |
1644 | (PLM_PACKET) ((PLM_UINT8) pPacket + MM_PACKET_DESC_SIZE); | |
1645 | } /* for(j.. */ | |
1646 | ||
1647 | /* Create receive packet descriptors from the memory block and add them */ | |
1648 | /* to the RxPacketFreeQ. Create the Standard packet descriptors. */ | |
1649 | for (j = 0; j < pDevice->RxStdDescCnt; j++) { | |
1650 | /* Receive producer ring. */ | |
1651 | pPacket->u.Rx.RcvProdRing = T3_STD_RCV_PROD_RING; | |
1652 | ||
1653 | /* Receive buffer size. */ | |
1654 | pPacket->u.Rx.RxBufferSize = MAX_STD_RCV_BUFFER_SIZE; | |
1655 | ||
1656 | /* Add the descriptor to RxPacketFreeQ. */ | |
1657 | QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket); | |
1658 | ||
1659 | /* Get the pointer to the next descriptor. MM_PACKET_DESC_SIZE */ | |
1660 | /* is the total size of the packet descriptor including the */ | |
1661 | /* os-specific extensions in the UM_PACKET structure. */ | |
1662 | pPacket = | |
1663 | (PLM_PACKET) ((PLM_UINT8) pPacket + MM_PACKET_DESC_SIZE); | |
1664 | } /* for */ | |
c609719b WD |
1665 | |
1666 | #if T3_JUMBO_RCV_RCB_ENTRY_COUNT | |
f539edc0 VB |
1667 | /* Create the Jumbo packet descriptors. */ |
1668 | for (j = 0; j < pDevice->RxJumboDescCnt; j++) { | |
1669 | /* Receive producer ring. */ | |
1670 | pPacket->u.Rx.RcvProdRing = T3_JUMBO_RCV_PROD_RING; | |
c609719b | 1671 | |
f539edc0 VB |
1672 | /* Receive buffer size. */ |
1673 | pPacket->u.Rx.RxBufferSize = pDevice->RxJumboBufferSize; | |
c609719b | 1674 | |
f539edc0 VB |
1675 | /* Add the descriptor to RxPacketFreeQ. */ |
1676 | QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket); | |
c609719b | 1677 | |
f539edc0 VB |
1678 | /* Get the pointer to the next descriptor. MM_PACKET_DESC_SIZE */ |
1679 | /* is the total size of the packet descriptor including the */ | |
1680 | /* os-specific extensions in the UM_PACKET structure. */ | |
1681 | pPacket = | |
1682 | (PLM_PACKET) ((PLM_UINT8) pPacket + MM_PACKET_DESC_SIZE); | |
1683 | } /* for */ | |
1684 | #endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ | |
1685 | ||
1686 | /* Initialize the rest of the packet descriptors. */ | |
1687 | Status = MM_InitializeUmPackets (pDevice); | |
1688 | if (Status != LM_STATUS_SUCCESS) { | |
1689 | return Status; | |
1690 | } | |
c609719b | 1691 | |
f539edc0 VB |
1692 | /* if */ |
1693 | /* Default receive mask. */ | |
1694 | pDevice->ReceiveMask = LM_ACCEPT_MULTICAST | LM_ACCEPT_BROADCAST | | |
1695 | LM_ACCEPT_UNICAST; | |
c609719b | 1696 | |
f539edc0 VB |
1697 | /* Make sure we are in the first 32k memory window or NicSendBd. */ |
1698 | REG_WR (pDevice, PciCfg.MemWindowBaseAddr, 0); | |
c609719b | 1699 | |
f539edc0 VB |
1700 | /* Initialize the hardware. */ |
1701 | Status = LM_ResetAdapter (pDevice); | |
1702 | if (Status != LM_STATUS_SUCCESS) { | |
1703 | return Status; | |
1704 | } | |
1705 | ||
1706 | /* We are done with initialization. */ | |
1707 | pDevice->InitDone = TRUE; | |
1708 | ||
1709 | return LM_STATUS_SUCCESS; | |
1710 | } /* LM_InitializeAdapter */ | |
c609719b | 1711 | |
c609719b WD |
1712 | /******************************************************************************/ |
1713 | /* Description: */ | |
1714 | /* This function Enables/Disables a given block. */ | |
1715 | /* */ | |
1716 | /* Return: */ | |
1717 | /* LM_STATUS_SUCCESS */ | |
1718 | /******************************************************************************/ | |
1719 | LM_STATUS | |
f539edc0 | 1720 | LM_CntrlBlock (PLM_DEVICE_BLOCK pDevice, LM_UINT32 mask, LM_UINT32 cntrl) |
c609719b | 1721 | { |
f539edc0 VB |
1722 | LM_UINT32 j, i, data; |
1723 | LM_UINT32 MaxWaitCnt; | |
1724 | ||
1725 | MaxWaitCnt = 2; | |
1726 | j = 0; | |
1727 | ||
1728 | for (i = 0; i < 32; i++) { | |
1729 | if (!(mask & (1 << i))) | |
1730 | continue; | |
1731 | ||
1732 | switch (1 << i) { | |
1733 | case T3_BLOCK_DMA_RD: | |
1734 | data = REG_RD (pDevice, DmaRead.Mode); | |
1735 | if (cntrl == LM_DISABLE) { | |
1736 | data &= ~DMA_READ_MODE_ENABLE; | |
1737 | REG_WR (pDevice, DmaRead.Mode, data); | |
1738 | for (j = 0; j < MaxWaitCnt; j++) { | |
1739 | if (! | |
1740 | (REG_RD (pDevice, DmaRead.Mode) & | |
1741 | DMA_READ_MODE_ENABLE)) | |
1742 | break; | |
1743 | MM_Wait (10); | |
1744 | } | |
1745 | } else | |
1746 | REG_WR (pDevice, DmaRead.Mode, | |
1747 | data | DMA_READ_MODE_ENABLE); | |
1748 | break; | |
8bde7f77 | 1749 | |
f539edc0 VB |
1750 | case T3_BLOCK_DMA_COMP: |
1751 | data = REG_RD (pDevice, DmaComp.Mode); | |
1752 | if (cntrl == LM_DISABLE) { | |
1753 | data &= ~DMA_COMP_MODE_ENABLE; | |
1754 | REG_WR (pDevice, DmaComp.Mode, data); | |
1755 | for (j = 0; j < MaxWaitCnt; j++) { | |
1756 | if (! | |
1757 | (REG_RD (pDevice, DmaComp.Mode) & | |
1758 | DMA_COMP_MODE_ENABLE)) | |
1759 | break; | |
1760 | MM_Wait (10); | |
1761 | } | |
1762 | } else | |
1763 | REG_WR (pDevice, DmaComp.Mode, | |
1764 | data | DMA_COMP_MODE_ENABLE); | |
1765 | break; | |
8bde7f77 | 1766 | |
f539edc0 VB |
1767 | case T3_BLOCK_RX_BD_INITIATOR: |
1768 | data = REG_RD (pDevice, RcvBdIn.Mode); | |
1769 | if (cntrl == LM_DISABLE) { | |
1770 | data &= ~RCV_BD_IN_MODE_ENABLE; | |
1771 | REG_WR (pDevice, RcvBdIn.Mode, data); | |
1772 | for (j = 0; j < MaxWaitCnt; j++) { | |
1773 | if (! | |
1774 | (REG_RD (pDevice, RcvBdIn.Mode) & | |
1775 | RCV_BD_IN_MODE_ENABLE)) | |
1776 | break; | |
1777 | MM_Wait (10); | |
1778 | } | |
1779 | } else | |
1780 | REG_WR (pDevice, RcvBdIn.Mode, | |
1781 | data | RCV_BD_IN_MODE_ENABLE); | |
1782 | break; | |
8bde7f77 | 1783 | |
f539edc0 VB |
1784 | case T3_BLOCK_RX_BD_COMP: |
1785 | data = REG_RD (pDevice, RcvBdComp.Mode); | |
1786 | if (cntrl == LM_DISABLE) { | |
1787 | data &= ~RCV_BD_COMP_MODE_ENABLE; | |
1788 | REG_WR (pDevice, RcvBdComp.Mode, data); | |
1789 | for (j = 0; j < MaxWaitCnt; j++) { | |
1790 | if (! | |
1791 | (REG_RD (pDevice, RcvBdComp.Mode) & | |
1792 | RCV_BD_COMP_MODE_ENABLE)) | |
1793 | break; | |
1794 | MM_Wait (10); | |
1795 | } | |
1796 | } else | |
1797 | REG_WR (pDevice, RcvBdComp.Mode, | |
1798 | data | RCV_BD_COMP_MODE_ENABLE); | |
1799 | break; | |
8bde7f77 | 1800 | |
f539edc0 VB |
1801 | case T3_BLOCK_DMA_WR: |
1802 | data = REG_RD (pDevice, DmaWrite.Mode); | |
1803 | if (cntrl == LM_DISABLE) { | |
1804 | data &= ~DMA_WRITE_MODE_ENABLE; | |
1805 | REG_WR (pDevice, DmaWrite.Mode, data); | |
1806 | ||
1807 | for (j = 0; j < MaxWaitCnt; j++) { | |
1808 | if (! | |
1809 | (REG_RD (pDevice, DmaWrite.Mode) & | |
1810 | DMA_WRITE_MODE_ENABLE)) | |
1811 | break; | |
1812 | MM_Wait (10); | |
1813 | } | |
1814 | } else | |
1815 | REG_WR (pDevice, DmaWrite.Mode, | |
1816 | data | DMA_WRITE_MODE_ENABLE); | |
1817 | break; | |
8bde7f77 | 1818 | |
f539edc0 VB |
1819 | case T3_BLOCK_MSI_HANDLER: |
1820 | data = REG_RD (pDevice, Msi.Mode); | |
1821 | if (cntrl == LM_DISABLE) { | |
1822 | data &= ~MSI_MODE_ENABLE; | |
1823 | REG_WR (pDevice, Msi.Mode, data); | |
1824 | for (j = 0; j < MaxWaitCnt; j++) { | |
1825 | if (! | |
1826 | (REG_RD (pDevice, Msi.Mode) & | |
1827 | MSI_MODE_ENABLE)) | |
1828 | break; | |
1829 | MM_Wait (10); | |
1830 | } | |
1831 | } else | |
1832 | REG_WR (pDevice, Msi.Mode, | |
1833 | data | MSI_MODE_ENABLE); | |
1834 | break; | |
8bde7f77 | 1835 | |
f539edc0 VB |
1836 | case T3_BLOCK_RX_LIST_PLMT: |
1837 | data = REG_RD (pDevice, RcvListPlmt.Mode); | |
1838 | if (cntrl == LM_DISABLE) { | |
1839 | data &= ~RCV_LIST_PLMT_MODE_ENABLE; | |
1840 | REG_WR (pDevice, RcvListPlmt.Mode, data); | |
1841 | for (j = 0; j < MaxWaitCnt; j++) { | |
1842 | if (! | |
1843 | (REG_RD (pDevice, RcvListPlmt.Mode) | |
1844 | & RCV_LIST_PLMT_MODE_ENABLE)) | |
1845 | break; | |
1846 | MM_Wait (10); | |
1847 | } | |
1848 | } else | |
1849 | REG_WR (pDevice, RcvListPlmt.Mode, | |
1850 | data | RCV_LIST_PLMT_MODE_ENABLE); | |
1851 | break; | |
8bde7f77 | 1852 | |
f539edc0 VB |
1853 | case T3_BLOCK_RX_LIST_SELECTOR: |
1854 | data = REG_RD (pDevice, RcvListSel.Mode); | |
1855 | if (cntrl == LM_DISABLE) { | |
1856 | data &= ~RCV_LIST_SEL_MODE_ENABLE; | |
1857 | REG_WR (pDevice, RcvListSel.Mode, data); | |
1858 | for (j = 0; j < MaxWaitCnt; j++) { | |
1859 | if (! | |
1860 | (REG_RD (pDevice, RcvListSel.Mode) & | |
1861 | RCV_LIST_SEL_MODE_ENABLE)) | |
1862 | break; | |
1863 | MM_Wait (10); | |
1864 | } | |
1865 | } else | |
1866 | REG_WR (pDevice, RcvListSel.Mode, | |
1867 | data | RCV_LIST_SEL_MODE_ENABLE); | |
1868 | break; | |
8bde7f77 | 1869 | |
f539edc0 VB |
1870 | case T3_BLOCK_RX_DATA_INITIATOR: |
1871 | data = REG_RD (pDevice, RcvDataBdIn.Mode); | |
1872 | if (cntrl == LM_DISABLE) { | |
1873 | data &= ~RCV_DATA_BD_IN_MODE_ENABLE; | |
1874 | REG_WR (pDevice, RcvDataBdIn.Mode, data); | |
1875 | for (j = 0; j < MaxWaitCnt; j++) { | |
1876 | if (! | |
1877 | (REG_RD (pDevice, RcvDataBdIn.Mode) | |
1878 | & RCV_DATA_BD_IN_MODE_ENABLE)) | |
1879 | break; | |
1880 | MM_Wait (10); | |
1881 | } | |
1882 | } else | |
1883 | REG_WR (pDevice, RcvDataBdIn.Mode, | |
1884 | data | RCV_DATA_BD_IN_MODE_ENABLE); | |
1885 | break; | |
8bde7f77 | 1886 | |
f539edc0 VB |
1887 | case T3_BLOCK_RX_DATA_COMP: |
1888 | data = REG_RD (pDevice, RcvDataComp.Mode); | |
1889 | if (cntrl == LM_DISABLE) { | |
1890 | data &= ~RCV_DATA_COMP_MODE_ENABLE; | |
1891 | REG_WR (pDevice, RcvDataComp.Mode, data); | |
1892 | for (j = 0; j < MaxWaitCnt; j++) { | |
1893 | if (! | |
1894 | (REG_RD (pDevice, RcvDataBdIn.Mode) | |
1895 | & RCV_DATA_COMP_MODE_ENABLE)) | |
1896 | break; | |
1897 | MM_Wait (10); | |
1898 | } | |
1899 | } else | |
1900 | REG_WR (pDevice, RcvDataComp.Mode, | |
1901 | data | RCV_DATA_COMP_MODE_ENABLE); | |
1902 | break; | |
8bde7f77 | 1903 | |
f539edc0 VB |
1904 | case T3_BLOCK_HOST_COALESING: |
1905 | data = REG_RD (pDevice, HostCoalesce.Mode); | |
1906 | if (cntrl == LM_DISABLE) { | |
1907 | data &= ~HOST_COALESCE_ENABLE; | |
1908 | REG_WR (pDevice, HostCoalesce.Mode, data); | |
1909 | for (j = 0; j < MaxWaitCnt; j++) { | |
1910 | if (! | |
1911 | (REG_RD (pDevice, SndBdIn.Mode) & | |
1912 | HOST_COALESCE_ENABLE)) | |
1913 | break; | |
1914 | MM_Wait (10); | |
1915 | } | |
1916 | } else | |
1917 | REG_WR (pDevice, HostCoalesce.Mode, | |
1918 | data | HOST_COALESCE_ENABLE); | |
1919 | break; | |
8bde7f77 | 1920 | |
f539edc0 VB |
1921 | case T3_BLOCK_MAC_RX_ENGINE: |
1922 | if (cntrl == LM_DISABLE) { | |
1923 | pDevice->RxMode &= ~RX_MODE_ENABLE; | |
1924 | REG_WR (pDevice, MacCtrl.RxMode, | |
1925 | pDevice->RxMode); | |
1926 | for (j = 0; j < MaxWaitCnt; j++) { | |
1927 | if (! | |
1928 | (REG_RD (pDevice, MacCtrl.RxMode) & | |
1929 | RX_MODE_ENABLE)) { | |
1930 | break; | |
1931 | } | |
1932 | MM_Wait (10); | |
1933 | } | |
1934 | } else { | |
1935 | pDevice->RxMode |= RX_MODE_ENABLE; | |
1936 | REG_WR (pDevice, MacCtrl.RxMode, | |
1937 | pDevice->RxMode); | |
8bde7f77 | 1938 | } |
f539edc0 | 1939 | break; |
8bde7f77 | 1940 | |
f539edc0 VB |
1941 | case T3_BLOCK_MBUF_CLUSTER_FREE: |
1942 | data = REG_RD (pDevice, MbufClusterFree.Mode); | |
1943 | if (cntrl == LM_DISABLE) { | |
1944 | data &= ~MBUF_CLUSTER_FREE_MODE_ENABLE; | |
1945 | REG_WR (pDevice, MbufClusterFree.Mode, data); | |
1946 | for (j = 0; j < MaxWaitCnt; j++) { | |
1947 | if (! | |
1948 | (REG_RD | |
1949 | (pDevice, | |
1950 | MbufClusterFree. | |
1951 | Mode) & | |
1952 | MBUF_CLUSTER_FREE_MODE_ENABLE)) | |
1953 | break; | |
1954 | MM_Wait (10); | |
1955 | } | |
1956 | } else | |
1957 | REG_WR (pDevice, MbufClusterFree.Mode, | |
1958 | data | MBUF_CLUSTER_FREE_MODE_ENABLE); | |
1959 | break; | |
8bde7f77 | 1960 | |
f539edc0 VB |
1961 | case T3_BLOCK_SEND_BD_INITIATOR: |
1962 | data = REG_RD (pDevice, SndBdIn.Mode); | |
1963 | if (cntrl == LM_DISABLE) { | |
1964 | data &= ~SND_BD_IN_MODE_ENABLE; | |
1965 | REG_WR (pDevice, SndBdIn.Mode, data); | |
1966 | for (j = 0; j < MaxWaitCnt; j++) { | |
1967 | if (! | |
1968 | (REG_RD (pDevice, SndBdIn.Mode) & | |
1969 | SND_BD_IN_MODE_ENABLE)) | |
1970 | break; | |
1971 | MM_Wait (10); | |
1972 | } | |
1973 | } else | |
1974 | REG_WR (pDevice, SndBdIn.Mode, | |
1975 | data | SND_BD_IN_MODE_ENABLE); | |
1976 | break; | |
8bde7f77 | 1977 | |
f539edc0 VB |
1978 | case T3_BLOCK_SEND_BD_COMP: |
1979 | data = REG_RD (pDevice, SndBdComp.Mode); | |
1980 | if (cntrl == LM_DISABLE) { | |
1981 | data &= ~SND_BD_COMP_MODE_ENABLE; | |
1982 | REG_WR (pDevice, SndBdComp.Mode, data); | |
1983 | for (j = 0; j < MaxWaitCnt; j++) { | |
1984 | if (! | |
1985 | (REG_RD (pDevice, SndBdComp.Mode) & | |
1986 | SND_BD_COMP_MODE_ENABLE)) | |
1987 | break; | |
1988 | MM_Wait (10); | |
1989 | } | |
1990 | } else | |
1991 | REG_WR (pDevice, SndBdComp.Mode, | |
1992 | data | SND_BD_COMP_MODE_ENABLE); | |
1993 | break; | |
8bde7f77 | 1994 | |
f539edc0 VB |
1995 | case T3_BLOCK_SEND_BD_SELECTOR: |
1996 | data = REG_RD (pDevice, SndBdSel.Mode); | |
1997 | if (cntrl == LM_DISABLE) { | |
1998 | data &= ~SND_BD_SEL_MODE_ENABLE; | |
1999 | REG_WR (pDevice, SndBdSel.Mode, data); | |
2000 | for (j = 0; j < MaxWaitCnt; j++) { | |
2001 | if (! | |
2002 | (REG_RD (pDevice, SndBdSel.Mode) & | |
2003 | SND_BD_SEL_MODE_ENABLE)) | |
2004 | break; | |
2005 | MM_Wait (10); | |
2006 | } | |
2007 | } else | |
2008 | REG_WR (pDevice, SndBdSel.Mode, | |
2009 | data | SND_BD_SEL_MODE_ENABLE); | |
2010 | break; | |
8bde7f77 | 2011 | |
f539edc0 VB |
2012 | case T3_BLOCK_SEND_DATA_INITIATOR: |
2013 | data = REG_RD (pDevice, SndDataIn.Mode); | |
2014 | if (cntrl == LM_DISABLE) { | |
2015 | data &= ~T3_SND_DATA_IN_MODE_ENABLE; | |
2016 | REG_WR (pDevice, SndDataIn.Mode, data); | |
2017 | for (j = 0; j < MaxWaitCnt; j++) { | |
2018 | if (! | |
2019 | (REG_RD (pDevice, SndDataIn.Mode) & | |
2020 | T3_SND_DATA_IN_MODE_ENABLE)) | |
2021 | break; | |
2022 | MM_Wait (10); | |
2023 | } | |
2024 | } else | |
2025 | REG_WR (pDevice, SndDataIn.Mode, | |
2026 | data | T3_SND_DATA_IN_MODE_ENABLE); | |
2027 | break; | |
8bde7f77 | 2028 | |
f539edc0 VB |
2029 | case T3_BLOCK_SEND_DATA_COMP: |
2030 | data = REG_RD (pDevice, SndDataComp.Mode); | |
2031 | if (cntrl == LM_DISABLE) { | |
2032 | data &= ~SND_DATA_COMP_MODE_ENABLE; | |
2033 | REG_WR (pDevice, SndDataComp.Mode, data); | |
2034 | for (j = 0; j < MaxWaitCnt; j++) { | |
2035 | if (! | |
2036 | (REG_RD (pDevice, SndDataComp.Mode) | |
2037 | & SND_DATA_COMP_MODE_ENABLE)) | |
2038 | break; | |
2039 | MM_Wait (10); | |
2040 | } | |
2041 | } else | |
2042 | REG_WR (pDevice, SndDataComp.Mode, | |
2043 | data | SND_DATA_COMP_MODE_ENABLE); | |
2044 | break; | |
8bde7f77 | 2045 | |
f539edc0 VB |
2046 | case T3_BLOCK_MAC_TX_ENGINE: |
2047 | if (cntrl == LM_DISABLE) { | |
2048 | pDevice->TxMode &= ~TX_MODE_ENABLE; | |
2049 | REG_WR (pDevice, MacCtrl.TxMode, | |
2050 | pDevice->TxMode); | |
2051 | for (j = 0; j < MaxWaitCnt; j++) { | |
2052 | if (! | |
2053 | (REG_RD (pDevice, MacCtrl.TxMode) & | |
2054 | TX_MODE_ENABLE)) | |
2055 | break; | |
2056 | MM_Wait (10); | |
2057 | } | |
2058 | } else { | |
2059 | pDevice->TxMode |= TX_MODE_ENABLE; | |
2060 | REG_WR (pDevice, MacCtrl.TxMode, | |
2061 | pDevice->TxMode); | |
2062 | } | |
2063 | break; | |
8bde7f77 | 2064 | |
f539edc0 VB |
2065 | case T3_BLOCK_MEM_ARBITOR: |
2066 | data = REG_RD (pDevice, MemArbiter.Mode); | |
2067 | if (cntrl == LM_DISABLE) { | |
2068 | data &= ~T3_MEM_ARBITER_MODE_ENABLE; | |
2069 | REG_WR (pDevice, MemArbiter.Mode, data); | |
2070 | for (j = 0; j < MaxWaitCnt; j++) { | |
2071 | if (! | |
2072 | (REG_RD (pDevice, MemArbiter.Mode) & | |
2073 | T3_MEM_ARBITER_MODE_ENABLE)) | |
2074 | break; | |
2075 | MM_Wait (10); | |
2076 | } | |
2077 | } else | |
2078 | REG_WR (pDevice, MemArbiter.Mode, | |
2079 | data | T3_MEM_ARBITER_MODE_ENABLE); | |
2080 | break; | |
8bde7f77 | 2081 | |
f539edc0 VB |
2082 | case T3_BLOCK_MBUF_MANAGER: |
2083 | data = REG_RD (pDevice, BufMgr.Mode); | |
2084 | if (cntrl == LM_DISABLE) { | |
2085 | data &= ~BUFMGR_MODE_ENABLE; | |
2086 | REG_WR (pDevice, BufMgr.Mode, data); | |
2087 | for (j = 0; j < MaxWaitCnt; j++) { | |
2088 | if (! | |
2089 | (REG_RD (pDevice, BufMgr.Mode) & | |
2090 | BUFMGR_MODE_ENABLE)) | |
2091 | break; | |
2092 | MM_Wait (10); | |
2093 | } | |
2094 | } else | |
2095 | REG_WR (pDevice, BufMgr.Mode, | |
2096 | data | BUFMGR_MODE_ENABLE); | |
2097 | break; | |
8bde7f77 | 2098 | |
f539edc0 VB |
2099 | case T3_BLOCK_MAC_GLOBAL: |
2100 | if (cntrl == LM_DISABLE) { | |
2101 | pDevice->MacMode &= ~(MAC_MODE_ENABLE_TDE | | |
2102 | MAC_MODE_ENABLE_RDE | | |
2103 | MAC_MODE_ENABLE_FHDE); | |
2104 | } else { | |
2105 | pDevice->MacMode |= (MAC_MODE_ENABLE_TDE | | |
2106 | MAC_MODE_ENABLE_RDE | | |
2107 | MAC_MODE_ENABLE_FHDE); | |
2108 | } | |
2109 | REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode); | |
2110 | break; | |
8bde7f77 | 2111 | |
f539edc0 VB |
2112 | default: |
2113 | return LM_STATUS_FAILURE; | |
2114 | } /* switch */ | |
8bde7f77 | 2115 | |
f539edc0 VB |
2116 | if (j >= MaxWaitCnt) { |
2117 | return LM_STATUS_FAILURE; | |
2118 | } | |
8bde7f77 | 2119 | } |
c609719b | 2120 | |
f539edc0 | 2121 | return LM_STATUS_SUCCESS; |
c609719b WD |
2122 | } |
2123 | ||
2124 | /******************************************************************************/ | |
2125 | /* Description: */ | |
2126 | /* This function reinitializes the adapter. */ | |
2127 | /* */ | |
2128 | /* Return: */ | |
2129 | /* LM_STATUS_SUCCESS */ | |
2130 | /******************************************************************************/ | |
f539edc0 | 2131 | LM_STATUS LM_ResetAdapter (PLM_DEVICE_BLOCK pDevice) |
c609719b | 2132 | { |
f539edc0 VB |
2133 | LM_UINT32 Value32; |
2134 | LM_UINT16 Value16; | |
2135 | LM_UINT32 j, k; | |
c609719b | 2136 | |
f539edc0 VB |
2137 | /* Disable interrupt. */ |
2138 | LM_DisableInterrupt (pDevice); | |
c609719b | 2139 | |
f539edc0 VB |
2140 | /* May get a spurious interrupt */ |
2141 | pDevice->pStatusBlkVirt->Status = STATUS_BLOCK_UPDATED; | |
c609719b | 2142 | |
f539edc0 VB |
2143 | /* Disable transmit and receive DMA engines. Abort all pending requests. */ |
2144 | if (pDevice->InitDone) { | |
2145 | LM_Abort (pDevice); | |
2146 | } | |
c609719b | 2147 | |
f539edc0 | 2148 | pDevice->ShuttingDown = FALSE; |
c609719b | 2149 | |
f539edc0 | 2150 | LM_ResetChip (pDevice); |
c609719b | 2151 | |
f539edc0 VB |
2152 | /* Bug: Athlon fix for B3 silicon only. This bit does not do anything */ |
2153 | /* in other chip revisions. */ | |
2154 | if (pDevice->DelayPciGrant) { | |
2155 | Value32 = REG_RD (pDevice, PciCfg.ClockCtrl); | |
2156 | REG_WR (pDevice, PciCfg.ClockCtrl, Value32 | BIT_31); | |
2157 | } | |
c609719b | 2158 | |
f539edc0 VB |
2159 | if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0) { |
2160 | if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE)) { | |
2161 | Value32 = REG_RD (pDevice, PciCfg.PciState); | |
2162 | Value32 |= T3_PCI_STATE_RETRY_SAME_DMA; | |
2163 | REG_WR (pDevice, PciCfg.PciState, Value32); | |
2164 | } | |
2165 | } | |
2166 | ||
2167 | /* Enable TaggedStatus mode. */ | |
2168 | if (pDevice->UseTaggedStatus) { | |
2169 | pDevice->MiscHostCtrl |= | |
2170 | MISC_HOST_CTRL_ENABLE_TAGGED_STATUS_MODE; | |
2171 | } | |
2172 | ||
2173 | /* Restore PCI configuration registers. */ | |
2174 | MM_WriteConfig32 (pDevice, PCI_CACHE_LINE_SIZE_REG, | |
2175 | pDevice->SavedCacheLineReg); | |
2176 | MM_WriteConfig32 (pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG, | |
2177 | (pDevice->SubsystemId << 16) | pDevice-> | |
2178 | SubsystemVendorId); | |
2179 | ||
2180 | /* Clear the statistics block. */ | |
2181 | for (j = 0x0300; j < 0x0b00; j++) { | |
2182 | MEM_WR_OFFSET (pDevice, j, 0); | |
2183 | } | |
2184 | ||
2185 | /* Initialize the statistis Block */ | |
2186 | pDevice->pStatusBlkVirt->Status = 0; | |
2187 | pDevice->pStatusBlkVirt->RcvStdConIdx = 0; | |
2188 | pDevice->pStatusBlkVirt->RcvJumboConIdx = 0; | |
2189 | pDevice->pStatusBlkVirt->RcvMiniConIdx = 0; | |
2190 | ||
2191 | for (j = 0; j < 16; j++) { | |
2192 | pDevice->pStatusBlkVirt->Idx[j].RcvProdIdx = 0; | |
2193 | pDevice->pStatusBlkVirt->Idx[j].SendConIdx = 0; | |
2194 | } | |
2195 | ||
2196 | for (k = 0; k < T3_STD_RCV_RCB_ENTRY_COUNT; k++) { | |
2197 | pDevice->pRxStdBdVirt[k].HostAddr.High = 0; | |
2198 | pDevice->pRxStdBdVirt[k].HostAddr.Low = 0; | |
2199 | } | |
c609719b WD |
2200 | |
2201 | #if T3_JUMBO_RCV_RCB_ENTRY_COUNT | |
f539edc0 VB |
2202 | /* Receive jumbo BD buffer. */ |
2203 | for (k = 0; k < T3_JUMBO_RCV_RCB_ENTRY_COUNT; k++) { | |
2204 | pDevice->pRxJumboBdVirt[k].HostAddr.High = 0; | |
2205 | pDevice->pRxJumboBdVirt[k].HostAddr.Low = 0; | |
2206 | } | |
c609719b WD |
2207 | #endif |
2208 | ||
f539edc0 | 2209 | REG_WR (pDevice, PciCfg.DmaReadWriteCtrl, pDevice->DmaReadWriteCtrl); |
c609719b | 2210 | |
f539edc0 VB |
2211 | /* GRC mode control register. */ |
2212 | #ifdef BIG_ENDIAN_PCI /* Jimmy, this ifdef block deleted in new code! */ | |
2213 | Value32 = | |
2214 | GRC_MODE_WORD_SWAP_DATA | | |
2215 | GRC_MODE_WORD_SWAP_NON_FRAME_DATA | | |
2216 | GRC_MODE_INT_ON_MAC_ATTN | GRC_MODE_HOST_STACK_UP; | |
c609719b | 2217 | #else |
f539edc0 VB |
2218 | /* No CPU Swap modes for PCI IO */ |
2219 | Value32 = | |
c609719b | 2220 | #ifdef BIG_ENDIAN_HOST |
f539edc0 VB |
2221 | GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | |
2222 | GRC_MODE_WORD_SWAP_NON_FRAME_DATA | | |
2223 | GRC_MODE_BYTE_SWAP_DATA | GRC_MODE_WORD_SWAP_DATA | | |
c609719b | 2224 | #else |
f539edc0 VB |
2225 | GRC_MODE_WORD_SWAP_NON_FRAME_DATA | |
2226 | GRC_MODE_BYTE_SWAP_DATA | GRC_MODE_WORD_SWAP_DATA | | |
c609719b | 2227 | #endif |
f539edc0 VB |
2228 | GRC_MODE_INT_ON_MAC_ATTN | GRC_MODE_HOST_STACK_UP; |
2229 | #endif /* !BIG_ENDIAN_PCI */ | |
2230 | ||
2231 | /* Configure send BD mode. */ | |
2232 | if (pDevice->NicSendBd == FALSE) { | |
2233 | Value32 |= GRC_MODE_HOST_SEND_BDS; | |
2234 | } else { | |
2235 | Value32 |= GRC_MODE_4X_NIC_BASED_SEND_RINGS; | |
8bde7f77 | 2236 | } |
f539edc0 VB |
2237 | |
2238 | /* Configure pseudo checksum mode. */ | |
2239 | if (pDevice->NoTxPseudoHdrChksum) { | |
2240 | Value32 |= GRC_MODE_TX_NO_PSEUDO_HEADER_CHKSUM; | |
8bde7f77 | 2241 | } |
f539edc0 VB |
2242 | |
2243 | if (pDevice->NoRxPseudoHdrChksum) { | |
2244 | Value32 |= GRC_MODE_RX_NO_PSEUDO_HEADER_CHKSUM; | |
8bde7f77 | 2245 | } |
f539edc0 VB |
2246 | |
2247 | REG_WR (pDevice, Grc.Mode, Value32); | |
2248 | ||
2249 | /* Setup the timer prescalar register. */ | |
8ed44d91 | 2250 | REG_WR (pDevice, Grc.MiscCfg, 65 << 1); /* Clock is alwasy 66MHz. */ |
f539edc0 VB |
2251 | |
2252 | /* Set up the MBUF pool base address and size. */ | |
2253 | REG_WR (pDevice, BufMgr.MbufPoolAddr, pDevice->MbufBase); | |
2254 | REG_WR (pDevice, BufMgr.MbufPoolSize, pDevice->MbufSize); | |
2255 | ||
2256 | /* Set up the DMA descriptor pool base address and size. */ | |
2257 | REG_WR (pDevice, BufMgr.DmaDescPoolAddr, T3_NIC_DMA_DESC_POOL_ADDR); | |
2258 | REG_WR (pDevice, BufMgr.DmaDescPoolSize, T3_NIC_DMA_DESC_POOL_SIZE); | |
2259 | ||
2260 | /* Configure MBUF and Threshold watermarks */ | |
2261 | /* Configure the DMA read MBUF low water mark. */ | |
2262 | if (pDevice->DmaMbufLowMark) { | |
2263 | REG_WR (pDevice, BufMgr.MbufReadDmaLowWaterMark, | |
2264 | pDevice->DmaMbufLowMark); | |
2265 | } else { | |
2266 | if (pDevice->TxMtu < MAX_ETHERNET_PACKET_BUFFER_SIZE) { | |
2267 | REG_WR (pDevice, BufMgr.MbufReadDmaLowWaterMark, | |
2268 | T3_DEF_DMA_MBUF_LOW_WMARK); | |
2269 | } else { | |
2270 | REG_WR (pDevice, BufMgr.MbufReadDmaLowWaterMark, | |
2271 | T3_DEF_DMA_MBUF_LOW_WMARK_JUMBO); | |
2272 | } | |
8bde7f77 | 2273 | } |
c609719b | 2274 | |
f539edc0 VB |
2275 | /* Configure the MAC Rx MBUF low water mark. */ |
2276 | if (pDevice->RxMacMbufLowMark) { | |
2277 | REG_WR (pDevice, BufMgr.MbufMacRxLowWaterMark, | |
2278 | pDevice->RxMacMbufLowMark); | |
2279 | } else { | |
2280 | if (pDevice->TxMtu < MAX_ETHERNET_PACKET_BUFFER_SIZE) { | |
2281 | REG_WR (pDevice, BufMgr.MbufMacRxLowWaterMark, | |
2282 | T3_DEF_RX_MAC_MBUF_LOW_WMARK); | |
2283 | } else { | |
2284 | REG_WR (pDevice, BufMgr.MbufMacRxLowWaterMark, | |
2285 | T3_DEF_RX_MAC_MBUF_LOW_WMARK_JUMBO); | |
2286 | } | |
2287 | } | |
c609719b | 2288 | |
f539edc0 VB |
2289 | /* Configure the MBUF high water mark. */ |
2290 | if (pDevice->MbufHighMark) { | |
2291 | REG_WR (pDevice, BufMgr.MbufHighWaterMark, | |
2292 | pDevice->MbufHighMark); | |
2293 | } else { | |
2294 | if (pDevice->TxMtu < MAX_ETHERNET_PACKET_BUFFER_SIZE) { | |
2295 | REG_WR (pDevice, BufMgr.MbufHighWaterMark, | |
2296 | T3_DEF_MBUF_HIGH_WMARK); | |
2297 | } else { | |
2298 | REG_WR (pDevice, BufMgr.MbufHighWaterMark, | |
2299 | T3_DEF_MBUF_HIGH_WMARK_JUMBO); | |
2300 | } | |
2301 | } | |
c609719b | 2302 | |
f539edc0 VB |
2303 | REG_WR (pDevice, BufMgr.DmaLowWaterMark, T3_DEF_DMA_DESC_LOW_WMARK); |
2304 | REG_WR (pDevice, BufMgr.DmaHighWaterMark, T3_DEF_DMA_DESC_HIGH_WMARK); | |
c609719b | 2305 | |
f539edc0 VB |
2306 | /* Enable buffer manager. */ |
2307 | REG_WR (pDevice, BufMgr.Mode, | |
2308 | BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE); | |
2309 | ||
2310 | for (j = 0; j < 2000; j++) { | |
2311 | if (REG_RD (pDevice, BufMgr.Mode) & BUFMGR_MODE_ENABLE) | |
2312 | break; | |
2313 | MM_Wait (10); | |
2314 | } | |
2315 | ||
2316 | if (j >= 2000) { | |
2317 | return LM_STATUS_FAILURE; | |
2318 | } | |
c609719b | 2319 | |
f539edc0 VB |
2320 | /* Enable the FTQs. */ |
2321 | REG_WR (pDevice, Ftq.Reset, 0xffffffff); | |
2322 | REG_WR (pDevice, Ftq.Reset, 0); | |
c609719b | 2323 | |
f539edc0 VB |
2324 | /* Wait until FTQ is ready */ |
2325 | for (j = 0; j < 2000; j++) { | |
2326 | if (REG_RD (pDevice, Ftq.Reset) == 0) | |
2327 | break; | |
2328 | MM_Wait (10); | |
2329 | } | |
c609719b | 2330 | |
f539edc0 VB |
2331 | if (j >= 2000) { |
2332 | return LM_STATUS_FAILURE; | |
2333 | } | |
c609719b | 2334 | |
f539edc0 VB |
2335 | /* Initialize the Standard Receive RCB. */ |
2336 | REG_WR (pDevice, RcvDataBdIn.StdRcvRcb.HostRingAddr.High, | |
2337 | pDevice->RxStdBdPhy.High); | |
2338 | REG_WR (pDevice, RcvDataBdIn.StdRcvRcb.HostRingAddr.Low, | |
2339 | pDevice->RxStdBdPhy.Low); | |
2340 | REG_WR (pDevice, RcvDataBdIn.StdRcvRcb.u.MaxLen_Flags, | |
2341 | MAX_STD_RCV_BUFFER_SIZE << 16); | |
c609719b | 2342 | |
f539edc0 VB |
2343 | /* Initialize the Jumbo Receive RCB. */ |
2344 | REG_WR (pDevice, RcvDataBdIn.JumboRcvRcb.u.MaxLen_Flags, | |
2345 | T3_RCB_FLAG_RING_DISABLED); | |
c609719b | 2346 | #if T3_JUMBO_RCV_RCB_ENTRY_COUNT |
f539edc0 VB |
2347 | REG_WR (pDevice, RcvDataBdIn.JumboRcvRcb.HostRingAddr.High, |
2348 | pDevice->RxJumboBdPhy.High); | |
2349 | REG_WR (pDevice, RcvDataBdIn.JumboRcvRcb.HostRingAddr.Low, | |
2350 | pDevice->RxJumboBdPhy.Low); | |
c609719b | 2351 | |
f539edc0 | 2352 | REG_WR (pDevice, RcvDataBdIn.JumboRcvRcb.u.MaxLen_Flags, 0); |
c609719b | 2353 | |
f539edc0 | 2354 | #endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ |
c609719b | 2355 | |
f539edc0 VB |
2356 | /* Initialize the Mini Receive RCB. */ |
2357 | REG_WR (pDevice, RcvDataBdIn.MiniRcvRcb.u.MaxLen_Flags, | |
2358 | T3_RCB_FLAG_RING_DISABLED); | |
c609719b | 2359 | |
f539edc0 VB |
2360 | { |
2361 | REG_WR (pDevice, RcvDataBdIn.StdRcvRcb.NicRingAddr, | |
2362 | (LM_UINT32) T3_NIC_STD_RCV_BUFFER_DESC_ADDR); | |
2363 | REG_WR (pDevice, RcvDataBdIn.JumboRcvRcb.NicRingAddr, | |
2364 | (LM_UINT32) T3_NIC_JUMBO_RCV_BUFFER_DESC_ADDR); | |
2365 | } | |
2366 | ||
2367 | /* Receive BD Ring replenish threshold. */ | |
2368 | REG_WR (pDevice, RcvBdIn.StdRcvThreshold, pDevice->RxStdDescCnt / 8); | |
2369 | #if T3_JUMBO_RCV_RCB_ENTRY_COUNT | |
2370 | REG_WR (pDevice, RcvBdIn.JumboRcvThreshold, | |
2371 | pDevice->RxJumboDescCnt / 8); | |
2372 | #endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ | |
2373 | ||
2374 | /* Disable all the unused rings. */ | |
2375 | for (j = 0; j < T3_MAX_SEND_RCB_COUNT; j++) { | |
2376 | MEM_WR (pDevice, SendRcb[j].u.MaxLen_Flags, | |
2377 | T3_RCB_FLAG_RING_DISABLED); | |
2378 | } /* for */ | |
2379 | ||
2380 | /* Initialize the indices. */ | |
2381 | pDevice->SendProdIdx = 0; | |
2382 | pDevice->SendConIdx = 0; | |
2383 | ||
2384 | MB_REG_WR (pDevice, Mailbox.SendHostProdIdx[0].Low, 0); | |
2385 | MB_REG_WR (pDevice, Mailbox.SendNicProdIdx[0].Low, 0); | |
2386 | ||
2387 | /* Set up host or NIC based send RCB. */ | |
2388 | if (pDevice->NicSendBd == FALSE) { | |
2389 | MEM_WR (pDevice, SendRcb[0].HostRingAddr.High, | |
2390 | pDevice->SendBdPhy.High); | |
2391 | MEM_WR (pDevice, SendRcb[0].HostRingAddr.Low, | |
2392 | pDevice->SendBdPhy.Low); | |
2393 | ||
2394 | /* Set up the NIC ring address in the RCB. */ | |
2395 | MEM_WR (pDevice, SendRcb[0].NicRingAddr, | |
2396 | T3_NIC_SND_BUFFER_DESC_ADDR); | |
2397 | ||
2398 | /* Setup the RCB. */ | |
2399 | MEM_WR (pDevice, SendRcb[0].u.MaxLen_Flags, | |
2400 | T3_SEND_RCB_ENTRY_COUNT << 16); | |
2401 | ||
2402 | for (k = 0; k < T3_SEND_RCB_ENTRY_COUNT; k++) { | |
2403 | pDevice->pSendBdVirt[k].HostAddr.High = 0; | |
2404 | pDevice->pSendBdVirt[k].HostAddr.Low = 0; | |
2405 | } | |
2406 | } else { | |
2407 | MEM_WR (pDevice, SendRcb[0].HostRingAddr.High, 0); | |
2408 | MEM_WR (pDevice, SendRcb[0].HostRingAddr.Low, 0); | |
2409 | MEM_WR (pDevice, SendRcb[0].NicRingAddr, | |
2410 | pDevice->SendBdPhy.Low); | |
2411 | ||
2412 | for (k = 0; k < T3_SEND_RCB_ENTRY_COUNT; k++) { | |
2413 | __raw_writel (0, | |
2414 | &(pDevice->pSendBdVirt[k].HostAddr.High)); | |
2415 | __raw_writel (0, | |
2416 | &(pDevice->pSendBdVirt[k].HostAddr.Low)); | |
2417 | __raw_writel (0, | |
2418 | &(pDevice->pSendBdVirt[k].u1.Len_Flags)); | |
2419 | pDevice->ShadowSendBd[k].HostAddr.High = 0; | |
2420 | pDevice->ShadowSendBd[k].u1.Len_Flags = 0; | |
2421 | } | |
2422 | } | |
2423 | atomic_set (&pDevice->SendBdLeft, T3_SEND_RCB_ENTRY_COUNT - 1); | |
2424 | ||
2425 | /* Configure the receive return rings. */ | |
2426 | for (j = 0; j < T3_MAX_RCV_RETURN_RCB_COUNT; j++) { | |
2427 | MEM_WR (pDevice, RcvRetRcb[j].u.MaxLen_Flags, | |
2428 | T3_RCB_FLAG_RING_DISABLED); | |
2429 | } | |
2430 | ||
2431 | pDevice->RcvRetConIdx = 0; | |
2432 | ||
2433 | MEM_WR (pDevice, RcvRetRcb[0].HostRingAddr.High, | |
2434 | pDevice->RcvRetBdPhy.High); | |
2435 | MEM_WR (pDevice, RcvRetRcb[0].HostRingAddr.Low, | |
2436 | pDevice->RcvRetBdPhy.Low); | |
c609719b | 2437 | |
8bde7f77 | 2438 | /* Set up the NIC ring address in the RCB. */ |
f539edc0 VB |
2439 | /* Not very clear from the spec. I am guessing that for Receive */ |
2440 | /* Return Ring, NicRingAddr is not used. */ | |
2441 | MEM_WR (pDevice, RcvRetRcb[0].NicRingAddr, 0); | |
c609719b | 2442 | |
8bde7f77 | 2443 | /* Setup the RCB. */ |
f539edc0 VB |
2444 | MEM_WR (pDevice, RcvRetRcb[0].u.MaxLen_Flags, |
2445 | T3_RCV_RETURN_RCB_ENTRY_COUNT << 16); | |
c609719b | 2446 | |
f539edc0 VB |
2447 | /* Reinitialize RX ring producer index */ |
2448 | MB_REG_WR (pDevice, Mailbox.RcvStdProdIdx.Low, 0); | |
2449 | MB_REG_WR (pDevice, Mailbox.RcvJumboProdIdx.Low, 0); | |
2450 | MB_REG_WR (pDevice, Mailbox.RcvMiniProdIdx.Low, 0); | |
c609719b WD |
2451 | |
2452 | #if T3_JUMBO_RCV_RCB_ENTRY_COUNT | |
f539edc0 VB |
2453 | pDevice->RxJumboProdIdx = 0; |
2454 | pDevice->RxJumboQueuedCnt = 0; | |
c609719b WD |
2455 | #endif |
2456 | ||
f539edc0 VB |
2457 | /* Reinitialize our copy of the indices. */ |
2458 | pDevice->RxStdProdIdx = 0; | |
2459 | pDevice->RxStdQueuedCnt = 0; | |
c609719b WD |
2460 | |
2461 | #if T3_JUMBO_RCV_ENTRY_COUNT | |
f539edc0 VB |
2462 | pDevice->RxJumboProdIdx = 0; |
2463 | #endif /* T3_JUMBO_RCV_ENTRY_COUNT */ | |
2464 | ||
2465 | /* Configure the MAC address. */ | |
c4b8762f | 2466 | LM_SetMacAddress (pDevice); |
f539edc0 VB |
2467 | |
2468 | /* Initialize the transmit random backoff seed. */ | |
2469 | Value32 = (pDevice->NodeAddress[0] + pDevice->NodeAddress[1] + | |
2470 | pDevice->NodeAddress[2] + pDevice->NodeAddress[3] + | |
2471 | pDevice->NodeAddress[4] + pDevice->NodeAddress[5]) & | |
2472 | MAC_TX_BACKOFF_SEED_MASK; | |
2473 | REG_WR (pDevice, MacCtrl.TxBackoffSeed, Value32); | |
2474 | ||
2475 | /* Receive MTU. Frames larger than the MTU is marked as oversized. */ | |
2476 | REG_WR (pDevice, MacCtrl.MtuSize, pDevice->RxMtu + 8); /* CRC + VLAN. */ | |
2477 | ||
2478 | /* Configure Time slot/IPG per 802.3 */ | |
2479 | REG_WR (pDevice, MacCtrl.TxLengths, 0x2620); | |
2480 | ||
2481 | /* | |
2482 | * Configure Receive Rules so that packets don't match | |
2483 | * Programmble rule will be queued to Return Ring 1 | |
2484 | */ | |
2485 | REG_WR (pDevice, MacCtrl.RcvRuleCfg, RX_RULE_DEFAULT_CLASS); | |
2486 | ||
2487 | /* | |
2488 | * Configure to have 16 Classes of Services (COS) and one | |
2489 | * queue per class. Bad frames are queued to RRR#1. | |
2490 | * And frames don't match rules are also queued to COS#1. | |
2491 | */ | |
2492 | REG_WR (pDevice, RcvListPlmt.Config, 0x181); | |
2493 | ||
2494 | /* Enable Receive Placement Statistics */ | |
2495 | REG_WR (pDevice, RcvListPlmt.StatsEnableMask, 0xffffff); | |
2496 | REG_WR (pDevice, RcvListPlmt.StatsCtrl, RCV_LIST_STATS_ENABLE); | |
2497 | ||
2498 | /* Enable Send Data Initator Statistics */ | |
2499 | REG_WR (pDevice, SndDataIn.StatsEnableMask, 0xffffff); | |
2500 | REG_WR (pDevice, SndDataIn.StatsCtrl, | |
2501 | T3_SND_DATA_IN_STATS_CTRL_ENABLE | | |
2502 | T3_SND_DATA_IN_STATS_CTRL_FASTER_UPDATE); | |
2503 | ||
2504 | /* Disable the host coalescing state machine before configuring it's */ | |
2505 | /* parameters. */ | |
2506 | REG_WR (pDevice, HostCoalesce.Mode, 0); | |
2507 | for (j = 0; j < 2000; j++) { | |
2508 | Value32 = REG_RD (pDevice, HostCoalesce.Mode); | |
2509 | if (!(Value32 & HOST_COALESCE_ENABLE)) { | |
2510 | break; | |
2511 | } | |
2512 | MM_Wait (10); | |
2513 | } | |
2514 | ||
2515 | /* Host coalescing configurations. */ | |
2516 | REG_WR (pDevice, HostCoalesce.RxCoalescingTicks, | |
2517 | pDevice->RxCoalescingTicks); | |
2518 | REG_WR (pDevice, HostCoalesce.TxCoalescingTicks, | |
2519 | pDevice->TxCoalescingTicks); | |
2520 | REG_WR (pDevice, HostCoalesce.RxMaxCoalescedFrames, | |
2521 | pDevice->RxMaxCoalescedFrames); | |
2522 | REG_WR (pDevice, HostCoalesce.TxMaxCoalescedFrames, | |
2523 | pDevice->TxMaxCoalescedFrames); | |
2524 | REG_WR (pDevice, HostCoalesce.RxCoalescedTickDuringInt, | |
2525 | pDevice->RxCoalescingTicksDuringInt); | |
2526 | REG_WR (pDevice, HostCoalesce.TxCoalescedTickDuringInt, | |
2527 | pDevice->TxCoalescingTicksDuringInt); | |
2528 | REG_WR (pDevice, HostCoalesce.RxMaxCoalescedFramesDuringInt, | |
2529 | pDevice->RxMaxCoalescedFramesDuringInt); | |
2530 | REG_WR (pDevice, HostCoalesce.TxMaxCoalescedFramesDuringInt, | |
2531 | pDevice->TxMaxCoalescedFramesDuringInt); | |
2532 | ||
2533 | /* Initialize the address of the status block. The NIC will DMA */ | |
2534 | /* the status block to this memory which resides on the host. */ | |
2535 | REG_WR (pDevice, HostCoalesce.StatusBlkHostAddr.High, | |
2536 | pDevice->StatusBlkPhy.High); | |
2537 | REG_WR (pDevice, HostCoalesce.StatusBlkHostAddr.Low, | |
2538 | pDevice->StatusBlkPhy.Low); | |
2539 | ||
2540 | /* Initialize the address of the statistics block. The NIC will DMA */ | |
2541 | /* the statistics to this block of memory. */ | |
2542 | REG_WR (pDevice, HostCoalesce.StatsBlkHostAddr.High, | |
2543 | pDevice->StatsBlkPhy.High); | |
2544 | REG_WR (pDevice, HostCoalesce.StatsBlkHostAddr.Low, | |
2545 | pDevice->StatsBlkPhy.Low); | |
2546 | ||
2547 | REG_WR (pDevice, HostCoalesce.StatsCoalescingTicks, | |
2548 | pDevice->StatsCoalescingTicks); | |
2549 | ||
2550 | REG_WR (pDevice, HostCoalesce.StatsBlkNicAddr, 0x300); | |
2551 | REG_WR (pDevice, HostCoalesce.StatusBlkNicAddr, 0xb00); | |
2552 | ||
2553 | /* Enable Host Coalesing state machine */ | |
2554 | REG_WR (pDevice, HostCoalesce.Mode, HOST_COALESCE_ENABLE | | |
2555 | pDevice->CoalesceMode); | |
2556 | ||
2557 | /* Enable the Receive BD Completion state machine. */ | |
2558 | REG_WR (pDevice, RcvBdComp.Mode, RCV_BD_COMP_MODE_ENABLE | | |
2559 | RCV_BD_COMP_MODE_ATTN_ENABLE); | |
2560 | ||
2561 | /* Enable the Receive List Placement state machine. */ | |
2562 | REG_WR (pDevice, RcvListPlmt.Mode, RCV_LIST_PLMT_MODE_ENABLE); | |
2563 | ||
2564 | /* Enable the Receive List Selector state machine. */ | |
2565 | REG_WR (pDevice, RcvListSel.Mode, RCV_LIST_SEL_MODE_ENABLE | | |
2566 | RCV_LIST_SEL_MODE_ATTN_ENABLE); | |
2567 | ||
2568 | /* Enable transmit DMA, clear statistics. */ | |
2569 | pDevice->MacMode = MAC_MODE_ENABLE_TX_STATISTICS | | |
2570 | MAC_MODE_ENABLE_RX_STATISTICS | MAC_MODE_ENABLE_TDE | | |
2571 | MAC_MODE_ENABLE_RDE | MAC_MODE_ENABLE_FHDE; | |
2572 | REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode | | |
2573 | MAC_MODE_CLEAR_RX_STATISTICS | MAC_MODE_CLEAR_TX_STATISTICS); | |
2574 | ||
2575 | /* GRC miscellaneous local control register. */ | |
2576 | pDevice->GrcLocalCtrl = GRC_MISC_LOCAL_CTRL_INT_ON_ATTN | | |
2577 | GRC_MISC_LOCAL_CTRL_AUTO_SEEPROM; | |
2578 | ||
2579 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { | |
2580 | pDevice->GrcLocalCtrl |= GRC_MISC_LOCAL_CTRL_GPIO_OE1 | | |
2581 | GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1; | |
2582 | } | |
2583 | ||
2584 | REG_WR (pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl); | |
2585 | MM_Wait (40); | |
2586 | ||
2587 | /* Reset RX counters. */ | |
2588 | for (j = 0; j < sizeof (LM_RX_COUNTERS); j++) { | |
2589 | ((PLM_UINT8) & pDevice->RxCounters)[j] = 0; | |
2590 | } | |
2591 | ||
2592 | /* Reset TX counters. */ | |
2593 | for (j = 0; j < sizeof (LM_TX_COUNTERS); j++) { | |
2594 | ((PLM_UINT8) & pDevice->TxCounters)[j] = 0; | |
2595 | } | |
2596 | ||
2597 | MB_REG_WR (pDevice, Mailbox.Interrupt[0].Low, 0); | |
2598 | ||
2599 | /* Enable the DMA Completion state machine. */ | |
2600 | REG_WR (pDevice, DmaComp.Mode, DMA_COMP_MODE_ENABLE); | |
2601 | ||
2602 | /* Enable the DMA Write state machine. */ | |
2603 | Value32 = DMA_WRITE_MODE_ENABLE | | |
2604 | DMA_WRITE_MODE_TARGET_ABORT_ATTN_ENABLE | | |
2605 | DMA_WRITE_MODE_MASTER_ABORT_ATTN_ENABLE | | |
2606 | DMA_WRITE_MODE_PARITY_ERROR_ATTN_ENABLE | | |
2607 | DMA_WRITE_MODE_ADDR_OVERFLOW_ATTN_ENABLE | | |
2608 | DMA_WRITE_MODE_FIFO_OVERRUN_ATTN_ENABLE | | |
2609 | DMA_WRITE_MODE_FIFO_UNDERRUN_ATTN_ENABLE | | |
2610 | DMA_WRITE_MODE_FIFO_OVERREAD_ATTN_ENABLE | | |
2611 | DMA_WRITE_MODE_LONG_READ_ATTN_ENABLE; | |
2612 | REG_WR (pDevice, DmaWrite.Mode, Value32); | |
2613 | ||
2614 | if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE)) { | |
2615 | if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0) { | |
2616 | Value16 = REG_RD (pDevice, PciCfg.PciXCommand); | |
2617 | Value16 &= | |
2618 | ~(PCIX_CMD_MAX_SPLIT_MASK | | |
2619 | PCIX_CMD_MAX_BURST_MASK); | |
2620 | Value16 |= | |
2621 | ((PCIX_CMD_MAX_BURST_CPIOB << | |
2622 | PCIX_CMD_MAX_BURST_SHL) & | |
2623 | PCIX_CMD_MAX_BURST_MASK); | |
2624 | if (pDevice->SplitModeEnable == SPLIT_MODE_ENABLE) { | |
2625 | Value16 |= | |
2626 | (pDevice-> | |
2627 | SplitModeMaxReq << PCIX_CMD_MAX_SPLIT_SHL) | |
2628 | & PCIX_CMD_MAX_SPLIT_MASK; | |
2629 | } | |
2630 | REG_WR (pDevice, PciCfg.PciXCommand, Value16); | |
2631 | } | |
2632 | } | |
2633 | ||
2634 | /* Enable the Read DMA state machine. */ | |
2635 | Value32 = DMA_READ_MODE_ENABLE | | |
2636 | DMA_READ_MODE_TARGET_ABORT_ATTN_ENABLE | | |
2637 | DMA_READ_MODE_MASTER_ABORT_ATTN_ENABLE | | |
2638 | DMA_READ_MODE_PARITY_ERROR_ATTN_ENABLE | | |
2639 | DMA_READ_MODE_ADDR_OVERFLOW_ATTN_ENABLE | | |
2640 | DMA_READ_MODE_FIFO_OVERRUN_ATTN_ENABLE | | |
2641 | DMA_READ_MODE_FIFO_UNDERRUN_ATTN_ENABLE | | |
2642 | DMA_READ_MODE_FIFO_OVERREAD_ATTN_ENABLE | | |
2643 | DMA_READ_MODE_LONG_READ_ATTN_ENABLE; | |
2644 | ||
2645 | if (pDevice->SplitModeEnable == SPLIT_MODE_ENABLE) { | |
2646 | Value32 |= DMA_READ_MODE_SPLIT_ENABLE; | |
2647 | } | |
2648 | REG_WR (pDevice, DmaRead.Mode, Value32); | |
2649 | ||
2650 | /* Enable the Receive Data Completion state machine. */ | |
2651 | REG_WR (pDevice, RcvDataComp.Mode, RCV_DATA_COMP_MODE_ENABLE | | |
2652 | RCV_DATA_COMP_MODE_ATTN_ENABLE); | |
2653 | ||
2654 | /* Enable the Mbuf Cluster Free state machine. */ | |
2655 | REG_WR (pDevice, MbufClusterFree.Mode, MBUF_CLUSTER_FREE_MODE_ENABLE); | |
2656 | ||
2657 | /* Enable the Send Data Completion state machine. */ | |
2658 | REG_WR (pDevice, SndDataComp.Mode, SND_DATA_COMP_MODE_ENABLE); | |
2659 | ||
2660 | /* Enable the Send BD Completion state machine. */ | |
2661 | REG_WR (pDevice, SndBdComp.Mode, SND_BD_COMP_MODE_ENABLE | | |
2662 | SND_BD_COMP_MODE_ATTN_ENABLE); | |
2663 | ||
2664 | /* Enable the Receive BD Initiator state machine. */ | |
2665 | REG_WR (pDevice, RcvBdIn.Mode, RCV_BD_IN_MODE_ENABLE | | |
2666 | RCV_BD_IN_MODE_BD_IN_DIABLED_RCB_ATTN_ENABLE); | |
2667 | ||
2668 | /* Enable the Receive Data and Receive BD Initiator state machine. */ | |
2669 | REG_WR (pDevice, RcvDataBdIn.Mode, RCV_DATA_BD_IN_MODE_ENABLE | | |
2670 | RCV_DATA_BD_IN_MODE_INVALID_RING_SIZE); | |
2671 | ||
2672 | /* Enable the Send Data Initiator state machine. */ | |
2673 | REG_WR (pDevice, SndDataIn.Mode, T3_SND_DATA_IN_MODE_ENABLE); | |
2674 | ||
2675 | /* Enable the Send BD Initiator state machine. */ | |
2676 | REG_WR (pDevice, SndBdIn.Mode, SND_BD_IN_MODE_ENABLE | | |
2677 | SND_BD_IN_MODE_ATTN_ENABLE); | |
2678 | ||
2679 | /* Enable the Send BD Selector state machine. */ | |
2680 | REG_WR (pDevice, SndBdSel.Mode, SND_BD_SEL_MODE_ENABLE | | |
2681 | SND_BD_SEL_MODE_ATTN_ENABLE); | |
c609719b WD |
2682 | |
2683 | #if INCLUDE_5701_AX_FIX | |
f539edc0 VB |
2684 | /* Load the firmware for the 5701_A0 workaround. */ |
2685 | if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0) { | |
2686 | LM_LoadRlsFirmware (pDevice); | |
2687 | } | |
c609719b WD |
2688 | #endif |
2689 | ||
f539edc0 VB |
2690 | /* Enable the transmitter. */ |
2691 | pDevice->TxMode = TX_MODE_ENABLE; | |
2692 | REG_WR (pDevice, MacCtrl.TxMode, pDevice->TxMode); | |
2693 | ||
2694 | /* Enable the receiver. */ | |
2695 | pDevice->RxMode = RX_MODE_ENABLE; | |
2696 | REG_WR (pDevice, MacCtrl.RxMode, pDevice->RxMode); | |
2697 | ||
2698 | if (pDevice->RestoreOnWakeUp) { | |
2699 | pDevice->RestoreOnWakeUp = FALSE; | |
2700 | pDevice->DisableAutoNeg = pDevice->WakeUpDisableAutoNeg; | |
2701 | pDevice->RequestedMediaType = pDevice->WakeUpRequestedMediaType; | |
8bde7f77 | 2702 | } |
c609719b | 2703 | |
f539edc0 VB |
2704 | /* Disable auto polling. */ |
2705 | pDevice->MiMode = 0xc0000; | |
2706 | REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode); | |
c609719b | 2707 | |
f539edc0 VB |
2708 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || |
2709 | T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { | |
2710 | Value32 = LED_CTRL_PHY_MODE_1; | |
2711 | } else { | |
2712 | if (pDevice->LedMode == LED_MODE_OUTPUT) { | |
2713 | Value32 = LED_CTRL_PHY_MODE_2; | |
2714 | } else { | |
2715 | Value32 = LED_CTRL_PHY_MODE_1; | |
2716 | } | |
8bde7f77 | 2717 | } |
f539edc0 VB |
2718 | REG_WR (pDevice, MacCtrl.LedCtrl, Value32); |
2719 | ||
2720 | /* Activate Link to enable MAC state machine */ | |
2721 | REG_WR (pDevice, MacCtrl.MiStatus, MI_STATUS_ENABLE_LINK_STATUS_ATTN); | |
c609719b | 2722 | |
f539edc0 VB |
2723 | if (pDevice->EnableTbi) { |
2724 | REG_WR (pDevice, MacCtrl.RxMode, RX_MODE_RESET); | |
2725 | MM_Wait (10); | |
2726 | REG_WR (pDevice, MacCtrl.RxMode, pDevice->RxMode); | |
2727 | if (pDevice->ChipRevId == T3_CHIP_ID_5703_A1) { | |
2728 | REG_WR (pDevice, MacCtrl.SerdesCfg, 0x616000); | |
2729 | } | |
2730 | } | |
2731 | /* Setup the phy chip. */ | |
2732 | LM_SetupPhy (pDevice); | |
c609719b | 2733 | |
f539edc0 VB |
2734 | if (!pDevice->EnableTbi) { |
2735 | /* Clear CRC stats */ | |
2736 | LM_ReadPhy (pDevice, 0x1e, &Value32); | |
2737 | LM_WritePhy (pDevice, 0x1e, Value32 | 0x8000); | |
2738 | LM_ReadPhy (pDevice, 0x14, &Value32); | |
2739 | } | |
c609719b | 2740 | |
f539edc0 VB |
2741 | /* Set up the receive mask. */ |
2742 | LM_SetReceiveMask (pDevice, pDevice->ReceiveMask); | |
c609719b | 2743 | |
f539edc0 VB |
2744 | /* Queue Rx packet buffers. */ |
2745 | if (pDevice->QueueRxPackets) { | |
2746 | LM_QueueRxPackets (pDevice); | |
2747 | } | |
c609719b | 2748 | |
f539edc0 VB |
2749 | /* Enable interrupt to the host. */ |
2750 | if (pDevice->InitDone) { | |
2751 | LM_EnableInterrupt (pDevice); | |
2752 | } | |
c609719b | 2753 | |
f539edc0 VB |
2754 | return LM_STATUS_SUCCESS; |
2755 | } /* LM_ResetAdapter */ | |
c609719b WD |
2756 | |
2757 | /******************************************************************************/ | |
2758 | /* Description: */ | |
2759 | /* This routine disables the adapter from generating interrupts. */ | |
2760 | /* */ | |
2761 | /* Return: */ | |
2762 | /* LM_STATUS_SUCCESS */ | |
2763 | /******************************************************************************/ | |
f539edc0 | 2764 | LM_STATUS LM_DisableInterrupt (PLM_DEVICE_BLOCK pDevice) |
c609719b | 2765 | { |
f539edc0 VB |
2766 | REG_WR (pDevice, PciCfg.MiscHostCtrl, pDevice->MiscHostCtrl | |
2767 | MISC_HOST_CTRL_MASK_PCI_INT); | |
2768 | MB_REG_WR (pDevice, Mailbox.Interrupt[0].Low, 1); | |
c609719b | 2769 | |
f539edc0 | 2770 | return LM_STATUS_SUCCESS; |
c609719b WD |
2771 | } |
2772 | ||
c609719b WD |
2773 | /******************************************************************************/ |
2774 | /* Description: */ | |
2775 | /* This routine enables the adapter to generate interrupts. */ | |
2776 | /* */ | |
2777 | /* Return: */ | |
2778 | /* LM_STATUS_SUCCESS */ | |
2779 | /******************************************************************************/ | |
f539edc0 | 2780 | LM_STATUS LM_EnableInterrupt (PLM_DEVICE_BLOCK pDevice) |
c609719b | 2781 | { |
f539edc0 VB |
2782 | REG_WR (pDevice, PciCfg.MiscHostCtrl, pDevice->MiscHostCtrl & |
2783 | ~MISC_HOST_CTRL_MASK_PCI_INT); | |
2784 | MB_REG_WR (pDevice, Mailbox.Interrupt[0].Low, 0); | |
c609719b | 2785 | |
f539edc0 VB |
2786 | if (pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) { |
2787 | REG_WR (pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl | | |
2788 | GRC_MISC_LOCAL_CTRL_SET_INT); | |
2789 | } | |
c609719b | 2790 | |
f539edc0 | 2791 | return LM_STATUS_SUCCESS; |
c609719b WD |
2792 | } |
2793 | ||
c609719b WD |
2794 | /******************************************************************************/ |
2795 | /* Description: */ | |
2796 | /* This routine puts a packet on the wire if there is a transmit DMA */ | |
2797 | /* descriptor available; otherwise the packet is queued for later */ | |
2798 | /* transmission. If the second argue is NULL, this routine will put */ | |
2799 | /* the queued packet on the wire if possible. */ | |
2800 | /* */ | |
2801 | /* Return: */ | |
2802 | /* LM_STATUS_SUCCESS */ | |
2803 | /******************************************************************************/ | |
2804 | #if 0 | |
f539edc0 | 2805 | LM_STATUS LM_SendPacket (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket) |
c609719b | 2806 | { |
f539edc0 VB |
2807 | LM_UINT32 FragCount; |
2808 | PT3_SND_BD pSendBd; | |
2809 | PT3_SND_BD pShadowSendBd; | |
2810 | LM_UINT32 Value32, Len; | |
2811 | LM_UINT32 Idx; | |
c609719b | 2812 | |
f539edc0 VB |
2813 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { |
2814 | return LM_5700SendPacket (pDevice, pPacket); | |
2815 | } | |
c609719b | 2816 | |
f539edc0 VB |
2817 | /* Update the SendBdLeft count. */ |
2818 | atomic_sub (pPacket->u.Tx.FragCount, &pDevice->SendBdLeft); | |
c609719b | 2819 | |
f539edc0 VB |
2820 | /* Initalize the send buffer descriptors. */ |
2821 | Idx = pDevice->SendProdIdx; | |
c609719b | 2822 | |
f539edc0 | 2823 | pSendBd = &pDevice->pSendBdVirt[Idx]; |
c609719b | 2824 | |
f539edc0 VB |
2825 | /* Next producer index. */ |
2826 | if (pDevice->NicSendBd == TRUE) { | |
2827 | T3_64BIT_HOST_ADDR paddr; | |
2828 | ||
2829 | pShadowSendBd = &pDevice->ShadowSendBd[Idx]; | |
2830 | for (FragCount = 0;;) { | |
2831 | MM_MapTxDma (pDevice, pPacket, &paddr, &Len, FragCount); | |
2832 | /* Initialize the pointer to the send buffer fragment. */ | |
2833 | if (paddr.High != pShadowSendBd->HostAddr.High) { | |
2834 | __raw_writel (paddr.High, | |
2835 | &(pSendBd->HostAddr.High)); | |
2836 | pShadowSendBd->HostAddr.High = paddr.High; | |
2837 | } | |
2838 | __raw_writel (paddr.Low, &(pSendBd->HostAddr.Low)); | |
2839 | ||
2840 | /* Setup the control flags and send buffer size. */ | |
2841 | Value32 = (Len << 16) | pPacket->Flags; | |
2842 | ||
2843 | Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK; | |
2844 | ||
2845 | FragCount++; | |
2846 | if (FragCount >= pPacket->u.Tx.FragCount) { | |
2847 | Value32 |= SND_BD_FLAG_END; | |
2848 | if (Value32 != pShadowSendBd->u1.Len_Flags) { | |
2849 | __raw_writel (Value32, | |
2850 | &(pSendBd->u1.Len_Flags)); | |
2851 | pShadowSendBd->u1.Len_Flags = Value32; | |
2852 | } | |
2853 | if (pPacket->Flags & SND_BD_FLAG_VLAN_TAG) { | |
2854 | __raw_writel (pPacket->VlanTag, | |
2855 | &(pSendBd->u2.VlanTag)); | |
2856 | } | |
2857 | break; | |
2858 | } else { | |
2859 | if (Value32 != pShadowSendBd->u1.Len_Flags) { | |
2860 | __raw_writel (Value32, | |
2861 | &(pSendBd->u1.Len_Flags)); | |
2862 | pShadowSendBd->u1.Len_Flags = Value32; | |
2863 | } | |
2864 | if (pPacket->Flags & SND_BD_FLAG_VLAN_TAG) { | |
2865 | __raw_writel (pPacket->VlanTag, | |
2866 | &(pSendBd->u2.VlanTag)); | |
2867 | } | |
2868 | } | |
8bde7f77 | 2869 | |
f539edc0 VB |
2870 | pSendBd++; |
2871 | pShadowSendBd++; | |
2872 | if (Idx == 0) { | |
2873 | pSendBd = &pDevice->pSendBdVirt[0]; | |
2874 | pShadowSendBd = &pDevice->ShadowSendBd[0]; | |
2875 | } | |
2876 | } /* for */ | |
8bde7f77 | 2877 | |
f539edc0 VB |
2878 | /* Put the packet descriptor in the ActiveQ. */ |
2879 | QQ_PushTail (&pDevice->TxPacketActiveQ.Container, pPacket); | |
8bde7f77 | 2880 | |
f539edc0 VB |
2881 | wmb (); |
2882 | MB_REG_WR (pDevice, Mailbox.SendNicProdIdx[0].Low, Idx); | |
c609719b | 2883 | |
f539edc0 VB |
2884 | } else { |
2885 | for (FragCount = 0;;) { | |
2886 | /* Initialize the pointer to the send buffer fragment. */ | |
2887 | MM_MapTxDma (pDevice, pPacket, &pSendBd->HostAddr, &Len, | |
2888 | FragCount); | |
c609719b | 2889 | |
f539edc0 | 2890 | pSendBd->u2.VlanTag = pPacket->VlanTag; |
c609719b | 2891 | |
f539edc0 VB |
2892 | /* Setup the control flags and send buffer size. */ |
2893 | Value32 = (Len << 16) | pPacket->Flags; | |
c609719b | 2894 | |
f539edc0 | 2895 | Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK; |
c609719b | 2896 | |
f539edc0 VB |
2897 | FragCount++; |
2898 | if (FragCount >= pPacket->u.Tx.FragCount) { | |
2899 | pSendBd->u1.Len_Flags = | |
2900 | Value32 | SND_BD_FLAG_END; | |
2901 | break; | |
2902 | } else { | |
2903 | pSendBd->u1.Len_Flags = Value32; | |
2904 | } | |
2905 | pSendBd++; | |
2906 | if (Idx == 0) { | |
2907 | pSendBd = &pDevice->pSendBdVirt[0]; | |
2908 | } | |
2909 | } /* for */ | |
c609719b | 2910 | |
f539edc0 VB |
2911 | /* Put the packet descriptor in the ActiveQ. */ |
2912 | QQ_PushTail (&pDevice->TxPacketActiveQ.Container, pPacket); | |
c609719b | 2913 | |
f539edc0 VB |
2914 | wmb (); |
2915 | MB_REG_WR (pDevice, Mailbox.SendHostProdIdx[0].Low, Idx); | |
c609719b | 2916 | |
f539edc0 | 2917 | } |
c609719b | 2918 | |
f539edc0 VB |
2919 | /* Update the producer index. */ |
2920 | pDevice->SendProdIdx = Idx; | |
c609719b | 2921 | |
f539edc0 | 2922 | return LM_STATUS_SUCCESS; |
c609719b WD |
2923 | } |
2924 | #endif | |
2925 | ||
f539edc0 | 2926 | LM_STATUS LM_SendPacket (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket) |
c609719b | 2927 | { |
f539edc0 VB |
2928 | LM_UINT32 FragCount; |
2929 | PT3_SND_BD pSendBd, pTmpSendBd, pShadowSendBd; | |
2930 | T3_SND_BD NicSendBdArr[MAX_FRAGMENT_COUNT]; | |
2931 | LM_UINT32 StartIdx, Idx; | |
2932 | ||
2933 | while (1) { | |
2934 | /* Initalize the send buffer descriptors. */ | |
2935 | StartIdx = Idx = pDevice->SendProdIdx; | |
2936 | ||
2937 | if (pDevice->NicSendBd) { | |
2938 | pTmpSendBd = pSendBd = &NicSendBdArr[0]; | |
2939 | } else { | |
2940 | pTmpSendBd = pSendBd = &pDevice->pSendBdVirt[Idx]; | |
2941 | } | |
c609719b | 2942 | |
f539edc0 VB |
2943 | /* Next producer index. */ |
2944 | for (FragCount = 0;;) { | |
2945 | LM_UINT32 Value32, Len; | |
8bde7f77 | 2946 | |
f539edc0 VB |
2947 | /* Initialize the pointer to the send buffer fragment. */ |
2948 | MM_MapTxDma (pDevice, pPacket, &pSendBd->HostAddr, &Len, | |
2949 | FragCount); | |
2950 | ||
2951 | pSendBd->u2.VlanTag = pPacket->VlanTag; | |
2952 | ||
2953 | /* Setup the control flags and send buffer size. */ | |
2954 | Value32 = (Len << 16) | pPacket->Flags; | |
2955 | ||
2956 | Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK; | |
2957 | ||
2958 | FragCount++; | |
2959 | if (FragCount >= pPacket->u.Tx.FragCount) { | |
2960 | pSendBd->u1.Len_Flags = | |
2961 | Value32 | SND_BD_FLAG_END; | |
2962 | break; | |
2963 | } else { | |
2964 | pSendBd->u1.Len_Flags = Value32; | |
2965 | } | |
2966 | pSendBd++; | |
2967 | if ((Idx == 0) && !pDevice->NicSendBd) { | |
2968 | pSendBd = &pDevice->pSendBdVirt[0]; | |
2969 | } | |
2970 | } /* for */ | |
2971 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { | |
2972 | if (LM_Test4GBoundary (pDevice, pPacket, pTmpSendBd) == | |
2973 | LM_STATUS_SUCCESS) { | |
2974 | if (MM_CoalesceTxBuffer (pDevice, pPacket) != | |
2975 | LM_STATUS_SUCCESS) { | |
2976 | QQ_PushHead (&pDevice->TxPacketFreeQ. | |
2977 | Container, pPacket); | |
2978 | return LM_STATUS_FAILURE; | |
2979 | } | |
2980 | continue; | |
2981 | } | |
2982 | } | |
2983 | break; | |
8bde7f77 | 2984 | } |
f539edc0 VB |
2985 | /* Put the packet descriptor in the ActiveQ. */ |
2986 | QQ_PushTail (&pDevice->TxPacketActiveQ.Container, pPacket); | |
8bde7f77 | 2987 | |
f539edc0 VB |
2988 | if (pDevice->NicSendBd) { |
2989 | pSendBd = &pDevice->pSendBdVirt[StartIdx]; | |
2990 | pShadowSendBd = &pDevice->ShadowSendBd[StartIdx]; | |
8bde7f77 | 2991 | |
f539edc0 VB |
2992 | while (StartIdx != Idx) { |
2993 | LM_UINT32 Value32; | |
8bde7f77 | 2994 | |
f539edc0 VB |
2995 | if ((Value32 = pTmpSendBd->HostAddr.High) != |
2996 | pShadowSendBd->HostAddr.High) { | |
2997 | __raw_writel (Value32, | |
2998 | &(pSendBd->HostAddr.High)); | |
2999 | pShadowSendBd->HostAddr.High = Value32; | |
3000 | } | |
8bde7f77 | 3001 | |
f539edc0 VB |
3002 | __raw_writel (pTmpSendBd->HostAddr.Low, |
3003 | &(pSendBd->HostAddr.Low)); | |
8bde7f77 | 3004 | |
f539edc0 VB |
3005 | if ((Value32 = pTmpSendBd->u1.Len_Flags) != |
3006 | pShadowSendBd->u1.Len_Flags) { | |
3007 | __raw_writel (Value32, | |
3008 | &(pSendBd->u1.Len_Flags)); | |
3009 | pShadowSendBd->u1.Len_Flags = Value32; | |
3010 | } | |
8bde7f77 | 3011 | |
f539edc0 VB |
3012 | if (pPacket->Flags & SND_BD_FLAG_VLAN_TAG) { |
3013 | __raw_writel (pTmpSendBd->u2.VlanTag, | |
3014 | &(pSendBd->u2.VlanTag)); | |
3015 | } | |
8bde7f77 | 3016 | |
f539edc0 VB |
3017 | StartIdx = |
3018 | (StartIdx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK; | |
3019 | if (StartIdx == 0) | |
3020 | pSendBd = &pDevice->pSendBdVirt[0]; | |
3021 | else | |
3022 | pSendBd++; | |
3023 | pTmpSendBd++; | |
3024 | } | |
3025 | wmb (); | |
3026 | MB_REG_WR (pDevice, Mailbox.SendNicProdIdx[0].Low, Idx); | |
c609719b | 3027 | |
f539edc0 VB |
3028 | if (T3_CHIP_REV (pDevice->ChipRevId) == T3_CHIP_REV_5700_BX) { |
3029 | MB_REG_WR (pDevice, Mailbox.SendNicProdIdx[0].Low, Idx); | |
3030 | } | |
3031 | } else { | |
3032 | wmb (); | |
3033 | MB_REG_WR (pDevice, Mailbox.SendHostProdIdx[0].Low, Idx); | |
3034 | ||
3035 | if (T3_CHIP_REV (pDevice->ChipRevId) == T3_CHIP_REV_5700_BX) { | |
3036 | MB_REG_WR (pDevice, Mailbox.SendHostProdIdx[0].Low, | |
3037 | Idx); | |
3038 | } | |
8bde7f77 | 3039 | } |
c609719b | 3040 | |
f539edc0 VB |
3041 | /* Update the SendBdLeft count. */ |
3042 | atomic_sub (pPacket->u.Tx.FragCount, &pDevice->SendBdLeft); | |
c609719b | 3043 | |
f539edc0 VB |
3044 | /* Update the producer index. */ |
3045 | pDevice->SendProdIdx = Idx; | |
c609719b | 3046 | |
f539edc0 | 3047 | return LM_STATUS_SUCCESS; |
c609719b WD |
3048 | } |
3049 | ||
3050 | STATIC LM_STATUS | |
f539edc0 VB |
3051 | LM_Test4GBoundary (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket, |
3052 | PT3_SND_BD pSendBd) | |
c609719b | 3053 | { |
f539edc0 VB |
3054 | int FragCount; |
3055 | LM_UINT32 Idx, Base, Len; | |
3056 | ||
3057 | Idx = pDevice->SendProdIdx; | |
3058 | for (FragCount = 0;;) { | |
3059 | Len = pSendBd->u1.Len_Flags >> 16; | |
3060 | if (((Base = pSendBd->HostAddr.Low) > 0xffffdcc0) && | |
3061 | (pSendBd->HostAddr.High == 0) && | |
3062 | ((Base + 8 + Len) < Base)) { | |
3063 | return LM_STATUS_SUCCESS; | |
3064 | } | |
3065 | FragCount++; | |
3066 | if (FragCount >= pPacket->u.Tx.FragCount) { | |
3067 | break; | |
3068 | } | |
3069 | pSendBd++; | |
3070 | if (!pDevice->NicSendBd) { | |
3071 | Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK; | |
3072 | if (Idx == 0) { | |
3073 | pSendBd = &pDevice->pSendBdVirt[0]; | |
3074 | } | |
3075 | } | |
8bde7f77 | 3076 | } |
f539edc0 | 3077 | return LM_STATUS_FAILURE; |
c609719b WD |
3078 | } |
3079 | ||
3080 | /******************************************************************************/ | |
3081 | /* Description: */ | |
3082 | /* */ | |
3083 | /* Return: */ | |
3084 | /******************************************************************************/ | |
3085 | __inline static unsigned long | |
f539edc0 VB |
3086 | ComputeCrc32 (unsigned char *pBuffer, unsigned long BufferSize) |
3087 | { | |
3088 | unsigned long Reg; | |
3089 | unsigned long Tmp; | |
3090 | unsigned long j, k; | |
c609719b | 3091 | |
f539edc0 | 3092 | Reg = 0xffffffff; |
c609719b | 3093 | |
f539edc0 VB |
3094 | for (j = 0; j < BufferSize; j++) { |
3095 | Reg ^= pBuffer[j]; | |
c609719b | 3096 | |
f539edc0 VB |
3097 | for (k = 0; k < 8; k++) { |
3098 | Tmp = Reg & 0x01; | |
c609719b | 3099 | |
f539edc0 | 3100 | Reg >>= 1; |
c609719b | 3101 | |
f539edc0 VB |
3102 | if (Tmp) { |
3103 | Reg ^= 0xedb88320; | |
3104 | } | |
3105 | } | |
8bde7f77 | 3106 | } |
c609719b | 3107 | |
f539edc0 VB |
3108 | return ~Reg; |
3109 | } /* ComputeCrc32 */ | |
c609719b | 3110 | |
c609719b WD |
3111 | /******************************************************************************/ |
3112 | /* Description: */ | |
3113 | /* This routine sets the receive control register according to ReceiveMask */ | |
3114 | /* */ | |
3115 | /* Return: */ | |
3116 | /* LM_STATUS_SUCCESS */ | |
3117 | /******************************************************************************/ | |
f539edc0 VB |
3118 | LM_STATUS LM_SetReceiveMask (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Mask) |
3119 | { | |
3120 | LM_UINT32 ReceiveMask; | |
3121 | LM_UINT32 RxMode; | |
3122 | LM_UINT32 j, k; | |
c609719b | 3123 | |
f539edc0 | 3124 | ReceiveMask = Mask; |
c609719b | 3125 | |
f539edc0 | 3126 | RxMode = pDevice->RxMode; |
c609719b | 3127 | |
f539edc0 VB |
3128 | if (Mask & LM_ACCEPT_UNICAST) { |
3129 | Mask &= ~LM_ACCEPT_UNICAST; | |
8bde7f77 | 3130 | } |
c609719b | 3131 | |
f539edc0 VB |
3132 | if (Mask & LM_ACCEPT_MULTICAST) { |
3133 | Mask &= ~LM_ACCEPT_MULTICAST; | |
3134 | } | |
3135 | ||
3136 | if (Mask & LM_ACCEPT_ALL_MULTICAST) { | |
3137 | Mask &= ~LM_ACCEPT_ALL_MULTICAST; | |
3138 | } | |
3139 | ||
3140 | if (Mask & LM_ACCEPT_BROADCAST) { | |
3141 | Mask &= ~LM_ACCEPT_BROADCAST; | |
3142 | } | |
c609719b | 3143 | |
f539edc0 VB |
3144 | RxMode &= ~RX_MODE_PROMISCUOUS_MODE; |
3145 | if (Mask & LM_PROMISCUOUS_MODE) { | |
3146 | RxMode |= RX_MODE_PROMISCUOUS_MODE; | |
3147 | Mask &= ~LM_PROMISCUOUS_MODE; | |
3148 | } | |
3149 | ||
3150 | RxMode &= ~(RX_MODE_ACCEPT_RUNTS | RX_MODE_ACCEPT_OVERSIZED); | |
3151 | if (Mask & LM_ACCEPT_ERROR_PACKET) { | |
3152 | RxMode |= RX_MODE_ACCEPT_RUNTS | RX_MODE_ACCEPT_OVERSIZED; | |
3153 | Mask &= ~LM_ACCEPT_ERROR_PACKET; | |
3154 | } | |
3155 | ||
3156 | /* Make sure all the bits are valid before committing changes. */ | |
3157 | if (Mask) { | |
3158 | return LM_STATUS_FAILURE; | |
3159 | } | |
c609719b | 3160 | |
f539edc0 VB |
3161 | /* Commit the new filter. */ |
3162 | pDevice->RxMode = RxMode; | |
3163 | REG_WR (pDevice, MacCtrl.RxMode, RxMode); | |
c609719b | 3164 | |
f539edc0 | 3165 | pDevice->ReceiveMask = ReceiveMask; |
c609719b | 3166 | |
f539edc0 VB |
3167 | /* Set up the MC hash table. */ |
3168 | if (ReceiveMask & LM_ACCEPT_ALL_MULTICAST) { | |
3169 | for (k = 0; k < 4; k++) { | |
3170 | REG_WR (pDevice, MacCtrl.HashReg[k], 0xffffffff); | |
3171 | } | |
3172 | } else if (ReceiveMask & LM_ACCEPT_MULTICAST) { | |
3173 | LM_UINT32 HashReg[4]; | |
3174 | ||
3175 | HashReg[0] = 0; | |
3176 | HashReg[1] = 0; | |
3177 | HashReg[2] = 0; | |
3178 | HashReg[3] = 0; | |
3179 | for (j = 0; j < pDevice->McEntryCount; j++) { | |
3180 | LM_UINT32 RegIndex; | |
3181 | LM_UINT32 Bitpos; | |
3182 | LM_UINT32 Crc32; | |
3183 | ||
3184 | Crc32 = | |
3185 | ComputeCrc32 (pDevice->McTable[j], | |
3186 | ETHERNET_ADDRESS_SIZE); | |
3187 | ||
3188 | /* The most significant 7 bits of the CRC32 (no inversion), */ | |
3189 | /* are used to index into one of the possible 128 bit positions. */ | |
3190 | Bitpos = ~Crc32 & 0x7f; | |
3191 | ||
3192 | /* Hash register index. */ | |
3193 | RegIndex = (Bitpos & 0x60) >> 5; | |
3194 | ||
3195 | /* Bit to turn on within a hash register. */ | |
3196 | Bitpos &= 0x1f; | |
3197 | ||
3198 | /* Enable the multicast bit. */ | |
3199 | HashReg[RegIndex] |= (1 << Bitpos); | |
3200 | } | |
c609719b | 3201 | |
f539edc0 VB |
3202 | /* REV_AX has problem with multicast filtering where it uses both */ |
3203 | /* DA and SA to perform hashing. */ | |
3204 | for (k = 0; k < 4; k++) { | |
3205 | REG_WR (pDevice, MacCtrl.HashReg[k], HashReg[k]); | |
3206 | } | |
3207 | } else { | |
3208 | /* Reject all multicast frames. */ | |
3209 | for (j = 0; j < 4; j++) { | |
3210 | REG_WR (pDevice, MacCtrl.HashReg[j], 0); | |
3211 | } | |
8bde7f77 | 3212 | } |
c609719b | 3213 | |
f539edc0 VB |
3214 | /* By default, Tigon3 will accept broadcast frames. We need to setup */ |
3215 | if (ReceiveMask & LM_ACCEPT_BROADCAST) { | |
3216 | REG_WR (pDevice, | |
3217 | MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Rule, | |
3218 | REJECT_BROADCAST_RULE1_RULE & RCV_DISABLE_RULE_MASK); | |
3219 | REG_WR (pDevice, | |
3220 | MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Value, | |
3221 | REJECT_BROADCAST_RULE1_VALUE & RCV_DISABLE_RULE_MASK); | |
3222 | REG_WR (pDevice, | |
3223 | MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Rule, | |
3224 | REJECT_BROADCAST_RULE1_RULE & RCV_DISABLE_RULE_MASK); | |
3225 | REG_WR (pDevice, | |
3226 | MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Value, | |
3227 | REJECT_BROADCAST_RULE1_VALUE & RCV_DISABLE_RULE_MASK); | |
3228 | } else { | |
3229 | REG_WR (pDevice, | |
3230 | MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Rule, | |
3231 | REJECT_BROADCAST_RULE1_RULE); | |
3232 | REG_WR (pDevice, | |
3233 | MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Value, | |
3234 | REJECT_BROADCAST_RULE1_VALUE); | |
3235 | REG_WR (pDevice, | |
3236 | MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Rule, | |
3237 | REJECT_BROADCAST_RULE2_RULE); | |
3238 | REG_WR (pDevice, | |
3239 | MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Value, | |
3240 | REJECT_BROADCAST_RULE2_VALUE); | |
3241 | } | |
3242 | ||
3243 | /* disable the rest of the rules. */ | |
3244 | for (j = RCV_LAST_RULE_IDX; j < 16; j++) { | |
3245 | REG_WR (pDevice, MacCtrl.RcvRules[j].Rule, 0); | |
3246 | REG_WR (pDevice, MacCtrl.RcvRules[j].Value, 0); | |
8bde7f77 | 3247 | } |
c609719b | 3248 | |
f539edc0 VB |
3249 | return LM_STATUS_SUCCESS; |
3250 | } /* LM_SetReceiveMask */ | |
c609719b | 3251 | |
c609719b WD |
3252 | /******************************************************************************/ |
3253 | /* Description: */ | |
3254 | /* Disable the interrupt and put the transmitter and receiver engines in */ | |
3255 | /* an idle state. Also aborts all pending send requests and receive */ | |
3256 | /* buffers. */ | |
3257 | /* */ | |
3258 | /* Return: */ | |
3259 | /* LM_STATUS_SUCCESS */ | |
3260 | /******************************************************************************/ | |
f539edc0 | 3261 | LM_STATUS LM_Abort (PLM_DEVICE_BLOCK pDevice) |
c609719b | 3262 | { |
f539edc0 VB |
3263 | PLM_PACKET pPacket; |
3264 | LM_UINT Idx; | |
3265 | ||
3266 | LM_DisableInterrupt (pDevice); | |
3267 | ||
3268 | /* Disable all the state machines. */ | |
3269 | LM_CntrlBlock (pDevice, T3_BLOCK_MAC_RX_ENGINE, LM_DISABLE); | |
3270 | LM_CntrlBlock (pDevice, T3_BLOCK_RX_BD_INITIATOR, LM_DISABLE); | |
3271 | LM_CntrlBlock (pDevice, T3_BLOCK_RX_LIST_PLMT, LM_DISABLE); | |
3272 | LM_CntrlBlock (pDevice, T3_BLOCK_RX_LIST_SELECTOR, LM_DISABLE); | |
3273 | LM_CntrlBlock (pDevice, T3_BLOCK_RX_DATA_INITIATOR, LM_DISABLE); | |
3274 | LM_CntrlBlock (pDevice, T3_BLOCK_RX_DATA_COMP, LM_DISABLE); | |
3275 | LM_CntrlBlock (pDevice, T3_BLOCK_RX_BD_COMP, LM_DISABLE); | |
3276 | ||
3277 | LM_CntrlBlock (pDevice, T3_BLOCK_SEND_BD_SELECTOR, LM_DISABLE); | |
3278 | LM_CntrlBlock (pDevice, T3_BLOCK_SEND_BD_INITIATOR, LM_DISABLE); | |
3279 | LM_CntrlBlock (pDevice, T3_BLOCK_SEND_DATA_INITIATOR, LM_DISABLE); | |
3280 | LM_CntrlBlock (pDevice, T3_BLOCK_DMA_RD, LM_DISABLE); | |
3281 | LM_CntrlBlock (pDevice, T3_BLOCK_SEND_DATA_COMP, LM_DISABLE); | |
3282 | LM_CntrlBlock (pDevice, T3_BLOCK_DMA_COMP, LM_DISABLE); | |
3283 | LM_CntrlBlock (pDevice, T3_BLOCK_SEND_BD_COMP, LM_DISABLE); | |
3284 | ||
3285 | /* Clear TDE bit */ | |
3286 | pDevice->MacMode &= ~MAC_MODE_ENABLE_TDE; | |
3287 | REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode); | |
3288 | ||
3289 | LM_CntrlBlock (pDevice, T3_BLOCK_MAC_TX_ENGINE, LM_DISABLE); | |
3290 | LM_CntrlBlock (pDevice, T3_BLOCK_HOST_COALESING, LM_DISABLE); | |
3291 | LM_CntrlBlock (pDevice, T3_BLOCK_DMA_WR, LM_DISABLE); | |
3292 | LM_CntrlBlock (pDevice, T3_BLOCK_MBUF_CLUSTER_FREE, LM_DISABLE); | |
3293 | ||
3294 | /* Reset all FTQs */ | |
3295 | REG_WR (pDevice, Ftq.Reset, 0xffffffff); | |
3296 | REG_WR (pDevice, Ftq.Reset, 0x0); | |
3297 | ||
3298 | LM_CntrlBlock (pDevice, T3_BLOCK_MBUF_MANAGER, LM_DISABLE); | |
3299 | LM_CntrlBlock (pDevice, T3_BLOCK_MEM_ARBITOR, LM_DISABLE); | |
3300 | ||
3301 | MM_ACQUIRE_INT_LOCK (pDevice); | |
3302 | ||
3303 | /* Abort packets that have already queued to go out. */ | |
3304 | pPacket = (PLM_PACKET) QQ_PopHead (&pDevice->TxPacketActiveQ.Container); | |
3305 | while (pPacket) { | |
3306 | ||
3307 | pPacket->PacketStatus = LM_STATUS_TRANSMIT_ABORTED; | |
3308 | pDevice->TxCounters.TxPacketAbortedCnt++; | |
3309 | ||
3310 | atomic_add (pPacket->u.Tx.FragCount, &pDevice->SendBdLeft); | |
3311 | ||
3312 | QQ_PushTail (&pDevice->TxPacketXmittedQ.Container, pPacket); | |
3313 | ||
3314 | pPacket = (PLM_PACKET) | |
3315 | QQ_PopHead (&pDevice->TxPacketActiveQ.Container); | |
3316 | } | |
3317 | ||
3318 | /* Cleanup the receive return rings. */ | |
3319 | LM_ServiceRxInterrupt (pDevice); | |
3320 | ||
3321 | /* Don't want to indicate rx packets in Ndis miniport shutdown context. */ | |
3322 | /* Doing so may cause system crash. */ | |
3323 | if (!pDevice->ShuttingDown) { | |
3324 | /* Indicate packets to the protocol. */ | |
3325 | MM_IndicateTxPackets (pDevice); | |
3326 | ||
3327 | /* Indicate received packets to the protocols. */ | |
3328 | MM_IndicateRxPackets (pDevice); | |
3329 | } else { | |
3330 | /* Move the receive packet descriptors in the ReceivedQ to the */ | |
3331 | /* free queue. */ | |
3332 | for (;;) { | |
3333 | pPacket = | |
3334 | (PLM_PACKET) QQ_PopHead (&pDevice-> | |
3335 | RxPacketReceivedQ. | |
3336 | Container); | |
3337 | if (pPacket == NULL) { | |
3338 | break; | |
3339 | } | |
3340 | QQ_PushTail (&pDevice->RxPacketFreeQ.Container, | |
3341 | pPacket); | |
3342 | } | |
8bde7f77 | 3343 | } |
c609719b | 3344 | |
f539edc0 VB |
3345 | /* Clean up the Std Receive Producer ring. */ |
3346 | Idx = pDevice->pStatusBlkVirt->RcvStdConIdx; | |
c609719b | 3347 | |
f539edc0 VB |
3348 | while (Idx != pDevice->RxStdProdIdx) { |
3349 | pPacket = (PLM_PACKET) (MM_UINT_PTR (pDevice->pPacketDescBase) + | |
3350 | MM_UINT_PTR (pDevice->pRxStdBdVirt[Idx]. | |
3351 | Opaque)); | |
c609719b | 3352 | |
f539edc0 | 3353 | QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket); |
c609719b | 3354 | |
f539edc0 VB |
3355 | Idx = (Idx + 1) & T3_STD_RCV_RCB_ENTRY_COUNT_MASK; |
3356 | } /* while */ | |
c609719b | 3357 | |
f539edc0 VB |
3358 | /* Reinitialize our copy of the indices. */ |
3359 | pDevice->RxStdProdIdx = 0; | |
c609719b WD |
3360 | |
3361 | #if T3_JUMBO_RCV_RCB_ENTRY_COUNT | |
f539edc0 VB |
3362 | /* Clean up the Jumbo Receive Producer ring. */ |
3363 | Idx = pDevice->pStatusBlkVirt->RcvJumboConIdx; | |
c609719b | 3364 | |
f539edc0 VB |
3365 | while (Idx != pDevice->RxJumboProdIdx) { |
3366 | pPacket = (PLM_PACKET) (MM_UINT_PTR (pDevice->pPacketDescBase) + | |
3367 | MM_UINT_PTR (pDevice-> | |
3368 | pRxJumboBdVirt[Idx]. | |
3369 | Opaque)); | |
c609719b | 3370 | |
f539edc0 | 3371 | QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket); |
c609719b | 3372 | |
f539edc0 VB |
3373 | Idx = (Idx + 1) & T3_JUMBO_RCV_RCB_ENTRY_COUNT_MASK; |
3374 | } /* while */ | |
c609719b | 3375 | |
f539edc0 VB |
3376 | /* Reinitialize our copy of the indices. */ |
3377 | pDevice->RxJumboProdIdx = 0; | |
3378 | #endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ | |
c609719b | 3379 | |
f539edc0 | 3380 | MM_RELEASE_INT_LOCK (pDevice); |
c609719b | 3381 | |
f539edc0 VB |
3382 | /* Initialize the statistis Block */ |
3383 | pDevice->pStatusBlkVirt->Status = 0; | |
3384 | pDevice->pStatusBlkVirt->RcvStdConIdx = 0; | |
3385 | pDevice->pStatusBlkVirt->RcvJumboConIdx = 0; | |
3386 | pDevice->pStatusBlkVirt->RcvMiniConIdx = 0; | |
c609719b | 3387 | |
f539edc0 VB |
3388 | return LM_STATUS_SUCCESS; |
3389 | } /* LM_Abort */ | |
c609719b | 3390 | |
c609719b WD |
3391 | /******************************************************************************/ |
3392 | /* Description: */ | |
3393 | /* Disable the interrupt and put the transmitter and receiver engines in */ | |
3394 | /* an idle state. Aborts all pending send requests and receive buffers. */ | |
3395 | /* Also free all the receive buffers. */ | |
3396 | /* */ | |
3397 | /* Return: */ | |
3398 | /* LM_STATUS_SUCCESS */ | |
3399 | /******************************************************************************/ | |
f539edc0 VB |
3400 | LM_STATUS LM_Halt (PLM_DEVICE_BLOCK pDevice) |
3401 | { | |
3402 | PLM_PACKET pPacket; | |
3403 | LM_UINT32 EntryCnt; | |
c609719b | 3404 | |
f539edc0 | 3405 | LM_Abort (pDevice); |
c609719b | 3406 | |
f539edc0 VB |
3407 | /* Get the number of entries in the queue. */ |
3408 | EntryCnt = QQ_GetEntryCnt (&pDevice->RxPacketFreeQ.Container); | |
c609719b | 3409 | |
f539edc0 VB |
3410 | /* Make sure all the packets have been accounted for. */ |
3411 | for (EntryCnt = 0; EntryCnt < pDevice->RxPacketDescCnt; EntryCnt++) { | |
3412 | pPacket = | |
3413 | (PLM_PACKET) QQ_PopHead (&pDevice->RxPacketFreeQ.Container); | |
3414 | if (pPacket == 0) | |
3415 | break; | |
c609719b | 3416 | |
f539edc0 | 3417 | MM_FreeRxBuffer (pDevice, pPacket); |
c609719b | 3418 | |
f539edc0 VB |
3419 | QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket); |
3420 | } | |
c609719b | 3421 | |
f539edc0 | 3422 | LM_ResetChip (pDevice); |
c609719b | 3423 | |
f539edc0 VB |
3424 | /* Restore PCI configuration registers. */ |
3425 | MM_WriteConfig32 (pDevice, PCI_CACHE_LINE_SIZE_REG, | |
3426 | pDevice->SavedCacheLineReg); | |
3427 | LM_RegWrInd (pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG, | |
3428 | (pDevice->SubsystemId << 16) | pDevice->SubsystemVendorId); | |
c609719b | 3429 | |
f539edc0 | 3430 | /* Reprogram the MAC address. */ |
c4b8762f | 3431 | LM_SetMacAddress (pDevice); |
c609719b | 3432 | |
f539edc0 VB |
3433 | return LM_STATUS_SUCCESS; |
3434 | } /* LM_Halt */ | |
c609719b | 3435 | |
f539edc0 | 3436 | STATIC LM_STATUS LM_ResetChip (PLM_DEVICE_BLOCK pDevice) |
c609719b | 3437 | { |
f539edc0 VB |
3438 | LM_UINT32 Value32; |
3439 | LM_UINT32 j; | |
3440 | ||
3441 | /* Wait for access to the nvram interface before resetting. This is */ | |
3442 | /* a workaround to prevent EEPROM corruption. */ | |
3443 | if (T3_ASIC_REV (pDevice->ChipRevId) != T3_ASIC_REV_5700 && | |
3444 | T3_ASIC_REV (pDevice->ChipRevId) != T3_ASIC_REV_5701) { | |
3445 | /* Request access to the flash interface. */ | |
3446 | REG_WR (pDevice, Nvram.SwArb, SW_ARB_REQ_SET1); | |
3447 | ||
3448 | for (j = 0; j < 100000; j++) { | |
3449 | Value32 = REG_RD (pDevice, Nvram.SwArb); | |
3450 | if (Value32 & SW_ARB_GNT1) { | |
3451 | break; | |
3452 | } | |
3453 | MM_Wait (10); | |
3454 | } | |
8bde7f77 | 3455 | } |
c609719b | 3456 | |
f539edc0 VB |
3457 | /* Global reset. */ |
3458 | REG_WR (pDevice, Grc.MiscCfg, GRC_MISC_CFG_CORE_CLOCK_RESET); | |
3459 | MM_Wait (40); | |
3460 | MM_Wait (40); | |
3461 | MM_Wait (40); | |
c609719b | 3462 | |
f539edc0 VB |
3463 | /* make sure we re-enable indirect accesses */ |
3464 | MM_WriteConfig32 (pDevice, T3_PCI_MISC_HOST_CTRL_REG, | |
3465 | pDevice->MiscHostCtrl); | |
c609719b | 3466 | |
f539edc0 VB |
3467 | /* Set MAX PCI retry to zero. */ |
3468 | Value32 = | |
3469 | T3_PCI_STATE_PCI_ROM_ENABLE | T3_PCI_STATE_PCI_ROM_RETRY_ENABLE; | |
3470 | if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0) { | |
3471 | if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE)) { | |
3472 | Value32 |= T3_PCI_STATE_RETRY_SAME_DMA; | |
3473 | } | |
8bde7f77 | 3474 | } |
f539edc0 | 3475 | MM_WriteConfig32 (pDevice, T3_PCI_STATE_REG, Value32); |
c609719b | 3476 | |
f539edc0 VB |
3477 | /* Restore PCI command register. */ |
3478 | MM_WriteConfig32 (pDevice, PCI_COMMAND_REG, | |
3479 | pDevice->PciCommandStatusWords); | |
c609719b | 3480 | |
f539edc0 VB |
3481 | /* Disable PCI-X relaxed ordering bit. */ |
3482 | MM_ReadConfig32 (pDevice, PCIX_CAP_REG, &Value32); | |
3483 | Value32 &= ~PCIX_ENABLE_RELAXED_ORDERING; | |
3484 | MM_WriteConfig32 (pDevice, PCIX_CAP_REG, Value32); | |
c609719b | 3485 | |
f539edc0 VB |
3486 | /* Enable memory arbiter. */ |
3487 | REG_WR (pDevice, MemArbiter.Mode, T3_MEM_ARBITER_MODE_ENABLE); | |
c609719b | 3488 | |
f539edc0 VB |
3489 | #ifdef BIG_ENDIAN_PCI /* This from jfd */ |
3490 | Value32 = GRC_MODE_WORD_SWAP_DATA | GRC_MODE_WORD_SWAP_NON_FRAME_DATA; | |
c609719b WD |
3491 | #else |
3492 | #ifdef BIG_ENDIAN_HOST | |
f539edc0 VB |
3493 | /* Reconfigure the mode register. */ |
3494 | Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | | |
3495 | GRC_MODE_WORD_SWAP_NON_FRAME_DATA | | |
3496 | GRC_MODE_BYTE_SWAP_DATA | GRC_MODE_WORD_SWAP_DATA; | |
c609719b | 3497 | #else |
f539edc0 VB |
3498 | /* Reconfigure the mode register. */ |
3499 | Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | GRC_MODE_BYTE_SWAP_DATA; | |
c609719b WD |
3500 | #endif |
3501 | #endif | |
f539edc0 VB |
3502 | REG_WR (pDevice, Grc.Mode, Value32); |
3503 | ||
3504 | /* Prevent PXE from restarting. */ | |
3505 | MEM_WR_OFFSET (pDevice, 0x0b50, T3_MAGIC_NUM); | |
3506 | ||
3507 | if (pDevice->EnableTbi) { | |
3508 | pDevice->MacMode = MAC_MODE_PORT_MODE_TBI; | |
3509 | REG_WR (pDevice, MacCtrl.Mode, MAC_MODE_PORT_MODE_TBI); | |
3510 | } else { | |
3511 | REG_WR (pDevice, MacCtrl.Mode, 0); | |
3512 | } | |
3513 | ||
3514 | /* Wait for the firmware to finish initialization. */ | |
3515 | for (j = 0; j < 100000; j++) { | |
3516 | MM_Wait (10); | |
3517 | ||
3518 | Value32 = MEM_RD_OFFSET (pDevice, 0x0b50); | |
3519 | if (Value32 == ~T3_MAGIC_NUM) { | |
3520 | break; | |
3521 | } | |
8bde7f77 | 3522 | } |
f539edc0 | 3523 | return LM_STATUS_SUCCESS; |
c609719b WD |
3524 | } |
3525 | ||
3526 | /******************************************************************************/ | |
3527 | /* Description: */ | |
3528 | /* */ | |
3529 | /* Return: */ | |
3530 | /******************************************************************************/ | |
f539edc0 VB |
3531 | __inline static void LM_ServiceTxInterrupt (PLM_DEVICE_BLOCK pDevice) |
3532 | { | |
3533 | PLM_PACKET pPacket; | |
3534 | LM_UINT32 HwConIdx; | |
3535 | LM_UINT32 SwConIdx; | |
3536 | ||
8bde7f77 | 3537 | HwConIdx = pDevice->pStatusBlkVirt->Idx[0].SendConIdx; |
c609719b | 3538 | |
f539edc0 VB |
3539 | /* Get our copy of the consumer index. The buffer descriptors */ |
3540 | /* that are in between the consumer indices are freed. */ | |
3541 | SwConIdx = pDevice->SendConIdx; | |
3542 | ||
3543 | /* Move the packets from the TxPacketActiveQ that are sent out to */ | |
3544 | /* the TxPacketXmittedQ. Packets that are sent use the */ | |
3545 | /* descriptors that are between SwConIdx and HwConIdx. */ | |
3546 | while (SwConIdx != HwConIdx) { | |
3547 | /* Get the packet that was sent from the TxPacketActiveQ. */ | |
3548 | pPacket = | |
3549 | (PLM_PACKET) QQ_PopHead (&pDevice->TxPacketActiveQ. | |
3550 | Container); | |
3551 | ||
3552 | /* Set the return status. */ | |
3553 | pPacket->PacketStatus = LM_STATUS_SUCCESS; | |
3554 | ||
3555 | /* Put the packet in the TxPacketXmittedQ for indication later. */ | |
3556 | QQ_PushTail (&pDevice->TxPacketXmittedQ.Container, pPacket); | |
3557 | ||
3558 | /* Move to the next packet's BD. */ | |
3559 | SwConIdx = (SwConIdx + pPacket->u.Tx.FragCount) & | |
3560 | T3_SEND_RCB_ENTRY_COUNT_MASK; | |
3561 | ||
3562 | /* Update the number of unused BDs. */ | |
3563 | atomic_add (pPacket->u.Tx.FragCount, &pDevice->SendBdLeft); | |
3564 | ||
3565 | /* Get the new updated HwConIdx. */ | |
3566 | HwConIdx = pDevice->pStatusBlkVirt->Idx[0].SendConIdx; | |
3567 | } /* while */ | |
c609719b | 3568 | |
f539edc0 VB |
3569 | /* Save the new SwConIdx. */ |
3570 | pDevice->SendConIdx = SwConIdx; | |
c609719b | 3571 | |
f539edc0 | 3572 | } /* LM_ServiceTxInterrupt */ |
c609719b | 3573 | |
c609719b WD |
3574 | /******************************************************************************/ |
3575 | /* Description: */ | |
3576 | /* */ | |
3577 | /* Return: */ | |
3578 | /******************************************************************************/ | |
f539edc0 VB |
3579 | __inline static void LM_ServiceRxInterrupt (PLM_DEVICE_BLOCK pDevice) |
3580 | { | |
3581 | PLM_PACKET pPacket; | |
3582 | PT3_RCV_BD pRcvBd; | |
3583 | LM_UINT32 HwRcvRetProdIdx; | |
3584 | LM_UINT32 SwRcvRetConIdx; | |
8bde7f77 | 3585 | |
f539edc0 VB |
3586 | /* Loop thru the receive return rings for received packets. */ |
3587 | HwRcvRetProdIdx = pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx; | |
8bde7f77 | 3588 | |
f539edc0 VB |
3589 | SwRcvRetConIdx = pDevice->RcvRetConIdx; |
3590 | while (SwRcvRetConIdx != HwRcvRetProdIdx) { | |
3591 | pRcvBd = &pDevice->pRcvRetBdVirt[SwRcvRetConIdx]; | |
8bde7f77 | 3592 | |
f539edc0 VB |
3593 | /* Get the received packet descriptor. */ |
3594 | pPacket = (PLM_PACKET) (MM_UINT_PTR (pDevice->pPacketDescBase) + | |
3595 | MM_UINT_PTR (pRcvBd->Opaque)); | |
8bde7f77 | 3596 | |
f539edc0 VB |
3597 | /* Check the error flag. */ |
3598 | if (pRcvBd->ErrorFlag && | |
3599 | pRcvBd->ErrorFlag != RCV_BD_ERR_ODD_NIBBLED_RCVD_MII) { | |
3600 | pPacket->PacketStatus = LM_STATUS_FAILURE; | |
8bde7f77 | 3601 | |
f539edc0 VB |
3602 | pDevice->RxCounters.RxPacketErrCnt++; |
3603 | ||
3604 | if (pRcvBd->ErrorFlag & RCV_BD_ERR_BAD_CRC) { | |
3605 | pDevice->RxCounters.RxErrCrcCnt++; | |
3606 | } | |
3607 | ||
3608 | if (pRcvBd->ErrorFlag & RCV_BD_ERR_COLL_DETECT) { | |
3609 | pDevice->RxCounters.RxErrCollCnt++; | |
3610 | } | |
3611 | ||
3612 | if (pRcvBd->ErrorFlag & RCV_BD_ERR_LINK_LOST_DURING_PKT) { | |
3613 | pDevice->RxCounters.RxErrLinkLostCnt++; | |
3614 | } | |
3615 | ||
3616 | if (pRcvBd->ErrorFlag & RCV_BD_ERR_PHY_DECODE_ERR) { | |
3617 | pDevice->RxCounters.RxErrPhyDecodeCnt++; | |
3618 | } | |
c609719b | 3619 | |
f539edc0 VB |
3620 | if (pRcvBd->ErrorFlag & RCV_BD_ERR_ODD_NIBBLED_RCVD_MII) { |
3621 | pDevice->RxCounters.RxErrOddNibbleCnt++; | |
3622 | } | |
3623 | ||
3624 | if (pRcvBd->ErrorFlag & RCV_BD_ERR_MAC_ABORT) { | |
3625 | pDevice->RxCounters.RxErrMacAbortCnt++; | |
3626 | } | |
3627 | ||
3628 | if (pRcvBd->ErrorFlag & RCV_BD_ERR_LEN_LT_64) { | |
3629 | pDevice->RxCounters.RxErrShortPacketCnt++; | |
3630 | } | |
3631 | ||
3632 | if (pRcvBd->ErrorFlag & RCV_BD_ERR_TRUNC_NO_RESOURCES) { | |
3633 | pDevice->RxCounters.RxErrNoResourceCnt++; | |
3634 | } | |
3635 | ||
3636 | if (pRcvBd->ErrorFlag & RCV_BD_ERR_GIANT_FRAME_RCVD) { | |
3637 | pDevice->RxCounters.RxErrLargePacketCnt++; | |
3638 | } | |
3639 | } else { | |
3640 | pPacket->PacketStatus = LM_STATUS_SUCCESS; | |
3641 | pPacket->PacketSize = pRcvBd->Len - 4; | |
3642 | ||
3643 | pPacket->Flags = pRcvBd->Flags; | |
3644 | if (pRcvBd->Flags & RCV_BD_FLAG_VLAN_TAG) { | |
3645 | pPacket->VlanTag = pRcvBd->VlanTag; | |
3646 | } | |
3647 | ||
3648 | pPacket->u.Rx.TcpUdpChecksum = pRcvBd->TcpUdpCksum; | |
3649 | } | |
3650 | ||
3651 | /* Put the packet descriptor containing the received packet */ | |
3652 | /* buffer in the RxPacketReceivedQ for indication later. */ | |
3653 | QQ_PushTail (&pDevice->RxPacketReceivedQ.Container, pPacket); | |
3654 | ||
3655 | /* Go to the next buffer descriptor. */ | |
3656 | SwRcvRetConIdx = (SwRcvRetConIdx + 1) & | |
3657 | T3_RCV_RETURN_RCB_ENTRY_COUNT_MASK; | |
3658 | ||
3659 | /* Get the updated HwRcvRetProdIdx. */ | |
3660 | HwRcvRetProdIdx = pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx; | |
3661 | } /* while */ | |
c609719b | 3662 | |
f539edc0 | 3663 | pDevice->RcvRetConIdx = SwRcvRetConIdx; |
c609719b | 3664 | |
f539edc0 VB |
3665 | /* Update the receive return ring consumer index. */ |
3666 | MB_REG_WR (pDevice, Mailbox.RcvRetConIdx[0].Low, SwRcvRetConIdx); | |
3667 | } /* LM_ServiceRxInterrupt */ | |
c609719b | 3668 | |
c609719b WD |
3669 | /******************************************************************************/ |
3670 | /* Description: */ | |
3671 | /* This is the interrupt event handler routine. It acknowledges all */ | |
3672 | /* pending interrupts and process all pending events. */ | |
3673 | /* */ | |
3674 | /* Return: */ | |
3675 | /* LM_STATUS_SUCCESS */ | |
3676 | /******************************************************************************/ | |
f539edc0 | 3677 | LM_STATUS LM_ServiceInterrupts (PLM_DEVICE_BLOCK pDevice) |
c609719b | 3678 | { |
f539edc0 VB |
3679 | LM_UINT32 Value32; |
3680 | int ServicePhyInt = FALSE; | |
3681 | ||
3682 | /* Setup the phy chip whenever the link status changes. */ | |
3683 | if (pDevice->LinkChngMode == T3_LINK_CHNG_MODE_USE_STATUS_REG) { | |
3684 | Value32 = REG_RD (pDevice, MacCtrl.Status); | |
3685 | if (pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT) { | |
3686 | if (Value32 & MAC_STATUS_MI_INTERRUPT) { | |
3687 | ServicePhyInt = TRUE; | |
3688 | } | |
3689 | } else if (Value32 & MAC_STATUS_LINK_STATE_CHANGED) { | |
3690 | ServicePhyInt = TRUE; | |
3691 | } | |
3692 | } else { | |
3693 | if (pDevice->pStatusBlkVirt-> | |
3694 | Status & STATUS_BLOCK_LINK_CHANGED_STATUS) { | |
3695 | pDevice->pStatusBlkVirt->Status = | |
3696 | STATUS_BLOCK_UPDATED | (pDevice->pStatusBlkVirt-> | |
3697 | Status & | |
3698 | ~STATUS_BLOCK_LINK_CHANGED_STATUS); | |
3699 | ServicePhyInt = TRUE; | |
3700 | } | |
8bde7f77 | 3701 | } |
c609719b | 3702 | #if INCLUDE_TBI_SUPPORT |
f539edc0 VB |
3703 | if (pDevice->IgnoreTbiLinkChange == TRUE) { |
3704 | ServicePhyInt = FALSE; | |
3705 | } | |
c609719b | 3706 | #endif |
f539edc0 VB |
3707 | if (ServicePhyInt == TRUE) { |
3708 | LM_SetupPhy (pDevice); | |
3709 | } | |
c609719b | 3710 | |
f539edc0 VB |
3711 | /* Service receive and transmit interrupts. */ |
3712 | LM_ServiceRxInterrupt (pDevice); | |
3713 | LM_ServiceTxInterrupt (pDevice); | |
c609719b | 3714 | |
f539edc0 VB |
3715 | /* No spinlock for this queue since this routine is serialized. */ |
3716 | if (!QQ_Empty (&pDevice->RxPacketReceivedQ.Container)) { | |
3717 | /* Indicate receive packets. */ | |
3718 | MM_IndicateRxPackets (pDevice); | |
3719 | /* LM_QueueRxPackets(pDevice); */ | |
3720 | } | |
c609719b | 3721 | |
f539edc0 VB |
3722 | /* No spinlock for this queue since this routine is serialized. */ |
3723 | if (!QQ_Empty (&pDevice->TxPacketXmittedQ.Container)) { | |
3724 | MM_IndicateTxPackets (pDevice); | |
3725 | } | |
c609719b | 3726 | |
f539edc0 VB |
3727 | return LM_STATUS_SUCCESS; |
3728 | } /* LM_ServiceInterrupts */ | |
c609719b | 3729 | |
c609719b WD |
3730 | /******************************************************************************/ |
3731 | /* Description: */ | |
3732 | /* */ | |
3733 | /* Return: */ | |
3734 | /******************************************************************************/ | |
f539edc0 VB |
3735 | LM_STATUS LM_MulticastAdd (PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMcAddress) |
3736 | { | |
3737 | PLM_UINT8 pEntry; | |
3738 | LM_UINT32 j; | |
c609719b | 3739 | |
f539edc0 VB |
3740 | pEntry = pDevice->McTable[0]; |
3741 | for (j = 0; j < pDevice->McEntryCount; j++) { | |
3742 | if (IS_ETH_ADDRESS_EQUAL (pEntry, pMcAddress)) { | |
3743 | /* Found a match, increment the instance count. */ | |
3744 | pEntry[LM_MC_INSTANCE_COUNT_INDEX] += 1; | |
c609719b | 3745 | |
f539edc0 VB |
3746 | return LM_STATUS_SUCCESS; |
3747 | } | |
c609719b | 3748 | |
f539edc0 VB |
3749 | pEntry += LM_MC_ENTRY_SIZE; |
3750 | } | |
c609719b | 3751 | |
f539edc0 VB |
3752 | if (pDevice->McEntryCount >= LM_MAX_MC_TABLE_SIZE) { |
3753 | return LM_STATUS_FAILURE; | |
3754 | } | |
c609719b | 3755 | |
f539edc0 | 3756 | pEntry = pDevice->McTable[pDevice->McEntryCount]; |
c609719b | 3757 | |
f539edc0 VB |
3758 | COPY_ETH_ADDRESS (pMcAddress, pEntry); |
3759 | pEntry[LM_MC_INSTANCE_COUNT_INDEX] = 1; | |
c609719b | 3760 | |
f539edc0 | 3761 | pDevice->McEntryCount++; |
c609719b | 3762 | |
f539edc0 | 3763 | LM_SetReceiveMask (pDevice, pDevice->ReceiveMask | LM_ACCEPT_MULTICAST); |
c609719b | 3764 | |
f539edc0 VB |
3765 | return LM_STATUS_SUCCESS; |
3766 | } /* LM_MulticastAdd */ | |
c609719b | 3767 | |
c609719b WD |
3768 | /******************************************************************************/ |
3769 | /* Description: */ | |
3770 | /* */ | |
3771 | /* Return: */ | |
3772 | /******************************************************************************/ | |
f539edc0 VB |
3773 | LM_STATUS LM_MulticastDel (PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMcAddress) |
3774 | { | |
3775 | PLM_UINT8 pEntry; | |
3776 | LM_UINT32 j; | |
3777 | ||
3778 | pEntry = pDevice->McTable[0]; | |
3779 | for (j = 0; j < pDevice->McEntryCount; j++) { | |
3780 | if (IS_ETH_ADDRESS_EQUAL (pEntry, pMcAddress)) { | |
3781 | /* Found a match, decrement the instance count. */ | |
3782 | pEntry[LM_MC_INSTANCE_COUNT_INDEX] -= 1; | |
3783 | ||
3784 | /* No more instance left, remove the address from the table. */ | |
3785 | /* Move the last entry in the table to the delete slot. */ | |
3786 | if (pEntry[LM_MC_INSTANCE_COUNT_INDEX] == 0 && | |
3787 | pDevice->McEntryCount > 1) { | |
3788 | ||
3789 | COPY_ETH_ADDRESS (pDevice-> | |
3790 | McTable[pDevice-> | |
3791 | McEntryCount - 1], | |
3792 | pEntry); | |
3793 | pEntry[LM_MC_INSTANCE_COUNT_INDEX] = | |
3794 | pDevice->McTable[pDevice->McEntryCount - 1] | |
3795 | [LM_MC_INSTANCE_COUNT_INDEX]; | |
3796 | } | |
3797 | pDevice->McEntryCount--; | |
3798 | ||
3799 | /* Update the receive mask if the table is empty. */ | |
3800 | if (pDevice->McEntryCount == 0) { | |
3801 | LM_SetReceiveMask (pDevice, | |
3802 | pDevice-> | |
3803 | ReceiveMask & | |
3804 | ~LM_ACCEPT_MULTICAST); | |
3805 | } | |
8bde7f77 | 3806 | |
f539edc0 VB |
3807 | return LM_STATUS_SUCCESS; |
3808 | } | |
8bde7f77 | 3809 | |
f539edc0 | 3810 | pEntry += LM_MC_ENTRY_SIZE; |
8bde7f77 | 3811 | } |
c609719b | 3812 | |
f539edc0 VB |
3813 | return LM_STATUS_FAILURE; |
3814 | } /* LM_MulticastDel */ | |
c609719b | 3815 | |
c609719b WD |
3816 | /******************************************************************************/ |
3817 | /* Description: */ | |
3818 | /* */ | |
3819 | /* Return: */ | |
3820 | /******************************************************************************/ | |
f539edc0 VB |
3821 | LM_STATUS LM_MulticastClear (PLM_DEVICE_BLOCK pDevice) |
3822 | { | |
3823 | pDevice->McEntryCount = 0; | |
c609719b | 3824 | |
f539edc0 VB |
3825 | LM_SetReceiveMask (pDevice, |
3826 | pDevice->ReceiveMask & ~LM_ACCEPT_MULTICAST); | |
c609719b | 3827 | |
f539edc0 VB |
3828 | return LM_STATUS_SUCCESS; |
3829 | } /* LM_MulticastClear */ | |
c609719b | 3830 | |
c609719b WD |
3831 | /******************************************************************************/ |
3832 | /* Description: */ | |
3833 | /* */ | |
3834 | /* Return: */ | |
3835 | /******************************************************************************/ | |
c4b8762f | 3836 | LM_STATUS LM_SetMacAddress (PLM_DEVICE_BLOCK pDevice) |
c609719b | 3837 | { |
f539edc0 | 3838 | LM_UINT32 j; |
c4b8762f | 3839 | PLM_UINT8 pMacAddress = pDevice->NodeAddress; |
f539edc0 VB |
3840 | |
3841 | for (j = 0; j < 4; j++) { | |
3842 | REG_WR (pDevice, MacCtrl.MacAddr[j].High, | |
3843 | (pMacAddress[0] << 8) | pMacAddress[1]); | |
3844 | REG_WR (pDevice, MacCtrl.MacAddr[j].Low, | |
3845 | (pMacAddress[2] << 24) | (pMacAddress[3] << 16) | | |
3846 | (pMacAddress[4] << 8) | pMacAddress[5]); | |
3847 | } | |
c609719b | 3848 | |
f539edc0 VB |
3849 | return LM_STATUS_SUCCESS; |
3850 | } | |
c609719b WD |
3851 | |
3852 | /******************************************************************************/ | |
3853 | /* Description: */ | |
3854 | /* Sets up the default line speed, and duplex modes based on the requested */ | |
3855 | /* media type. */ | |
3856 | /* */ | |
3857 | /* Return: */ | |
3858 | /* None. */ | |
3859 | /******************************************************************************/ | |
3860 | static LM_STATUS | |
f539edc0 VB |
3861 | LM_TranslateRequestedMediaType (LM_REQUESTED_MEDIA_TYPE RequestedMediaType, |
3862 | PLM_MEDIA_TYPE pMediaType, | |
3863 | PLM_LINE_SPEED pLineSpeed, | |
3864 | PLM_DUPLEX_MODE pDuplexMode) | |
3865 | { | |
3866 | *pMediaType = LM_MEDIA_TYPE_AUTO; | |
3867 | *pLineSpeed = LM_LINE_SPEED_UNKNOWN; | |
3868 | *pDuplexMode = LM_DUPLEX_MODE_UNKNOWN; | |
3869 | ||
3870 | /* determine media type */ | |
3871 | switch (RequestedMediaType) { | |
8bde7f77 | 3872 | case LM_REQUESTED_MEDIA_TYPE_BNC: |
f539edc0 VB |
3873 | *pMediaType = LM_MEDIA_TYPE_BNC; |
3874 | *pLineSpeed = LM_LINE_SPEED_10MBPS; | |
3875 | *pDuplexMode = LM_DUPLEX_MODE_HALF; | |
3876 | break; | |
8bde7f77 WD |
3877 | |
3878 | case LM_REQUESTED_MEDIA_TYPE_UTP_AUTO: | |
f539edc0 VB |
3879 | *pMediaType = LM_MEDIA_TYPE_UTP; |
3880 | break; | |
8bde7f77 WD |
3881 | |
3882 | case LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS: | |
f539edc0 VB |
3883 | *pMediaType = LM_MEDIA_TYPE_UTP; |
3884 | *pLineSpeed = LM_LINE_SPEED_10MBPS; | |
3885 | *pDuplexMode = LM_DUPLEX_MODE_HALF; | |
3886 | break; | |
8bde7f77 WD |
3887 | |
3888 | case LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS_FULL_DUPLEX: | |
f539edc0 VB |
3889 | *pMediaType = LM_MEDIA_TYPE_UTP; |
3890 | *pLineSpeed = LM_LINE_SPEED_10MBPS; | |
3891 | *pDuplexMode = LM_DUPLEX_MODE_FULL; | |
3892 | break; | |
8bde7f77 WD |
3893 | |
3894 | case LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS: | |
f539edc0 VB |
3895 | *pMediaType = LM_MEDIA_TYPE_UTP; |
3896 | *pLineSpeed = LM_LINE_SPEED_100MBPS; | |
3897 | *pDuplexMode = LM_DUPLEX_MODE_HALF; | |
3898 | break; | |
8bde7f77 WD |
3899 | |
3900 | case LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS_FULL_DUPLEX: | |
f539edc0 VB |
3901 | *pMediaType = LM_MEDIA_TYPE_UTP; |
3902 | *pLineSpeed = LM_LINE_SPEED_100MBPS; | |
3903 | *pDuplexMode = LM_DUPLEX_MODE_FULL; | |
3904 | break; | |
8bde7f77 WD |
3905 | |
3906 | case LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS: | |
f539edc0 VB |
3907 | *pMediaType = LM_MEDIA_TYPE_UTP; |
3908 | *pLineSpeed = LM_LINE_SPEED_1000MBPS; | |
3909 | *pDuplexMode = LM_DUPLEX_MODE_HALF; | |
3910 | break; | |
8bde7f77 WD |
3911 | |
3912 | case LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS_FULL_DUPLEX: | |
f539edc0 VB |
3913 | *pMediaType = LM_MEDIA_TYPE_UTP; |
3914 | *pLineSpeed = LM_LINE_SPEED_1000MBPS; | |
3915 | *pDuplexMode = LM_DUPLEX_MODE_FULL; | |
3916 | break; | |
8bde7f77 WD |
3917 | |
3918 | case LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS: | |
f539edc0 VB |
3919 | *pMediaType = LM_MEDIA_TYPE_FIBER; |
3920 | *pLineSpeed = LM_LINE_SPEED_100MBPS; | |
3921 | *pDuplexMode = LM_DUPLEX_MODE_HALF; | |
3922 | break; | |
8bde7f77 WD |
3923 | |
3924 | case LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS_FULL_DUPLEX: | |
f539edc0 VB |
3925 | *pMediaType = LM_MEDIA_TYPE_FIBER; |
3926 | *pLineSpeed = LM_LINE_SPEED_100MBPS; | |
3927 | *pDuplexMode = LM_DUPLEX_MODE_FULL; | |
3928 | break; | |
8bde7f77 WD |
3929 | |
3930 | case LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS: | |
f539edc0 VB |
3931 | *pMediaType = LM_MEDIA_TYPE_FIBER; |
3932 | *pLineSpeed = LM_LINE_SPEED_1000MBPS; | |
3933 | *pDuplexMode = LM_DUPLEX_MODE_HALF; | |
3934 | break; | |
8bde7f77 WD |
3935 | |
3936 | case LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS_FULL_DUPLEX: | |
f539edc0 VB |
3937 | *pMediaType = LM_MEDIA_TYPE_FIBER; |
3938 | *pLineSpeed = LM_LINE_SPEED_1000MBPS; | |
3939 | *pDuplexMode = LM_DUPLEX_MODE_FULL; | |
3940 | break; | |
8bde7f77 WD |
3941 | |
3942 | default: | |
f539edc0 VB |
3943 | break; |
3944 | } /* switch */ | |
c609719b | 3945 | |
f539edc0 VB |
3946 | return LM_STATUS_SUCCESS; |
3947 | } /* LM_TranslateRequestedMediaType */ | |
c609719b WD |
3948 | |
3949 | /******************************************************************************/ | |
3950 | /* Description: */ | |
3951 | /* */ | |
3952 | /* Return: */ | |
3953 | /* LM_STATUS_LINK_ACTIVE */ | |
3954 | /* LM_STATUS_LINK_DOWN */ | |
3955 | /******************************************************************************/ | |
f539edc0 | 3956 | static LM_STATUS LM_InitBcm540xPhy (PLM_DEVICE_BLOCK pDevice) |
c609719b | 3957 | { |
f539edc0 VB |
3958 | LM_LINE_SPEED CurrentLineSpeed; |
3959 | LM_DUPLEX_MODE CurrentDuplexMode; | |
3960 | LM_STATUS CurrentLinkStatus; | |
3961 | LM_UINT32 Value32; | |
3962 | LM_UINT32 j; | |
3963 | ||
3964 | #if 1 /* jmb: bugfix -- moved here, out of code that sets initial pwr state */ | |
3965 | LM_WritePhy (pDevice, BCM5401_AUX_CTRL, 0x2); | |
c609719b | 3966 | #endif |
f539edc0 VB |
3967 | if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID) { |
3968 | LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); | |
3969 | LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); | |
c609719b | 3970 | |
f539edc0 VB |
3971 | if (!pDevice->InitDone) { |
3972 | Value32 = 0; | |
3973 | } | |
c609719b | 3974 | |
f539edc0 VB |
3975 | if (!(Value32 & PHY_STATUS_LINK_PASS)) { |
3976 | LM_WritePhy (pDevice, BCM5401_AUX_CTRL, 0x0c20); | |
c609719b | 3977 | |
f539edc0 VB |
3978 | LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x0012); |
3979 | LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x1804); | |
c609719b | 3980 | |
f539edc0 VB |
3981 | LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x0013); |
3982 | LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x1204); | |
c609719b | 3983 | |
f539edc0 VB |
3984 | LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006); |
3985 | LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x0132); | |
c609719b | 3986 | |
f539edc0 VB |
3987 | LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006); |
3988 | LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x0232); | |
c609719b | 3989 | |
f539edc0 VB |
3990 | LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x201f); |
3991 | LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x0a20); | |
c609719b | 3992 | |
f539edc0 VB |
3993 | LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); |
3994 | for (j = 0; j < 1000; j++) { | |
3995 | MM_Wait (10); | |
c609719b | 3996 | |
f539edc0 VB |
3997 | LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); |
3998 | if (Value32 & PHY_STATUS_LINK_PASS) { | |
3999 | MM_Wait (40); | |
4000 | break; | |
4001 | } | |
8bde7f77 | 4002 | } |
c609719b | 4003 | |
f539edc0 VB |
4004 | if ((pDevice->PhyId & PHY_ID_REV_MASK) == |
4005 | PHY_BCM5401_B0_REV) { | |
4006 | if (!(Value32 & PHY_STATUS_LINK_PASS) | |
4007 | && (pDevice->OldLineSpeed == | |
4008 | LM_LINE_SPEED_1000MBPS)) { | |
4009 | LM_WritePhy (pDevice, PHY_CTRL_REG, | |
4010 | PHY_CTRL_PHY_RESET); | |
4011 | for (j = 0; j < 100; j++) { | |
4012 | MM_Wait (10); | |
4013 | ||
4014 | LM_ReadPhy (pDevice, | |
4015 | PHY_CTRL_REG, | |
4016 | &Value32); | |
4017 | if (! | |
4018 | (Value32 & | |
4019 | PHY_CTRL_PHY_RESET)) { | |
4020 | MM_Wait (40); | |
4021 | break; | |
4022 | } | |
4023 | } | |
4024 | ||
4025 | LM_WritePhy (pDevice, BCM5401_AUX_CTRL, | |
4026 | 0x0c20); | |
4027 | ||
4028 | LM_WritePhy (pDevice, | |
4029 | BCM540X_DSP_ADDRESS_REG, | |
4030 | 0x0012); | |
4031 | LM_WritePhy (pDevice, | |
4032 | BCM540X_DSP_RW_PORT, | |
4033 | 0x1804); | |
4034 | ||
4035 | LM_WritePhy (pDevice, | |
4036 | BCM540X_DSP_ADDRESS_REG, | |
4037 | 0x0013); | |
4038 | LM_WritePhy (pDevice, | |
4039 | BCM540X_DSP_RW_PORT, | |
4040 | 0x1204); | |
4041 | ||
4042 | LM_WritePhy (pDevice, | |
4043 | BCM540X_DSP_ADDRESS_REG, | |
4044 | 0x8006); | |
4045 | LM_WritePhy (pDevice, | |
4046 | BCM540X_DSP_RW_PORT, | |
4047 | 0x0132); | |
4048 | ||
4049 | LM_WritePhy (pDevice, | |
4050 | BCM540X_DSP_ADDRESS_REG, | |
4051 | 0x8006); | |
4052 | LM_WritePhy (pDevice, | |
4053 | BCM540X_DSP_RW_PORT, | |
4054 | 0x0232); | |
4055 | ||
4056 | LM_WritePhy (pDevice, | |
4057 | BCM540X_DSP_ADDRESS_REG, | |
4058 | 0x201f); | |
4059 | LM_WritePhy (pDevice, | |
4060 | BCM540X_DSP_RW_PORT, | |
4061 | 0x0a20); | |
4062 | } | |
4063 | } | |
4064 | } | |
4065 | } else if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 || | |
4066 | pDevice->ChipRevId == T3_CHIP_ID_5701_B0) { | |
4067 | /* Bug: 5701 A0, B0 TX CRC workaround. */ | |
4068 | LM_WritePhy (pDevice, 0x15, 0x0a75); | |
4069 | LM_WritePhy (pDevice, 0x1c, 0x8c68); | |
4070 | LM_WritePhy (pDevice, 0x1c, 0x8d68); | |
4071 | LM_WritePhy (pDevice, 0x1c, 0x8c68); | |
4072 | } | |
4073 | ||
4074 | /* Acknowledge interrupts. */ | |
4075 | LM_ReadPhy (pDevice, BCM540X_INT_STATUS_REG, &Value32); | |
4076 | LM_ReadPhy (pDevice, BCM540X_INT_STATUS_REG, &Value32); | |
4077 | ||
4078 | /* Configure the interrupt mask. */ | |
4079 | if (pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT) { | |
4080 | LM_WritePhy (pDevice, BCM540X_INT_MASK_REG, | |
4081 | ~BCM540X_INT_LINK_CHANGE); | |
4082 | } | |
4083 | ||
4084 | /* Configure PHY led mode. */ | |
4085 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701 || | |
4086 | (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700)) { | |
4087 | if (pDevice->LedMode == LED_MODE_THREE_LINK) { | |
4088 | LM_WritePhy (pDevice, BCM540X_EXT_CTRL_REG, | |
4089 | BCM540X_EXT_CTRL_LINK3_LED_MODE); | |
4090 | } else { | |
4091 | LM_WritePhy (pDevice, BCM540X_EXT_CTRL_REG, 0); | |
8bde7f77 | 4092 | } |
8bde7f77 | 4093 | } |
c609719b | 4094 | |
f539edc0 | 4095 | CurrentLinkStatus = LM_STATUS_LINK_DOWN; |
c609719b | 4096 | |
f539edc0 VB |
4097 | /* Get current link and duplex mode. */ |
4098 | for (j = 0; j < 100; j++) { | |
4099 | LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); | |
4100 | LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); | |
c609719b | 4101 | |
f539edc0 VB |
4102 | if (Value32 & PHY_STATUS_LINK_PASS) { |
4103 | break; | |
4104 | } | |
4105 | MM_Wait (40); | |
8bde7f77 | 4106 | } |
8bde7f77 | 4107 | |
f539edc0 | 4108 | if (Value32 & PHY_STATUS_LINK_PASS) { |
8bde7f77 | 4109 | |
f539edc0 VB |
4110 | /* Determine the current line and duplex settings. */ |
4111 | LM_ReadPhy (pDevice, BCM540X_AUX_STATUS_REG, &Value32); | |
4112 | for (j = 0; j < 2000; j++) { | |
4113 | MM_Wait (10); | |
8bde7f77 | 4114 | |
f539edc0 VB |
4115 | LM_ReadPhy (pDevice, BCM540X_AUX_STATUS_REG, &Value32); |
4116 | if (Value32) { | |
4117 | break; | |
4118 | } | |
4119 | } | |
8bde7f77 | 4120 | |
f539edc0 VB |
4121 | switch (Value32 & BCM540X_AUX_SPEED_MASK) { |
4122 | case BCM540X_AUX_10BASET_HD: | |
4123 | CurrentLineSpeed = LM_LINE_SPEED_10MBPS; | |
4124 | CurrentDuplexMode = LM_DUPLEX_MODE_HALF; | |
4125 | break; | |
8bde7f77 | 4126 | |
f539edc0 VB |
4127 | case BCM540X_AUX_10BASET_FD: |
4128 | CurrentLineSpeed = LM_LINE_SPEED_10MBPS; | |
4129 | CurrentDuplexMode = LM_DUPLEX_MODE_FULL; | |
4130 | break; | |
8bde7f77 | 4131 | |
f539edc0 VB |
4132 | case BCM540X_AUX_100BASETX_HD: |
4133 | CurrentLineSpeed = LM_LINE_SPEED_100MBPS; | |
4134 | CurrentDuplexMode = LM_DUPLEX_MODE_HALF; | |
4135 | break; | |
8bde7f77 | 4136 | |
f539edc0 VB |
4137 | case BCM540X_AUX_100BASETX_FD: |
4138 | CurrentLineSpeed = LM_LINE_SPEED_100MBPS; | |
4139 | CurrentDuplexMode = LM_DUPLEX_MODE_FULL; | |
4140 | break; | |
8bde7f77 | 4141 | |
f539edc0 VB |
4142 | case BCM540X_AUX_100BASET_HD: |
4143 | CurrentLineSpeed = LM_LINE_SPEED_1000MBPS; | |
4144 | CurrentDuplexMode = LM_DUPLEX_MODE_HALF; | |
4145 | break; | |
8bde7f77 | 4146 | |
f539edc0 VB |
4147 | case BCM540X_AUX_100BASET_FD: |
4148 | CurrentLineSpeed = LM_LINE_SPEED_1000MBPS; | |
4149 | CurrentDuplexMode = LM_DUPLEX_MODE_FULL; | |
4150 | break; | |
8bde7f77 | 4151 | |
f539edc0 | 4152 | default: |
8bde7f77 | 4153 | |
f539edc0 VB |
4154 | CurrentLineSpeed = LM_LINE_SPEED_UNKNOWN; |
4155 | CurrentDuplexMode = LM_DUPLEX_MODE_UNKNOWN; | |
4156 | break; | |
4157 | } | |
8bde7f77 | 4158 | |
f539edc0 VB |
4159 | /* Make sure we are in auto-neg mode. */ |
4160 | for (j = 0; j < 200; j++) { | |
4161 | LM_ReadPhy (pDevice, PHY_CTRL_REG, &Value32); | |
4162 | if (Value32 && Value32 != 0x7fff) { | |
4163 | break; | |
4164 | } | |
8bde7f77 | 4165 | |
f539edc0 VB |
4166 | if (Value32 == 0 && pDevice->RequestedMediaType == |
4167 | LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS) { | |
4168 | break; | |
4169 | } | |
8bde7f77 | 4170 | |
f539edc0 | 4171 | MM_Wait (10); |
8bde7f77 | 4172 | } |
f539edc0 VB |
4173 | |
4174 | /* Use the current line settings for "auto" mode. */ | |
4175 | if (pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_AUTO | |
4176 | || pDevice->RequestedMediaType == | |
4177 | LM_REQUESTED_MEDIA_TYPE_UTP_AUTO) { | |
4178 | if (Value32 & PHY_CTRL_AUTO_NEG_ENABLE) { | |
4179 | CurrentLinkStatus = LM_STATUS_LINK_ACTIVE; | |
4180 | ||
4181 | /* We may be exiting low power mode and the link is in */ | |
4182 | /* 10mb. In this case, we need to restart autoneg. */ | |
4183 | LM_ReadPhy (pDevice, BCM540X_1000BASET_CTRL_REG, | |
4184 | &Value32); | |
4185 | pDevice->advertising1000 = Value32; | |
4186 | /* 5702FE supports 10/100Mb only. */ | |
4187 | if (T3_ASIC_REV (pDevice->ChipRevId) != | |
4188 | T3_ASIC_REV_5703 | |
4189 | || pDevice->BondId != | |
4190 | GRC_MISC_BD_ID_5702FE) { | |
4191 | if (! | |
4192 | (Value32 & | |
4193 | (BCM540X_AN_AD_1000BASET_HALF | | |
4194 | BCM540X_AN_AD_1000BASET_FULL))) { | |
4195 | CurrentLinkStatus = | |
4196 | LM_STATUS_LINK_SETTING_MISMATCH; | |
4197 | } | |
4198 | } | |
4199 | } else { | |
4200 | CurrentLinkStatus = | |
4201 | LM_STATUS_LINK_SETTING_MISMATCH; | |
4202 | } | |
4203 | } else { | |
4204 | /* Force line settings. */ | |
4205 | /* Use the current setting if it matches the user's requested */ | |
4206 | /* setting. */ | |
4207 | LM_ReadPhy (pDevice, PHY_CTRL_REG, &Value32); | |
4208 | if ((pDevice->LineSpeed == CurrentLineSpeed) && | |
4209 | (pDevice->DuplexMode == CurrentDuplexMode)) { | |
4210 | if ((pDevice->DisableAutoNeg && | |
4211 | !(Value32 & PHY_CTRL_AUTO_NEG_ENABLE)) || | |
4212 | (!pDevice->DisableAutoNeg && | |
4213 | (Value32 & PHY_CTRL_AUTO_NEG_ENABLE))) { | |
4214 | CurrentLinkStatus = | |
4215 | LM_STATUS_LINK_ACTIVE; | |
4216 | } else { | |
4217 | CurrentLinkStatus = | |
4218 | LM_STATUS_LINK_SETTING_MISMATCH; | |
4219 | } | |
4220 | } else { | |
4221 | CurrentLinkStatus = | |
4222 | LM_STATUS_LINK_SETTING_MISMATCH; | |
4223 | } | |
8bde7f77 | 4224 | } |
8bde7f77 | 4225 | |
f539edc0 VB |
4226 | /* Save line settings. */ |
4227 | pDevice->LineSpeed = CurrentLineSpeed; | |
4228 | pDevice->DuplexMode = CurrentDuplexMode; | |
4229 | pDevice->MediaType = LM_MEDIA_TYPE_UTP; | |
4230 | } | |
c609719b | 4231 | |
f539edc0 VB |
4232 | return CurrentLinkStatus; |
4233 | } /* LM_InitBcm540xPhy */ | |
c609719b WD |
4234 | |
4235 | /******************************************************************************/ | |
4236 | /* Description: */ | |
4237 | /* */ | |
4238 | /* Return: */ | |
4239 | /******************************************************************************/ | |
4240 | LM_STATUS | |
f539edc0 VB |
4241 | LM_SetFlowControl (PLM_DEVICE_BLOCK pDevice, |
4242 | LM_UINT32 LocalPhyAd, LM_UINT32 RemotePhyAd) | |
c609719b | 4243 | { |
f539edc0 | 4244 | LM_FLOW_CONTROL FlowCap; |
c609719b | 4245 | |
f539edc0 VB |
4246 | /* Resolve flow control. */ |
4247 | FlowCap = LM_FLOW_CONTROL_NONE; | |
c609719b | 4248 | |
f539edc0 VB |
4249 | /* See Table 28B-3 of 802.3ab-1999 spec. */ |
4250 | if (pDevice->FlowControlCap & LM_FLOW_CONTROL_AUTO_PAUSE) { | |
4251 | if (LocalPhyAd & PHY_AN_AD_PAUSE_CAPABLE) { | |
4252 | if (LocalPhyAd & PHY_AN_AD_ASYM_PAUSE) { | |
4253 | if (RemotePhyAd & | |
4254 | PHY_LINK_PARTNER_PAUSE_CAPABLE) { | |
4255 | FlowCap = | |
4256 | LM_FLOW_CONTROL_TRANSMIT_PAUSE | | |
4257 | LM_FLOW_CONTROL_RECEIVE_PAUSE; | |
4258 | } else if (RemotePhyAd & | |
4259 | PHY_LINK_PARTNER_ASYM_PAUSE) { | |
4260 | FlowCap = LM_FLOW_CONTROL_RECEIVE_PAUSE; | |
4261 | } | |
4262 | } else { | |
4263 | if (RemotePhyAd & | |
4264 | PHY_LINK_PARTNER_PAUSE_CAPABLE) { | |
4265 | FlowCap = | |
4266 | LM_FLOW_CONTROL_TRANSMIT_PAUSE | | |
4267 | LM_FLOW_CONTROL_RECEIVE_PAUSE; | |
4268 | } | |
4269 | } | |
4270 | } else if (LocalPhyAd & PHY_AN_AD_ASYM_PAUSE) { | |
4271 | if ((RemotePhyAd & PHY_LINK_PARTNER_PAUSE_CAPABLE) && | |
4272 | (RemotePhyAd & PHY_LINK_PARTNER_ASYM_PAUSE)) { | |
4273 | FlowCap = LM_FLOW_CONTROL_TRANSMIT_PAUSE; | |
4274 | } | |
4275 | } | |
4276 | } else { | |
4277 | FlowCap = pDevice->FlowControlCap; | |
4278 | } | |
4279 | ||
4280 | /* Enable/disable rx PAUSE. */ | |
4281 | pDevice->RxMode &= ~RX_MODE_ENABLE_FLOW_CONTROL; | |
4282 | if (FlowCap & LM_FLOW_CONTROL_RECEIVE_PAUSE && | |
4283 | (pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE || | |
4284 | pDevice->FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE)) { | |
4285 | pDevice->FlowControl |= LM_FLOW_CONTROL_RECEIVE_PAUSE; | |
4286 | pDevice->RxMode |= RX_MODE_ENABLE_FLOW_CONTROL; | |
4287 | ||
4288 | } | |
4289 | REG_WR (pDevice, MacCtrl.RxMode, pDevice->RxMode); | |
4290 | ||
4291 | /* Enable/disable tx PAUSE. */ | |
4292 | pDevice->TxMode &= ~TX_MODE_ENABLE_FLOW_CONTROL; | |
4293 | if (FlowCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE && | |
4294 | (pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE || | |
4295 | pDevice->FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE)) { | |
4296 | pDevice->FlowControl |= LM_FLOW_CONTROL_TRANSMIT_PAUSE; | |
4297 | pDevice->TxMode |= TX_MODE_ENABLE_FLOW_CONTROL; | |
c609719b | 4298 | |
f539edc0 VB |
4299 | } |
4300 | REG_WR (pDevice, MacCtrl.TxMode, pDevice->TxMode); | |
4301 | ||
4302 | return LM_STATUS_SUCCESS; | |
4303 | } | |
c609719b WD |
4304 | |
4305 | #if INCLUDE_TBI_SUPPORT | |
4306 | /******************************************************************************/ | |
4307 | /* Description: */ | |
4308 | /* */ | |
4309 | /* Return: */ | |
4310 | /******************************************************************************/ | |
f539edc0 | 4311 | STATIC LM_STATUS LM_InitBcm800xPhy (PLM_DEVICE_BLOCK pDevice) |
c609719b | 4312 | { |
f539edc0 VB |
4313 | LM_UINT32 Value32; |
4314 | LM_UINT32 j; | |
c609719b | 4315 | |
f539edc0 | 4316 | Value32 = REG_RD (pDevice, MacCtrl.Status); |
c609719b | 4317 | |
f539edc0 VB |
4318 | /* Reset the SERDES during init and when we have link. */ |
4319 | if (!pDevice->InitDone || Value32 & MAC_STATUS_PCS_SYNCED) { | |
4320 | /* Set PLL lock range. */ | |
4321 | LM_WritePhy (pDevice, 0x16, 0x8007); | |
c609719b | 4322 | |
f539edc0 VB |
4323 | /* Software reset. */ |
4324 | LM_WritePhy (pDevice, 0x00, 0x8000); | |
c609719b | 4325 | |
f539edc0 VB |
4326 | /* Wait for reset to complete. */ |
4327 | for (j = 0; j < 500; j++) { | |
4328 | MM_Wait (10); | |
4329 | } | |
c609719b | 4330 | |
f539edc0 VB |
4331 | /* Config mode; seletct PMA/Ch 1 regs. */ |
4332 | LM_WritePhy (pDevice, 0x10, 0x8411); | |
c609719b | 4333 | |
f539edc0 VB |
4334 | /* Enable auto-lock and comdet, select txclk for tx. */ |
4335 | LM_WritePhy (pDevice, 0x11, 0x0a10); | |
c609719b | 4336 | |
f539edc0 VB |
4337 | LM_WritePhy (pDevice, 0x18, 0x00a0); |
4338 | LM_WritePhy (pDevice, 0x16, 0x41ff); | |
c609719b | 4339 | |
f539edc0 VB |
4340 | /* Assert and deassert POR. */ |
4341 | LM_WritePhy (pDevice, 0x13, 0x0400); | |
4342 | MM_Wait (40); | |
4343 | LM_WritePhy (pDevice, 0x13, 0x0000); | |
c609719b | 4344 | |
f539edc0 VB |
4345 | LM_WritePhy (pDevice, 0x11, 0x0a50); |
4346 | MM_Wait (40); | |
4347 | LM_WritePhy (pDevice, 0x11, 0x0a10); | |
c609719b | 4348 | |
f539edc0 VB |
4349 | /* Delay for signal to stabilize. */ |
4350 | for (j = 0; j < 15000; j++) { | |
4351 | MM_Wait (10); | |
4352 | } | |
c609719b | 4353 | |
f539edc0 VB |
4354 | /* Deselect the channel register so we can read the PHY id later. */ |
4355 | LM_WritePhy (pDevice, 0x10, 0x8011); | |
4356 | } | |
c609719b | 4357 | |
f539edc0 | 4358 | return LM_STATUS_SUCCESS; |
c609719b WD |
4359 | } |
4360 | ||
c609719b WD |
4361 | /******************************************************************************/ |
4362 | /* Description: */ | |
4363 | /* */ | |
4364 | /* Return: */ | |
4365 | /******************************************************************************/ | |
f539edc0 | 4366 | STATIC LM_STATUS LM_SetupFiberPhy (PLM_DEVICE_BLOCK pDevice) |
c609719b | 4367 | { |
f539edc0 VB |
4368 | LM_STATUS CurrentLinkStatus; |
4369 | AUTONEG_STATUS AnStatus = 0; | |
4370 | LM_UINT32 Value32; | |
4371 | LM_UINT32 Cnt; | |
4372 | LM_UINT32 j, k; | |
c609719b | 4373 | |
f539edc0 | 4374 | pDevice->MacMode &= ~(MAC_MODE_HALF_DUPLEX | MAC_MODE_PORT_MODE_MASK); |
c609719b | 4375 | |
f539edc0 VB |
4376 | /* Initialize the send_config register. */ |
4377 | REG_WR (pDevice, MacCtrl.TxAutoNeg, 0); | |
c609719b | 4378 | |
f539edc0 VB |
4379 | /* Enable TBI and full duplex mode. */ |
4380 | pDevice->MacMode |= MAC_MODE_PORT_MODE_TBI; | |
4381 | REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode); | |
c609719b | 4382 | |
f539edc0 VB |
4383 | /* Initialize the BCM8002 SERDES PHY. */ |
4384 | switch (pDevice->PhyId & PHY_ID_MASK) { | |
8bde7f77 | 4385 | case PHY_BCM8002_PHY_ID: |
f539edc0 VB |
4386 | LM_InitBcm800xPhy (pDevice); |
4387 | break; | |
c609719b | 4388 | |
8bde7f77 | 4389 | default: |
f539edc0 VB |
4390 | break; |
4391 | } | |
c609719b | 4392 | |
f539edc0 VB |
4393 | /* Enable link change interrupt. */ |
4394 | REG_WR (pDevice, MacCtrl.MacEvent, | |
4395 | MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN); | |
8bde7f77 | 4396 | |
f539edc0 VB |
4397 | /* Default to link down. */ |
4398 | CurrentLinkStatus = LM_STATUS_LINK_DOWN; | |
8bde7f77 | 4399 | |
f539edc0 VB |
4400 | /* Get the link status. */ |
4401 | Value32 = REG_RD (pDevice, MacCtrl.Status); | |
4402 | if (Value32 & MAC_STATUS_PCS_SYNCED) { | |
4403 | if ((pDevice->RequestedMediaType == | |
4404 | LM_REQUESTED_MEDIA_TYPE_AUTO) | |
4405 | || (pDevice->DisableAutoNeg == FALSE)) { | |
4406 | /* auto-negotiation mode. */ | |
4407 | /* Initialize the autoneg default capaiblities. */ | |
4408 | AutonegInit (&pDevice->AnInfo); | |
4409 | ||
4410 | /* Set the context pointer to point to the main device structure. */ | |
4411 | pDevice->AnInfo.pContext = pDevice; | |
4412 | ||
4413 | /* Setup flow control advertisement register. */ | |
4414 | Value32 = GetPhyAdFlowCntrlSettings (pDevice); | |
4415 | if (Value32 & PHY_AN_AD_PAUSE_CAPABLE) { | |
4416 | pDevice->AnInfo.mr_adv_sym_pause = 1; | |
4417 | } else { | |
4418 | pDevice->AnInfo.mr_adv_sym_pause = 0; | |
4419 | } | |
8bde7f77 | 4420 | |
f539edc0 VB |
4421 | if (Value32 & PHY_AN_AD_ASYM_PAUSE) { |
4422 | pDevice->AnInfo.mr_adv_asym_pause = 1; | |
4423 | } else { | |
4424 | pDevice->AnInfo.mr_adv_asym_pause = 0; | |
4425 | } | |
8bde7f77 | 4426 | |
f539edc0 VB |
4427 | /* Try to autoneg up to six times. */ |
4428 | if (pDevice->IgnoreTbiLinkChange) { | |
4429 | Cnt = 1; | |
4430 | } else { | |
4431 | Cnt = 6; | |
4432 | } | |
4433 | for (j = 0; j < Cnt; j++) { | |
4434 | REG_WR (pDevice, MacCtrl.TxAutoNeg, 0); | |
4435 | ||
4436 | Value32 = | |
4437 | pDevice->MacMode & ~MAC_MODE_PORT_MODE_MASK; | |
4438 | REG_WR (pDevice, MacCtrl.Mode, Value32); | |
4439 | MM_Wait (20); | |
4440 | ||
4441 | REG_WR (pDevice, MacCtrl.Mode, | |
4442 | pDevice-> | |
4443 | MacMode | MAC_MODE_SEND_CONFIGS); | |
4444 | ||
4445 | MM_Wait (20); | |
4446 | ||
4447 | pDevice->AnInfo.State = AN_STATE_UNKNOWN; | |
4448 | pDevice->AnInfo.CurrentTime_us = 0; | |
4449 | ||
4450 | REG_WR (pDevice, Grc.Timer, 0); | |
4451 | for (k = 0; | |
4452 | (pDevice->AnInfo.CurrentTime_us < 75000) | |
4453 | && (k < 75000); k++) { | |
4454 | AnStatus = | |
4455 | Autoneg8023z (&pDevice->AnInfo); | |
4456 | ||
4457 | if ((AnStatus == AUTONEG_STATUS_DONE) || | |
4458 | (AnStatus == AUTONEG_STATUS_FAILED)) | |
4459 | { | |
4460 | break; | |
4461 | } | |
4462 | ||
4463 | pDevice->AnInfo.CurrentTime_us = | |
4464 | REG_RD (pDevice, Grc.Timer); | |
4465 | ||
4466 | } | |
4467 | if ((AnStatus == AUTONEG_STATUS_DONE) || | |
4468 | (AnStatus == AUTONEG_STATUS_FAILED)) { | |
4469 | break; | |
4470 | } | |
4471 | if (j >= 1) { | |
4472 | if (!(REG_RD (pDevice, MacCtrl.Status) & | |
4473 | MAC_STATUS_PCS_SYNCED)) { | |
4474 | break; | |
4475 | } | |
4476 | } | |
4477 | } | |
8bde7f77 | 4478 | |
f539edc0 VB |
4479 | /* Stop sending configs. */ |
4480 | MM_AnTxIdle (&pDevice->AnInfo); | |
4481 | ||
4482 | /* Resolve flow control settings. */ | |
4483 | if ((AnStatus == AUTONEG_STATUS_DONE) && | |
4484 | pDevice->AnInfo.mr_an_complete | |
4485 | && pDevice->AnInfo.mr_link_ok | |
4486 | && pDevice->AnInfo.mr_lp_adv_full_duplex) { | |
4487 | LM_UINT32 RemotePhyAd; | |
4488 | LM_UINT32 LocalPhyAd; | |
4489 | ||
4490 | LocalPhyAd = 0; | |
4491 | if (pDevice->AnInfo.mr_adv_sym_pause) { | |
4492 | LocalPhyAd |= PHY_AN_AD_PAUSE_CAPABLE; | |
4493 | } | |
4494 | ||
4495 | if (pDevice->AnInfo.mr_adv_asym_pause) { | |
4496 | LocalPhyAd |= PHY_AN_AD_ASYM_PAUSE; | |
4497 | } | |
4498 | ||
4499 | RemotePhyAd = 0; | |
4500 | if (pDevice->AnInfo.mr_lp_adv_sym_pause) { | |
4501 | RemotePhyAd |= | |
4502 | PHY_LINK_PARTNER_PAUSE_CAPABLE; | |
4503 | } | |
4504 | ||
4505 | if (pDevice->AnInfo.mr_lp_adv_asym_pause) { | |
4506 | RemotePhyAd |= | |
4507 | PHY_LINK_PARTNER_ASYM_PAUSE; | |
4508 | } | |
4509 | ||
4510 | LM_SetFlowControl (pDevice, LocalPhyAd, | |
4511 | RemotePhyAd); | |
4512 | ||
4513 | CurrentLinkStatus = LM_STATUS_LINK_ACTIVE; | |
4514 | } | |
4515 | for (j = 0; j < 30; j++) { | |
4516 | MM_Wait (20); | |
4517 | REG_WR (pDevice, MacCtrl.Status, | |
4518 | MAC_STATUS_SYNC_CHANGED | | |
4519 | MAC_STATUS_CFG_CHANGED); | |
4520 | MM_Wait (20); | |
4521 | if ((REG_RD (pDevice, MacCtrl.Status) & | |
4522 | (MAC_STATUS_SYNC_CHANGED | | |
4523 | MAC_STATUS_CFG_CHANGED)) == 0) | |
4524 | break; | |
4525 | } | |
4526 | if (pDevice->PollTbiLink) { | |
4527 | Value32 = REG_RD (pDevice, MacCtrl.Status); | |
4528 | if (Value32 & MAC_STATUS_RECEIVING_CFG) { | |
4529 | pDevice->IgnoreTbiLinkChange = TRUE; | |
4530 | } else { | |
4531 | pDevice->IgnoreTbiLinkChange = FALSE; | |
4532 | } | |
4533 | } | |
4534 | Value32 = REG_RD (pDevice, MacCtrl.Status); | |
4535 | if (CurrentLinkStatus == LM_STATUS_LINK_DOWN && | |
4536 | (Value32 & MAC_STATUS_PCS_SYNCED) && | |
4537 | ((Value32 & MAC_STATUS_RECEIVING_CFG) == 0)) { | |
4538 | CurrentLinkStatus = LM_STATUS_LINK_ACTIVE; | |
4539 | } | |
4540 | } else { | |
4541 | /* We are forcing line speed. */ | |
4542 | pDevice->FlowControlCap &= ~LM_FLOW_CONTROL_AUTO_PAUSE; | |
4543 | LM_SetFlowControl (pDevice, 0, 0); | |
4544 | ||
4545 | CurrentLinkStatus = LM_STATUS_LINK_ACTIVE; | |
4546 | REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode | | |
4547 | MAC_MODE_SEND_CONFIGS); | |
8bde7f77 | 4548 | } |
f539edc0 VB |
4549 | } |
4550 | /* Set the link polarity bit. */ | |
4551 | pDevice->MacMode &= ~MAC_MODE_LINK_POLARITY; | |
4552 | REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode); | |
8bde7f77 | 4553 | |
f539edc0 VB |
4554 | pDevice->pStatusBlkVirt->Status = STATUS_BLOCK_UPDATED | |
4555 | (pDevice->pStatusBlkVirt-> | |
4556 | Status & ~STATUS_BLOCK_LINK_CHANGED_STATUS); | |
8bde7f77 | 4557 | |
f539edc0 VB |
4558 | for (j = 0; j < 100; j++) { |
4559 | REG_WR (pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED | | |
4560 | MAC_STATUS_CFG_CHANGED); | |
4561 | MM_Wait (5); | |
4562 | if ((REG_RD (pDevice, MacCtrl.Status) & | |
4563 | (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED)) == 0) | |
4564 | break; | |
4565 | } | |
8bde7f77 | 4566 | |
f539edc0 VB |
4567 | Value32 = REG_RD (pDevice, MacCtrl.Status); |
4568 | if ((Value32 & MAC_STATUS_PCS_SYNCED) == 0) { | |
4569 | CurrentLinkStatus = LM_STATUS_LINK_DOWN; | |
4570 | if (pDevice->DisableAutoNeg == FALSE) { | |
4571 | REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode | | |
4572 | MAC_MODE_SEND_CONFIGS); | |
4573 | MM_Wait (1); | |
4574 | REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode); | |
8bde7f77 | 4575 | } |
f539edc0 | 4576 | } |
8bde7f77 | 4577 | |
f539edc0 VB |
4578 | /* Initialize the current link status. */ |
4579 | if (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) { | |
4580 | pDevice->LineSpeed = LM_LINE_SPEED_1000MBPS; | |
4581 | pDevice->DuplexMode = LM_DUPLEX_MODE_FULL; | |
4582 | REG_WR (pDevice, MacCtrl.LedCtrl, LED_CTRL_OVERRIDE_LINK_LED | | |
4583 | LED_CTRL_1000MBPS_LED_ON); | |
4584 | } else { | |
4585 | pDevice->LineSpeed = LM_LINE_SPEED_UNKNOWN; | |
4586 | pDevice->DuplexMode = LM_DUPLEX_MODE_UNKNOWN; | |
4587 | REG_WR (pDevice, MacCtrl.LedCtrl, LED_CTRL_OVERRIDE_LINK_LED | | |
4588 | LED_CTRL_OVERRIDE_TRAFFIC_LED); | |
4589 | } | |
8bde7f77 | 4590 | |
f539edc0 VB |
4591 | /* Indicate link status. */ |
4592 | if (pDevice->LinkStatus != CurrentLinkStatus) { | |
4593 | pDevice->LinkStatus = CurrentLinkStatus; | |
4594 | MM_IndicateStatus (pDevice, CurrentLinkStatus); | |
8bde7f77 | 4595 | } |
c609719b | 4596 | |
f539edc0 VB |
4597 | return LM_STATUS_SUCCESS; |
4598 | } | |
4599 | #endif /* INCLUDE_TBI_SUPPORT */ | |
c609719b WD |
4600 | |
4601 | /******************************************************************************/ | |
4602 | /* Description: */ | |
4603 | /* */ | |
4604 | /* Return: */ | |
4605 | /******************************************************************************/ | |
f539edc0 | 4606 | LM_STATUS LM_SetupCopperPhy (PLM_DEVICE_BLOCK pDevice) |
c609719b | 4607 | { |
f539edc0 VB |
4608 | LM_STATUS CurrentLinkStatus; |
4609 | LM_UINT32 Value32; | |
c609719b | 4610 | |
f539edc0 VB |
4611 | /* Assume there is not link first. */ |
4612 | CurrentLinkStatus = LM_STATUS_LINK_DOWN; | |
c609719b | 4613 | |
f539edc0 VB |
4614 | /* Disable phy link change attention. */ |
4615 | REG_WR (pDevice, MacCtrl.MacEvent, 0); | |
c609719b | 4616 | |
f539edc0 VB |
4617 | /* Clear link change attention. */ |
4618 | REG_WR (pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED | | |
4619 | MAC_STATUS_CFG_CHANGED); | |
c609719b | 4620 | |
f539edc0 VB |
4621 | /* Disable auto-polling for the moment. */ |
4622 | pDevice->MiMode = 0xc0000; | |
4623 | REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode); | |
4624 | MM_Wait (40); | |
c609719b | 4625 | |
f539edc0 VB |
4626 | /* Determine the requested line speed and duplex. */ |
4627 | pDevice->OldLineSpeed = pDevice->LineSpeed; | |
4628 | LM_TranslateRequestedMediaType (pDevice->RequestedMediaType, | |
4629 | &pDevice->MediaType, | |
4630 | &pDevice->LineSpeed, | |
4631 | &pDevice->DuplexMode); | |
c609719b | 4632 | |
f539edc0 VB |
4633 | /* Initialize the phy chip. */ |
4634 | switch (pDevice->PhyId & PHY_ID_MASK) { | |
8bde7f77 WD |
4635 | case PHY_BCM5400_PHY_ID: |
4636 | case PHY_BCM5401_PHY_ID: | |
4637 | case PHY_BCM5411_PHY_ID: | |
4638 | case PHY_BCM5701_PHY_ID: | |
4639 | case PHY_BCM5703_PHY_ID: | |
4640 | case PHY_BCM5704_PHY_ID: | |
f539edc0 VB |
4641 | CurrentLinkStatus = LM_InitBcm540xPhy (pDevice); |
4642 | break; | |
c609719b | 4643 | |
8bde7f77 | 4644 | default: |
f539edc0 VB |
4645 | break; |
4646 | } | |
c609719b | 4647 | |
f539edc0 VB |
4648 | if (CurrentLinkStatus == LM_STATUS_LINK_SETTING_MISMATCH) { |
4649 | CurrentLinkStatus = LM_STATUS_LINK_DOWN; | |
4650 | } | |
4651 | ||
4652 | /* Setup flow control. */ | |
4653 | pDevice->FlowControl = LM_FLOW_CONTROL_NONE; | |
4654 | if (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) { | |
4655 | LM_FLOW_CONTROL FlowCap; /* Flow control capability. */ | |
4656 | ||
4657 | FlowCap = LM_FLOW_CONTROL_NONE; | |
4658 | ||
4659 | if (pDevice->DuplexMode == LM_DUPLEX_MODE_FULL) { | |
4660 | if (pDevice->DisableAutoNeg == FALSE || | |
4661 | pDevice->RequestedMediaType == | |
4662 | LM_REQUESTED_MEDIA_TYPE_AUTO | |
4663 | || pDevice->RequestedMediaType == | |
4664 | LM_REQUESTED_MEDIA_TYPE_UTP_AUTO) { | |
4665 | LM_UINT32 ExpectedPhyAd; | |
4666 | LM_UINT32 LocalPhyAd; | |
4667 | LM_UINT32 RemotePhyAd; | |
4668 | ||
4669 | LM_ReadPhy (pDevice, PHY_AN_AD_REG, | |
4670 | &LocalPhyAd); | |
4671 | pDevice->advertising = LocalPhyAd; | |
4672 | LocalPhyAd &= | |
4673 | (PHY_AN_AD_ASYM_PAUSE | | |
4674 | PHY_AN_AD_PAUSE_CAPABLE); | |
4675 | ||
4676 | ExpectedPhyAd = | |
4677 | GetPhyAdFlowCntrlSettings (pDevice); | |
4678 | ||
4679 | if (LocalPhyAd != ExpectedPhyAd) { | |
4680 | CurrentLinkStatus = LM_STATUS_LINK_DOWN; | |
4681 | } else { | |
4682 | LM_ReadPhy (pDevice, | |
4683 | PHY_LINK_PARTNER_ABILITY_REG, | |
4684 | &RemotePhyAd); | |
4685 | ||
4686 | LM_SetFlowControl (pDevice, LocalPhyAd, | |
4687 | RemotePhyAd); | |
4688 | } | |
4689 | } else { | |
4690 | pDevice->FlowControlCap &= | |
4691 | ~LM_FLOW_CONTROL_AUTO_PAUSE; | |
4692 | LM_SetFlowControl (pDevice, 0, 0); | |
4693 | } | |
4694 | } | |
4695 | } | |
c609719b | 4696 | |
f539edc0 VB |
4697 | if (CurrentLinkStatus == LM_STATUS_LINK_DOWN) { |
4698 | LM_ForceAutoNeg (pDevice, pDevice->RequestedMediaType); | |
c609719b | 4699 | |
f539edc0 VB |
4700 | /* If we force line speed, we make get link right away. */ |
4701 | LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); | |
4702 | LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); | |
4703 | if (Value32 & PHY_STATUS_LINK_PASS) { | |
4704 | CurrentLinkStatus = LM_STATUS_LINK_ACTIVE; | |
4705 | } | |
4706 | } | |
8bde7f77 | 4707 | |
f539edc0 VB |
4708 | /* GMII interface. */ |
4709 | pDevice->MacMode &= ~MAC_MODE_PORT_MODE_MASK; | |
4710 | if (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) { | |
4711 | if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS || | |
4712 | pDevice->LineSpeed == LM_LINE_SPEED_10MBPS) { | |
4713 | pDevice->MacMode |= MAC_MODE_PORT_MODE_MII; | |
4714 | } else { | |
4715 | pDevice->MacMode |= MAC_MODE_PORT_MODE_GMII; | |
4716 | } | |
4717 | } else { | |
4718 | pDevice->MacMode |= MAC_MODE_PORT_MODE_GMII; | |
4719 | } | |
8bde7f77 | 4720 | |
f539edc0 VB |
4721 | /* Set the MAC to operate in the appropriate duplex mode. */ |
4722 | pDevice->MacMode &= ~MAC_MODE_HALF_DUPLEX; | |
4723 | if (pDevice->DuplexMode == LM_DUPLEX_MODE_HALF) { | |
4724 | pDevice->MacMode |= MAC_MODE_HALF_DUPLEX; | |
4725 | } | |
8bde7f77 | 4726 | |
f539edc0 VB |
4727 | /* Set the link polarity bit. */ |
4728 | pDevice->MacMode &= ~MAC_MODE_LINK_POLARITY; | |
4729 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { | |
4730 | if ((pDevice->LedMode == LED_MODE_LINK10) || | |
4731 | (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE && | |
4732 | pDevice->LineSpeed == LM_LINE_SPEED_10MBPS)) { | |
4733 | pDevice->MacMode |= MAC_MODE_LINK_POLARITY; | |
4734 | } | |
4735 | } else { | |
4736 | if (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) { | |
4737 | pDevice->MacMode |= MAC_MODE_LINK_POLARITY; | |
8bde7f77 | 4738 | } |
8bde7f77 | 4739 | |
f539edc0 VB |
4740 | /* Set LED mode. */ |
4741 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || | |
4742 | T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { | |
4743 | Value32 = LED_CTRL_PHY_MODE_1; | |
4744 | } else { | |
4745 | if (pDevice->LedMode == LED_MODE_OUTPUT) { | |
4746 | Value32 = LED_CTRL_PHY_MODE_2; | |
4747 | } else { | |
4748 | Value32 = LED_CTRL_PHY_MODE_1; | |
4749 | } | |
8bde7f77 | 4750 | } |
f539edc0 | 4751 | REG_WR (pDevice, MacCtrl.LedCtrl, Value32); |
8bde7f77 | 4752 | } |
c609719b | 4753 | |
f539edc0 | 4754 | REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode); |
c609719b | 4755 | |
f539edc0 VB |
4756 | /* Enable auto polling. */ |
4757 | if (pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING) { | |
4758 | pDevice->MiMode |= MI_MODE_AUTO_POLLING_ENABLE; | |
4759 | REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode); | |
8bde7f77 | 4760 | } |
c609719b | 4761 | |
f539edc0 VB |
4762 | /* Enable phy link change attention. */ |
4763 | if (pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT) { | |
4764 | REG_WR (pDevice, MacCtrl.MacEvent, | |
4765 | MAC_EVENT_ENABLE_MI_INTERRUPT); | |
4766 | } else { | |
4767 | REG_WR (pDevice, MacCtrl.MacEvent, | |
4768 | MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN); | |
8bde7f77 | 4769 | } |
f539edc0 VB |
4770 | if ((T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) && |
4771 | (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) && | |
4772 | (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) && | |
4773 | (((pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) && | |
4774 | (pDevice->PciState & T3_PCI_STATE_BUS_SPEED_HIGH)) || | |
4775 | !(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE))) { | |
4776 | MM_Wait (120); | |
4777 | REG_WR (pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED | | |
4778 | MAC_STATUS_CFG_CHANGED); | |
4779 | MEM_WR_OFFSET (pDevice, T3_FIRMWARE_MAILBOX, | |
4780 | T3_MAGIC_NUM_DISABLE_DMAW_ON_LINK_CHANGE); | |
8bde7f77 WD |
4781 | } |
4782 | ||
f539edc0 VB |
4783 | /* Indicate link status. */ |
4784 | if (pDevice->LinkStatus != CurrentLinkStatus) { | |
4785 | pDevice->LinkStatus = CurrentLinkStatus; | |
4786 | MM_IndicateStatus (pDevice, CurrentLinkStatus); | |
8bde7f77 | 4787 | } |
f539edc0 VB |
4788 | |
4789 | return LM_STATUS_SUCCESS; | |
4790 | } /* LM_SetupCopperPhy */ | |
c609719b WD |
4791 | |
4792 | /******************************************************************************/ | |
4793 | /* Description: */ | |
4794 | /* */ | |
4795 | /* Return: */ | |
4796 | /******************************************************************************/ | |
f539edc0 | 4797 | LM_STATUS LM_SetupPhy (PLM_DEVICE_BLOCK pDevice) |
c609719b | 4798 | { |
f539edc0 VB |
4799 | LM_STATUS LmStatus; |
4800 | LM_UINT32 Value32; | |
c609719b WD |
4801 | |
4802 | #if INCLUDE_TBI_SUPPORT | |
f539edc0 VB |
4803 | if (pDevice->EnableTbi) { |
4804 | LmStatus = LM_SetupFiberPhy (pDevice); | |
4805 | } else | |
4806 | #endif /* INCLUDE_TBI_SUPPORT */ | |
4807 | { | |
4808 | LmStatus = LM_SetupCopperPhy (pDevice); | |
4809 | } | |
4810 | if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0) { | |
4811 | if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE)) { | |
4812 | Value32 = REG_RD (pDevice, PciCfg.PciState); | |
4813 | REG_WR (pDevice, PciCfg.PciState, | |
4814 | Value32 | T3_PCI_STATE_RETRY_SAME_DMA); | |
4815 | } | |
4816 | } | |
4817 | if ((pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) && | |
4818 | (pDevice->DuplexMode == LM_DUPLEX_MODE_HALF)) { | |
4819 | REG_WR (pDevice, MacCtrl.TxLengths, 0x26ff); | |
4820 | } else { | |
4821 | REG_WR (pDevice, MacCtrl.TxLengths, 0x2620); | |
4822 | } | |
4823 | ||
4824 | return LmStatus; | |
c609719b WD |
4825 | } |
4826 | ||
4827 | /******************************************************************************/ | |
4828 | /* Description: */ | |
4829 | /* */ | |
4830 | /* Return: */ | |
4831 | /******************************************************************************/ | |
4832 | LM_VOID | |
f539edc0 VB |
4833 | LM_ReadPhy (PLM_DEVICE_BLOCK pDevice, LM_UINT32 PhyReg, PLM_UINT32 pData32) |
4834 | { | |
4835 | LM_UINT32 Value32; | |
4836 | LM_UINT32 j; | |
c609719b | 4837 | |
f539edc0 VB |
4838 | if (pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING) { |
4839 | REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode & | |
4840 | ~MI_MODE_AUTO_POLLING_ENABLE); | |
4841 | MM_Wait (40); | |
4842 | } | |
c609719b | 4843 | |
f539edc0 VB |
4844 | Value32 = (pDevice->PhyAddr << MI_COM_FIRST_PHY_ADDR_BIT) | |
4845 | ((PhyReg & MI_COM_PHY_REG_ADDR_MASK) << | |
4846 | MI_COM_FIRST_PHY_REG_ADDR_BIT) | MI_COM_CMD_READ | MI_COM_START; | |
c609719b | 4847 | |
f539edc0 | 4848 | REG_WR (pDevice, MacCtrl.MiCom, Value32); |
c609719b | 4849 | |
f539edc0 VB |
4850 | for (j = 0; j < 20; j++) { |
4851 | MM_Wait (25); | |
c609719b | 4852 | |
f539edc0 | 4853 | Value32 = REG_RD (pDevice, MacCtrl.MiCom); |
c609719b | 4854 | |
f539edc0 VB |
4855 | if (!(Value32 & MI_COM_BUSY)) { |
4856 | MM_Wait (5); | |
4857 | Value32 = REG_RD (pDevice, MacCtrl.MiCom); | |
4858 | Value32 &= MI_COM_PHY_DATA_MASK; | |
4859 | break; | |
4860 | } | |
8bde7f77 | 4861 | } |
c609719b | 4862 | |
f539edc0 VB |
4863 | if (Value32 & MI_COM_BUSY) { |
4864 | Value32 = 0; | |
4865 | } | |
c609719b | 4866 | |
f539edc0 | 4867 | *pData32 = Value32; |
c609719b | 4868 | |
f539edc0 VB |
4869 | if (pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING) { |
4870 | REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode); | |
4871 | MM_Wait (40); | |
4872 | } | |
4873 | } /* LM_ReadPhy */ | |
c609719b | 4874 | |
c609719b WD |
4875 | /******************************************************************************/ |
4876 | /* Description: */ | |
4877 | /* */ | |
4878 | /* Return: */ | |
4879 | /******************************************************************************/ | |
4880 | LM_VOID | |
f539edc0 VB |
4881 | LM_WritePhy (PLM_DEVICE_BLOCK pDevice, LM_UINT32 PhyReg, LM_UINT32 Data32) |
4882 | { | |
4883 | LM_UINT32 Value32; | |
4884 | LM_UINT32 j; | |
c609719b | 4885 | |
f539edc0 VB |
4886 | if (pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING) { |
4887 | REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode & | |
4888 | ~MI_MODE_AUTO_POLLING_ENABLE); | |
4889 | MM_Wait (40); | |
4890 | } | |
c609719b | 4891 | |
f539edc0 VB |
4892 | Value32 = (pDevice->PhyAddr << MI_COM_FIRST_PHY_ADDR_BIT) | |
4893 | ((PhyReg & MI_COM_PHY_REG_ADDR_MASK) << | |
4894 | MI_COM_FIRST_PHY_REG_ADDR_BIT) | (Data32 & MI_COM_PHY_DATA_MASK) | | |
4895 | MI_COM_CMD_WRITE | MI_COM_START; | |
c609719b | 4896 | |
f539edc0 | 4897 | REG_WR (pDevice, MacCtrl.MiCom, Value32); |
c609719b | 4898 | |
f539edc0 VB |
4899 | for (j = 0; j < 20; j++) { |
4900 | MM_Wait (25); | |
c609719b | 4901 | |
f539edc0 | 4902 | Value32 = REG_RD (pDevice, MacCtrl.MiCom); |
c609719b | 4903 | |
f539edc0 VB |
4904 | if (!(Value32 & MI_COM_BUSY)) { |
4905 | MM_Wait (5); | |
4906 | break; | |
4907 | } | |
8bde7f77 | 4908 | } |
c609719b | 4909 | |
f539edc0 VB |
4910 | if (pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING) { |
4911 | REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode); | |
4912 | MM_Wait (40); | |
4913 | } | |
4914 | } /* LM_WritePhy */ | |
c609719b WD |
4915 | |
4916 | /******************************************************************************/ | |
4917 | /* Description: */ | |
4918 | /* */ | |
4919 | /* Return: */ | |
4920 | /******************************************************************************/ | |
f539edc0 VB |
4921 | LM_STATUS LM_SetPowerState (PLM_DEVICE_BLOCK pDevice, LM_POWER_STATE PowerLevel) |
4922 | { | |
4923 | LM_UINT32 PmeSupport; | |
4924 | LM_UINT32 Value32; | |
4925 | LM_UINT32 PmCtrl; | |
c609719b | 4926 | |
f539edc0 VB |
4927 | /* make sureindirect accesses are enabled */ |
4928 | MM_WriteConfig32 (pDevice, T3_PCI_MISC_HOST_CTRL_REG, | |
4929 | pDevice->MiscHostCtrl); | |
c609719b | 4930 | |
f539edc0 VB |
4931 | /* Clear the PME_ASSERT bit and the power state bits. Also enable */ |
4932 | /* the PME bit. */ | |
4933 | MM_ReadConfig32 (pDevice, T3_PCI_PM_STATUS_CTRL_REG, &PmCtrl); | |
c609719b | 4934 | |
f539edc0 VB |
4935 | PmCtrl |= T3_PM_PME_ASSERTED; |
4936 | PmCtrl &= ~T3_PM_POWER_STATE_MASK; | |
c609719b | 4937 | |
f539edc0 VB |
4938 | /* Set the appropriate power state. */ |
4939 | if (PowerLevel == LM_POWER_STATE_D0) { | |
c609719b | 4940 | |
f539edc0 VB |
4941 | /* Bring the card out of low power mode. */ |
4942 | PmCtrl |= T3_PM_POWER_STATE_D0; | |
4943 | MM_WriteConfig32 (pDevice, T3_PCI_PM_STATUS_CTRL_REG, PmCtrl); | |
c609719b | 4944 | |
f539edc0 VB |
4945 | REG_WR (pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl); |
4946 | MM_Wait (40); | |
4947 | #if 0 /* Bugfix by jmb...can't call WritePhy here because pDevice not fully initialized */ | |
4948 | LM_WritePhy (pDevice, BCM5401_AUX_CTRL, 0x02); | |
c609719b WD |
4949 | #endif |
4950 | ||
f539edc0 VB |
4951 | return LM_STATUS_SUCCESS; |
4952 | } else if (PowerLevel == LM_POWER_STATE_D1) { | |
4953 | PmCtrl |= T3_PM_POWER_STATE_D1; | |
4954 | } else if (PowerLevel == LM_POWER_STATE_D2) { | |
4955 | PmCtrl |= T3_PM_POWER_STATE_D2; | |
4956 | } else if (PowerLevel == LM_POWER_STATE_D3) { | |
4957 | PmCtrl |= T3_PM_POWER_STATE_D3; | |
4958 | } else { | |
4959 | return LM_STATUS_FAILURE; | |
8bde7f77 | 4960 | } |
f539edc0 | 4961 | PmCtrl |= T3_PM_PME_ENABLE; |
8bde7f77 | 4962 | |
f539edc0 VB |
4963 | /* Mask out all interrupts so LM_SetupPhy won't be called while we are */ |
4964 | /* setting new line speed. */ | |
4965 | Value32 = REG_RD (pDevice, PciCfg.MiscHostCtrl); | |
4966 | REG_WR (pDevice, PciCfg.MiscHostCtrl, | |
4967 | Value32 | MISC_HOST_CTRL_MASK_PCI_INT); | |
8bde7f77 | 4968 | |
f539edc0 VB |
4969 | if (!pDevice->RestoreOnWakeUp) { |
4970 | pDevice->RestoreOnWakeUp = TRUE; | |
4971 | pDevice->WakeUpDisableAutoNeg = pDevice->DisableAutoNeg; | |
4972 | pDevice->WakeUpRequestedMediaType = pDevice->RequestedMediaType; | |
8bde7f77 WD |
4973 | } |
4974 | ||
f539edc0 VB |
4975 | /* Force auto-negotiation to 10 line speed. */ |
4976 | pDevice->DisableAutoNeg = FALSE; | |
4977 | pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS; | |
4978 | LM_SetupPhy (pDevice); | |
8bde7f77 | 4979 | |
f539edc0 VB |
4980 | /* Put the driver in the initial state, and go through the power down */ |
4981 | /* sequence. */ | |
4982 | LM_Halt (pDevice); | |
8bde7f77 | 4983 | |
f539edc0 | 4984 | MM_ReadConfig32 (pDevice, T3_PCI_PM_CAP_REG, &PmeSupport); |
8bde7f77 | 4985 | |
f539edc0 | 4986 | if (pDevice->WakeUpModeCap != LM_WAKE_UP_MODE_NONE) { |
8bde7f77 | 4987 | |
f539edc0 VB |
4988 | /* Enable WOL. */ |
4989 | LM_WritePhy (pDevice, BCM5401_AUX_CTRL, 0x5a); | |
4990 | MM_Wait (40); | |
8bde7f77 | 4991 | |
f539edc0 VB |
4992 | /* Set LED mode. */ |
4993 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || | |
4994 | T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { | |
4995 | Value32 = LED_CTRL_PHY_MODE_1; | |
4996 | } else { | |
4997 | if (pDevice->LedMode == LED_MODE_OUTPUT) { | |
4998 | Value32 = LED_CTRL_PHY_MODE_2; | |
4999 | } else { | |
5000 | Value32 = LED_CTRL_PHY_MODE_1; | |
5001 | } | |
5002 | } | |
8bde7f77 | 5003 | |
f539edc0 VB |
5004 | Value32 = MAC_MODE_PORT_MODE_MII; |
5005 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { | |
5006 | if (pDevice->LedMode == LED_MODE_LINK10 || | |
5007 | pDevice->WolSpeed == WOL_SPEED_10MB) { | |
5008 | Value32 |= MAC_MODE_LINK_POLARITY; | |
5009 | } | |
5010 | } else { | |
5011 | Value32 |= MAC_MODE_LINK_POLARITY; | |
5012 | } | |
5013 | REG_WR (pDevice, MacCtrl.Mode, Value32); | |
5014 | MM_Wait (40); | |
5015 | MM_Wait (40); | |
5016 | MM_Wait (40); | |
5017 | ||
5018 | /* Always enable magic packet wake-up if we have vaux. */ | |
5019 | if ((PmeSupport & T3_PCI_PM_CAP_PME_D3COLD) && | |
5020 | (pDevice->WakeUpModeCap & LM_WAKE_UP_MODE_MAGIC_PACKET)) { | |
5021 | Value32 |= MAC_MODE_DETECT_MAGIC_PACKET_ENABLE; | |
5022 | } | |
8bde7f77 | 5023 | |
f539edc0 VB |
5024 | REG_WR (pDevice, MacCtrl.Mode, Value32); |
5025 | ||
5026 | /* Enable the receiver. */ | |
5027 | REG_WR (pDevice, MacCtrl.RxMode, RX_MODE_ENABLE); | |
8bde7f77 | 5028 | } |
c609719b | 5029 | |
f539edc0 VB |
5030 | /* Disable tx/rx clocks, and seletect an alternate clock. */ |
5031 | if (pDevice->WolSpeed == WOL_SPEED_100MB) { | |
5032 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || | |
5033 | T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { | |
5034 | Value32 = | |
5035 | T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK | | |
5036 | T3_PCI_SELECT_ALTERNATE_CLOCK; | |
5037 | } else { | |
5038 | Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK; | |
5039 | } | |
5040 | REG_WR (pDevice, PciCfg.ClockCtrl, Value32); | |
5041 | ||
5042 | MM_Wait (40); | |
5043 | ||
5044 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || | |
5045 | T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { | |
5046 | Value32 = | |
5047 | T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK | | |
5048 | T3_PCI_SELECT_ALTERNATE_CLOCK | | |
5049 | T3_PCI_44MHZ_CORE_CLOCK; | |
5050 | } else { | |
5051 | Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK | | |
5052 | T3_PCI_44MHZ_CORE_CLOCK; | |
5053 | } | |
5054 | ||
5055 | REG_WR (pDevice, PciCfg.ClockCtrl, Value32); | |
c609719b | 5056 | |
f539edc0 | 5057 | MM_Wait (40); |
c609719b | 5058 | |
f539edc0 VB |
5059 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || |
5060 | T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { | |
5061 | Value32 = | |
5062 | T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK | | |
5063 | T3_PCI_44MHZ_CORE_CLOCK; | |
5064 | } else { | |
5065 | Value32 = T3_PCI_44MHZ_CORE_CLOCK; | |
5066 | } | |
5067 | ||
5068 | REG_WR (pDevice, PciCfg.ClockCtrl, Value32); | |
5069 | } else { | |
5070 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || | |
5071 | T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { | |
5072 | Value32 = | |
5073 | T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK | | |
5074 | T3_PCI_SELECT_ALTERNATE_CLOCK | | |
5075 | T3_PCI_POWER_DOWN_PCI_PLL133; | |
5076 | } else { | |
5077 | Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK | | |
5078 | T3_PCI_POWER_DOWN_PCI_PLL133; | |
5079 | } | |
5080 | ||
5081 | REG_WR (pDevice, PciCfg.ClockCtrl, Value32); | |
8bde7f77 | 5082 | } |
c609719b | 5083 | |
f539edc0 VB |
5084 | MM_Wait (40); |
5085 | ||
5086 | if (!pDevice->EepromWp | |
5087 | && (pDevice->WakeUpModeCap != LM_WAKE_UP_MODE_NONE)) { | |
5088 | /* Switch adapter to auxilliary power. */ | |
5089 | if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || | |
5090 | T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { | |
5091 | /* GPIO0 = 1, GPIO1 = 1, GPIO2 = 0. */ | |
5092 | REG_WR (pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl | | |
5093 | GRC_MISC_LOCAL_CTRL_GPIO_OE0 | | |
5094 | GRC_MISC_LOCAL_CTRL_GPIO_OE1 | | |
5095 | GRC_MISC_LOCAL_CTRL_GPIO_OE2 | | |
5096 | GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 | | |
5097 | GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1); | |
5098 | MM_Wait (40); | |
5099 | } else { | |
5100 | /* GPIO0 = 0, GPIO1 = 1, GPIO2 = 1. */ | |
5101 | REG_WR (pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl | | |
5102 | GRC_MISC_LOCAL_CTRL_GPIO_OE0 | | |
5103 | GRC_MISC_LOCAL_CTRL_GPIO_OE1 | | |
5104 | GRC_MISC_LOCAL_CTRL_GPIO_OE2 | | |
5105 | GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 | | |
5106 | GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT2); | |
5107 | MM_Wait (40); | |
5108 | ||
5109 | /* GPIO0 = 1, GPIO1 = 1, GPIO2 = 1. */ | |
5110 | REG_WR (pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl | | |
5111 | GRC_MISC_LOCAL_CTRL_GPIO_OE0 | | |
5112 | GRC_MISC_LOCAL_CTRL_GPIO_OE1 | | |
5113 | GRC_MISC_LOCAL_CTRL_GPIO_OE2 | | |
5114 | GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 | | |
5115 | GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 | | |
5116 | GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT2); | |
5117 | MM_Wait (40); | |
5118 | ||
5119 | /* GPIO0 = 1, GPIO1 = 1, GPIO2 = 0. */ | |
5120 | REG_WR (pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl | | |
5121 | GRC_MISC_LOCAL_CTRL_GPIO_OE0 | | |
5122 | GRC_MISC_LOCAL_CTRL_GPIO_OE1 | | |
5123 | GRC_MISC_LOCAL_CTRL_GPIO_OE2 | | |
5124 | GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 | | |
5125 | GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1); | |
5126 | MM_Wait (40); | |
5127 | } | |
5128 | } | |
5129 | ||
5130 | /* Set the phy to low power mode. */ | |
5131 | /* Put the the hardware in low power mode. */ | |
5132 | MM_WriteConfig32 (pDevice, T3_PCI_PM_STATUS_CTRL_REG, PmCtrl); | |
5133 | ||
5134 | return LM_STATUS_SUCCESS; | |
5135 | } /* LM_SetPowerState */ | |
c609719b | 5136 | |
c609719b WD |
5137 | /******************************************************************************/ |
5138 | /* Description: */ | |
5139 | /* */ | |
5140 | /* Return: */ | |
5141 | /******************************************************************************/ | |
f539edc0 | 5142 | static LM_UINT32 GetPhyAdFlowCntrlSettings (PLM_DEVICE_BLOCK pDevice) |
c609719b | 5143 | { |
f539edc0 VB |
5144 | LM_UINT32 Value32; |
5145 | ||
5146 | Value32 = 0; | |
5147 | ||
5148 | /* Auto negotiation flow control only when autonegotiation is enabled. */ | |
5149 | if (pDevice->DisableAutoNeg == FALSE || | |
5150 | pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_AUTO || | |
5151 | pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_UTP_AUTO) { | |
5152 | /* Please refer to Table 28B-3 of the 802.3ab-1999 spec. */ | |
5153 | if ((pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE) || | |
5154 | ((pDevice->FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE) | |
5155 | && (pDevice-> | |
5156 | FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE))) { | |
5157 | Value32 |= PHY_AN_AD_PAUSE_CAPABLE; | |
5158 | } else if (pDevice-> | |
5159 | FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE) { | |
5160 | Value32 |= PHY_AN_AD_ASYM_PAUSE; | |
5161 | } else if (pDevice-> | |
5162 | FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE) { | |
5163 | Value32 |= | |
5164 | PHY_AN_AD_PAUSE_CAPABLE | PHY_AN_AD_ASYM_PAUSE; | |
5165 | } | |
8bde7f77 | 5166 | } |
c609719b | 5167 | |
f539edc0 | 5168 | return Value32; |
c609719b WD |
5169 | } |
5170 | ||
c609719b WD |
5171 | /******************************************************************************/ |
5172 | /* Description: */ | |
5173 | /* */ | |
5174 | /* Return: */ | |
5175 | /* LM_STATUS_FAILURE */ | |
5176 | /* LM_STATUS_SUCCESS */ | |
5177 | /* */ | |
5178 | /******************************************************************************/ | |
5179 | static LM_STATUS | |
f539edc0 VB |
5180 | LM_ForceAutoNegBcm540xPhy (PLM_DEVICE_BLOCK pDevice, |
5181 | LM_REQUESTED_MEDIA_TYPE RequestedMediaType) | |
c609719b | 5182 | { |
f539edc0 VB |
5183 | LM_MEDIA_TYPE MediaType; |
5184 | LM_LINE_SPEED LineSpeed; | |
5185 | LM_DUPLEX_MODE DuplexMode; | |
5186 | LM_UINT32 NewPhyCtrl; | |
5187 | LM_UINT32 Value32; | |
5188 | LM_UINT32 Cnt; | |
5189 | ||
5190 | /* Get the interface type, line speed, and duplex mode. */ | |
5191 | LM_TranslateRequestedMediaType (RequestedMediaType, &MediaType, | |
5192 | &LineSpeed, &DuplexMode); | |
5193 | ||
5194 | if (pDevice->RestoreOnWakeUp) { | |
5195 | LM_WritePhy (pDevice, BCM540X_1000BASET_CTRL_REG, 0); | |
5196 | pDevice->advertising1000 = 0; | |
5197 | Value32 = PHY_AN_AD_10BASET_FULL | PHY_AN_AD_10BASET_HALF; | |
5198 | if (pDevice->WolSpeed == WOL_SPEED_100MB) { | |
5199 | Value32 |= | |
5200 | PHY_AN_AD_100BASETX_FULL | PHY_AN_AD_100BASETX_HALF; | |
5201 | } | |
5202 | Value32 |= PHY_AN_AD_PROTOCOL_802_3_CSMA_CD; | |
5203 | Value32 |= GetPhyAdFlowCntrlSettings (pDevice); | |
5204 | LM_WritePhy (pDevice, PHY_AN_AD_REG, Value32); | |
5205 | pDevice->advertising = Value32; | |
5206 | } | |
5207 | /* Setup the auto-negotiation advertisement register. */ | |
5208 | else if (LineSpeed == LM_LINE_SPEED_UNKNOWN) { | |
5209 | /* Setup the 10/100 Mbps auto-negotiation advertisement register. */ | |
5210 | Value32 = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD | | |
5211 | PHY_AN_AD_10BASET_HALF | PHY_AN_AD_10BASET_FULL | | |
5212 | PHY_AN_AD_100BASETX_FULL | PHY_AN_AD_100BASETX_HALF; | |
5213 | Value32 |= GetPhyAdFlowCntrlSettings (pDevice); | |
5214 | ||
5215 | LM_WritePhy (pDevice, PHY_AN_AD_REG, Value32); | |
5216 | pDevice->advertising = Value32; | |
5217 | ||
5218 | /* Advertise 1000Mbps */ | |
5219 | Value32 = | |
5220 | BCM540X_AN_AD_1000BASET_HALF | BCM540X_AN_AD_1000BASET_FULL; | |
c609719b WD |
5221 | |
5222 | #if INCLUDE_5701_AX_FIX | |
f539edc0 VB |
5223 | /* Bug: workaround for CRC error in gigabit mode when we are in */ |
5224 | /* slave mode. This will force the PHY to operate in */ | |
5225 | /* master mode. */ | |
5226 | if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 || | |
5227 | pDevice->ChipRevId == T3_CHIP_ID_5701_B0) { | |
5228 | Value32 |= BCM540X_CONFIG_AS_MASTER | | |
5229 | BCM540X_ENABLE_CONFIG_AS_MASTER; | |
5230 | } | |
c609719b WD |
5231 | #endif |
5232 | ||
f539edc0 VB |
5233 | LM_WritePhy (pDevice, BCM540X_1000BASET_CTRL_REG, Value32); |
5234 | pDevice->advertising1000 = Value32; | |
5235 | } else { | |
5236 | if (LineSpeed == LM_LINE_SPEED_1000MBPS) { | |
5237 | Value32 = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD; | |
5238 | Value32 |= GetPhyAdFlowCntrlSettings (pDevice); | |
5239 | ||
5240 | LM_WritePhy (pDevice, PHY_AN_AD_REG, Value32); | |
5241 | pDevice->advertising = Value32; | |
5242 | ||
5243 | if (DuplexMode != LM_DUPLEX_MODE_FULL) { | |
5244 | Value32 = BCM540X_AN_AD_1000BASET_HALF; | |
5245 | } else { | |
5246 | Value32 = BCM540X_AN_AD_1000BASET_FULL; | |
5247 | } | |
8bde7f77 | 5248 | |
f539edc0 VB |
5249 | LM_WritePhy (pDevice, BCM540X_1000BASET_CTRL_REG, |
5250 | Value32); | |
5251 | pDevice->advertising1000 = Value32; | |
5252 | } else if (LineSpeed == LM_LINE_SPEED_100MBPS) { | |
5253 | LM_WritePhy (pDevice, BCM540X_1000BASET_CTRL_REG, 0); | |
5254 | pDevice->advertising1000 = 0; | |
5255 | ||
5256 | if (DuplexMode != LM_DUPLEX_MODE_FULL) { | |
5257 | Value32 = PHY_AN_AD_100BASETX_HALF; | |
5258 | } else { | |
5259 | Value32 = PHY_AN_AD_100BASETX_FULL; | |
5260 | } | |
8bde7f77 | 5261 | |
f539edc0 VB |
5262 | Value32 |= PHY_AN_AD_PROTOCOL_802_3_CSMA_CD; |
5263 | Value32 |= GetPhyAdFlowCntrlSettings (pDevice); | |
8bde7f77 | 5264 | |
f539edc0 VB |
5265 | LM_WritePhy (pDevice, PHY_AN_AD_REG, Value32); |
5266 | pDevice->advertising = Value32; | |
5267 | } else if (LineSpeed == LM_LINE_SPEED_10MBPS) { | |
5268 | LM_WritePhy (pDevice, BCM540X_1000BASET_CTRL_REG, 0); | |
5269 | pDevice->advertising1000 = 0; | |
8bde7f77 | 5270 | |
f539edc0 VB |
5271 | if (DuplexMode != LM_DUPLEX_MODE_FULL) { |
5272 | Value32 = PHY_AN_AD_10BASET_HALF; | |
5273 | } else { | |
5274 | Value32 = PHY_AN_AD_10BASET_FULL; | |
5275 | } | |
8bde7f77 | 5276 | |
f539edc0 VB |
5277 | Value32 |= PHY_AN_AD_PROTOCOL_802_3_CSMA_CD; |
5278 | Value32 |= GetPhyAdFlowCntrlSettings (pDevice); | |
8bde7f77 | 5279 | |
f539edc0 VB |
5280 | LM_WritePhy (pDevice, PHY_AN_AD_REG, Value32); |
5281 | pDevice->advertising = Value32; | |
5282 | } | |
8bde7f77 WD |
5283 | } |
5284 | ||
f539edc0 VB |
5285 | /* Force line speed if auto-negotiation is disabled. */ |
5286 | if (pDevice->DisableAutoNeg && LineSpeed != LM_LINE_SPEED_UNKNOWN) { | |
5287 | /* This code path is executed only when there is link. */ | |
5288 | pDevice->MediaType = MediaType; | |
5289 | pDevice->LineSpeed = LineSpeed; | |
5290 | pDevice->DuplexMode = DuplexMode; | |
8bde7f77 | 5291 | |
f539edc0 VB |
5292 | /* Force line seepd. */ |
5293 | NewPhyCtrl = 0; | |
5294 | switch (LineSpeed) { | |
5295 | case LM_LINE_SPEED_10MBPS: | |
5296 | NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_10MBPS; | |
5297 | break; | |
5298 | case LM_LINE_SPEED_100MBPS: | |
5299 | NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_100MBPS; | |
5300 | break; | |
5301 | case LM_LINE_SPEED_1000MBPS: | |
5302 | NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_1000MBPS; | |
5303 | break; | |
5304 | default: | |
5305 | NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_1000MBPS; | |
5306 | break; | |
5307 | } | |
8bde7f77 | 5308 | |
f539edc0 VB |
5309 | if (DuplexMode == LM_DUPLEX_MODE_FULL) { |
5310 | NewPhyCtrl |= PHY_CTRL_FULL_DUPLEX_MODE; | |
5311 | } | |
8bde7f77 | 5312 | |
f539edc0 VB |
5313 | /* Don't do anything if the PHY_CTRL is already what we wanted. */ |
5314 | LM_ReadPhy (pDevice, PHY_CTRL_REG, &Value32); | |
5315 | if (Value32 != NewPhyCtrl) { | |
5316 | /* Temporary bring the link down before forcing line speed. */ | |
5317 | LM_WritePhy (pDevice, PHY_CTRL_REG, | |
5318 | PHY_CTRL_LOOPBACK_MODE); | |
8bde7f77 | 5319 | |
f539edc0 VB |
5320 | /* Wait for link to go down. */ |
5321 | for (Cnt = 0; Cnt < 15000; Cnt++) { | |
5322 | MM_Wait (10); | |
8bde7f77 | 5323 | |
f539edc0 VB |
5324 | LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); |
5325 | LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); | |
5326 | ||
5327 | if (!(Value32 & PHY_STATUS_LINK_PASS)) { | |
5328 | MM_Wait (40); | |
5329 | break; | |
5330 | } | |
5331 | } | |
c609719b | 5332 | |
f539edc0 VB |
5333 | LM_WritePhy (pDevice, PHY_CTRL_REG, NewPhyCtrl); |
5334 | MM_Wait (40); | |
5335 | } | |
5336 | } else { | |
5337 | LM_WritePhy (pDevice, PHY_CTRL_REG, PHY_CTRL_AUTO_NEG_ENABLE | | |
5338 | PHY_CTRL_RESTART_AUTO_NEG); | |
5339 | } | |
c609719b | 5340 | |
f539edc0 VB |
5341 | return LM_STATUS_SUCCESS; |
5342 | } /* LM_ForceAutoNegBcm540xPhy */ | |
c609719b | 5343 | |
c609719b WD |
5344 | /******************************************************************************/ |
5345 | /* Description: */ | |
5346 | /* */ | |
5347 | /* Return: */ | |
5348 | /******************************************************************************/ | |
5349 | static LM_STATUS | |
f539edc0 VB |
5350 | LM_ForceAutoNeg (PLM_DEVICE_BLOCK pDevice, |
5351 | LM_REQUESTED_MEDIA_TYPE RequestedMediaType) | |
c609719b | 5352 | { |
f539edc0 | 5353 | LM_STATUS LmStatus; |
c609719b | 5354 | |
f539edc0 VB |
5355 | /* Initialize the phy chip. */ |
5356 | switch (pDevice->PhyId & PHY_ID_MASK) { | |
8bde7f77 WD |
5357 | case PHY_BCM5400_PHY_ID: |
5358 | case PHY_BCM5401_PHY_ID: | |
5359 | case PHY_BCM5411_PHY_ID: | |
5360 | case PHY_BCM5701_PHY_ID: | |
5361 | case PHY_BCM5703_PHY_ID: | |
5362 | case PHY_BCM5704_PHY_ID: | |
f539edc0 VB |
5363 | LmStatus = |
5364 | LM_ForceAutoNegBcm540xPhy (pDevice, RequestedMediaType); | |
5365 | break; | |
c609719b | 5366 | |
8bde7f77 | 5367 | default: |
f539edc0 VB |
5368 | LmStatus = LM_STATUS_FAILURE; |
5369 | break; | |
5370 | } | |
c609719b | 5371 | |
f539edc0 VB |
5372 | return LmStatus; |
5373 | } /* LM_ForceAutoNeg */ | |
c609719b WD |
5374 | |
5375 | /******************************************************************************/ | |
5376 | /* Description: */ | |
5377 | /* */ | |
5378 | /* Return: */ | |
5379 | /******************************************************************************/ | |
f539edc0 VB |
5380 | LM_STATUS LM_LoadFirmware (PLM_DEVICE_BLOCK pDevice, |
5381 | PT3_FWIMG_INFO pFwImg, | |
5382 | LM_UINT32 LoadCpu, LM_UINT32 StartCpu) | |
c609719b | 5383 | { |
f539edc0 VB |
5384 | LM_UINT32 i; |
5385 | LM_UINT32 address; | |
c609719b | 5386 | |
f539edc0 VB |
5387 | if (LoadCpu & T3_RX_CPU_ID) { |
5388 | if (LM_HaltCpu (pDevice, T3_RX_CPU_ID) != LM_STATUS_SUCCESS) { | |
5389 | return LM_STATUS_FAILURE; | |
5390 | } | |
8bde7f77 | 5391 | |
f539edc0 VB |
5392 | /* First of all clear scrach pad memory */ |
5393 | for (i = 0; i < T3_RX_CPU_SPAD_SIZE; i += 4) { | |
5394 | LM_RegWrInd (pDevice, T3_RX_CPU_SPAD_ADDR + i, 0); | |
5395 | } | |
8bde7f77 | 5396 | |
f539edc0 VB |
5397 | /* Copy code first */ |
5398 | address = T3_RX_CPU_SPAD_ADDR + (pFwImg->Text.Offset & 0xffff); | |
5399 | for (i = 0; i <= pFwImg->Text.Length; i += 4) { | |
5400 | LM_RegWrInd (pDevice, address + i, | |
5401 | ((LM_UINT32 *) pFwImg->Text.Buffer)[i / | |
5402 | 4]); | |
5403 | } | |
8bde7f77 | 5404 | |
f539edc0 VB |
5405 | address = |
5406 | T3_RX_CPU_SPAD_ADDR + (pFwImg->ROnlyData.Offset & 0xffff); | |
5407 | for (i = 0; i <= pFwImg->ROnlyData.Length; i += 4) { | |
5408 | LM_RegWrInd (pDevice, address + i, | |
5409 | ((LM_UINT32 *) pFwImg->ROnlyData. | |
5410 | Buffer)[i / 4]); | |
5411 | } | |
8bde7f77 | 5412 | |
f539edc0 VB |
5413 | address = T3_RX_CPU_SPAD_ADDR + (pFwImg->Data.Offset & 0xffff); |
5414 | for (i = 0; i <= pFwImg->Data.Length; i += 4) { | |
5415 | LM_RegWrInd (pDevice, address + i, | |
5416 | ((LM_UINT32 *) pFwImg->Data.Buffer)[i / | |
5417 | 4]); | |
5418 | } | |
8bde7f77 | 5419 | } |
c609719b | 5420 | |
f539edc0 VB |
5421 | if (LoadCpu & T3_TX_CPU_ID) { |
5422 | if (LM_HaltCpu (pDevice, T3_TX_CPU_ID) != LM_STATUS_SUCCESS) { | |
5423 | return LM_STATUS_FAILURE; | |
5424 | } | |
8bde7f77 | 5425 | |
f539edc0 VB |
5426 | /* First of all clear scrach pad memory */ |
5427 | for (i = 0; i < T3_TX_CPU_SPAD_SIZE; i += 4) { | |
5428 | LM_RegWrInd (pDevice, T3_TX_CPU_SPAD_ADDR + i, 0); | |
5429 | } | |
8bde7f77 | 5430 | |
f539edc0 VB |
5431 | /* Copy code first */ |
5432 | address = T3_TX_CPU_SPAD_ADDR + (pFwImg->Text.Offset & 0xffff); | |
5433 | for (i = 0; i <= pFwImg->Text.Length; i += 4) { | |
5434 | LM_RegWrInd (pDevice, address + i, | |
5435 | ((LM_UINT32 *) pFwImg->Text.Buffer)[i / | |
5436 | 4]); | |
5437 | } | |
8bde7f77 | 5438 | |
f539edc0 VB |
5439 | address = |
5440 | T3_TX_CPU_SPAD_ADDR + (pFwImg->ROnlyData.Offset & 0xffff); | |
5441 | for (i = 0; i <= pFwImg->ROnlyData.Length; i += 4) { | |
5442 | LM_RegWrInd (pDevice, address + i, | |
5443 | ((LM_UINT32 *) pFwImg->ROnlyData. | |
5444 | Buffer)[i / 4]); | |
5445 | } | |
8bde7f77 | 5446 | |
f539edc0 VB |
5447 | address = T3_TX_CPU_SPAD_ADDR + (pFwImg->Data.Offset & 0xffff); |
5448 | for (i = 0; i <= pFwImg->Data.Length; i += 4) { | |
5449 | LM_RegWrInd (pDevice, address + i, | |
5450 | ((LM_UINT32 *) pFwImg->Data.Buffer)[i / | |
5451 | 4]); | |
5452 | } | |
8bde7f77 | 5453 | } |
c609719b | 5454 | |
f539edc0 VB |
5455 | if (StartCpu & T3_RX_CPU_ID) { |
5456 | /* Start Rx CPU */ | |
5457 | REG_WR (pDevice, rxCpu.reg.state, 0xffffffff); | |
5458 | REG_WR (pDevice, rxCpu.reg.PC, pFwImg->StartAddress); | |
5459 | for (i = 0; i < 5; i++) { | |
5460 | if (pFwImg->StartAddress == | |
5461 | REG_RD (pDevice, rxCpu.reg.PC)) | |
5462 | break; | |
5463 | ||
5464 | REG_WR (pDevice, rxCpu.reg.state, 0xffffffff); | |
5465 | REG_WR (pDevice, rxCpu.reg.mode, CPU_MODE_HALT); | |
5466 | REG_WR (pDevice, rxCpu.reg.PC, pFwImg->StartAddress); | |
5467 | MM_Wait (1000); | |
5468 | } | |
c609719b | 5469 | |
f539edc0 VB |
5470 | REG_WR (pDevice, rxCpu.reg.state, 0xffffffff); |
5471 | REG_WR (pDevice, rxCpu.reg.mode, 0); | |
8bde7f77 | 5472 | } |
c609719b | 5473 | |
f539edc0 VB |
5474 | if (StartCpu & T3_TX_CPU_ID) { |
5475 | /* Start Tx CPU */ | |
5476 | REG_WR (pDevice, txCpu.reg.state, 0xffffffff); | |
5477 | REG_WR (pDevice, txCpu.reg.PC, pFwImg->StartAddress); | |
5478 | for (i = 0; i < 5; i++) { | |
5479 | if (pFwImg->StartAddress == | |
5480 | REG_RD (pDevice, txCpu.reg.PC)) | |
5481 | break; | |
c609719b | 5482 | |
f539edc0 VB |
5483 | REG_WR (pDevice, txCpu.reg.state, 0xffffffff); |
5484 | REG_WR (pDevice, txCpu.reg.mode, CPU_MODE_HALT); | |
5485 | REG_WR (pDevice, txCpu.reg.PC, pFwImg->StartAddress); | |
5486 | MM_Wait (1000); | |
5487 | } | |
c609719b | 5488 | |
f539edc0 VB |
5489 | REG_WR (pDevice, txCpu.reg.state, 0xffffffff); |
5490 | REG_WR (pDevice, txCpu.reg.mode, 0); | |
8bde7f77 | 5491 | } |
c609719b | 5492 | |
f539edc0 | 5493 | return LM_STATUS_SUCCESS; |
c609719b WD |
5494 | } |
5495 | ||
f539edc0 | 5496 | STATIC LM_STATUS LM_HaltCpu (PLM_DEVICE_BLOCK pDevice, LM_UINT32 cpu_number) |
c609719b | 5497 | { |
f539edc0 | 5498 | LM_UINT32 i; |
c609719b | 5499 | |
f539edc0 VB |
5500 | if (cpu_number == T3_RX_CPU_ID) { |
5501 | for (i = 0; i < 10000; i++) { | |
5502 | REG_WR (pDevice, rxCpu.reg.state, 0xffffffff); | |
5503 | REG_WR (pDevice, rxCpu.reg.mode, CPU_MODE_HALT); | |
c609719b | 5504 | |
f539edc0 VB |
5505 | if (REG_RD (pDevice, rxCpu.reg.mode) & CPU_MODE_HALT) |
5506 | break; | |
5507 | } | |
c609719b | 5508 | |
f539edc0 VB |
5509 | REG_WR (pDevice, rxCpu.reg.state, 0xffffffff); |
5510 | REG_WR (pDevice, rxCpu.reg.mode, CPU_MODE_HALT); | |
5511 | MM_Wait (10); | |
5512 | } else { | |
5513 | for (i = 0; i < 10000; i++) { | |
5514 | REG_WR (pDevice, txCpu.reg.state, 0xffffffff); | |
5515 | REG_WR (pDevice, txCpu.reg.mode, CPU_MODE_HALT); | |
c609719b | 5516 | |
f539edc0 VB |
5517 | if (REG_RD (pDevice, txCpu.reg.mode) & CPU_MODE_HALT) |
5518 | break; | |
5519 | } | |
8bde7f77 | 5520 | } |
c609719b | 5521 | |
f539edc0 | 5522 | return ((i == 10000) ? LM_STATUS_FAILURE : LM_STATUS_SUCCESS); |
c609719b WD |
5523 | } |
5524 | ||
f539edc0 | 5525 | int LM_BlinkLED (PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlinkDurationSec) |
c609719b WD |
5526 | { |
5527 | LM_UINT32 Oldcfg; | |
5528 | int j; | |
5529 | int ret = 0; | |
5530 | ||
f539edc0 | 5531 | if (BlinkDurationSec == 0) { |
c609719b | 5532 | return 0; |
8bde7f77 | 5533 | } |
f539edc0 | 5534 | if (BlinkDurationSec > 120) { |
8bde7f77 | 5535 | BlinkDurationSec = 120; |
c609719b WD |
5536 | } |
5537 | ||
f539edc0 VB |
5538 | Oldcfg = REG_RD (pDevice, MacCtrl.LedCtrl); |
5539 | for (j = 0; j < BlinkDurationSec * 2; j++) { | |
5540 | if (j % 2) { | |
8bde7f77 | 5541 | /* Turn on the LEDs. */ |
f539edc0 | 5542 | REG_WR (pDevice, MacCtrl.LedCtrl, |
c609719b WD |
5543 | LED_CTRL_OVERRIDE_LINK_LED | |
5544 | LED_CTRL_1000MBPS_LED_ON | | |
5545 | LED_CTRL_100MBPS_LED_ON | | |
5546 | LED_CTRL_10MBPS_LED_ON | | |
5547 | LED_CTRL_OVERRIDE_TRAFFIC_LED | | |
5548 | LED_CTRL_BLINK_TRAFFIC_LED | | |
5549 | LED_CTRL_TRAFFIC_LED); | |
f539edc0 | 5550 | } else { |
8bde7f77 | 5551 | /* Turn off the LEDs. */ |
f539edc0 | 5552 | REG_WR (pDevice, MacCtrl.LedCtrl, |
c609719b WD |
5553 | LED_CTRL_OVERRIDE_LINK_LED | |
5554 | LED_CTRL_OVERRIDE_TRAFFIC_LED); | |
5555 | } | |
5556 | ||
5557 | #ifndef EMBEDDED | |
8bde7f77 | 5558 | current->state = TASK_INTERRUPTIBLE; |
f539edc0 | 5559 | if (schedule_timeout (HZ / 2) != 0) { |
8bde7f77 WD |
5560 | ret = -EINTR; |
5561 | break; | |
5562 | } | |
c609719b | 5563 | #else |
f539edc0 | 5564 | udelay (100000); /* 1s sleep */ |
c609719b WD |
5565 | #endif |
5566 | } | |
f539edc0 | 5567 | REG_WR (pDevice, MacCtrl.LedCtrl, Oldcfg); |
c609719b WD |
5568 | return ret; |
5569 | } | |
5570 | ||
f539edc0 VB |
5571 | int t3_do_dma (PLM_DEVICE_BLOCK pDevice, |
5572 | LM_PHYSICAL_ADDRESS host_addr_phy, int length, int dma_read) | |
c609719b | 5573 | { |
f539edc0 VB |
5574 | T3_DMA_DESC dma_desc; |
5575 | int i; | |
5576 | LM_UINT32 dma_desc_addr; | |
5577 | LM_UINT32 value32; | |
5578 | ||
5579 | REG_WR (pDevice, BufMgr.Mode, 0); | |
5580 | REG_WR (pDevice, Ftq.Reset, 0); | |
5581 | ||
5582 | dma_desc.host_addr.High = host_addr_phy.High; | |
5583 | dma_desc.host_addr.Low = host_addr_phy.Low; | |
5584 | dma_desc.nic_mbuf = 0x2100; | |
5585 | dma_desc.len = length; | |
5586 | dma_desc.flags = 0x00000004; /* Generate Rx-CPU event */ | |
5587 | ||
5588 | if (dma_read) { | |
5589 | dma_desc.cqid_sqid = (T3_QID_RX_BD_COMP << 8) | | |
5590 | T3_QID_DMA_HIGH_PRI_READ; | |
5591 | REG_WR (pDevice, DmaRead.Mode, DMA_READ_MODE_ENABLE); | |
5592 | } else { | |
5593 | dma_desc.cqid_sqid = (T3_QID_RX_DATA_COMP << 8) | | |
5594 | T3_QID_DMA_HIGH_PRI_WRITE; | |
5595 | REG_WR (pDevice, DmaWrite.Mode, DMA_WRITE_MODE_ENABLE); | |
5596 | } | |
5597 | ||
5598 | dma_desc_addr = T3_NIC_DMA_DESC_POOL_ADDR; | |
5599 | ||
5600 | /* Writing this DMA descriptor to DMA memory */ | |
5601 | for (i = 0; i < sizeof (T3_DMA_DESC); i += 4) { | |
5602 | value32 = *((PLM_UINT32) (((PLM_UINT8) & dma_desc) + i)); | |
5603 | MM_WriteConfig32 (pDevice, T3_PCI_MEM_WIN_ADDR_REG, | |
5604 | dma_desc_addr + i); | |
5605 | MM_WriteConfig32 (pDevice, T3_PCI_MEM_WIN_DATA_REG, | |
5606 | cpu_to_le32 (value32)); | |
5607 | } | |
5608 | MM_WriteConfig32 (pDevice, T3_PCI_MEM_WIN_ADDR_REG, 0); | |
5609 | ||
8bde7f77 | 5610 | if (dma_read) |
f539edc0 VB |
5611 | REG_WR (pDevice, Ftq.DmaHighReadFtqFifoEnqueueDequeue, |
5612 | dma_desc_addr); | |
8bde7f77 | 5613 | else |
f539edc0 VB |
5614 | REG_WR (pDevice, Ftq.DmaHighWriteFtqFifoEnqueueDequeue, |
5615 | dma_desc_addr); | |
5616 | ||
5617 | for (i = 0; i < 40; i++) { | |
5618 | if (dma_read) | |
5619 | value32 = | |
5620 | REG_RD (pDevice, | |
5621 | Ftq.RcvBdCompFtqFifoEnqueueDequeue); | |
5622 | else | |
5623 | value32 = | |
5624 | REG_RD (pDevice, | |
5625 | Ftq.RcvDataCompFtqFifoEnqueueDequeue); | |
c609719b | 5626 | |
f539edc0 VB |
5627 | if ((value32 & 0xffff) == dma_desc_addr) |
5628 | break; | |
c609719b | 5629 | |
f539edc0 VB |
5630 | MM_Wait (10); |
5631 | } | |
c609719b | 5632 | |
f539edc0 | 5633 | return LM_STATUS_SUCCESS; |
c609719b WD |
5634 | } |
5635 | ||
5636 | STATIC LM_STATUS | |
f539edc0 VB |
5637 | LM_DmaTest (PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pBufferVirt, |
5638 | LM_PHYSICAL_ADDRESS BufferPhy, LM_UINT32 BufferSize) | |
c609719b | 5639 | { |
f539edc0 VB |
5640 | int j; |
5641 | LM_UINT32 *ptr; | |
5642 | int dma_success = 0; | |
5643 | ||
5644 | if (T3_ASIC_REV (pDevice->ChipRevId) != T3_ASIC_REV_5700 && | |
5645 | T3_ASIC_REV (pDevice->ChipRevId) != T3_ASIC_REV_5701) { | |
5646 | return LM_STATUS_SUCCESS; | |
5647 | } | |
5648 | while (!dma_success) { | |
5649 | /* Fill data with incremental patterns */ | |
5650 | ptr = (LM_UINT32 *) pBufferVirt; | |
5651 | for (j = 0; j < BufferSize / 4; j++) | |
5652 | *ptr++ = j; | |
5653 | ||
5654 | if (t3_do_dma (pDevice, BufferPhy, BufferSize, 1) == | |
5655 | LM_STATUS_FAILURE) { | |
5656 | return LM_STATUS_FAILURE; | |
5657 | } | |
c609719b | 5658 | |
f539edc0 VB |
5659 | MM_Wait (40); |
5660 | ptr = (LM_UINT32 *) pBufferVirt; | |
5661 | /* Fill data with zero */ | |
5662 | for (j = 0; j < BufferSize / 4; j++) | |
5663 | *ptr++ = 0; | |
8bde7f77 | 5664 | |
f539edc0 VB |
5665 | if (t3_do_dma (pDevice, BufferPhy, BufferSize, 0) == |
5666 | LM_STATUS_FAILURE) { | |
5667 | return LM_STATUS_FAILURE; | |
5668 | } | |
8bde7f77 | 5669 | |
f539edc0 VB |
5670 | MM_Wait (40); |
5671 | /* Check for data */ | |
5672 | ptr = (LM_UINT32 *) pBufferVirt; | |
5673 | for (j = 0; j < BufferSize / 4; j++) { | |
5674 | if (*ptr++ != j) { | |
5675 | if ((pDevice-> | |
5676 | DmaReadWriteCtrl & | |
5677 | DMA_CTRL_WRITE_BOUNDARY_MASK) | |
5678 | == DMA_CTRL_WRITE_BOUNDARY_DISABLE) { | |
5679 | pDevice->DmaReadWriteCtrl = | |
5680 | (pDevice-> | |
5681 | DmaReadWriteCtrl & | |
5682 | ~DMA_CTRL_WRITE_BOUNDARY_MASK) | | |
5683 | DMA_CTRL_WRITE_BOUNDARY_16; | |
5684 | REG_WR (pDevice, | |
5685 | PciCfg.DmaReadWriteCtrl, | |
5686 | pDevice->DmaReadWriteCtrl); | |
5687 | break; | |
5688 | } else { | |
5689 | return LM_STATUS_FAILURE; | |
5690 | } | |
5691 | } | |
5692 | } | |
5693 | if (j == (BufferSize / 4)) | |
5694 | dma_success = 1; | |
8bde7f77 | 5695 | } |
f539edc0 | 5696 | return LM_STATUS_SUCCESS; |
c609719b | 5697 | } |