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