-//\r
-// Global variables\r
-// these 2 global variables are used only for 3.0 undi. we could not place\r
-// them in the snp structure because we will not know which snp structure\r
-// in the callback context!\r
-//\r
-BOOLEAN mInitializeLock = TRUE;\r
-EFI_LOCK mLock;\r
-\r
-//\r
-// End Global variables\r
-//\r
-extern EFI_PCI_IO_PROTOCOL *mPciIo;\r
-\r
-/**\r
- Convert a virtual or CPU address provided by SNP to a physical or device\r
- address.\r
-\r
- This is a callback routine supplied to UNDI at undi_start time. Since EFI uses\r
- the identical mapping, this routine returns the physical address same as the\r
- virtual address for most of the addresses. an address above 4GB cannot\r
- generally be used as a device address, it needs to be mapped to a lower\r
- physical address. This routine does not call the map routine itself, but it\r
- assumes that the mapping was done at the time of providing the address to\r
- UNDI. This routine just looks up the address in a map table (which is the v2p\r
- structure chain).\r
-\r
- @param CpuAddr Virtual address.\r
- @param DeviceAddrPtr Pointer to the physical address, or 0 in case of any\r
- error.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-SnpUndi32CallbackV2p30 (\r
- IN UINT64 CpuAddr,\r
- IN OUT UINT64 DeviceAddrPtr\r
- )\r
-{\r
- V2P *V2p;\r
- //\r
- // Do nothing if virtual address is zero or physical pointer is NULL.\r
- // No need to map if the virtual address is within 4GB limit since\r
- // EFI uses identical mapping\r
- //\r
- if ((CpuAddr == 0) || (DeviceAddrPtr == 0)) {\r
- DEBUG ((EFI_D_NET, "\nv2p: Null virtual address or physical pointer.\n"));\r
- return ;\r
- }\r
-\r
- if (CpuAddr < FOUR_GIGABYTES) {\r
- *(UINT64 *) (UINTN) DeviceAddrPtr = CpuAddr;\r
- return ;\r
- }\r
- //\r
- // SNP creates a vaddr tp paddr mapping at the time of calling undi with any\r
- // big address, this callback routine just looks up in the v2p list and\r
- // returns the physical address for any given virtual address.\r
- //\r
- if (FindV2p (&V2p, (VOID *) (UINTN) CpuAddr) != EFI_SUCCESS) {\r
- *(UINT64 *) (UINTN) DeviceAddrPtr = CpuAddr;\r
- } else {\r
- *(UINT64 *) (UINTN) DeviceAddrPtr = V2p->PhysicalAddress;\r
- }\r
-}\r
-\r
-/**\r
- Acquire or release a lock of an exclusive access to a critical section of the\r
- code/data.\r
-\r
- This is a callback routine supplied to UNDI at undi_start time.\r
-\r
- @param Enable Non-zero indicates acquire; Zero indicates release.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-SnpUndi32CallbackBlock30 (\r
- IN UINT32 Enable\r
- )\r
-{\r
- //\r
- // tcpip was calling snp at tpl_notify and if we acquire a lock that was\r
- // created at a lower level (TPL_CALLBACK) it gives an assert!\r
- //\r
- if (mInitializeLock) {\r
- EfiInitializeLock (&mLock, TPL_NOTIFY);\r
- mInitializeLock = FALSE;\r
- }\r
-\r
- if (Enable != 0) {\r
- EfiAcquireLock (&mLock);\r
- } else {\r
- EfiReleaseLock (&mLock);\r
- }\r
-}\r
-\r
-/**\r
- Delay MicroSeconds of micro seconds.\r
-\r
- This is a callback routine supplied to UNDI at undi_start time.\r
-\r
- @param MicroSeconds Number of micro seconds to pause, ususlly multiple of 10.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-SnpUndi32CallbackDelay30 (\r
- IN UINT64 MicroSeconds\r
- )\r
-{\r
- if (MicroSeconds != 0) {\r
- gBS->Stall ((UINTN) MicroSeconds);\r
- }\r
-}\r
-\r
-/**\r
- IO routine for UNDI.\r
-\r
- This is a callback routine supplied to UNDI at undi_start time. This is not\r
- currently being used by UNDI3.0 because Undi3.0 uses io/mem offsets relative\r
- to the beginning of the device io/mem address and so it needs to use the\r
- PCI_IO_FUNCTION that abstracts the start of the device's io/mem addresses.\r
- Since SNP cannot retrive the context of the undi3.0 interface it cannot use\r
- the PCI_IO_FUNCTION that specific for that NIC and uses one global IO\r
- functions structure, this does not work. This however works fine for EFI1.0\r
- Undis because they use absolute addresses for io/mem access.\r
-\r
- @param ReadOrWrite Indicates read or write, IO or Memory.\r
- @param NumBytes Number of bytes to read or write.\r
- @param Address IO or memory address to read from or write to.\r
- @param BufferAddr Memory location to read into or that contains the bytes to\r
- write.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-SnpUndi32CallbackMemio30 (\r
- IN UINT8 ReadOrWrite,\r
- IN UINT8 NumBytes,\r
- IN UINT64 Address,\r
- IN OUT UINT64 BufferAddr\r
- )\r
-{\r
- EFI_PCI_IO_PROTOCOL_WIDTH Width;\r
-\r
- switch (NumBytes) {\r
- case 2:\r
- Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 1;\r
- break;\r
-\r
- case 4:\r
- Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 2;\r
- break;\r
-\r
- case 8:\r
- Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 3;\r
- break;\r
-\r
- default:\r
- Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 0;\r
- }\r
-\r
- switch (ReadOrWrite) {\r
- case PXE_IO_READ:\r
- mPciIo->Io.Read (\r
- mPciIo,\r
- Width,\r
- 1, // BAR 1, IO base address\r
- Address,\r
- 1, // count\r
- (VOID *) (UINTN) BufferAddr\r
- );\r
- break;\r
-\r
- case PXE_IO_WRITE:\r
- mPciIo->Io.Write (\r
- mPciIo,\r
- Width,\r
- 1, // BAR 1, IO base address\r
- Address,\r
- 1, // count\r
- (VOID *) (UINTN) BufferAddr\r
- );\r
- break;\r
-\r
- case PXE_MEM_READ:\r
- mPciIo->Mem.Read (\r
- mPciIo,\r
- Width,\r
- 0, // BAR 0, Memory base address\r
- Address,\r
- 1, // count\r
- (VOID *) (UINTN) BufferAddr\r
- );\r
- break;\r
-\r
- case PXE_MEM_WRITE:\r
- mPciIo->Mem.Write (\r
- mPciIo,\r
- Width,\r
- 0, // BAR 0, Memory base address\r
- Address,\r
- 1, // count\r
- (VOID *) (UINTN) BufferAddr\r
- );\r
- break;\r
- }\r
-\r
- return ;\r
-}\r
-\r