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.
18 2000-Feb-03 M(f)J Genesis.
31 EFI_MAC_ADDRESS
*DestinationAddrPtr
,
32 EFI_MAC_ADDRESS
*SourceAddrPtr
,
38 This routine calls undi to create the meadia header for the given data buffer.
41 snp - pointer to SNP driver structure
42 MacHeaderPtr - address where the media header will be filled in.
43 MacHeaderSize - size of the memory at MacHeaderPtr
44 BufferPtr - data buffer pointer
45 BufferLength - Size of data in the BufferPtr
46 DestinationAddrPtr - address of the destination mac address buffer
47 SourceAddrPtr - address of the source mac address buffer
48 ProtocolPtr - address of the protocol type
51 EFI_SUCCESS - if successfully completed the undi call
52 Other - error return from undi call.
56 PXE_CPB_FILL_HEADER_FRAGMENTED
*cpb
;
58 struct s_v2p
*pkt_v2p
;
64 (VOID
*) cpb
->SrcAddr
,
65 (VOID
*) SourceAddrPtr
,
66 snp
->mode
.HwAddressSize
70 (VOID
*) cpb
->SrcAddr
,
71 (VOID
*) &(snp
->mode
.CurrentAddress
),
72 snp
->mode
.HwAddressSize
77 (VOID
*) cpb
->DestAddr
,
78 (VOID
*) DestinationAddrPtr
,
79 snp
->mode
.HwAddressSize
83 // we need to do the byte swapping
85 cpb
->Protocol
= (UINT16
) PXE_SWAP_UINT16 (*ProtocolPtr
);
87 cpb
->PacketLen
= (UINT32
) (BufferLength
);
88 cpb
->MediaHeaderLen
= (UINT16
) MacHeaderSize
;
93 cpb
->FragDesc
[0].FragAddr
= (UINT64
) (UINTN
) MacHeaderPtr
;
94 cpb
->FragDesc
[0].FragLen
= (UINT32
) MacHeaderSize
;
95 cpb
->FragDesc
[1].FragAddr
= (UINT64
) (UINTN
) BufferPtr
;
96 cpb
->FragDesc
[1].FragLen
= (UINT32
) BufferLength
;
98 cpb
->FragDesc
[0].reserved
= cpb
->FragDesc
[1].reserved
= 0;
100 if (snp
->IsOldUndi
) {
101 TempData
= (UINT64
) (UINTN
) MacHeaderPtr
;
102 if (TempData
>= FOUR_GIGABYTES
) {
103 cpb
->FragDesc
[0].FragAddr
= (UINT64
) (UINTN
) snp
->fill_hdr_buf
;
104 cpb
->FragDesc
[0].FragLen
= (UINT32
) snp
->init_info
.MediaHeaderLen
;
107 TempData
= (UINT64
) (UINTN
) (BufferPtr
);
108 if (TempData
>= FOUR_GIGABYTES
) {
110 // Let the device just read this buffer
114 EfiPciIoOperationBusMasterRead
,
118 if (Status
!= EFI_SUCCESS
) {
122 // give the virtual address to UNDI and it will call back on Virt2Phys
123 // to get the mapped address, if it needs it
125 cpb
->FragDesc
[1].FragLen
= (UINT32
) pkt_v2p
->bsize
;
129 snp
->cdb
.OpCode
= PXE_OPCODE_FILL_HEADER
;
130 snp
->cdb
.OpFlags
= PXE_OPFLAGS_FILL_HEADER_FRAGMENTED
;
132 snp
->cdb
.DBsize
= PXE_DBSIZE_NOT_USED
;
133 snp
->cdb
.DBaddr
= PXE_DBADDR_NOT_USED
;
135 snp
->cdb
.CPBsize
= sizeof (PXE_CPB_FILL_HEADER_FRAGMENTED
);
136 snp
->cdb
.CPBaddr
= (UINT64
) (UINTN
) cpb
;
138 snp
->cdb
.StatCode
= PXE_STATCODE_INITIALIZE
;
139 snp
->cdb
.StatFlags
= PXE_STATFLAGS_INITIALIZE
;
140 snp
->cdb
.IFnum
= snp
->if_num
;
141 snp
->cdb
.Control
= PXE_CONTROL_LAST_CDB_IN_LIST
;
144 // Issue UNDI command and check result.
146 DEBUG ((EFI_D_NET
, "\nsnp->undi.fill_header() "));
148 (*snp
->issue_undi32_command
) ((UINT64
) (UINTN
) &snp
->cdb
);
150 if (snp
->IsOldUndi
) {
151 TempData
= (UINT64
) (UINTN
) (BufferPtr
);
152 if (TempData
>= FOUR_GIGABYTES
) {
156 // if we used the global buffer for header, copy the contents
158 TempData
= (UINT64
) (UINTN
) MacHeaderPtr
;
159 if (TempData
>= FOUR_GIGABYTES
) {
163 snp
->init_info
.MediaHeaderLen
168 switch (snp
->cdb
.StatCode
) {
169 case PXE_STATCODE_SUCCESS
:
172 case PXE_STATCODE_INVALID_PARAMETER
:
175 "\nsnp->undi.fill_header() %xh:%xh\n",
180 return EFI_INVALID_PARAMETER
;
185 "\nsnp->undi.fill_header() %xh:%xh\n",
190 return EFI_DEVICE_ERROR
;
203 This routine calls undi to transmit the given data buffer
206 snp - pointer to SNP driver structure
207 BufferPtr - data buffer pointer
208 BufferLength - Size of data in the BufferPtr
211 EFI_SUCCESS - if successfully completed the undi call
212 Other - error return from undi call.
216 PXE_CPB_TRANSMIT
*cpb
;
222 cpb
->FrameAddr
= (UINT64
) (UINTN
) BufferPtr
;
223 cpb
->DataLen
= (UINT32
) BufferLength
;
225 TempData
= (UINT64
) (UINTN
) BufferPtr
;
226 if (snp
->IsOldUndi
&& (TempData
>= FOUR_GIGABYTES
)) {
228 // we need to create a mapping now and give it to the undi when it calls
229 // the Virt2Phys on this address.
230 // this is a transmit, just map it for the device to READ
234 EfiPciIoOperationBusMasterRead
,
238 if (Status
!= EFI_SUCCESS
) {
242 cpb
->DataLen
= (UINT32
) v2p
->bsize
;
245 cpb
->MediaheaderLen
= 0;
248 snp
->cdb
.OpFlags
= PXE_OPFLAGS_TRANSMIT_WHOLE
;
250 snp
->cdb
.CPBsize
= sizeof (PXE_CPB_TRANSMIT
);
251 snp
->cdb
.CPBaddr
= (UINT64
) (UINTN
) cpb
;
253 snp
->cdb
.OpCode
= PXE_OPCODE_TRANSMIT
;
254 snp
->cdb
.DBsize
= PXE_DBSIZE_NOT_USED
;
255 snp
->cdb
.DBaddr
= PXE_DBADDR_NOT_USED
;
257 snp
->cdb
.StatCode
= PXE_STATCODE_INITIALIZE
;
258 snp
->cdb
.StatFlags
= PXE_STATFLAGS_INITIALIZE
;
259 snp
->cdb
.IFnum
= snp
->if_num
;
260 snp
->cdb
.Control
= PXE_CONTROL_LAST_CDB_IN_LIST
;
263 // Issue UNDI command and check result.
265 DEBUG ((EFI_D_NET
, "\nsnp->undi.transmit() "));
266 DEBUG ((EFI_D_NET
, "\nsnp->cdb.OpCode == %x", snp
->cdb
.OpCode
));
267 DEBUG ((EFI_D_NET
, "\nsnp->cdb.CPBaddr == %X", snp
->cdb
.CPBaddr
));
268 DEBUG ((EFI_D_NET
, "\nsnp->cdb.DBaddr == %X", snp
->cdb
.DBaddr
));
269 DEBUG ((EFI_D_NET
, "\ncpb->FrameAddr == %X\n", cpb
->FrameAddr
));
271 (*snp
->issue_undi32_command
) ((UINT64
) (UINTN
) &snp
->cdb
);
273 DEBUG ((EFI_D_NET
, "\nexit snp->undi.transmit() "));
274 DEBUG ((EFI_D_NET
, "\nsnp->cdb.StatCode == %r", snp
->cdb
.StatCode
));
277 // we will unmap the buffers in get_status call, not here
279 switch (snp
->cdb
.StatCode
) {
280 case PXE_STATCODE_SUCCESS
:
283 case PXE_STATCODE_QUEUE_FULL
:
284 case PXE_STATCODE_BUSY
:
285 Status
= EFI_NOT_READY
;
289 Status
= EFI_DEVICE_ERROR
;
294 "\nsnp->undi.transmit() %xh:%xh\n",
304 snp_undi32_transmit (
305 IN EFI_SIMPLE_NETWORK_PROTOCOL
* this,
306 IN UINTN MacHeaderSize
,
307 IN UINTN BufferLength
,
309 IN EFI_MAC_ADDRESS
* SourceAddrPtr OPTIONAL
,
310 IN EFI_MAC_ADDRESS
* DestinationAddrPtr OPTIONAL
,
311 IN UINT16
*ProtocolPtr OPTIONAL
316 This is the snp interface routine for transmitting a packet. this routine
317 basically retrieves the snp structure, checks the snp state and calls
318 pxe_fill_header and pxe_transmit calls to complete the transmission.
321 this - pointer to SNP driver context
322 MacHeaderSize - size of the memory at MacHeaderPtr
323 BufferLength - Size of data in the BufferPtr
324 BufferPtr - data buffer pointer
325 SourceAddrPtr - address of the source mac address buffer
326 DestinationAddrPtr - address of the destination mac address buffer
327 ProtocolPtr - address of the protocol type
330 EFI_SUCCESS - if successfully completed the undi call
331 Other - error return from undi call.
339 return EFI_INVALID_PARAMETER
;
342 snp
= EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
345 return EFI_DEVICE_ERROR
;
348 switch (snp
->mode
.State
) {
349 case EfiSimpleNetworkInitialized
:
352 case EfiSimpleNetworkStopped
:
353 return EFI_NOT_STARTED
;
355 case EfiSimpleNetworkStarted
:
356 return EFI_DEVICE_ERROR
;
359 return EFI_DEVICE_ERROR
;
362 if (BufferPtr
== NULL
) {
363 return EFI_INVALID_PARAMETER
;
366 if (BufferLength
< snp
->mode
.MediaHeaderSize
) {
367 return EFI_BUFFER_TOO_SMALL
;
371 // if the MacHeaderSize is non-zero, we need to fill up the header and for that
372 // we need the destination address and the protocol
374 if (MacHeaderSize
!= 0) {
375 if (MacHeaderSize
!= snp
->mode
.MediaHeaderSize
|| DestinationAddrPtr
== 0 || ProtocolPtr
== 0) {
376 return EFI_INVALID_PARAMETER
;
379 Status
= pxe_fillheader (
383 (UINT8
*) BufferPtr
+ MacHeaderSize
,
384 BufferLength
- MacHeaderSize
,
390 if (Status
!= EFI_SUCCESS
) {
395 return pxe_transmit (snp
, BufferPtr
, BufferLength
);