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