]> git.proxmox.com Git - mirror_edk2.git/blame - OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772b/SimpleNetwork.c
OptionRomPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / OptionRomPkg / Bus / Usb / UsbNetworking / Ax88772b / SimpleNetwork.c
CommitLineData
7f556e4d 1/** @file\r
2 Provides the Simple Network functions.\r
3\r
96ae5934
MK
4 Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.\r
5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
7f556e4d 6\r
7**/\r
8\r
9#include "Ax88772.h"\r
10\r
11/**\r
12 This function updates the filtering on the receiver.\r
13\r
14 This support routine calls ::Ax88772MacAddressSet to update\r
15 the MAC address. This routine then rebuilds the multicast\r
16 hash by calling ::Ax88772MulticastClear and ::Ax88772MulticastSet.\r
17 Finally this routine enables the receiver by calling\r
18 ::Ax88772RxControl.\r
19 \r
20 @param [in] pSimpleNetwork Simple network mode pointer \r
21\r
22 @retval EFI_SUCCESS This operation was successful.\r
23 @retval EFI_NOT_STARTED The network interface was not started.\r
24 @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
25 EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
26 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
27 @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.\r
28\r
29**/\r
30EFI_STATUS\r
31ReceiveFilterUpdate (\r
32 IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork\r
33 )\r
34{\r
35 EFI_SIMPLE_NETWORK_MODE * pMode;\r
36 NIC_DEVICE * pNicDevice;\r
37 EFI_STATUS Status;\r
38 UINT32 Index;\r
39\r
40 //\r
41 // Set the MAC address\r
42 //\r
43 pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );\r
44 pMode = pSimpleNetwork->Mode;\r
45\r
46 //\r
47 // Clear the multicast hash table\r
48 //\r
49 Ax88772MulticastClear ( pNicDevice );\r
50\r
51 //\r
52 // Load the multicast hash table\r
53 //\r
54 if ( 0 != ( pMode->ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST )) {\r
55 for ( Index = 0; Index < pMode->MCastFilterCount; Index++ ) {\r
56 //\r
57 // Enable the next multicast address\r
58 //\r
59 Ax88772MulticastSet ( pNicDevice,\r
60 &pMode->MCastFilter[ Index ].Addr[0]);\r
61 }\r
62 }\r
63\r
64 Status = Ax88772RxControl ( pNicDevice, pMode->ReceiveFilterSetting );\r
65\r
66 return Status;\r
67}\r
68\r
69\r
70/**\r
71 This function updates the SNP driver status.\r
72 \r
73 This function gets the current interrupt and recycled transmit\r
74 buffer status from the network interface. The interrupt status\r
75 and the media status are returned as a bit mask in InterruptStatus.\r
76 If InterruptStatus is NULL, the interrupt status will not be read.\r
77 Upon successful return of the media status, the MediaPresent field\r
78 of EFI_SIMPLE_NETWORK_MODE will be updated to reflect any change\r
79 of media status. If TxBuf is not NULL, a recycled transmit buffer\r
80 address will be retrived. If a recycled transmit buffer address\r
81 is returned in TxBuf, then the buffer has been successfully\r
82 transmitted, and the status for that buffer is cleared.\r
83\r
84 This function calls ::Ax88772Rx to update the media status and\r
85 queue any receive packets.\r
86\r
87 @param [in] pSimpleNetwork Protocol instance pointer\r
88 @param [in] pInterruptStatus A pointer to the bit mask of the current active interrupts.\r
89 If this is NULL, the interrupt status will not be read from\r
90 the device. If this is not NULL, the interrupt status will\r
91 be read from teh device. When the interrupt status is read,\r
92 it will also be cleared. Clearing the transmit interrupt\r
93 does not empty the recycled transmit buffer array.\r
94 @param [out] ppTxBuf Recycled transmit buffer address. The network interface will\r
95 not transmit if its internal recycled transmit buffer array is\r
96 full. Reading the transmit buffer does not clear the transmit\r
97 interrupt. If this is NULL, then the transmit buffer status\r
98 will not be read. If there are not transmit buffers to recycle\r
99 and TxBuf is not NULL, *TxBuf will be set to NULL.\r
100\r
101 @retval EFI_SUCCESS This operation was successful.\r
102 @retval EFI_NOT_STARTED The network interface was not started.\r
103 @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
104 EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
105 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
106\r
107**/\r
108EFI_STATUS\r
109EFIAPI\r
110SN_GetStatus (\r
111 IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,\r
112 OUT UINT32 * pInterruptStatus,\r
113 OUT VOID ** ppTxBuf\r
114 )\r
115{\r
116 EFI_SIMPLE_NETWORK_MODE * pMode;\r
117 NIC_DEVICE * pNicDevice;\r
118 EFI_STATUS Status;\r
119 BOOLEAN bFullDuplex;\r
120 BOOLEAN bLinkUp;\r
121 BOOLEAN bSpeed100;\r
122 EFI_TPL TplPrevious;\r
123 \r
124 TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);\r
125 //\r
126 // Verify the parameters\r
127 //\r
128 if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {\r
129 //\r
130 // Return the transmit buffer\r
131 //\r
132 \r
133 pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );\r
134 if (( NULL != ppTxBuf ) && ( NULL != pNicDevice->pTxBuffer )) {\r
135 *ppTxBuf = pNicDevice->pTxBuffer;\r
136 pNicDevice->pTxBuffer = NULL;\r
137 }\r
138 \r
139 //\r
140 // Determine if interface is running\r
141 //\r
142 pMode = pSimpleNetwork->Mode;\r
143 if ( EfiSimpleNetworkInitialized == pMode->State ) {\r
144\r
145 if ( pNicDevice->LinkIdleCnt > MAX_LINKIDLE_THRESHOLD) {\r
146\r
147 bLinkUp = pNicDevice->bLinkUp;\r
148 bSpeed100 = pNicDevice->b100Mbps;\r
149 bFullDuplex = pNicDevice->bFullDuplex;\r
150 Status = Ax88772NegotiateLinkComplete ( pNicDevice,\r
151 &pNicDevice->PollCount,\r
152 &pNicDevice->bComplete,\r
153 &pNicDevice->bLinkUp,\r
154 &pNicDevice->b100Mbps,\r
155 &pNicDevice->bFullDuplex );\r
156\r
157 //\r
158 // Determine if the autonegotiation is complete\r
159 //\r
160 if ( pNicDevice->bComplete ) {\r
161 if ( pNicDevice->bLinkUp ) {\r
162 if (( bSpeed100 && ( !pNicDevice->b100Mbps ))\r
163 || (( !bSpeed100 ) && pNicDevice->b100Mbps )\r
164 || ( bFullDuplex && ( !pNicDevice->bFullDuplex ))\r
165 || (( !bFullDuplex ) && pNicDevice->bFullDuplex )) {\r
166 pNicDevice->PollCount = 0;\r
167 DEBUG (( EFI_D_INFO , "Reset to establish proper link setup: %d Mbps, %a duplex\r\n",\r
168 pNicDevice->b100Mbps ? 100 : 10, pNicDevice->bFullDuplex ? "Full" : "Half"));\r
169 Status = SN_Reset ( &pNicDevice->SimpleNetwork, FALSE );\r
170 }\r
171 if (( !bLinkUp ) && pNicDevice->bLinkUp ) {\r
172 //\r
173 // Display the autonegotiation status\r
174 //\r
175 DEBUG (( EFI_D_INFO , "Link: Up, %d Mbps, %a duplex\r\n",\r
176 pNicDevice->b100Mbps ? 100 : 10, pNicDevice->bFullDuplex ? "Full" : "Half"));\r
177\r
178 }\r
179 pNicDevice->LinkIdleCnt = 0;\r
180 }\r
181 }\r
182 //\r
183 // Update the link status\r
184 //\r
185 if ( bLinkUp && ( !pNicDevice->bLinkUp )) {\r
186 DEBUG (( EFI_D_INFO , "Link: Down\r\n"));\r
187 }\r
188 }\r
189\r
190 pMode->MediaPresent = pNicDevice->bLinkUp;\r
191 //\r
192 // Return the interrupt status\r
193 //\r
194 if ( NULL != pInterruptStatus ) {\r
195 *pInterruptStatus = 0;\r
196 } \r
197 Status = EFI_SUCCESS;\r
198 }\r
199 else {\r
4986bbaf
YP
200 if ( EfiSimpleNetworkStarted == pMode->State ) {\r
201 Status = EFI_DEVICE_ERROR;\r
202 }\r
203 else {\r
204 Status = EFI_NOT_STARTED;\r
205 }\r
7f556e4d 206 }\r
207 \r
208 }\r
209 else {\r
210 Status = EFI_INVALID_PARAMETER;\r
211 }\r
212 gBS->RestoreTPL(TplPrevious) ;\r
213\r
214 return Status;\r
215}\r
216\r
217\r
218/**\r
219 Resets the network adapter and allocates the transmit and receive buffers\r
220 required by the network interface; optionally, also requests allocation of\r
221 additional transmit and receive buffers. This routine must be called before\r
222 any other routine in the Simple Network protocol is called.\r
223\r
224 @param [in] pSimpleNetwork Protocol instance pointer\r
225 @param [in] ExtraRxBufferSize Size in bytes to add to the receive buffer allocation\r
226 @param [in] ExtraTxBufferSize Size in bytes to add to the transmit buffer allocation\r
227\r
228 @retval EFI_SUCCESS This operation was successful.\r
229 @retval EFI_NOT_STARTED The network interface was not started.\r
97b67051 230 @retval EFI_OUT_OF_RESOURCES There was not enough memory for the transmit and receive buffers\r
7f556e4d 231 @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
232 EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
233 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
234 @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.\r
235\r
236**/\r
237EFI_STATUS\r
238EFIAPI\r
239SN_Initialize ( \r
240 IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,\r
241 IN UINTN ExtraRxBufferSize,\r
242 IN UINTN ExtraTxBufferSize\r
243 )\r
244{\r
245 EFI_SIMPLE_NETWORK_MODE * pMode;\r
246 EFI_STATUS Status;\r
247 UINT32 TmpState;\r
248 EFI_TPL TplPrevious;\r
249 \r
250 TplPrevious = gBS->RaiseTPL (TPL_CALLBACK);\r
251 //\r
252 // Verify the parameters\r
253 //\r
254 if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {\r
255 //\r
256 // Determine if the interface is already started\r
257 //\r
258 pMode = pSimpleNetwork->Mode;\r
259 if ( EfiSimpleNetworkStarted == pMode->State ) {\r
260 if (( 0 == ExtraRxBufferSize ) && ( 0 == ExtraTxBufferSize )) {\r
261 //\r
262 // Start the adapter\r
263 //\r
264 TmpState = pMode->State;\r
265 pMode->State = EfiSimpleNetworkInitialized;\r
266 Status = SN_Reset ( pSimpleNetwork, FALSE );\r
267 if ( EFI_ERROR ( Status )) {\r
268 //\r
269 // Update the network state\r
270 //\r
271 pMode->State = TmpState;\r
272 DEBUG (( EFI_D_ERROR , "SN_reset failed\n"));\r
273 }\r
274 }\r
275 else {\r
276 DEBUG (( EFI_D_ERROR , "Increase ExtraRxBufferSize = %d ExtraTxBufferSize=%d\n", \r
277 ExtraRxBufferSize, ExtraTxBufferSize));\r
278 Status = EFI_UNSUPPORTED;\r
279 }\r
280 }\r
281 else {\r
282 Status = EFI_NOT_STARTED;\r
283 }\r
284 }\r
285 else {\r
286 Status = EFI_INVALID_PARAMETER;\r
287 }\r
288 gBS->RestoreTPL (TplPrevious);\r
289\r
290 return Status;\r
291}\r
292\r
293\r
294/**\r
295 This function converts a multicast IP address to a multicast HW MAC address\r
296 for all packet transactions.\r
297\r
298 @param [in] pSimpleNetwork Protocol instance pointer\r
299 @param [in] bIPv6 Set to TRUE if the multicast IP address is IPv6 [RFC2460].\r
300 Set to FALSE if the multicast IP address is IPv4 [RFC 791].\r
301 @param [in] pIP The multicast IP address that is to be converted to a\r
302 multicast HW MAC address.\r
303 @param [in] pMAC The multicast HW MAC address that is to be generated from IP.\r
304\r
305 @retval EFI_SUCCESS This operation was successful.\r
306 @retval EFI_NOT_STARTED The network interface was not started.\r
307 @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
308 EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
309 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
310 @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.\r
311\r
312**/\r
313EFI_STATUS\r
314EFIAPI\r
315SN_MCastIPtoMAC (\r
316 IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,\r
317 IN BOOLEAN bIPv6,\r
318 IN EFI_IP_ADDRESS * pIP,\r
4986bbaf 319 OUT EFI_MAC_ADDRESS * pMAC\r
7f556e4d 320 )\r
321{\r
322 EFI_STATUS Status;\r
323 EFI_TPL TplPrevious;\r
324\r
325 TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);\r
326 //\r
327 // Get pointer to SNP driver instance for *this.\r
328 //\r
329 if (pSimpleNetwork == NULL) {\r
330 gBS->RestoreTPL(TplPrevious);\r
331 return EFI_INVALID_PARAMETER;\r
332 }\r
333\r
334 if (pIP == NULL || pMAC == NULL) {\r
335 gBS->RestoreTPL(TplPrevious);\r
336 return EFI_INVALID_PARAMETER;\r
337 }\r
338\r
339 if (bIPv6){\r
340 Status = EFI_UNSUPPORTED;\r
341 } \r
342 else {\r
343 //\r
344 // check if the ip given is a mcast IP\r
345 //\r
346 if ((pIP->v4.Addr[0] & 0xF0) != 0xE0) {\r
347 gBS->RestoreTPL(TplPrevious);\r
348 return EFI_INVALID_PARAMETER;\r
349 }\r
350 else {\r
4986bbaf
YP
351 if (pSimpleNetwork->Mode->State == EfiSimpleNetworkInitialized)\r
352 {\r
353 pMAC->Addr[0] = 0x01;\r
354 pMAC->Addr[1] = 0x00;\r
355 pMAC->Addr[2] = 0x5e;\r
356 pMAC->Addr[3] = (UINT8) (pIP->v4.Addr[1] & 0x7f);\r
357 pMAC->Addr[4] = (UINT8) pIP->v4.Addr[2];\r
358 pMAC->Addr[5] = (UINT8) pIP->v4.Addr[3];\r
359 Status = EFI_SUCCESS;\r
360 }\r
361 else if (pSimpleNetwork->Mode->State == EfiSimpleNetworkStarted) {\r
362 Status = EFI_DEVICE_ERROR;\r
363 }\r
364 else {\r
365 Status = EFI_NOT_STARTED;\r
366 }\r
7f556e4d 367 gBS->RestoreTPL(TplPrevious);\r
368 }\r
369 }\r
370 return Status;\r
371}\r
372\r
373\r
374/**\r
375 This function performs read and write operations on the NVRAM device\r
376 attached to a network interface.\r
377\r
378 @param [in] pSimpleNetwork Protocol instance pointer\r
379 @param [in] ReadWrite TRUE for read operations, FALSE for write operations.\r
380 @param [in] Offset Byte offset in the NVRAM device at which to start the\r
381 read or write operation. This must be a multiple of\r
382 NvRamAccessSize and less than NvRamSize.\r
383 @param [in] BufferSize The number of bytes to read or write from the NVRAM device.\r
384 This must also be a multiple of NvramAccessSize.\r
385 @param [in, out] pBuffer A pointer to the data buffer.\r
386\r
387 @retval EFI_SUCCESS This operation was successful.\r
388 @retval EFI_NOT_STARTED The network interface was not started.\r
389 @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
390 EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
391 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
392 @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.\r
393\r
394**/\r
395EFI_STATUS\r
396EFIAPI\r
397SN_NvData (\r
398 IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,\r
399 IN BOOLEAN ReadWrite,\r
400 IN UINTN Offset,\r
401 IN UINTN BufferSize,\r
402 IN OUT VOID * pBuffer\r
403 )\r
404{\r
405 EFI_STATUS Status;\r
406 //\r
407 // This is not currently supported\r
408 //\r
409 Status = EFI_UNSUPPORTED;\r
410 return Status;\r
411}\r
412\r
413VOID \r
414FillPkt2Queue (\r
415 IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,\r
416 IN UINTN BufLength)\r
417{\r
418\r
419 UINT16 * pLength;\r
420 UINT16 * pLengthBar;\r
421 UINT8* pData;\r
422 UINT32 offset;\r
423 NIC_DEVICE * pNicDevice;\r
424 \r
425 pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork);\r
426 for ( offset = 0; offset < BufLength; ){\r
427 pLength = (UINT16*) (pNicDevice->pBulkInBuff + offset);\r
428 pLengthBar = (UINT16*) (pNicDevice->pBulkInBuff + offset +2);\r
429 \r
430 *pLength &= 0x7ff;\r
431 *pLengthBar &= 0x7ff;\r
432 *pLengthBar |= 0xf800;\r
433 \r
434 if ((*pLength ^ *pLengthBar ) != 0xFFFF) {\r
435 DEBUG (( EFI_D_ERROR , "Pkt length error. BufLength = %d\n", BufLength));\r
436 return;\r
437 } \r
438 \r
439 if (TRUE == pNicDevice->pNextFill->f_Used) {\r
440 return;\r
441 }\r
442 else {\r
443 pData = pNicDevice->pBulkInBuff + offset + 4;\r
444 pNicDevice->pNextFill->f_Used = TRUE;\r
445 pNicDevice->pNextFill->Length = *pLength;\r
446 CopyMem (&pNicDevice->pNextFill->Data[0], pData, *pLength);\r
447 \r
448 pNicDevice->pNextFill = pNicDevice->pNextFill->pNext;\r
449 offset += ((*pLength + HW_HDR_LENGTH - 1) &~3) + 1;\r
450 pNicDevice->PktCntInQueue++;\r
451 }\r
452 \r
453 }\r
454}\r
455\r
456EFI_STATUS\r
457EFIAPI\r
458SN_Receive (\r
459 IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,\r
460 OUT UINTN * pHeaderSize,\r
461 OUT UINTN * pBufferSize,\r
462 OUT VOID * pBuffer,\r
463 OUT EFI_MAC_ADDRESS * pSrcAddr,\r
464 OUT EFI_MAC_ADDRESS * pDestAddr,\r
465 OUT UINT16 * pProtocol\r
466 )\r
467{\r
468 EFI_SIMPLE_NETWORK_MODE * pMode;\r
469 NIC_DEVICE * pNicDevice;\r
470 EFI_STATUS Status;\r
471 EFI_TPL TplPrevious;\r
472 UINT16 Type;\r
473 EFI_USB_IO_PROTOCOL *pUsbIo;\r
474 UINTN LengthInBytes;\r
475 UINT32 TransferStatus;\r
476 RX_PKT * pFirstFill;\r
477 TplPrevious = gBS->RaiseTPL (TPL_CALLBACK);\r
478 \r
479 //\r
480 // Verify the parameters\r
481 //\r
4986bbaf
YP
482 if (( NULL != pSimpleNetwork ) && \r
483 ( NULL != pSimpleNetwork->Mode ) && \r
484 (NULL != pBufferSize) && \r
485 (NULL != pBuffer)) {\r
7f556e4d 486 //\r
487 // The interface must be running\r
488 //\r
489 pMode = pSimpleNetwork->Mode;\r
490 if ( EfiSimpleNetworkInitialized == pMode->State ) {\r
491 //\r
492 // Update the link status\r
493 //\r
494 pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );\r
495 pNicDevice->LinkIdleCnt++;\r
496 pMode->MediaPresent = pNicDevice->bLinkUp;\r
497 \r
498 if ( pMode->MediaPresent && pNicDevice->bComplete) {\r
499 \r
500 \r
501 if (pNicDevice->PktCntInQueue != 0 ) {\r
502 DEBUG (( EFI_D_INFO, "pNicDevice->PktCntInQueue = %d\n",\r
503 pNicDevice->PktCntInQueue));\r
504 }\r
505 \r
506 LengthInBytes = MAX_BULKIN_SIZE;\r
507 if (pNicDevice->PktCntInQueue == 0 ){\r
508 //\r
509 // Attempt to do bulk in\r
510 //\r
511 SetMem (&pNicDevice->pBulkInBuff[0], 4, 0);\r
512 pUsbIo = pNicDevice->pUsbIo;\r
513 Status = pUsbIo->UsbBulkTransfer ( pUsbIo,\r
514 USB_ENDPOINT_DIR_IN | BULK_IN_ENDPOINT,\r
515 &pNicDevice->pBulkInBuff[0],\r
516 &LengthInBytes,\r
517 BULKIN_TIMEOUT,\r
518 &TransferStatus );\r
519 \r
520 if (LengthInBytes != 0 && !EFI_ERROR(Status) && !EFI_ERROR(TransferStatus) ){\r
521 FillPkt2Queue(pSimpleNetwork, LengthInBytes);\r
522 }\r
523 }\r
524 \r
525 pFirstFill = pNicDevice->pFirstFill;\r
526 \r
527 if (TRUE == pFirstFill->f_Used) {\r
528 ETHERNET_HEADER * pHeader;\r
529 pNicDevice->LinkIdleCnt = 0;\r
530 CopyMem (pBuffer, &pFirstFill->Data[0], pFirstFill->Length);\r
531 pHeader = (ETHERNET_HEADER *) &pFirstFill->Data[0];\r
532 \r
533 DEBUG (( EFI_D_INFO, "RX: %02x-%02x-%02x-%02x-%02x-%02x " \r
534 "%02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n",\r
535 pFirstFill->Data[0],\r
536 pFirstFill->Data[1],\r
537 pFirstFill->Data[2],\r
538 pFirstFill->Data[3],\r
539 pFirstFill->Data[4],\r
540 pFirstFill->Data[5],\r
541 pFirstFill->Data[6],\r
542 pFirstFill->Data[7],\r
543 pFirstFill->Data[8],\r
544 pFirstFill->Data[9],\r
545 pFirstFill->Data[10],\r
546 pFirstFill->Data[11],\r
547 pFirstFill->Data[12],\r
548 pFirstFill->Data[13],\r
549 pFirstFill->Length)); \r
550 \r
551 if ( NULL != pHeaderSize ) {\r
552 *pHeaderSize = sizeof ( *pHeader );\r
553 }\r
554 if ( NULL != pDestAddr ) {\r
555 CopyMem ( pDestAddr, &pHeader->dest_addr, PXE_HWADDR_LEN_ETHER );\r
556 }\r
557 if ( NULL != pSrcAddr ) {\r
558 CopyMem ( pSrcAddr, &pHeader->src_addr, PXE_HWADDR_LEN_ETHER );\r
559 }\r
560 if ( NULL != pProtocol ) {\r
561 Type = pHeader->type;\r
562 Type = (UINT16)(( Type >> 8 ) | ( Type << 8 ));\r
563 *pProtocol = Type;\r
564 }\r
565 Status = EFI_SUCCESS;\r
566 if (*pBufferSize < pFirstFill->Length) {\r
567 DEBUG (( EFI_D_ERROR, "RX: Buffer was too small"));\r
568 Status = EFI_BUFFER_TOO_SMALL;\r
569 }\r
570 *pBufferSize = pFirstFill->Length;\r
571 pFirstFill->f_Used = FALSE;\r
572 pNicDevice->pFirstFill = pFirstFill->pNext;\r
573 pNicDevice->PktCntInQueue--;\r
574 }\r
575 else {\r
576 pNicDevice->LinkIdleCnt++;\r
577 Status = EFI_NOT_READY;\r
578 }\r
579 }\r
580 else {\r
581 //\r
582 // Link no up\r
583 //\r
584 pNicDevice->LinkIdleCnt++;\r
585 Status = EFI_NOT_READY; \r
586 }\r
587 \r
588 }\r
589 else {\r
4986bbaf
YP
590 if (EfiSimpleNetworkStarted == pMode->State) {\r
591 Status = EFI_DEVICE_ERROR;\r
592 }\r
593 else {\r
594 Status = EFI_NOT_STARTED;\r
595 }\r
7f556e4d 596 }\r
597 }\r
598 else {\r
599 Status = EFI_INVALID_PARAMETER;\r
600 } \r
601 gBS->RestoreTPL (TplPrevious);\r
602 return Status;\r
603}\r
604\r
605/**\r
606 This function is used to enable and disable the hardware and software receive\r
607 filters for the underlying network device.\r
608\r
609 The receive filter change is broken down into three steps:\r
610\r
611 1. The filter mask bits that are set (ON) in the Enable parameter\r
612 are added to the current receive filter settings.\r
613\r
614 2. The filter mask bits that are set (ON) in the Disable parameter\r
615 are subtracted from the updated receive filter settins.\r
616\r
617 3. If the resulting filter settigns is not supported by the hardware\r
618 a more liberal setting is selected.\r
619\r
620 If the same bits are set in the Enable and Disable parameters, then the bits\r
621 in the Disable parameter takes precedence.\r
622\r
623 If the ResetMCastFilter parameter is TRUE, then the multicast address list\r
624 filter is disabled (irregardless of what other multicast bits are set in\r
625 the enable and Disable parameters). The SNP->Mode->MCastFilterCount field\r
626 is set to zero. The SNP->Mode->MCastFilter contents are undefined.\r
627\r
628 After enableing or disabling receive filter settings, software should\r
629 verify the new settings by checking the SNP->Mode->ReceeiveFilterSettings,\r
630 SNP->Mode->MCastFilterCount and SNP->Mode->MCastFilter fields.\r
631\r
632 Note: Some network drivers and/or devices will automatically promote\r
633 receive filter settings if the requested setting can not be honored.\r
634 For example, if a request for four multicast addresses is made and\r
635 the underlying hardware only supports two multicast addresses the\r
636 driver might set the promiscuous or promiscuous multicast receive filters\r
637 instead. The receiving software is responsible for discarding any extra\r
638 packets that get through the hardware receive filters.\r
639\r
640 If ResetMCastFilter is TRUE, then the multicast receive filter list\r
641 on the network interface will be reset to the default multicast receive\r
642 filter list. If ResetMCastFilter is FALSE, and this network interface\r
643 allows the multicast receive filter list to be modified, then the\r
644 MCastFilterCnt and MCastFilter are used to update the current multicast\r
645 receive filter list. The modified receive filter list settings can be\r
646 found in the MCastFilter field of EFI_SIMPLE_NETWORK_MODE.\r
647\r
648 This routine calls ::ReceiveFilterUpdate to update the receive\r
649 state in the network adapter.\r
650\r
651 @param [in] pSimpleNetwork Protocol instance pointer\r
652 @param [in] Enable A bit mask of receive filters to enable on the network interface.\r
653 @param [in] Disable A bit mask of receive filters to disable on the network interface.\r
654 For backward compatibility with EFI 1.1 platforms, the\r
655 EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit must be set\r
656 when the ResetMCastFilter parameter is TRUE.\r
657 @param [in] bResetMCastFilter Set to TRUE to reset the contents of the multicast receive\r
658 filters on the network interface to their default values.\r
659 @param [in] MCastFilterCnt Number of multicast HW MAC address in the new MCastFilter list.\r
660 This value must be less than or equal to the MaxMCastFilterCnt\r
661 field of EFI_SIMPLE_NETWORK_MODE. This field is optional if\r
662 ResetMCastFilter is TRUE.\r
663 @param [in] pMCastFilter A pointer to a list of new multicast receive filter HW MAC\r
664 addresses. This list will replace any existing multicast\r
665 HW MAC address list. This field is optional if ResetMCastFilter\r
666 is TRUE.\r
667\r
668 @retval EFI_SUCCESS This operation was successful.\r
669 @retval EFI_NOT_STARTED The network interface was not started.\r
670 @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
671 EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
672 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
673 @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.\r
674\r
675**/\r
676EFI_STATUS\r
677EFIAPI\r
678SN_ReceiveFilters (\r
679 IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,\r
680 IN UINT32 Enable,\r
681 IN UINT32 Disable,\r
682/*\r
683#define EFI_SIMPLE_NETWORK_RECEIVE_UNICAST 0x01\r
684#define EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST 0x02\r
685#define EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST 0x04\r
686#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS 0x08\r
687#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST 0x10\r
688*/\r
689 IN BOOLEAN bResetMCastFilter,\r
690 IN UINTN MCastFilterCnt,\r
691 IN EFI_MAC_ADDRESS * pMCastFilter\r
692 )\r
693{\r
694 EFI_SIMPLE_NETWORK_MODE * pMode;\r
695 EFI_STATUS Status = EFI_SUCCESS; \r
696 EFI_TPL TplPrevious; \r
7f556e4d 697\r
698 TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);\r
7f556e4d 699 pMode = pSimpleNetwork->Mode;\r
700\r
701 if (pSimpleNetwork == NULL) {\r
702 gBS->RestoreTPL(TplPrevious);\r
703 return EFI_INVALID_PARAMETER;\r
704 }\r
705\r
706 switch (pMode->State) {\r
707 case EfiSimpleNetworkInitialized:\r
708 break;\r
709 case EfiSimpleNetworkStopped:\r
710 Status = EFI_NOT_STARTED;\r
711 gBS->RestoreTPL(TplPrevious);\r
712 return Status;\r
713 default:\r
714 Status = EFI_DEVICE_ERROR;\r
715 gBS->RestoreTPL(TplPrevious);\r
716 return Status;\r
717 }\r
718\r
719 //\r
720 // check if we are asked to enable or disable something that the UNDI\r
721 // does not even support!\r
722 //\r
723 if (((Enable &~pMode->ReceiveFilterMask) != 0) ||\r
724 ((Disable &~pMode->ReceiveFilterMask) != 0)) {\r
725 Status = EFI_INVALID_PARAMETER;\r
726 gBS->RestoreTPL(TplPrevious);\r
727 return Status;\r
728 }\r
729 \r
730 if (bResetMCastFilter) {\r
731 Disable |= (EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST & pMode->ReceiveFilterMask);\r
732 pMode->MCastFilterCount = 0;\r
733 if ( (0 == (pMode->ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST)) \r
734 && Enable == 0 && Disable == 2) {\r
735 gBS->RestoreTPL(TplPrevious);\r
736 return EFI_SUCCESS;\r
737 }\r
738 } \r
739 else {\r
740 if (MCastFilterCnt != 0) {\r
741 UINTN i; \r
742 EFI_MAC_ADDRESS * pMulticastAddress;\r
743 pMulticastAddress = pMCastFilter;\r
744 \r
745 if ((MCastFilterCnt > pMode->MaxMCastFilterCount) ||\r
746 (pMCastFilter == NULL)) {\r
747 Status = EFI_INVALID_PARAMETER;\r
748 gBS->RestoreTPL(TplPrevious);\r
749 return Status;\r
750 }\r
751 \r
752 for ( i = 0 ; i < MCastFilterCnt ; i++ ) {\r
753 UINT8 tmp;\r
754 tmp = pMulticastAddress->Addr[0];\r
755 if ( (tmp & 0x01) != 0x01 ) {\r
756 gBS->RestoreTPL(TplPrevious);\r
757 return EFI_INVALID_PARAMETER;\r
758 }\r
759 pMulticastAddress++;\r
760 }\r
761 \r
762 pMode->MCastFilterCount = (UINT32)MCastFilterCnt;\r
763 CopyMem (&pMode->MCastFilter[0],\r
764 pMCastFilter,\r
765 MCastFilterCnt * sizeof ( EFI_MAC_ADDRESS));\r
766 }\r
767 }\r
768 \r
769 if (Enable == 0 && Disable == 0 && !bResetMCastFilter && MCastFilterCnt == 0) {\r
770 Status = EFI_SUCCESS;\r
771 gBS->RestoreTPL(TplPrevious);\r
772 return Status;\r
773 }\r
774\r
775 if ((Enable & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0 && MCastFilterCnt == 0) {\r
776 Status = EFI_INVALID_PARAMETER;\r
777 gBS->RestoreTPL(TplPrevious);\r
778 return Status;\r
779 }\r
780 \r
781 pMode->ReceiveFilterSetting |= Enable;\r
782 pMode->ReceiveFilterSetting &= ~Disable;\r
783 Status = ReceiveFilterUpdate (pSimpleNetwork);\r
784 \r
785 if (EFI_DEVICE_ERROR == Status || EFI_INVALID_PARAMETER == Status)\r
786 Status = EFI_SUCCESS;\r
787\r
788 gBS->RestoreTPL(TplPrevious);\r
789 return Status;\r
790}\r
791\r
792/**\r
793 Reset the network adapter.\r
794\r
795 Resets a network adapter and reinitializes it with the parameters that\r
796 were provided in the previous call to Initialize (). The transmit and\r
797 receive queues are cleared. Receive filters, the station address, the\r
798 statistics, and the multicast-IP-to-HW MAC addresses are not reset by\r
799 this call.\r
800\r
801 This routine calls ::Ax88772Reset to perform the adapter specific\r
802 reset operation. This routine also starts the link negotiation\r
803 by calling ::Ax88772NegotiateLinkStart.\r
804\r
805 @param [in] pSimpleNetwork Protocol instance pointer\r
806 @param [in] bExtendedVerification Indicates that the driver may perform a more\r
807 exhaustive verification operation of the device\r
808 during reset.\r
809\r
810 @retval EFI_SUCCESS This operation was successful.\r
811 @retval EFI_NOT_STARTED The network interface was not started.\r
812 @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
813 EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
814 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
815 @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.\r
816\r
817**/\r
818EFI_STATUS\r
819EFIAPI\r
820SN_Reset (\r
821 IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,\r
822 IN BOOLEAN bExtendedVerification\r
823 )\r
824{\r
825 EFI_SIMPLE_NETWORK_MODE * pMode;\r
826 NIC_DEVICE * pNicDevice;\r
827 EFI_STATUS Status;\r
828 EFI_TPL TplPrevious;\r
829\r
830 TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);\r
831 //\r
832 // Verify the parameters\r
833 //\r
834 if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {\r
835 pMode = pSimpleNetwork->Mode;\r
836 if ( EfiSimpleNetworkInitialized == pMode->State ) {\r
837 //\r
838 // Update the device state\r
839 //\r
840 pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );\r
841 pNicDevice->bComplete = FALSE;\r
842 pNicDevice->bLinkUp = FALSE; \r
843 pNicDevice->bHavePkt = FALSE;\r
844 pMode = pSimpleNetwork->Mode;\r
845 pMode->MediaPresent = FALSE;\r
846\r
847 //\r
848 // Reset the device\r
849 //\r
850 Status = Ax88772Reset ( pNicDevice );\r
851 if ( !EFI_ERROR ( Status )) {\r
852 //\r
853 // Update the receive filters in the adapter\r
854 //\r
855 Status = ReceiveFilterUpdate ( pSimpleNetwork );\r
856\r
857 //\r
858 // Try to get a connection to the network\r
859 //\r
860 if ( !EFI_ERROR ( Status )) {\r
861 //\r
862 // Start the autonegotiation\r
863 //\r
864 Status = Ax88772NegotiateLinkStart ( pNicDevice );\r
865 }\r
866 }\r
867 }\r
868 else {\r
4986bbaf
YP
869 if (EfiSimpleNetworkStarted == pMode->State) {\r
870 Status = EFI_DEVICE_ERROR;\r
871 }\r
872 else {\r
873 Status = EFI_NOT_STARTED;\r
874 }\r
7f556e4d 875 } \r
876 }\r
877 else {\r
878 Status = EFI_INVALID_PARAMETER;\r
879 }\r
880 gBS->RestoreTPL ( TplPrevious );\r
881 return Status;\r
882}\r
883\r
884/**\r
885 Initialize the simple network protocol.\r
886\r
887 This routine calls ::Ax88772MacAddressGet to obtain the\r
888 MAC address.\r
889\r
890 @param [in] pNicDevice NIC_DEVICE_INSTANCE pointer\r
891\r
892 @retval EFI_SUCCESS Setup was successful\r
893\r
894**/\r
895EFI_STATUS\r
896SN_Setup (\r
897 IN NIC_DEVICE * pNicDevice\r
898 )\r
899{\r
900 \r
901\r
902 EFI_SIMPLE_NETWORK_MODE * pMode;\r
903 EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork;\r
904 EFI_STATUS Status;\r
905 RX_PKT * pCurr = NULL;\r
906 RX_PKT * pPrev = NULL;\r
907\r
908 pSimpleNetwork = &pNicDevice->SimpleNetwork; \r
909 pSimpleNetwork->Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;\r
910 pSimpleNetwork->Start = (EFI_SIMPLE_NETWORK_START)SN_Start;\r
911 pSimpleNetwork->Stop = (EFI_SIMPLE_NETWORK_STOP)SN_Stop;\r
912 pSimpleNetwork->Initialize = (EFI_SIMPLE_NETWORK_INITIALIZE)SN_Initialize;\r
913 pSimpleNetwork->Reset = (EFI_SIMPLE_NETWORK_RESET)SN_Reset;\r
914 pSimpleNetwork->Shutdown = (EFI_SIMPLE_NETWORK_SHUTDOWN)SN_Shutdown;\r
915 pSimpleNetwork->ReceiveFilters = (EFI_SIMPLE_NETWORK_RECEIVE_FILTERS)SN_ReceiveFilters;\r
916 pSimpleNetwork->StationAddress = (EFI_SIMPLE_NETWORK_STATION_ADDRESS)SN_StationAddress;\r
917 pSimpleNetwork->Statistics = (EFI_SIMPLE_NETWORK_STATISTICS)SN_Statistics;\r
918 pSimpleNetwork->MCastIpToMac = (EFI_SIMPLE_NETWORK_MCAST_IP_TO_MAC)SN_MCastIPtoMAC;\r
919 pSimpleNetwork->NvData = (EFI_SIMPLE_NETWORK_NVDATA)SN_NvData;\r
920 pSimpleNetwork->GetStatus = (EFI_SIMPLE_NETWORK_GET_STATUS)SN_GetStatus;\r
921 pSimpleNetwork->Transmit = (EFI_SIMPLE_NETWORK_TRANSMIT)SN_Transmit;\r
922 pSimpleNetwork->Receive = (EFI_SIMPLE_NETWORK_RECEIVE)SN_Receive;\r
923 pSimpleNetwork->WaitForPacket = NULL;\r
924 pMode = &pNicDevice->SimpleNetworkData;\r
925 pSimpleNetwork->Mode = pMode;\r
926 pMode->State = EfiSimpleNetworkStopped;\r
927 pMode->HwAddressSize = PXE_HWADDR_LEN_ETHER;\r
928 pMode->MediaHeaderSize = sizeof ( ETHERNET_HEADER );\r
929 pMode->MaxPacketSize = MAX_ETHERNET_PKT_SIZE;\r
930 pMode->NvRamSize = 0;\r
931 pMode->NvRamAccessSize = 0;\r
932 pMode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST\r
933 | EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST\r
934 | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST\r
935 | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS\r
936 | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
937 pMode->ReceiveFilterSetting = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST\r
938 | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;\r
939 pMode->MaxMCastFilterCount = MAX_MCAST_FILTER_CNT;\r
940 pMode->MCastFilterCount = 0;\r
941 SetMem ( &pMode->BroadcastAddress,\r
942 PXE_HWADDR_LEN_ETHER,\r
943 0xff );\r
944 pMode->IfType = EfiNetworkInterfaceUndi;\r
945 pMode->MacAddressChangeable = TRUE;\r
946 pMode->MultipleTxSupported = FALSE;\r
947 pMode->MediaPresentSupported = TRUE;\r
948 pMode->MediaPresent = FALSE;\r
949 pNicDevice->LinkIdleCnt = 0;\r
950 //\r
951 // Read the MAC address\r
952 //\r
953 pNicDevice->PhyId = PHY_ID_INTERNAL;\r
954 pNicDevice->b100Mbps = TRUE;\r
955 pNicDevice->bFullDuplex = TRUE;\r
956 \r
957 Status = Ax88772MacAddressGet (\r
958 pNicDevice,\r
959 &pMode->PermanentAddress.Addr[0]);\r
960\r
961 if ( !EFI_ERROR ( Status )) {\r
962 int i; \r
963 //\r
964 // Use the hardware address as the current address\r
965 //\r
966\r
967 CopyMem ( &pMode->CurrentAddress,\r
968 &pMode->PermanentAddress,\r
969 PXE_HWADDR_LEN_ETHER );\r
970 \r
971 CopyMem ( &pNicDevice->MAC,\r
972 &pMode->PermanentAddress,\r
973 PXE_HWADDR_LEN_ETHER );\r
974 \r
975 pNicDevice->PktCntInQueue = 0;\r
976 \r
977 for ( i = 0 ; i < MAX_QUEUE_SIZE ; i++) {\r
978 Status = gBS->AllocatePool ( EfiRuntimeServicesData, \r
979 sizeof (RX_PKT),\r
980 (VOID **) &pCurr);\r
981 if ( EFI_ERROR(Status)) {\r
982 DEBUG (( EFI_D_ERROR, "Memory are not enough\n"));\r
983 return Status;\r
984 } \r
985 pCurr->f_Used = FALSE;\r
986 \r
987 if ( i ) {\r
988 pPrev->pNext = pCurr;\r
989 }\r
990 else {\r
991 pNicDevice->QueueHead = pCurr;\r
992 }\r
993 \r
994 if (MAX_QUEUE_SIZE - 1 == i) {\r
995 pCurr->pNext = pNicDevice->QueueHead;\r
996 }\r
997 \r
998 pPrev = pCurr;\r
999 }\r
1000 \r
1001 pNicDevice->pNextFill = pNicDevice->QueueHead;\r
1002 pNicDevice->pFirstFill = pNicDevice->QueueHead;\r
1003 \r
1004 Status = gBS->AllocatePool (EfiRuntimeServicesData,\r
1005 MAX_BULKIN_SIZE,\r
1006 (VOID **) &pNicDevice->pBulkInBuff);\r
1007 \r
1008 if (EFI_ERROR(Status)) {\r
1009 DEBUG (( EFI_D_ERROR, "gBS->AllocatePool for pBulkInBuff error. Status = %r\n",\r
1010 Status));\r
1011 return Status;\r
1012 }\r
1013 }\r
1014 else {\r
1015 DEBUG (( EFI_D_ERROR, "Ax88772MacAddressGet error. Status = %r\n", Status));\r
1016 return Status;\r
1017 }\r
1018 \r
1019 Status = gBS->AllocatePool ( EfiRuntimeServicesData,\r
1020 sizeof ( RX_TX_PACKET ),\r
1021 (VOID **) &pNicDevice->pRxTest );\r
1022\r
1023 if (EFI_ERROR (Status)) {\r
1024 DEBUG (( EFI_D_ERROR, "gBS->AllocatePool:pNicDevice->pRxTest error. Status = %r\n",\r
1025 Status));\r
1026 return Status;\r
1027 }\r
1028 \r
1029 Status = gBS->AllocatePool ( EfiRuntimeServicesData,\r
1030 sizeof ( RX_TX_PACKET ),\r
1031 (VOID **) &pNicDevice->pTxTest );\r
1032\r
1033 if (EFI_ERROR (Status)) {\r
1034 DEBUG (( EFI_D_ERROR, "gBS->AllocatePool:pNicDevice->pTxTest error. Status = %r\n",\r
1035 Status));\r
1036 gBS->FreePool (pNicDevice->pRxTest);\r
1037 }\r
1038\r
1039 return Status;\r
1040}\r
1041\r
1042\r
1043/**\r
1044 This routine starts the network interface.\r
1045\r
1046 @param [in] pSimpleNetwork Protocol instance pointer\r
1047\r
1048 @retval EFI_SUCCESS This operation was successful.\r
1049 @retval EFI_ALREADY_STARTED The network interface was already started.\r
1050 @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
1051 EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
1052 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
1053 @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.\r
1054\r
1055**/\r
1056EFI_STATUS\r
1057EFIAPI\r
1058SN_Start (\r
1059 IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork\r
1060 )\r
1061{\r
1062 NIC_DEVICE * pNicDevice;\r
1063 EFI_SIMPLE_NETWORK_MODE * pMode;\r
1064 EFI_STATUS Status;\r
1065 EFI_TPL TplPrevious;\r
1066 int i = 0;\r
1067 RX_PKT * pCurr = NULL;\r
1068\r
1069 TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);\r
1070 //\r
1071 // Verify the parameters\r
1072 //\r
1073 Status = EFI_INVALID_PARAMETER;\r
1074 if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {\r
1075 pMode = pSimpleNetwork->Mode;\r
1076 if ( EfiSimpleNetworkStopped == pMode->State ) {\r
1077 //\r
1078 // Initialize the mode structuref\r
1079 // NVRAM access is not supported\r
1080 //\r
1081 ZeroMem ( pMode, sizeof ( *pMode ));\r
1082 \r
1083 pMode->State = EfiSimpleNetworkStarted;\r
1084 pMode->HwAddressSize = PXE_HWADDR_LEN_ETHER;\r
1085 pMode->MediaHeaderSize = sizeof ( ETHERNET_HEADER );\r
1086 pMode->MaxPacketSize = MAX_ETHERNET_PKT_SIZE;\r
1087 pMode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST\r
1088 | EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST\r
1089 | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST\r
1090 | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS\r
1091 | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
1092 pMode->ReceiveFilterSetting = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;\r
1093 pMode->MaxMCastFilterCount = MAX_MCAST_FILTER_CNT;\r
1094 pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );\r
1095 Status = Ax88772MacAddressGet ( pNicDevice, &pMode->PermanentAddress.Addr[0]);\r
1096 CopyMem ( &pMode->CurrentAddress,\r
1097 &pMode->PermanentAddress,\r
1098 sizeof ( pMode->CurrentAddress ));\r
1099 SetMem(&pMode->BroadcastAddress, PXE_HWADDR_LEN_ETHER, 0xff);\r
1100 pMode->IfType = EfiNetworkInterfaceUndi;\r
1101 pMode->MacAddressChangeable = TRUE;\r
1102 pMode->MultipleTxSupported = FALSE;\r
1103 pMode->MediaPresentSupported = TRUE;\r
1104 pMode->MediaPresent = FALSE; \r
1105 pNicDevice->PktCntInQueue = 0;\r
1106 pNicDevice->pNextFill = pNicDevice->QueueHead;\r
1107 pNicDevice->pFirstFill = pNicDevice->QueueHead;\r
1108 pCurr = pNicDevice->QueueHead;\r
1109 \r
1110 for ( i = 0 ; i < MAX_QUEUE_SIZE ; i++) { \r
1111 pCurr->f_Used = FALSE;\r
1112 pCurr = pCurr->pNext;\r
1113 }\r
1114 \r
1115 }\r
1116 else {\r
1117 Status = EFI_ALREADY_STARTED;\r
1118 }\r
1119 }\r
1120 gBS->RestoreTPL ( TplPrevious );\r
1121 return Status;\r
1122}\r
1123\r
1124\r
1125/**\r
1126 Set the MAC address.\r
1127 \r
1128 This function modifies or resets the current station address of a\r
1129 network interface. If Reset is TRUE, then the current station address\r
1130 is set ot the network interface's permanent address. If Reset if FALSE\r
1131 then the current station address is changed to the address specified by\r
1132 pNew.\r
1133\r
1134 This routine calls ::Ax88772MacAddressSet to update the MAC address\r
1135 in the network adapter.\r
1136\r
1137 @param [in] pSimpleNetwork Protocol instance pointer\r
1138 @param [in] bReset Flag used to reset the station address to the\r
1139 network interface's permanent address.\r
1140 @param [in] pNew New station address to be used for the network\r
1141 interface.\r
1142\r
1143 @retval EFI_SUCCESS This operation was successful.\r
1144 @retval EFI_NOT_STARTED The network interface was not started.\r
1145 @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
1146 EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
1147 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
1148 @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.\r
1149\r
1150**/\r
1151EFI_STATUS\r
1152EFIAPI\r
1153SN_StationAddress (\r
1154 IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,\r
1155 IN BOOLEAN bReset,\r
1156 IN EFI_MAC_ADDRESS * pNew\r
1157 )\r
1158{\r
1159 NIC_DEVICE * pNicDevice;\r
1160 EFI_SIMPLE_NETWORK_MODE * pMode;\r
1161 EFI_STATUS Status;\r
1162 EFI_TPL TplPrevious;\r
1163 \r
1164 TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);\r
1165 //\r
1166 // Verify the parameters\r
1167 //\r
1168 if (( NULL != pSimpleNetwork )\r
1169 && ( NULL != pSimpleNetwork->Mode )\r
4986bbaf 1170 && (( bReset ) || ( ( !bReset) && ( NULL != pNew )))) {\r
7f556e4d 1171 //\r
1172 // Verify that the adapter is already started\r
1173 //\r
1174 pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );\r
1175 pMode = pSimpleNetwork->Mode;\r
4986bbaf 1176 if ( EfiSimpleNetworkInitialized == pMode->State ) {\r
7f556e4d 1177 //\r
1178 // Determine the adapter MAC address\r
1179 //\r
1180 if ( bReset ) {\r
1181 //\r
1182 // Use the permanent address\r
1183 //\r
1184 CopyMem ( &pMode->CurrentAddress,\r
1185 &pMode->PermanentAddress,\r
1186 sizeof ( pMode->CurrentAddress ));\r
1187 }\r
1188 else {\r
1189 //\r
1190 // Use the specified address\r
1191 //\r
1192 CopyMem ( &pMode->CurrentAddress,\r
1193 pNew,\r
1194 sizeof ( pMode->CurrentAddress ));\r
1195 }\r
1196\r
1197 //\r
1198 // Update the address on the adapter\r
1199 //\r
1200 Status = Ax88772MacAddressSet ( pNicDevice, &pMode->CurrentAddress.Addr[0]);\r
1201 }\r
1202 else {\r
4986bbaf
YP
1203 if (EfiSimpleNetworkStarted == pMode->State) {\r
1204 Status = EFI_DEVICE_ERROR;\r
1205 }\r
1206 else {\r
1207 Status = EFI_NOT_STARTED;\r
1208 }\r
7f556e4d 1209 }\r
1210 }\r
1211 else {\r
1212 Status = EFI_INVALID_PARAMETER;\r
1213 }\r
1214 gBS->RestoreTPL ( TplPrevious );\r
1215 return Status;\r
1216}\r
1217\r
1218\r
1219/**\r
1220 This function resets or collects the statistics on a network interface.\r
1221 If the size of the statistics table specified by StatisticsSize is not\r
1222 big enough for all of the statistics that are collected by the network\r
1223 interface, then a partial buffer of statistics is returned in\r
1224 StatisticsTable.\r
1225\r
1226 @param [in] pSimpleNetwork Protocol instance pointer\r
1227 @param [in] bReset Set to TRUE to reset the statistics for the network interface.\r
1228 @param [in, out] pStatisticsSize On input the size, in bytes, of StatisticsTable. On output\r
1229 the size, in bytes, of the resulting table of statistics.\r
1230 @param [out] pStatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that\r
1231 conains the statistics.\r
1232\r
1233 @retval EFI_SUCCESS This operation was successful.\r
1234 @retval EFI_NOT_STARTED The network interface was not started.\r
1235 @retval EFI_BUFFER_TOO_SMALL The pStatisticsTable is NULL or the buffer is too small.\r
1236 @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
1237 EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
1238 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
1239 @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.\r
1240\r
1241 typedef struct {\r
1242 UINT64 RxTotalFrames;\r
1243 UINT64 RxGoodFrames;\r
1244 UINT64 RxUndersizeFrames;\r
1245 UINT64 RxOversizeFrames;\r
1246 UINT64 RxDroppedFrames;\r
1247 UINT64 RxUnicastFrames;\r
1248 UINT64 RxBroadcastFrames;\r
1249 UINT64 RxMulticastFrames;\r
1250 UINT64 RxCrcErrorFrames;\r
1251 UINT64 RxTotalBytes;\r
1252 UINT64 TxTotalFrames;\r
1253 UINT64 TxGoodFrames;\r
1254 UINT64 TxUndersizeFrames;\r
1255 UINT64 TxOversizeFrames;\r
1256 UINT64 TxDroppedFrames;\r
1257 UINT64 TxUnicastFrames;\r
1258 UINT64 TxBroadcastFrames;\r
1259 UINT64 TxMulticastFrames;\r
1260 UINT64 TxCrcErrorFrames;\r
1261 UINT64 TxTotalBytes;\r
1262 UINT64 Collisions;\r
1263 UINT64 UnsupportedProtocol;\r
1264 } EFI_NETWORK_STATISTICS;\r
1265**/\r
1266EFI_STATUS\r
1267EFIAPI\r
1268SN_Statistics (\r
1269 IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,\r
1270 IN BOOLEAN bReset,\r
1271 IN OUT UINTN * pStatisticsSize,\r
1272 OUT EFI_NETWORK_STATISTICS * pStatisticsTable\r
1273 )\r
1274{\r
1275 EFI_STATUS Status;\r
4986bbaf
YP
1276 EFI_SIMPLE_NETWORK_MODE * pMode;\r
1277 //\r
1278 // Verify the prarameters\r
1279 //\r
1280 if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {\r
1281 pMode = pSimpleNetwork->Mode;\r
1282 //\r
1283 // Determine if the interface is started \r
1284 //\r
1285 if (EfiSimpleNetworkInitialized == pMode->State){\r
1286 //\r
1287 // Determine if the StatisticsSize is big enough\r
1288 //\r
1289 if (sizeof (EFI_NETWORK_STATISTICS) <= *pStatisticsSize){\r
1290 if (bReset) {\r
1291 Status = EFI_SUCCESS;\r
1292 } \r
1293 else {\r
1294 Status = EFI_UNSUPPORTED;\r
1295 }\r
1296 }\r
1297 else {\r
1298 Status = EFI_BUFFER_TOO_SMALL;\r
1299 }\r
1300 }\r
1301 else{\r
1302 if (EfiSimpleNetworkStarted == pMode->State) {\r
1303 Status = EFI_DEVICE_ERROR;\r
1304 }\r
1305 else {\r
1306 Status = EFI_NOT_STARTED;\r
1307 }\r
1308 }\r
1309 }\r
1310 else {\r
1311 Status = EFI_INVALID_PARAMETER;\r
1312 }\r
7f556e4d 1313\r
1314 return Status;\r
1315}\r
1316\r
1317\r
1318/**\r
1319 This function stops a network interface. This call is only valid\r
1320 if the network interface is in the started state.\r
1321\r
1322 @param [in] pSimpleNetwork Protocol instance pointer\r
1323\r
1324 @retval EFI_SUCCESS This operation was successful.\r
1325 @retval EFI_NOT_STARTED The network interface was not started.\r
1326 @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
1327 EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
1328 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
1329 @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.\r
1330\r
1331**/\r
1332EFI_STATUS\r
1333EFIAPI\r
1334SN_Stop (\r
1335 IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork\r
1336 )\r
1337{\r
1338 EFI_SIMPLE_NETWORK_MODE * pMode;\r
1339 EFI_STATUS Status;\r
1340 EFI_TPL TplPrevious;\r
1341 \r
1342 TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);\r
1343 //\r
1344 // Verify the parameters\r
1345 //\r
1346 if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {\r
1347 //\r
1348 // Determine if the interface is started\r
1349 //\r
1350 pMode = pSimpleNetwork->Mode; \r
1351 if ( EfiSimpleNetworkStarted == pMode->State ) {\r
1352 pMode->State = EfiSimpleNetworkStopped;\r
1353 Status = EFI_SUCCESS; \r
1354 }\r
1355 else {\r
1356 Status = EFI_NOT_STARTED;\r
1357 }\r
1358 } \r
1359 else {\r
1360 Status = EFI_INVALID_PARAMETER;\r
1361 }\r
1362 \r
1363 gBS->RestoreTPL ( TplPrevious );\r
1364 return Status;\r
1365}\r
1366\r
1367\r
1368/**\r
1369 This function releases the memory buffers assigned in the Initialize() call.\r
1370 Pending transmits and receives are lost, and interrupts are cleared and disabled.\r
1371 After this call, only Initialize() and Stop() calls may be used.\r
1372\r
1373 @param [in] pSimpleNetwork Protocol instance pointer\r
1374\r
1375 @retval EFI_SUCCESS This operation was successful.\r
1376 @retval EFI_NOT_STARTED The network interface was not started.\r
1377 @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
1378 EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
1379 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
1380 @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.\r
1381\r
1382**/\r
1383EFI_STATUS\r
1384EFIAPI\r
1385SN_Shutdown (\r
1386 IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork\r
1387 )\r
1388{\r
1389 EFI_SIMPLE_NETWORK_MODE * pMode;\r
1390 UINT32 RxFilter;\r
1391 EFI_STATUS Status;\r
1392 EFI_TPL TplPrevious;\r
1393 \r
1394 TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);\r
1395 //\r
1396 // Verify the parameters\r
1397 //\r
1398 if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {\r
1399 //\r
1400 // Determine if the interface is already started\r
1401 //\r
1402 pMode = pSimpleNetwork->Mode;\r
1403 if ( EfiSimpleNetworkInitialized == pMode->State ) {\r
1404 //\r
1405 // Stop the adapter\r
1406 //\r
1407 RxFilter = pMode->ReceiveFilterSetting;\r
1408 pMode->ReceiveFilterSetting = 0;\r
1409 Status = SN_Reset ( pSimpleNetwork, FALSE );\r
1410 pMode->ReceiveFilterSetting = RxFilter;\r
1411 if ( !EFI_ERROR ( Status )) {\r
1412\r
1413 //\r
1414 // Update the network state\r
1415 //\r
1416 pMode->State = EfiSimpleNetworkStarted;\r
1417 }\r
1418 else if ( EFI_DEVICE_ERROR == Status ) {\r
1419 pMode->State = EfiSimpleNetworkStopped;\r
1420 }\r
1421 }\r
1422 else {\r
1423 Status = EFI_NOT_STARTED;\r
1424 }\r
1425 }\r
1426 else {\r
1427 Status = EFI_INVALID_PARAMETER;\r
1428 }\r
1429 gBS->RestoreTPL ( TplPrevious );\r
1430 return Status;\r
1431}\r
1432\r
1433\r
1434/**\r
1435 Send a packet over the network.\r
1436\r
1437 This function places the packet specified by Header and Buffer on\r
1438 the transmit queue. This function performs a non-blocking transmit\r
1439 operation. When the transmit is complete, the buffer is returned\r
1440 via the GetStatus() call.\r
1441\r
1442 This routine calls ::Ax88772Rx to empty the network adapter of\r
1443 receive packets. The routine then passes the transmit packet\r
1444 to the network adapter.\r
1445\r
1446 @param [in] pSimpleNetwork Protocol instance pointer\r
1447 @param [in] HeaderSize The size, in bytes, of the media header to be filled in by\r
1448 the Transmit() function. If HeaderSize is non-zero, then\r
1449 it must be equal to SimpleNetwork->Mode->MediaHeaderSize\r
1450 and DestAddr and Protocol parameters must not be NULL.\r
1451 @param [in] BufferSize The size, in bytes, of the entire packet (media header and\r
1452 data) to be transmitted through the network interface.\r
1453 @param [in] pBuffer A pointer to the packet (media header followed by data) to\r
1454 to be transmitted. This parameter can not be NULL. If\r
1455 HeaderSize is zero, then the media header is Buffer must\r
1456 already be filled in by the caller. If HeaderSize is nonzero,\r
1457 then the media header will be filled in by the Transmit()\r
1458 function.\r
1459 @param [in] pSrcAddr The source HW MAC address. If HeaderSize is zero, then\r
1460 this parameter is ignored. If HeaderSize is nonzero and\r
1461 SrcAddr is NULL, then SimpleNetwork->Mode->CurrentAddress\r
1462 is used for the source HW MAC address.\r
1463 @param [in] pDestAddr The destination HW MAC address. If HeaderSize is zero, then\r
1464 this parameter is ignored.\r
1465 @param [in] pProtocol The type of header to build. If HeaderSize is zero, then\r
1466 this parameter is ignored.\r
1467\r
1468 @retval EFI_SUCCESS This operation was successful.\r
1469 @retval EFI_NOT_STARTED The network interface was not started.\r
1470 @retval EFI_NOT_READY The network interface is too busy to accept this transmit request.\r
1471 @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.\r
1472 @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid\r
1473 EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
1474 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
1475\r
1476**/\r
1477EFI_STATUS\r
1478EFIAPI\r
1479SN_Transmit (\r
1480 IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,\r
1481 IN UINTN HeaderSize,\r
1482 IN UINTN BufferSize,\r
1483 IN VOID * pBuffer,\r
1484 IN EFI_MAC_ADDRESS * pSrcAddr,\r
1485 IN EFI_MAC_ADDRESS * pDestAddr,\r
1486 IN UINT16 * pProtocol\r
1487 )\r
1488{\r
1489 ETHERNET_HEADER * pHeader;\r
1490 EFI_SIMPLE_NETWORK_MODE * pMode;\r
1491 NIC_DEVICE * pNicDevice;\r
1492 EFI_USB_IO_PROTOCOL * pUsbIo;\r
1493 EFI_STATUS Status;\r
1494 UINTN TransferLength;\r
1495 UINT32 TransferStatus;\r
1496 UINT16 Type;\r
1497 EFI_TPL TplPrevious;\r
1498\r
1499 TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);\r
1500\r
1501 // Verify the parameters\r
1502 //\r
4986bbaf
YP
1503 if (( NULL != pSimpleNetwork ) && \r
1504 ( NULL != pSimpleNetwork->Mode ) && \r
1505 ( NULL != pBuffer) && \r
1506 ( (HeaderSize == 0) || ( (NULL != pDestAddr) && (NULL != pProtocol) ))) {\r
7f556e4d 1507 //\r
1508 // The interface must be running\r
1509 //\r
1510 pMode = pSimpleNetwork->Mode;\r
4986bbaf
YP
1511 //\r
1512 // Verify parameter of HeaderSize\r
1513 //\r
1514 if ((HeaderSize == 0) || (HeaderSize == pMode->MediaHeaderSize)){\r
7f556e4d 1515 //\r
4986bbaf 1516 // Determine if BufferSize is big enough\r
7f556e4d 1517 //\r
4986bbaf
YP
1518 if (BufferSize >= pMode->MediaHeaderSize){\r
1519 if ( EfiSimpleNetworkInitialized == pMode->State ) {\r
1520 //\r
1521 // Update the link status\r
1522 //\r
1523 pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );\r
1524 pMode->MediaPresent = pNicDevice->bLinkUp;\r
7f556e4d 1525\r
4986bbaf
YP
1526 //\r
1527 // Release the synchronization with Ax88772Timer\r
1528 // \r
1529 if ( pMode->MediaPresent && pNicDevice->bComplete) {\r
1530 //\r
1531 // Copy the packet into the USB buffer\r
1532 //\r
7f556e4d 1533\r
4986bbaf
YP
1534 CopyMem ( &pNicDevice->pTxTest->Data[0], pBuffer, BufferSize ); \r
1535 pNicDevice->pTxTest->Length = (UINT16) BufferSize;\r
7f556e4d 1536\r
4986bbaf
YP
1537 //\r
1538 // Transmit the packet\r
1539 //\r
1540 pHeader = (ETHERNET_HEADER *) &pNicDevice->pTxTest->Data[0];\r
1541 if ( 0 != HeaderSize ) {\r
1542 if ( NULL != pDestAddr ) {\r
1543 CopyMem ( &pHeader->dest_addr, pDestAddr, PXE_HWADDR_LEN_ETHER );\r
1544 }\r
1545 if ( NULL != pSrcAddr ) {\r
1546 CopyMem ( &pHeader->src_addr, pSrcAddr, PXE_HWADDR_LEN_ETHER );\r
1547 }\r
1548 else {\r
1549 CopyMem ( &pHeader->src_addr, &pMode->CurrentAddress.Addr[0], PXE_HWADDR_LEN_ETHER );\r
1550 }\r
1551 if ( NULL != pProtocol ) {\r
1552 Type = *pProtocol;\r
1553 }\r
1554 else {\r
1555 Type = pNicDevice->pTxTest->Length;\r
1556 }\r
1557 Type = (UINT16)(( Type >> 8 ) | ( Type << 8 ));\r
1558 pHeader->type = Type;\r
1559 }\r
1560 if ( pNicDevice->pTxTest->Length < MIN_ETHERNET_PKT_SIZE ) {\r
1561 pNicDevice->pTxTest->Length = MIN_ETHERNET_PKT_SIZE;\r
1562 ZeroMem ( &pNicDevice->pTxTest->Data[ BufferSize ],\r
1563 pNicDevice->pTxTest->Length - BufferSize );\r
1564 }\r
1565 \r
1566 DEBUG ((EFI_D_INFO, "TX: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x"\r
1567 " %02x-%02x %d bytes\r\n",\r
1568 pNicDevice->pTxTest->Data[0],\r
1569 pNicDevice->pTxTest->Data[1],\r
1570 pNicDevice->pTxTest->Data[2],\r
1571 pNicDevice->pTxTest->Data[3],\r
1572 pNicDevice->pTxTest->Data[4],\r
1573 pNicDevice->pTxTest->Data[5],\r
1574 pNicDevice->pTxTest->Data[6],\r
1575 pNicDevice->pTxTest->Data[7],\r
1576 pNicDevice->pTxTest->Data[8],\r
1577 pNicDevice->pTxTest->Data[9],\r
1578 pNicDevice->pTxTest->Data[10],\r
1579 pNicDevice->pTxTest->Data[11],\r
1580 pNicDevice->pTxTest->Data[12],\r
1581 pNicDevice->pTxTest->Data[13],\r
1582 pNicDevice->pTxTest->Length ));\r
1583\r
1584 pNicDevice->pTxTest->LengthBar = ~(pNicDevice->pTxTest->Length);\r
1585 TransferLength = sizeof ( pNicDevice->pTxTest->Length )\r
1586 + sizeof ( pNicDevice->pTxTest->LengthBar )\r
1587 + pNicDevice->pTxTest->Length;\r
1588 \r
1589 if (TransferLength % 512 == 0 || TransferLength % 1024 == 0)\r
1590 TransferLength +=4;\r
1591\r
1592 //\r
1593 // Work around USB bus driver bug where a timeout set by receive\r
1594 // succeeds but the timeout expires immediately after, causing the\r
1595 // transmit operation to timeout.\r
1596 //\r
1597 pUsbIo = pNicDevice->pUsbIo;\r
1598 Status = pUsbIo->UsbBulkTransfer ( pUsbIo,\r
1599 BULK_OUT_ENDPOINT,\r
1600 &pNicDevice->pTxTest->Length,\r
1601 &TransferLength,\r
1602 0xfffffffe, \r
1603 &TransferStatus );\r
1604 if ( !EFI_ERROR ( Status )) {\r
1605 Status = TransferStatus;\r
1606 }\r
1607\r
1608 if ( !EFI_ERROR ( Status )) {\r
1609 pNicDevice->pTxBuffer = pBuffer;\r
1610 }\r
1611 else {\r
1612 if ((TransferLength != (UINTN)( pNicDevice->pTxTest->Length + 4 )) &&\r
1613 (TransferLength != (UINTN)(( pNicDevice->pTxTest->Length + 4 ) + 4))) {\r
1614 DEBUG ((EFI_D_INFO, "TransferLength didn't match Packet Length\n"));\r
1615 }\r
1616 //\r
1617 // Reset the controller to fix the error\r
1618 //\r
1619 if ( EFI_DEVICE_ERROR == Status ) {\r
1620 SN_Reset ( pSimpleNetwork, FALSE );\r
1621 }\r
1622 Status = EFI_NOT_READY;\r
1623 }\r
7f556e4d 1624 }\r
1625 else {\r
4986bbaf
YP
1626 //\r
1627 // No packets available.\r
1628 //\r
1629 Status = EFI_NOT_READY;\r
7f556e4d 1630 }\r
4986bbaf 1631 \r
7f556e4d 1632 }\r
1633 else {\r
4986bbaf
YP
1634 if (EfiSimpleNetworkStarted == pMode->State) {\r
1635 Status = EFI_DEVICE_ERROR;\r
7f556e4d 1636 }\r
4986bbaf
YP
1637 else {\r
1638 Status = EFI_NOT_STARTED ;\r
7f556e4d 1639 }\r
7f556e4d 1640 }\r
1641 }\r
1642 else {\r
4986bbaf 1643 Status = EFI_BUFFER_TOO_SMALL;\r
7f556e4d 1644 }\r
7f556e4d 1645 }\r
1646 else {\r
4986bbaf 1647 Status = EFI_INVALID_PARAMETER;\r
7f556e4d 1648 }\r
1649 }\r
1650 else {\r
1651 Status = EFI_INVALID_PARAMETER;\r
1652 }\r
1653 \r
1654 gBS->RestoreTPL (TplPrevious);\r
1655\r
1656 return Status;\r
1657}\r