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