2 Copyright (c) 2006, 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.
29 EFI_MAC_ADDRESS
*SourceAddrPtr
,
30 EFI_MAC_ADDRESS
*DestinationAddrPtr
,
36 this routine calls undi to receive a packet and fills in the data in the
40 snp - pointer to snp driver structure
41 BufferPtr - pointer to the memory for the received data
42 BuffSizePtr - is a pointer to the length of the buffer on entry and contains
43 the length of the received data on return
44 HeaderSizePtr - pointer to the header portion of the data received.
45 SourceAddrPtr - optional parameter, is a pointer to contain the source
46 ethernet address on return
47 DestinationAddrPtr - optional parameter, is a pointer to contain the destination
48 ethernet address on return
49 ProtocolPtr - optional parameter, is a pointer to contain the protocol type
50 from the ethernet header on return
64 buf_size
= *BuffSizePtr
;
67 // In case of the older 3.0 UNDI, if the input buffer address is beyond 4GB,
68 // DO NOT call the map function on the given buffer, instead use
69 // a global buffer. The reason is that UNDI3.0 has some unnecessary check of
70 // making sure that all the addresses (whether or not they will be given
71 // to the NIC ) supplied to it are below 4GB. It may or may not use
72 // the mapped address after all (like in case of CPB and DB)!
73 // Instead of using the global buffer whose address is allocated within the
74 // 2GB limit if I start mapping the given buffer we lose the data, here is
76 // if our address is > 4GB, the map call creates another buffer below 2GB and
77 // copies data to/from the original buffer to the mapped buffer either at
78 // map time or unmap time depending on the map direction.
79 // UNDI will not complain since we already mapped the buffer to be
80 // within the 2GB limit but will not use (I know undi) the mapped address
81 // since it does not give the user buffers to the NIC's receive unit,
82 // It just copies the received packet into the user buffer using the virtual
83 // (CPU) address rather than the mapped (device or physical) address.
84 // When the UNDI call returns, if we then unmap the buffer, we will lose
85 // the contents because unmap copies the contents of the mapped buffer into
86 // the original buffer (since the direction is FROM_DEVICE) !!!
88 // this is not a problem in Undi 3.1 because this undi uses it's map callback
89 // routine to map a cpu address to device address and it does it only if
90 // it is giving the address to the device and unmaps it before using the cpu
93 TempData
= (UINT64
) (UINTN
) BufferPtr
;
94 if (snp
->IsOldUndi
&& (TempData
>= FOUR_GIGABYTES
)) {
95 cpb
->BufferAddr
= (UINT64
) (UINTN
) snp
->receive_buf
;
96 cpb
->BufferLen
= (UINT32
) (snp
->init_info
.MediaHeaderLen
+ snp
->init_info
.FrameDataLen
);
98 cpb
->BufferAddr
= (UINT64
) (UINTN
) BufferPtr
;
99 cpb
->BufferLen
= (UINT32
) *BuffSizePtr
;
104 snp
->cdb
.OpCode
= PXE_OPCODE_RECEIVE
;
105 snp
->cdb
.OpFlags
= PXE_OPFLAGS_NOT_USED
;
107 snp
->cdb
.CPBsize
= sizeof (PXE_CPB_RECEIVE
);
108 snp
->cdb
.CPBaddr
= (UINT64
) (UINTN
) cpb
;
110 snp
->cdb
.DBsize
= sizeof (PXE_DB_RECEIVE
);
111 snp
->cdb
.DBaddr
= (UINT64
) (UINTN
) db
;
113 snp
->cdb
.StatCode
= PXE_STATCODE_INITIALIZE
;
114 snp
->cdb
.StatFlags
= PXE_STATFLAGS_INITIALIZE
;
115 snp
->cdb
.IFnum
= snp
->if_num
;
116 snp
->cdb
.Control
= PXE_CONTROL_LAST_CDB_IN_LIST
;
119 // Issue UNDI command and check result.
121 DEBUG ((EFI_D_INFO
, "\nsnp->undi.receive () "));
123 (*snp
->issue_undi32_command
) ((UINT64
) (UINTN
) &snp
->cdb
);
125 switch (snp
->cdb
.StatCode
) {
126 case PXE_STATCODE_SUCCESS
:
129 case PXE_STATCODE_NO_DATA
:
132 "\nsnp->undi.receive () %xh:%xh\n",
137 return EFI_NOT_READY
;
142 "\nsnp->undi.receive() %xh:%xh\n",
147 return EFI_DEVICE_ERROR
;
150 *BuffSizePtr
= db
->FrameLen
;
152 if (HeaderSizePtr
!= NULL
) {
153 *HeaderSizePtr
= db
->MediaHeaderLen
;
156 if (SourceAddrPtr
!= NULL
) {
157 CopyMem (SourceAddrPtr
, &db
->SrcAddr
, snp
->mode
.HwAddressSize
);
160 if (DestinationAddrPtr
!= NULL
) {
161 CopyMem (DestinationAddrPtr
, &db
->DestAddr
, snp
->mode
.HwAddressSize
);
164 if (ProtocolPtr
!= NULL
) {
165 *ProtocolPtr
= (UINT16
) PXE_SWAP_UINT16 (db
->Protocol
); /* we need to do the byte swapping */
168 TempData
= (UINT64
) (UINTN
) BufferPtr
;
169 if (snp
->IsOldUndi
&& (TempData
>= FOUR_GIGABYTES
)) {
170 CopyMem (BufferPtr
, snp
->receive_buf
, snp
->init_info
.MediaHeaderLen
+ snp
->init_info
.FrameDataLen
);
173 return (*BuffSizePtr
<= buf_size
) ? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
179 IN EFI_SIMPLE_NETWORK_PROTOCOL
* this,
180 OUT UINTN
*HeaderSizePtr OPTIONAL
,
181 IN OUT UINTN
*BuffSizePtr
,
183 OUT EFI_MAC_ADDRESS
* SourceAddrPtr OPTIONAL
,
184 OUT EFI_MAC_ADDRESS
* DestinationAddrPtr OPTIONAL
,
185 OUT UINT16
*ProtocolPtr OPTIONAL
190 This is the SNP interface routine for receiving network data.
191 This routine basically retrieves snp structure, checks the SNP state and
192 calls the pxe_receive routine to actually do the receive!
195 this - context pointer
196 HeaderSizePtr - optional parameter and is a pointer to the header portion of
198 BuffSizePtr - is a pointer to the length of the buffer on entry and contains
199 the length of the received data on return
200 BufferPtr - pointer to the memory for the received data
201 SourceAddrPtr - optional parameter, is a pointer to contain the source
202 ethernet address on return
203 DestinationAddrPtr - optional parameter, is a pointer to contain the destination
204 ethernet address on return
205 ProtocolPtr - optional parameter, is a pointer to contain the protocol type
206 from the ethernet header on return
215 return EFI_INVALID_PARAMETER
;
218 snp
= EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
221 return EFI_DEVICE_ERROR
;
224 switch (snp
->mode
.State
) {
225 case EfiSimpleNetworkInitialized
:
228 case EfiSimpleNetworkStopped
:
229 return EFI_NOT_STARTED
;
231 case EfiSimpleNetworkStarted
:
232 return EFI_DEVICE_ERROR
;
235 return EFI_DEVICE_ERROR
;
238 if ((BuffSizePtr
== NULL
) || (BufferPtr
== NULL
)) {
239 return EFI_INVALID_PARAMETER
;
242 if (!snp
->mode
.ReceiveFilterSetting
) {
243 return EFI_DEVICE_ERROR
;