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