2 Copyright (c) 2004 - 2007, Intel Corporation
3 All rights reserved. This program and the accompanying materials
4 are licensed and made available under the terms and conditions of the BSD License
5 which accompanies this distribution. The full text of the license may be found at
6 http://opensource.org/licenses/bsd-license.php
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 2000-Feb-03 M(f)J Genesis.
25 this routine calls undi to receive a packet and fills in the data in the
28 @param snp pointer to snp driver structure
29 @param BufferPtr pointer to the memory for the received data
30 @param BuffSizePtr is a pointer to the length of the buffer on entry and
31 contains the length of the received data on return
32 @param HeaderSizePtr pointer to the header portion of the data received.
33 @param SourceAddrPtr optional parameter, is a pointer to contain the
34 source ethernet address on return
35 @param DestinationAddrPtr optional parameter, is a pointer to contain the
36 destination ethernet address on return
37 @param ProtocolPtr optional parameter, is a pointer to contain the
38 protocol type from the ethernet header on return
49 EFI_MAC_ADDRESS
*SourceAddrPtr
,
50 EFI_MAC_ADDRESS
*DestinationAddrPtr
,
61 buf_size
= *BuffSizePtr
;
64 // In case of the older 3.0 UNDI, if the input buffer address is beyond 4GB,
65 // DO NOT call the map function on the given buffer, instead use
66 // a global buffer. The reason is that UNDI3.0 has some unnecessary check of
67 // making sure that all the addresses (whether or not they will be given
68 // to the NIC ) supplied to it are below 4GB. It may or may not use
69 // the mapped address after all (like in case of CPB and DB)!
70 // Instead of using the global buffer whose address is allocated within the
71 // 2GB limit if I start mapping the given buffer we lose the data, here is
73 // if our address is > 4GB, the map call creates another buffer below 2GB and
74 // copies data to/from the original buffer to the mapped buffer either at
75 // map time or unmap time depending on the map direction.
76 // UNDI will not complain since we already mapped the buffer to be
77 // within the 2GB limit but will not use (I know undi) the mapped address
78 // since it does not give the user buffers to the NIC's receive unit,
79 // It just copies the received packet into the user buffer using the virtual
80 // (CPU) address rather than the mapped (device or physical) address.
81 // When the UNDI call returns, if we then unmap the buffer, we will lose
82 // the contents because unmap copies the contents of the mapped buffer into
83 // the original buffer (since the direction is FROM_DEVICE) !!!
85 // this is not a problem in Undi 3.1 because this undi uses it's map callback
86 // routine to map a cpu address to device address and it does it only if
87 // it is giving the address to the device and unmaps it before using the cpu
90 TempData
= (UINT64
) (UINTN
) BufferPtr
;
91 if (snp
->IsOldUndi
&& (TempData
>= FOUR_GIGABYTES
)) {
92 cpb
->BufferAddr
= (UINT64
)(UINTN
) snp
->receive_buf
;
93 cpb
->BufferLen
= (UINT32
) (snp
->init_info
.MediaHeaderLen
+ snp
->init_info
.FrameDataLen
);
95 cpb
->BufferAddr
= (UINT64
)(UINTN
) BufferPtr
;
96 cpb
->BufferLen
= (UINT32
) *BuffSizePtr
;
101 snp
->cdb
.OpCode
= PXE_OPCODE_RECEIVE
;
102 snp
->cdb
.OpFlags
= PXE_OPFLAGS_NOT_USED
;
104 snp
->cdb
.CPBsize
= sizeof (PXE_CPB_RECEIVE
);
105 snp
->cdb
.CPBaddr
= (UINT64
)(UINTN
) cpb
;
107 snp
->cdb
.DBsize
= sizeof (PXE_DB_RECEIVE
);
108 snp
->cdb
.DBaddr
= (UINT64
)(UINTN
) db
;
110 snp
->cdb
.StatCode
= PXE_STATCODE_INITIALIZE
;
111 snp
->cdb
.StatFlags
= PXE_STATFLAGS_INITIALIZE
;
112 snp
->cdb
.IFnum
= snp
->if_num
;
113 snp
->cdb
.Control
= PXE_CONTROL_LAST_CDB_IN_LIST
;
116 // Issue UNDI command and check result.
118 DEBUG ((EFI_D_INFO
, "\nsnp->undi.receive () "));
120 (*snp
->issue_undi32_command
) ((UINT64
)(UINTN
) &snp
->cdb
);
122 switch (snp
->cdb
.StatCode
) {
123 case PXE_STATCODE_SUCCESS
:
126 case PXE_STATCODE_NO_DATA
:
129 "\nsnp->undi.receive () %xh:%xh\n",
134 return EFI_NOT_READY
;
139 "\nsnp->undi.receive() %xh:%xh\n",
144 return EFI_DEVICE_ERROR
;
147 *BuffSizePtr
= db
->FrameLen
;
149 if (HeaderSizePtr
!= NULL
) {
150 *HeaderSizePtr
= db
->MediaHeaderLen
;
153 if (SourceAddrPtr
!= NULL
) {
154 CopyMem (SourceAddrPtr
, &db
->SrcAddr
, snp
->mode
.HwAddressSize
);
157 if (DestinationAddrPtr
!= NULL
) {
158 CopyMem (DestinationAddrPtr
, &db
->DestAddr
, snp
->mode
.HwAddressSize
);
161 if (ProtocolPtr
!= NULL
) {
162 *ProtocolPtr
= (UINT16
) PXE_SWAP_UINT16 (db
->Protocol
); /* we need to do the byte swapping */
165 TempData
= (UINT64
) (UINTN
) BufferPtr
;
166 if (snp
->IsOldUndi
&& (TempData
>= FOUR_GIGABYTES
)) {
167 CopyMem (BufferPtr
, snp
->receive_buf
, snp
->init_info
.MediaHeaderLen
+ snp
->init_info
.FrameDataLen
);
170 return (*BuffSizePtr
<= buf_size
) ? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
175 This is the SNP interface routine for receiving network data.
176 This routine basically retrieves snp structure, checks the SNP state and
177 calls the pxe_receive routine to actually do the receive!
179 @param this context pointer
180 @param HeaderSizePtr optional parameter and is a pointer to the header
181 portion of the data received.
182 @param BuffSizePtr is a pointer to the length of the buffer on entry and
183 contains the length of the received data on return
184 @param BufferPtr pointer to the memory for the received data
185 @param SourceAddrPtr optional parameter, is a pointer to contain the
186 source ethernet address on return
187 @param DestinationAddrPtr optional parameter, is a pointer to contain the
188 destination ethernet address on return
189 @param ProtocolPtr optional parameter, is a pointer to contain the
190 protocol type from the ethernet header on return
197 IN EFI_SIMPLE_NETWORK_PROTOCOL
* this,
198 OUT UINTN
*HeaderSizePtr OPTIONAL
,
199 IN OUT UINTN
*BuffSizePtr
,
201 OUT EFI_MAC_ADDRESS
* SourceAddrPtr OPTIONAL
,
202 OUT EFI_MAC_ADDRESS
* DestinationAddrPtr OPTIONAL
,
203 OUT UINT16
*ProtocolPtr OPTIONAL
211 return EFI_INVALID_PARAMETER
;
214 snp
= EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
216 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
218 switch (snp
->mode
.State
) {
219 case EfiSimpleNetworkInitialized
:
222 case EfiSimpleNetworkStopped
:
223 Status
= EFI_NOT_STARTED
;
227 Status
= EFI_DEVICE_ERROR
;
231 if ((BuffSizePtr
== NULL
) || (BufferPtr
== NULL
)) {
232 Status
= EFI_INVALID_PARAMETER
;
236 if (!snp
->mode
.ReceiveFilterSetting
) {
237 Status
= EFI_DEVICE_ERROR
;
241 Status
= pxe_receive (
252 gBS
->RestoreTPL (OldTpl
);