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.
15 This file contains two sets of callback routines for undi3.0 and undi3.1.
16 the callback routines for Undi3.1 have an extra parameter UniqueId which
17 stores the interface context for the NIC that snp is trying to talk..
26 // these 2 global variables are used only for 3.0 undi. we could not place
27 // them in the snp structure because we will not know which snp structure
28 // in the callback context!
30 STATIC BOOLEAN mInitializeLock
= TRUE
;
31 STATIC EFI_LOCK mLock
;
34 // End Global variables
38 snp_undi32_callback_v2p_30 (
40 IN OUT UINT64 DeviceAddrPtr
45 This is a callback routine supplied to UNDI at undi_start time.
46 UNDI call this routine with a virtual or CPU address that SNP provided
47 to convert it to a physical or device address. Since EFI uses the identical
48 mapping, this routine returns the physical address same as the virtual address
49 for most of the addresses. an address above 4GB cannot generally be used as a
50 device address, it needs to be mapped to a lower physical address. This routine
51 does not call the map routine itself, but it assumes that the mapping was done
52 at the time of providing the address to UNDI. This routine just looks up the
53 address in a map table (which is the v2p structure chain)
56 CpuAddr - virtual address of a buffer
57 DeviceAddrPtr - pointer to the physical address
60 void - The DeviceAddrPtr will contain 0 in case of any error
66 // Do nothing if virtual address is zero or physical pointer is NULL.
67 // No need to map if the virtual address is within 4GB limit since
68 // EFI uses identical mapping
70 if ((CpuAddr
== 0) || (DeviceAddrPtr
== 0)) {
71 DEBUG ((EFI_D_ERROR
, "\nv2p: Null virtual address or physical pointer.\n"));
75 if (CpuAddr
< FOUR_GIGABYTES
) {
76 *(UINT64
*) (UINTN
) DeviceAddrPtr
= CpuAddr
;
80 // SNP creates a vaddr tp paddr mapping at the time of calling undi with any
81 // big address, this callback routine just looks up in the v2p list and
82 // returns the physical address for any given virtual address.
84 if (find_v2p (&v2p
, (VOID
*) (UINTN
) CpuAddr
) != EFI_SUCCESS
) {
85 *(UINT64
*) (UINTN
) DeviceAddrPtr
= CpuAddr
;
87 *(UINT64
*) (UINTN
) DeviceAddrPtr
= v2p
->paddr
;
92 snp_undi32_callback_block_30 (
98 This is a callback routine supplied to UNDI at undi_start time.
99 UNDI call this routine when it wants to have exclusive access to a critical
100 section of the code/data
103 Enable - non-zero indicates acquire
104 zero indicates release
111 // tcpip was calling snp at tpl_notify and if we acquire a lock that was
112 // created at a lower level (TPL_CALLBACK) it gives an assert!
114 if (mInitializeLock
) {
115 EfiInitializeLock (&mLock
, EFI_TPL_NOTIFY
);
116 mInitializeLock
= FALSE
;
120 EfiAcquireLock (&mLock
);
122 EfiReleaseLock (&mLock
);
127 snp_undi32_callback_delay_30 (
128 IN UINT64 MicroSeconds
133 This is a callback routine supplied to UNDI at undi_start time.
134 UNDI call this routine with the number of micro seconds when it wants to
138 MicroSeconds - number of micro seconds to pause, ususlly multiple of 10
144 if (MicroSeconds
!= 0) {
145 gBS
->Stall ((UINTN
) MicroSeconds
);
150 snp_undi32_callback_memio_30 (
151 IN UINT8 ReadOrWrite
,
154 IN OUT UINT64 BufferAddr
159 This is a callback routine supplied to UNDI at undi_start time.
160 This is the IO routine for UNDI. This is not currently being used by UNDI3.0
161 because Undi3.0 uses io/mem offsets relative to the beginning of the device
162 io/mem address and so it needs to use the PCI_IO_FUNCTION that abstracts the
163 start of the device's io/mem addresses. Since SNP cannot retrive the context
164 of the undi3.0 interface it cannot use the PCI_IO_FUNCTION that specific for
165 that NIC and uses one global IO functions structure, this does not work.
166 This however works fine for EFI1.0 Undis because they use absolute addresses
170 ReadOrWrite - indicates read or write, IO or Memory
171 NumBytes - number of bytes to read or write
172 Address - IO or memory address to read from or write to
173 BufferAddr - memory location to read into or that contains the bytes
180 EFI_PCI_IO_PROTOCOL_WIDTH Width
;
184 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) 1;
188 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) 2;
192 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) 3;
196 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) 0;
199 switch (ReadOrWrite
) {
201 mPciIoFncs
->Io
.Read (
204 1, // BAR 1, IO base address
207 (VOID
*) (UINTN
) BufferAddr
212 mPciIoFncs
->Io
.Write (
215 1, // BAR 1, IO base address
218 (VOID
*) (UINTN
) BufferAddr
223 mPciIoFncs
->Mem
.Read (
226 0, // BAR 0, Memory base address
229 (VOID
*) (UINTN
) BufferAddr
234 mPciIoFncs
->Mem
.Write (
237 0, // BAR 0, Memory base address
240 (VOID
*) (UINTN
) BufferAddr
248 // New callbacks for 3.1:
249 // there won't be a virtual2physical callback for UNDI 3.1 because undi3.1 uses
250 // the MemMap call to map the required address by itself!
253 snp_undi32_callback_block (
260 This is a callback routine supplied to UNDI3.1 at undi_start time.
261 UNDI call this routine when it wants to have exclusive access to a critical
262 section of the code/data
265 UniqueId - This was supplied to UNDI at Undi_Start, SNP uses this to store
266 Undi interface context (Undi does not read or write this variable)
267 Enable - non-zero indicates acquire
268 zero indicates release
277 snp
= (SNP_DRIVER
*) (UINTN
) UniqueId
;
279 // tcpip was calling snp at tpl_notify and when we acquire a lock that was
280 // created at a lower level (TPL_CALLBACK) it gives an assert!
283 EfiAcquireLock (&snp
->lock
);
285 EfiReleaseLock (&snp
->lock
);
290 snp_undi32_callback_delay (
292 IN UINT64 MicroSeconds
297 This is a callback routine supplied to UNDI at undi_start time.
298 UNDI call this routine with the number of micro seconds when it wants to
302 MicroSeconds - number of micro seconds to pause, ususlly multiple of 10
308 if (MicroSeconds
!= 0) {
309 gBS
->Stall ((UINTN
) MicroSeconds
);
314 * IO routine for UNDI start CPB.
317 snp_undi32_callback_memio (
327 This is a callback routine supplied to UNDI at undi_start time.
328 This is the IO routine for UNDI3.1.
331 ReadOrWrite - indicates read or write, IO or Memory
332 NumBytes - number of bytes to read or write
333 Address - IO or memory address to read from or write to
334 BufferAddr - memory location to read into or that contains the bytes
342 EFI_PCI_IO_PROTOCOL_WIDTH Width
;
344 snp
= (SNP_DRIVER
*) (UINTN
) UniqueId
;
346 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) 0;
349 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) 1;
353 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) 2;
357 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) 3;
361 switch (ReadOrWrite
) {
363 snp
->IoFncs
->Io
.Read (
366 snp
->IoBarIndex
, // BAR 1 (for 32bit regs), IO base address
369 (VOID
*) (UINTN
) BufferAddr
374 snp
->IoFncs
->Io
.Write (
377 snp
->IoBarIndex
, // BAR 1 (for 32bit regs), IO base address
380 (VOID
*) (UINTN
) BufferAddr
385 snp
->IoFncs
->Mem
.Read (
388 snp
->MemoryBarIndex
, // BAR 0, Memory base address
391 (VOID
*) (UINTN
) BufferAddr
396 snp
->IoFncs
->Mem
.Write (
399 snp
->MemoryBarIndex
, // BAR 0, Memory base address
402 (VOID
*) (UINTN
) BufferAddr
411 snp_undi32_callback_map (
416 IN OUT UINT64 DeviceAddrPtr
421 This is a callback routine supplied to UNDI at undi_start time.
422 UNDI call this routine when it has to map a CPU address to a device
426 UniqueId - This was supplied to UNDI at Undi_Start, SNP uses this to store
427 Undi interface context (Undi does not read or write this variable)
428 CpuAddr - Virtual address to be mapped!
429 NumBytes - size of memory to be mapped
430 Direction - direction of data flow for this memory's usage:
431 cpu->device, device->cpu or both ways
432 DeviceAddrPtr - pointer to return the mapped device address
439 EFI_PHYSICAL_ADDRESS
*DevAddrPtr
;
440 EFI_PCI_IO_PROTOCOL_OPERATION DirectionFlag
;
446 BuffSize
= (UINTN
) NumBytes
;
447 snp
= (SNP_DRIVER
*) (UINTN
) UniqueId
;
448 DevAddrPtr
= (EFI_PHYSICAL_ADDRESS
*) (UINTN
) DeviceAddrPtr
;
456 case TO_AND_FROM_DEVICE
:
457 DirectionFlag
= EfiPciIoOperationBusMasterCommonBuffer
;
461 DirectionFlag
= EfiPciIoOperationBusMasterWrite
;
465 DirectionFlag
= EfiPciIoOperationBusMasterRead
;
471 // any non zero indicates error!
476 // find an unused map_list entry
478 for (Index
= 0; Index
< MAX_MAP_LENGTH
; Index
++) {
479 if (snp
->map_list
[Index
].virt
== 0) {
484 if (Index
>= MAX_MAP_LENGTH
) {
485 SNP_PRINT (L
"SNP maplist is FULL\n");
490 snp
->map_list
[Index
].virt
= (EFI_PHYSICAL_ADDRESS
) CpuAddr
;
492 Status
= snp
->IoFncs
->Map (
495 (VOID
*) (UINTN
) CpuAddr
,
498 &(snp
->map_list
[Index
].map_cookie
)
500 if (Status
!= EFI_SUCCESS
) {
502 snp
->map_list
[Index
].virt
= 0;
509 snp_undi32_callback_unmap (
519 This is a callback routine supplied to UNDI at undi_start time.
520 UNDI call this routine when it wants to unmap an address that was previously
521 mapped using map callback
524 UniqueId - This was supplied to UNDI at Undi_Start, SNP uses this to store
525 Undi interface context (Undi does not read or write this variable)
526 CpuAddr - Virtual address that was mapped!
527 NumBytes - size of memory mapped
528 Direction- direction of data flow for this memory's usage:
529 cpu->device, device->cpu or both ways
530 DeviceAddr - the mapped device address
539 snp
= (SNP_DRIVER
*) (UINTN
) UniqueId
;
541 for (Index
= 0; Index
< MAX_MAP_LENGTH
; Index
++) {
542 if (snp
->map_list
[Index
].virt
== CpuAddr
) {
547 if (Index
>= MAX_MAP_LENGTH
)
550 Print (L
"SNP could not find a mapping, failed to unmap.\n");
555 snp
->IoFncs
->Unmap (snp
->IoFncs
, snp
->map_list
[Index
].map_cookie
);
556 snp
->map_list
[Index
].virt
= 0;
557 snp
->map_list
[Index
].map_cookie
= NULL
;
562 snp_undi32_callback_sync (
572 This is a callback routine supplied to UNDI at undi_start time.
573 UNDI call this routine when it wants synchronize the virtual buffer contents
574 with the mapped buffer contents. The virtual and mapped buffers need not
575 correspond to the same physical memory (especially if the virtual address is
576 > 4GB). Depending on the direction for which the buffer is mapped, undi will
577 need to synchronize their contents whenever it writes to/reads from the buffer
578 using either the cpu address or the device address.
580 EFI does not provide a sync call, since virt=physical, we sould just do
581 the synchronization ourself here!
584 UniqueId - This was supplied to UNDI at Undi_Start, SNP uses this to store
585 Undi interface context (Undi does not read or write this variable)
586 CpuAddr - Virtual address that was mapped!
587 NumBytes - size of memory mapped
588 Direction- direction of data flow for this memory's usage:
589 cpu->device, device->cpu or both ways
590 DeviceAddr - the mapped device address
596 if ((CpuAddr
== 0) || (DeviceAddr
== 0) || (NumBytes
== 0)) {
603 CopyMem ((UINT8
*) (UINTN
) CpuAddr
, (UINT8
*) (UINTN
) DeviceAddr
, NumBytes
);
607 CopyMem ((UINT8
*) (UINTN
) DeviceAddr
, (UINT8
*) (UINTN
) CpuAddr
, NumBytes
);