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.
30 EFI_MAC_ADDRESS
*SourceAddrPtr
,
31 EFI_MAC_ADDRESS
*DestinationAddrPtr
,
37 this routine calls undi to receive a packet and fills in the data in the
41 snp - pointer to snp driver structure
42 BufferPtr - pointer to the memory for the received data
43 BuffSizePtr - is a pointer to the length of the buffer on entry and contains
44 the length of the received data on return
45 HeaderSizePtr - pointer to the header portion of the data received.
46 SourceAddrPtr - optional parameter, is a pointer to contain the source
47 ethernet address on return
48 DestinationAddrPtr - optional parameter, is a pointer to contain the destination
49 ethernet address on return
50 ProtocolPtr - optional parameter, is a pointer to contain the protocol type
51 from the ethernet header on return
65 buf_size
= *BuffSizePtr
;
68 // In case of the older 3.0 UNDI, if the input buffer address is beyond 4GB,
69 // DO NOT call the map function on the given buffer, instead use
70 // a global buffer. The reason is that UNDI3.0 has some unnecessary check of
71 // making sure that all the addresses (whether or not they will be given
72 // to the NIC ) supplied to it are below 4GB. It may or may not use
73 // the mapped address after all (like in case of CPB and DB)!
74 // Instead of using the global buffer whose address is allocated within the
75 // 2GB limit if I start mapping the given buffer we lose the data, here is
77 // if our address is > 4GB, the map call creates another buffer below 2GB and
78 // copies data to/from the original buffer to the mapped buffer either at
79 // map time or unmap time depending on the map direction.
80 // UNDI will not complain since we already mapped the buffer to be
81 // within the 2GB limit but will not use (I know undi) the mapped address
82 // since it does not give the user buffers to the NIC's receive unit,
83 // It just copies the received packet into the user buffer using the virtual
84 // (CPU) address rather than the mapped (device or physical) address.
85 // When the UNDI call returns, if we then unmap the buffer, we will lose
86 // the contents because unmap copies the contents of the mapped buffer into
87 // the original buffer (since the direction is FROM_DEVICE) !!!
89 // this is not a problem in Undi 3.1 because this undi uses it's map callback
90 // routine to map a cpu address to device address and it does it only if
91 // it is giving the address to the device and unmaps it before using the cpu
94 TempData
= (UINT64
) (UINTN
) BufferPtr
;
95 if (snp
->IsOldUndi
&& (TempData
>= FOUR_GIGABYTES
)) {
96 cpb
->BufferAddr
= (UINT64
) (UINTN
) snp
->receive_buf
;
97 cpb
->BufferLen
= (UINT32
) (snp
->init_info
.MediaHeaderLen
+ snp
->init_info
.FrameDataLen
);
99 cpb
->BufferAddr
= (UINT64
) (UINTN
) BufferPtr
;
100 cpb
->BufferLen
= (UINT32
) *BuffSizePtr
;
105 snp
->cdb
.OpCode
= PXE_OPCODE_RECEIVE
;
106 snp
->cdb
.OpFlags
= PXE_OPFLAGS_NOT_USED
;
108 snp
->cdb
.CPBsize
= sizeof (PXE_CPB_RECEIVE
);
109 snp
->cdb
.CPBaddr
= (UINT64
) (UINTN
) cpb
;
111 snp
->cdb
.DBsize
= sizeof (PXE_DB_RECEIVE
);
112 snp
->cdb
.DBaddr
= (UINT64
) (UINTN
) db
;
114 snp
->cdb
.StatCode
= PXE_STATCODE_INITIALIZE
;
115 snp
->cdb
.StatFlags
= PXE_STATFLAGS_INITIALIZE
;
116 snp
->cdb
.IFnum
= snp
->if_num
;
117 snp
->cdb
.Control
= PXE_CONTROL_LAST_CDB_IN_LIST
;
120 // Issue UNDI command and check result.
122 DEBUG ((EFI_D_INFO
, "\nsnp->undi.receive () "));
124 (*snp
->issue_undi32_command
) ((UINT64
) (UINTN
) &snp
->cdb
);
126 switch (snp
->cdb
.StatCode
) {
127 case PXE_STATCODE_SUCCESS
:
130 case PXE_STATCODE_NO_DATA
:
133 "\nsnp->undi.receive () %xh:%xh\n",
138 return EFI_NOT_READY
;
143 "\nsnp->undi.receive() %xh:%xh\n",
148 return EFI_DEVICE_ERROR
;
151 *BuffSizePtr
= db
->FrameLen
;
153 if (HeaderSizePtr
!= NULL
) {
154 *HeaderSizePtr
= db
->MediaHeaderLen
;
157 if (SourceAddrPtr
!= NULL
) {
158 CopyMem (SourceAddrPtr
, &db
->SrcAddr
, snp
->mode
.HwAddressSize
);
161 if (DestinationAddrPtr
!= NULL
) {
162 CopyMem (DestinationAddrPtr
, &db
->DestAddr
, snp
->mode
.HwAddressSize
);
165 if (ProtocolPtr
!= NULL
) {
166 *ProtocolPtr
= (UINT16
) PXE_SWAP_UINT16 (db
->Protocol
); /* we need to do the byte swapping */
169 TempData
= (UINT64
) (UINTN
) BufferPtr
;
170 if (snp
->IsOldUndi
&& (TempData
>= FOUR_GIGABYTES
)) {
171 CopyMem (BufferPtr
, snp
->receive_buf
, snp
->init_info
.MediaHeaderLen
+ snp
->init_info
.FrameDataLen
);
174 return (*BuffSizePtr
<= buf_size
) ? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
180 IN EFI_SIMPLE_NETWORK_PROTOCOL
* this,
181 OUT UINTN
*HeaderSizePtr OPTIONAL
,
182 IN OUT UINTN
*BuffSizePtr
,
184 OUT EFI_MAC_ADDRESS
* SourceAddrPtr OPTIONAL
,
185 OUT EFI_MAC_ADDRESS
* DestinationAddrPtr OPTIONAL
,
186 OUT UINT16
*ProtocolPtr OPTIONAL
191 This is the SNP interface routine for receiving network data.
192 This routine basically retrieves snp structure, checks the SNP state and
193 calls the pxe_receive routine to actually do the receive!
196 this - context pointer
197 HeaderSizePtr - optional parameter and is a pointer to the header portion of
199 BuffSizePtr - is a pointer to the length of the buffer on entry and contains
200 the length of the received data on return
201 BufferPtr - pointer to the memory for the received data
202 SourceAddrPtr - optional parameter, is a pointer to contain the source
203 ethernet address on return
204 DestinationAddrPtr - optional parameter, is a pointer to contain the destination
205 ethernet address on return
206 ProtocolPtr - optional parameter, is a pointer to contain the protocol type
207 from the ethernet header on return
216 return EFI_INVALID_PARAMETER
;
219 snp
= EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
222 return EFI_DEVICE_ERROR
;
225 switch (snp
->mode
.State
) {
226 case EfiSimpleNetworkInitialized
:
229 case EfiSimpleNetworkStopped
:
230 return EFI_NOT_STARTED
;
232 case EfiSimpleNetworkStarted
:
233 return EFI_DEVICE_ERROR
;
236 return EFI_DEVICE_ERROR
;
239 if ((BuffSizePtr
== NULL
) || (BufferPtr
== NULL
)) {
240 return EFI_INVALID_PARAMETER
;
243 if (!snp
->mode
.ReceiveFilterSetting
) {
244 return EFI_DEVICE_ERROR
;