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.
32 EFI_MAC_ADDRESS
*DestinationAddrPtr
,
33 EFI_MAC_ADDRESS
*SourceAddrPtr
,
39 This routine calls undi to create the meadia header for the given data buffer.
42 snp - pointer to SNP driver structure
43 MacHeaderPtr - address where the media header will be filled in.
44 MacHeaderSize - size of the memory at MacHeaderPtr
45 BufferPtr - data buffer pointer
46 BufferLength - Size of data in the BufferPtr
47 DestinationAddrPtr - address of the destination mac address buffer
48 SourceAddrPtr - address of the source mac address buffer
49 ProtocolPtr - address of the protocol type
52 EFI_SUCCESS - if successfully completed the undi call
53 Other - error return from undi call.
57 PXE_CPB_FILL_HEADER_FRAGMENTED
*cpb
;
59 struct s_v2p
*pkt_v2p
;
65 (VOID
*) cpb
->SrcAddr
,
66 (VOID
*) SourceAddrPtr
,
67 snp
->mode
.HwAddressSize
71 (VOID
*) cpb
->SrcAddr
,
72 (VOID
*) &(snp
->mode
.CurrentAddress
),
73 snp
->mode
.HwAddressSize
78 (VOID
*) cpb
->DestAddr
,
79 (VOID
*) DestinationAddrPtr
,
80 snp
->mode
.HwAddressSize
84 // we need to do the byte swapping
86 cpb
->Protocol
= (UINT16
) PXE_SWAP_UINT16 (*ProtocolPtr
);
88 cpb
->PacketLen
= (UINT32
) (BufferLength
);
89 cpb
->MediaHeaderLen
= (UINT16
) MacHeaderSize
;
94 cpb
->FragDesc
[0].FragAddr
= (UINT64
) (UINTN
) MacHeaderPtr
;
95 cpb
->FragDesc
[0].FragLen
= (UINT32
) MacHeaderSize
;
96 cpb
->FragDesc
[1].FragAddr
= (UINT64
) (UINTN
) BufferPtr
;
97 cpb
->FragDesc
[1].FragLen
= (UINT32
) BufferLength
;
99 cpb
->FragDesc
[0].reserved
= cpb
->FragDesc
[1].reserved
= 0;
101 if (snp
->IsOldUndi
) {
102 TempData
= (UINT64
) (UINTN
) MacHeaderPtr
;
103 if (TempData
>= FOUR_GIGABYTES
) {
104 cpb
->FragDesc
[0].FragAddr
= (UINT64
) (UINTN
) snp
->fill_hdr_buf
;
105 cpb
->FragDesc
[0].FragLen
= (UINT32
) snp
->init_info
.MediaHeaderLen
;
108 TempData
= (UINT64
) (UINTN
) (BufferPtr
);
109 if (TempData
>= FOUR_GIGABYTES
) {
111 // Let the device just read this buffer
115 EfiPciIoOperationBusMasterRead
,
119 if (Status
!= EFI_SUCCESS
) {
123 // give the virtual address to UNDI and it will call back on Virt2Phys
124 // to get the mapped address, if it needs it
126 cpb
->FragDesc
[1].FragLen
= (UINT32
) pkt_v2p
->bsize
;
130 snp
->cdb
.OpCode
= PXE_OPCODE_FILL_HEADER
;
131 snp
->cdb
.OpFlags
= PXE_OPFLAGS_FILL_HEADER_FRAGMENTED
;
133 snp
->cdb
.DBsize
= PXE_DBSIZE_NOT_USED
;
134 snp
->cdb
.DBaddr
= PXE_DBADDR_NOT_USED
;
136 snp
->cdb
.CPBsize
= sizeof (PXE_CPB_FILL_HEADER_FRAGMENTED
);
137 snp
->cdb
.CPBaddr
= (UINT64
) (UINTN
) cpb
;
139 snp
->cdb
.StatCode
= PXE_STATCODE_INITIALIZE
;
140 snp
->cdb
.StatFlags
= PXE_STATFLAGS_INITIALIZE
;
141 snp
->cdb
.IFnum
= snp
->if_num
;
142 snp
->cdb
.Control
= PXE_CONTROL_LAST_CDB_IN_LIST
;
145 // Issue UNDI command and check result.
147 DEBUG ((EFI_D_NET
, "\nsnp->undi.fill_header() "));
149 (*snp
->issue_undi32_command
) ((UINT64
) (UINTN
) &snp
->cdb
);
151 if (snp
->IsOldUndi
) {
152 TempData
= (UINT64
) (UINTN
) (BufferPtr
);
153 if (TempData
>= FOUR_GIGABYTES
) {
157 // if we used the global buffer for header, copy the contents
159 TempData
= (UINT64
) (UINTN
) MacHeaderPtr
;
160 if (TempData
>= FOUR_GIGABYTES
) {
164 snp
->init_info
.MediaHeaderLen
169 switch (snp
->cdb
.StatCode
) {
170 case PXE_STATCODE_SUCCESS
:
173 case PXE_STATCODE_INVALID_PARAMETER
:
176 "\nsnp->undi.fill_header() %xh:%xh\n",
181 return EFI_INVALID_PARAMETER
;
186 "\nsnp->undi.fill_header() %xh:%xh\n",
191 return EFI_DEVICE_ERROR
;
205 This routine calls undi to transmit the given data buffer
208 snp - pointer to SNP driver structure
209 BufferPtr - data buffer pointer
210 BufferLength - Size of data in the BufferPtr
213 EFI_SUCCESS - if successfully completed the undi call
214 Other - error return from undi call.
218 PXE_CPB_TRANSMIT
*cpb
;
224 cpb
->FrameAddr
= (UINT64
) (UINTN
) BufferPtr
;
225 cpb
->DataLen
= (UINT32
) BufferLength
;
227 TempData
= (UINT64
) (UINTN
) BufferPtr
;
228 if (snp
->IsOldUndi
&& (TempData
>= FOUR_GIGABYTES
)) {
230 // we need to create a mapping now and give it to the undi when it calls
231 // the Virt2Phys on this address.
232 // this is a transmit, just map it for the device to READ
236 EfiPciIoOperationBusMasterRead
,
240 if (Status
!= EFI_SUCCESS
) {
244 cpb
->DataLen
= (UINT32
) v2p
->bsize
;
247 cpb
->MediaheaderLen
= 0;
250 snp
->cdb
.OpFlags
= PXE_OPFLAGS_TRANSMIT_WHOLE
;
252 snp
->cdb
.CPBsize
= sizeof (PXE_CPB_TRANSMIT
);
253 snp
->cdb
.CPBaddr
= (UINT64
) (UINTN
) cpb
;
255 snp
->cdb
.OpCode
= PXE_OPCODE_TRANSMIT
;
256 snp
->cdb
.DBsize
= PXE_DBSIZE_NOT_USED
;
257 snp
->cdb
.DBaddr
= PXE_DBADDR_NOT_USED
;
259 snp
->cdb
.StatCode
= PXE_STATCODE_INITIALIZE
;
260 snp
->cdb
.StatFlags
= PXE_STATFLAGS_INITIALIZE
;
261 snp
->cdb
.IFnum
= snp
->if_num
;
262 snp
->cdb
.Control
= PXE_CONTROL_LAST_CDB_IN_LIST
;
265 // Issue UNDI command and check result.
267 DEBUG ((EFI_D_NET
, "\nsnp->undi.transmit() "));
268 DEBUG ((EFI_D_NET
, "\nsnp->cdb.OpCode == %x", snp
->cdb
.OpCode
));
269 DEBUG ((EFI_D_NET
, "\nsnp->cdb.CPBaddr == %X", snp
->cdb
.CPBaddr
));
270 DEBUG ((EFI_D_NET
, "\nsnp->cdb.DBaddr == %X", snp
->cdb
.DBaddr
));
271 DEBUG ((EFI_D_NET
, "\ncpb->FrameAddr == %X\n", cpb
->FrameAddr
));
273 (*snp
->issue_undi32_command
) ((UINT64
) (UINTN
) &snp
->cdb
);
275 DEBUG ((EFI_D_NET
, "\nexit snp->undi.transmit() "));
276 DEBUG ((EFI_D_NET
, "\nsnp->cdb.StatCode == %r", snp
->cdb
.StatCode
));
279 // we will unmap the buffers in get_status call, not here
281 switch (snp
->cdb
.StatCode
) {
282 case PXE_STATCODE_SUCCESS
:
285 case PXE_STATCODE_QUEUE_FULL
:
286 case PXE_STATCODE_BUSY
:
287 Status
= EFI_NOT_READY
;
291 Status
= EFI_DEVICE_ERROR
;
296 "\nsnp->undi.transmit() %xh:%xh\n",
306 snp_undi32_transmit (
307 IN EFI_SIMPLE_NETWORK_PROTOCOL
* this,
308 IN UINTN MacHeaderSize
,
309 IN UINTN BufferLength
,
311 IN EFI_MAC_ADDRESS
* SourceAddrPtr OPTIONAL
,
312 IN EFI_MAC_ADDRESS
* DestinationAddrPtr OPTIONAL
,
313 IN UINT16
*ProtocolPtr OPTIONAL
318 This is the snp interface routine for transmitting a packet. this routine
319 basically retrieves the snp structure, checks the snp state and calls
320 pxe_fill_header and pxe_transmit calls to complete the transmission.
323 this - pointer to SNP driver context
324 MacHeaderSize - size of the memory at MacHeaderPtr
325 BufferLength - Size of data in the BufferPtr
326 BufferPtr - data buffer pointer
327 SourceAddrPtr - address of the source mac address buffer
328 DestinationAddrPtr - address of the destination mac address buffer
329 ProtocolPtr - address of the protocol type
332 EFI_SUCCESS - if successfully completed the undi call
333 Other - error return from undi call.
341 return EFI_INVALID_PARAMETER
;
344 snp
= EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
347 return EFI_DEVICE_ERROR
;
350 switch (snp
->mode
.State
) {
351 case EfiSimpleNetworkInitialized
:
354 case EfiSimpleNetworkStopped
:
355 return EFI_NOT_STARTED
;
357 case EfiSimpleNetworkStarted
:
358 return EFI_DEVICE_ERROR
;
361 return EFI_DEVICE_ERROR
;
364 if (BufferPtr
== NULL
) {
365 return EFI_INVALID_PARAMETER
;
368 if (BufferLength
< snp
->mode
.MediaHeaderSize
) {
369 return EFI_BUFFER_TOO_SMALL
;
373 // if the MacHeaderSize is non-zero, we need to fill up the header and for that
374 // we need the destination address and the protocol
376 if (MacHeaderSize
!= 0) {
377 if (MacHeaderSize
!= snp
->mode
.MediaHeaderSize
|| DestinationAddrPtr
== 0 || ProtocolPtr
== 0) {
378 return EFI_INVALID_PARAMETER
;
381 Status
= pxe_fillheader (
385 (UINT8
*) BufferPtr
+ MacHeaderSize
,
386 BufferLength
- MacHeaderSize
,
392 if (Status
!= EFI_SUCCESS
) {
397 return pxe_transmit (snp
, BufferPtr
, BufferLength
);