2 This file contains two sets of callback routines for undi3.0 and undi3.1.
3 the callback routines for Undi3.1 have an extra parameter UniqueId which
4 stores the interface context for the NIC that snp is trying to talk.
6 Copyright (c) 2006 - 2008, Intel Corporation. <BR>
7 All rights reserved. This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 // these 2 global variables are used only for 3.0 undi. we could not place
22 // them in the snp structure because we will not know which snp structure
23 // in the callback context!
25 BOOLEAN mInitializeLock
= TRUE
;
29 // End Global variables
31 extern EFI_PCI_IO_PROTOCOL
*mPciIo
;
34 This is a callback routine supplied to UNDI at undi_start time.
35 UNDI call this routine with a virtual or CPU address that SNP provided to
36 convert it to a physical or device address. Since EFI uses the identical
37 mapping, this routine returns the physical address same as the virtual address
38 for most of the addresses. an address above 4GB cannot generally be used as a
39 device address, it needs to be mapped to a lower physical address. This
40 routine does not call the map routine itself, but it assumes that the mapping
41 was done at the time of providing the address to UNDI. This routine just
42 looks up the address in a map table (which is the v2p structure chain).
44 @param CpuAddr virtual address of a buffer.
45 @param DeviceAddrPtr pointer to the physical address.
46 The DeviceAddrPtr will contain 0 in case of any error.
50 SnpUndi32CallbackV2p30 (
52 IN OUT UINT64 DeviceAddrPtr
57 // Do nothing if virtual address is zero or physical pointer is NULL.
58 // No need to map if the virtual address is within 4GB limit since
59 // EFI uses identical mapping
61 if ((CpuAddr
== 0) || (DeviceAddrPtr
== 0)) {
62 DEBUG ((EFI_D_NET
, "\nv2p: Null virtual address or physical pointer.\n"));
66 if (CpuAddr
< FOUR_GIGABYTES
) {
67 *(UINT64
*) (UINTN
) DeviceAddrPtr
= CpuAddr
;
71 // SNP creates a vaddr tp paddr mapping at the time of calling undi with any
72 // big address, this callback routine just looks up in the v2p list and
73 // returns the physical address for any given virtual address.
75 if (FindV2p (&V2p
, (VOID
*) (UINTN
) CpuAddr
) != EFI_SUCCESS
) {
76 *(UINT64
*) (UINTN
) DeviceAddrPtr
= CpuAddr
;
78 *(UINT64
*) (UINTN
) DeviceAddrPtr
= V2p
->PhysicalAddress
;
83 This is a callback routine supplied to UNDI at undi_start time.
84 UNDI call this routine when it wants to have exclusive access to a critical
85 section of the code/data.
87 @param Enable non-zero indicates acquire
88 zero indicates release
92 SnpUndi32CallbackBlock30 (
97 // tcpip was calling snp at tpl_notify and if we acquire a lock that was
98 // created at a lower level (TPL_CALLBACK) it gives an assert!
100 if (mInitializeLock
) {
101 EfiInitializeLock (&mLock
, TPL_NOTIFY
);
102 mInitializeLock
= FALSE
;
106 EfiAcquireLock (&mLock
);
108 EfiReleaseLock (&mLock
);
113 This is a callback routine supplied to UNDI at undi_start time.
114 UNDI call this routine with the number of micro seconds when it wants to
117 @param MicroSeconds number of micro seconds to pause, ususlly multiple of 10.
121 SnpUndi32CallbackDelay30 (
122 IN UINT64 MicroSeconds
125 if (MicroSeconds
!= 0) {
126 gBS
->Stall ((UINTN
) MicroSeconds
);
131 This is a callback routine supplied to UNDI at undi_start time.
132 This is the IO routine for UNDI. This is not currently being used by UNDI3.0
133 because Undi3.0 uses io/mem offsets relative to the beginning of the device
134 io/mem address and so it needs to use the PCI_IO_FUNCTION that abstracts the
135 start of the device's io/mem addresses. Since SNP cannot retrive the context
136 of the undi3.0 interface it cannot use the PCI_IO_FUNCTION that specific for
137 that NIC and uses one global IO functions structure, this does not work.
138 This however works fine for EFI1.0 Undis because they use absolute addresses
141 @param ReadOrWrite indicates read or write, IO or Memory
142 @param NumBytes number of bytes to read or write
143 @param Address IO or memory address to read from or write to
144 @param BufferAddr memory location to read into or that contains the bytes to
149 SnpUndi32CallbackMemio30 (
150 IN UINT8 ReadOrWrite
,
153 IN OUT UINT64 BufferAddr
156 EFI_PCI_IO_PROTOCOL_WIDTH Width
;
160 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) 1;
164 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) 2;
168 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) 3;
172 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) 0;
175 switch (ReadOrWrite
) {
180 1, // BAR 1, IO base address
183 (VOID
*) (UINTN
) BufferAddr
191 1, // BAR 1, IO base address
194 (VOID
*) (UINTN
) BufferAddr
202 0, // BAR 0, Memory base address
205 (VOID
*) (UINTN
) BufferAddr
213 0, // BAR 0, Memory base address
216 (VOID
*) (UINTN
) BufferAddr
225 This is a callback routine supplied to UNDI3.1 at undi_start time.
226 UNDI call this routine when it wants to have exclusive access to a critical
227 section of the code/data.
228 New callbacks for 3.1:
229 there won't be a virtual2physical callback for UNDI 3.1 because undi3.1 uses
230 the MemMap call to map the required address by itself!
232 @param UniqueId This was supplied to UNDI at Undi_Start, SNP uses this to
233 store Undi interface context (Undi does not read or write
235 @param Enable non-zero indicates acquire
236 zero indicates release
239 SnpUndi32CallbackBlock (
246 Snp
= (SNP_DRIVER
*) (UINTN
) UniqueId
;
248 // tcpip was calling snp at tpl_notify and when we acquire a lock that was
249 // created at a lower level (TPL_CALLBACK) it gives an assert!
252 EfiAcquireLock (&Snp
->Lock
);
254 EfiReleaseLock (&Snp
->Lock
);
259 This is a callback routine supplied to UNDI at undi_start time.
260 UNDI call this routine with the number of micro seconds when it wants to
263 @param UniqueId This was supplied to UNDI at Undi_Start, SNP uses this to
264 store Undi interface context (Undi does not read or write
266 @param MicroSeconds number of micro seconds to pause, ususlly multiple of 10.
269 SnpUndi32CallbackDelay (
271 IN UINT64 MicroSeconds
274 if (MicroSeconds
!= 0) {
275 gBS
->Stall ((UINTN
) MicroSeconds
);
280 This is a callback routine supplied to UNDI at undi_start time.
281 This is the IO routine for UNDI3.1 to start CPB.
283 @param UniqueId This was supplied to UNDI at Undi_Start, SNP uses this
284 to store Undi interface context (Undi does not read or
286 @param ReadOrWrite indicates read or write, IO or Memory.
287 @param NumBytes number of bytes to read or write.
288 @param MemOrPortAddr IO or memory address to read from or write to.
289 @param BufferPtr memory location to read into or that contains the bytes
293 SnpUndi32CallbackMemio (
295 IN UINT8 ReadOrWrite
,
297 IN UINT64 MemOrPortAddr
,
298 IN OUT UINT64 BufferPtr
302 EFI_PCI_IO_PROTOCOL_WIDTH Width
;
304 Snp
= (SNP_DRIVER
*) (UINTN
) UniqueId
;
306 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) 0;
309 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) 1;
313 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) 2;
317 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) 3;
321 switch (ReadOrWrite
) {
323 Snp
->PciIo
->Io
.Read (
326 Snp
->IoBarIndex
, // BAR 1 (for 32bit regs), IO base address
329 (VOID
*) (UINTN
) BufferPtr
334 Snp
->PciIo
->Io
.Write (
337 Snp
->IoBarIndex
, // BAR 1 (for 32bit regs), IO base address
340 (VOID
*) (UINTN
) BufferPtr
345 Snp
->PciIo
->Mem
.Read (
348 Snp
->MemoryBarIndex
, // BAR 0, Memory base address
351 (VOID
*) (UINTN
) BufferPtr
356 Snp
->PciIo
->Mem
.Write (
359 Snp
->MemoryBarIndex
, // BAR 0, Memory base address
362 (VOID
*) (UINTN
) BufferPtr
371 This is a callback routine supplied to UNDI at undi_start time.
372 UNDI call this routine when it has to map a CPU address to a device
375 @param UniqueId - This was supplied to UNDI at Undi_Start, SNP uses this to store
376 Undi interface context (Undi does not read or write this variable)
377 @param CpuAddr - Virtual address to be mapped!
378 @param NumBytes - size of memory to be mapped
379 @param Direction - direction of data flow for this memory's usage:
380 cpu->device, device->cpu or both ways
381 @param DeviceAddrPtr - pointer to return the mapped device address
385 SnpUndi32CallbackMap (
390 IN OUT UINT64 DeviceAddrPtr
393 EFI_PHYSICAL_ADDRESS
*DevAddrPtr
;
394 EFI_PCI_IO_PROTOCOL_OPERATION DirectionFlag
;
400 BuffSize
= (UINTN
) NumBytes
;
401 Snp
= (SNP_DRIVER
*) (UINTN
) UniqueId
;
402 DevAddrPtr
= (EFI_PHYSICAL_ADDRESS
*) (UINTN
) DeviceAddrPtr
;
410 case TO_AND_FROM_DEVICE
:
411 DirectionFlag
= EfiPciIoOperationBusMasterCommonBuffer
;
415 DirectionFlag
= EfiPciIoOperationBusMasterWrite
;
419 DirectionFlag
= EfiPciIoOperationBusMasterRead
;
425 // any non zero indicates error!
430 // find an unused map_list entry
432 for (Index
= 0; Index
< MAX_MAP_LENGTH
; Index
++) {
433 if (Snp
->MapList
[Index
].VirtualAddress
== 0) {
438 if (Index
>= MAX_MAP_LENGTH
) {
439 DEBUG ((EFI_D_INFO
, "SNP maplist is FULL\n"));
444 Snp
->MapList
[Index
].VirtualAddress
= (EFI_PHYSICAL_ADDRESS
) CpuAddr
;
446 Status
= Snp
->PciIo
->Map (
449 (VOID
*) (UINTN
) CpuAddr
,
452 &(Snp
->MapList
[Index
].MapCookie
)
454 if (Status
!= EFI_SUCCESS
) {
456 Snp
->MapList
[Index
].VirtualAddress
= 0;
463 This is a callback routine supplied to UNDI at undi_start time.
464 UNDI call this routine when it wants to unmap an address that was previously
465 mapped using map callback.
467 @param UniqueId This was supplied to UNDI at Undi_Start, SNP uses this to store.
468 Undi interface context (Undi does not read or write this variable)
469 @param CpuAddr Virtual address that was mapped!
470 @param NumBytes size of memory mapped
471 @param Direction direction of data flow for this memory's usage:
472 cpu->device, device->cpu or both ways
473 @param DeviceAddr the mapped device address
477 SnpUndi32CallbackUnmap (
488 Snp
= (SNP_DRIVER
*) (UINTN
) UniqueId
;
490 for (Index
= 0; Index
< MAX_MAP_LENGTH
; Index
++) {
491 if (Snp
->MapList
[Index
].VirtualAddress
== CpuAddr
) {
496 if (Index
>= MAX_MAP_LENGTH
)
498 DEBUG ((EFI_D_ERROR
, "SNP could not find a mapping, failed to unmap.\n"));
502 Snp
->PciIo
->Unmap (Snp
->PciIo
, Snp
->MapList
[Index
].MapCookie
);
503 Snp
->MapList
[Index
].VirtualAddress
= 0;
504 Snp
->MapList
[Index
].MapCookie
= NULL
;
509 This is a callback routine supplied to UNDI at undi_start time.
510 UNDI call this routine when it wants synchronize the virtual buffer contents
511 with the mapped buffer contents. The virtual and mapped buffers need not
512 correspond to the same physical memory (especially if the virtual address is
513 > 4GB). Depending on the direction for which the buffer is mapped, undi will
514 need to synchronize their contents whenever it writes to/reads from the buffer
515 using either the cpu address or the device address.
517 EFI does not provide a sync call, since virt=physical, we sould just do
518 the synchronization ourself here!
520 @param UniqueId This was supplied to UNDI at Undi_Start, SNP uses this to store
521 Undi interface context (Undi does not read or write this variable)
522 @param CpuAddr Virtual address that was mapped!
523 @param NumBytes size of memory mapped.
524 @param Direction direction of data flow for this memory's usage:
525 cpu->device, device->cpu or both ways.
526 @param DeviceAddr the mapped device address.
530 SnpUndi32CallbackSync (
538 if ((CpuAddr
== 0) || (DeviceAddr
== 0) || (NumBytes
== 0)) {
545 CopyMem ((UINT8
*) (UINTN
) CpuAddr
, (UINT8
*) (UINTN
) DeviceAddr
, NumBytes
);
549 CopyMem ((UINT8
*) (UINTN
) DeviceAddr
, (UINT8
*) (UINTN
) CpuAddr
, NumBytes
);