+++ /dev/null
-/** @file\r
- This file contains the callback routines for undi3.1.\r
- the callback routines for Undi3.1 have an extra parameter UniqueId which\r
- stores the interface context for the NIC that snp is trying to talk.\r
-\r
-Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
-SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "Snp.h"\r
-\r
-/**\r
- Acquire or release a lock of the exclusive access to a critical section of the\r
- code/data.\r
-\r
- This is a callback routine supplied to UNDI3.1 at undi_start time.\r
- New callbacks for 3.1: there won't be a virtual2physical callback for UNDI 3.1\r
- because undi3.1 uses the MemMap call to map the required address by itself!\r
-\r
- @param UniqueId This was supplied to UNDI at Undi_Start, SNP uses this to\r
- store Undi interface context (Undi does not read or write\r
- this variable).\r
- @param Enable Non-zero indicates acquire; Zero indicates release.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-SnpUndi32CallbackBlock (\r
- IN UINT64 UniqueId,\r
- IN UINT32 Enable\r
- )\r
-{\r
- SNP_DRIVER *Snp;\r
-\r
- Snp = (SNP_DRIVER *) (UINTN) UniqueId;\r
- //\r
- // tcpip was calling snp at tpl_notify and when we acquire a lock that was\r
- // created at a lower level (TPL_CALLBACK) it gives an assert!\r
- //\r
- if (Enable != 0) {\r
- EfiAcquireLock (&Snp->Lock);\r
- } else {\r
- EfiReleaseLock (&Snp->Lock);\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 UniqueId This was supplied to UNDI at Undi_Start, SNP uses this to\r
- store Undi interface context (Undi does not read or write\r
- this variable).\r
- @param MicroSeconds Number of micro seconds to pause, ususlly multiple of 10.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-SnpUndi32CallbackDelay (\r
- IN UINT64 UniqueId,\r
- IN UINT64 MicroSeconds\r
- )\r
-{\r
- if (MicroSeconds != 0) {\r
- gBS->Stall ((UINTN) MicroSeconds);\r
- }\r
-}\r
-\r
-/**\r
- IO routine for UNDI3.1.\r
-\r
- This is a callback routine supplied to UNDI at undi_start time.\r
-\r
- @param UniqueId This was supplied to UNDI at Undi_Start, SNP uses this\r
- to store Undi interface context (Undi does not read or\r
- write this variable).\r
- @param ReadOrWrite Indicates read or write, IO or Memory.\r
- @param NumBytes Number of bytes to read or write.\r
- @param MemOrPortAddr IO or memory address to read from or write to.\r
- @param BufferPtr Memory location to read into or that contains the bytes\r
- to write.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-SnpUndi32CallbackMemio (\r
- IN UINT64 UniqueId,\r
- IN UINT8 ReadOrWrite,\r
- IN UINT8 NumBytes,\r
- IN UINT64 MemOrPortAddr,\r
- IN OUT UINT64 BufferPtr\r
- )\r
-{\r
- SNP_DRIVER *Snp;\r
- EFI_PCI_IO_PROTOCOL_WIDTH Width;\r
-\r
- Snp = (SNP_DRIVER *) (UINTN) UniqueId;\r
-\r
- Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 0;\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
-\r
- switch (ReadOrWrite) {\r
- case PXE_IO_READ:\r
- Snp->PciIo->Io.Read (\r
- Snp->PciIo,\r
- Width,\r
- Snp->IoBarIndex, // BAR 1 (for 32bit regs), IO base address\r
- MemOrPortAddr,\r
- 1, // count\r
- (VOID *) (UINTN) BufferPtr\r
- );\r
- break;\r
-\r
- case PXE_IO_WRITE:\r
- Snp->PciIo->Io.Write (\r
- Snp->PciIo,\r
- Width,\r
- Snp->IoBarIndex, // BAR 1 (for 32bit regs), IO base address\r
- MemOrPortAddr,\r
- 1, // count\r
- (VOID *) (UINTN) BufferPtr\r
- );\r
- break;\r
-\r
- case PXE_MEM_READ:\r
- Snp->PciIo->Mem.Read (\r
- Snp->PciIo,\r
- Width,\r
- Snp->MemoryBarIndex, // BAR 0, Memory base address\r
- MemOrPortAddr,\r
- 1, // count\r
- (VOID *) (UINTN) BufferPtr\r
- );\r
- break;\r
-\r
- case PXE_MEM_WRITE:\r
- Snp->PciIo->Mem.Write (\r
- Snp->PciIo,\r
- Width,\r
- Snp->MemoryBarIndex, // BAR 0, Memory base address\r
- MemOrPortAddr,\r
- 1, // count\r
- (VOID *) (UINTN) BufferPtr\r
- );\r
- break;\r
- }\r
-\r
- return ;\r
-}\r
-\r
-/**\r
- Map a CPU address to a device address.\r
-\r
- This is a callback routine supplied to UNDI at undi_start time.\r
-\r
- @param UniqueId This was supplied to UNDI at Undi_Start, SNP uses this to\r
- store Undi interface context (Undi does not read or write\r
- this variable).\r
- @param CpuAddr Virtual address to be mapped.\r
- @param NumBytes Size of memory to be mapped.\r
- @param Direction Direction of data flow for this memory's usage:\r
- cpu->device, device->cpu or both ways.\r
- @param DeviceAddrPtr Pointer to return the mapped device address.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-SnpUndi32CallbackMap (\r
- IN UINT64 UniqueId,\r
- IN UINT64 CpuAddr,\r
- IN UINT32 NumBytes,\r
- IN UINT32 Direction,\r
- IN OUT UINT64 DeviceAddrPtr\r
- )\r
-{\r
- EFI_PHYSICAL_ADDRESS *DevAddrPtr;\r
- EFI_PCI_IO_PROTOCOL_OPERATION DirectionFlag;\r
- UINTN BuffSize;\r
- SNP_DRIVER *Snp;\r
- UINTN Index;\r
- EFI_STATUS Status;\r
-\r
- BuffSize = (UINTN) NumBytes;\r
- Snp = (SNP_DRIVER *) (UINTN) UniqueId;\r
- DevAddrPtr = (EFI_PHYSICAL_ADDRESS *) (UINTN) DeviceAddrPtr;\r
-\r
- if (CpuAddr == 0) {\r
- *DevAddrPtr = 0;\r
- return ;\r
- }\r
-\r
- switch (Direction) {\r
- case TO_AND_FROM_DEVICE:\r
- DirectionFlag = EfiPciIoOperationBusMasterCommonBuffer;\r
- break;\r
-\r
- case FROM_DEVICE:\r
- DirectionFlag = EfiPciIoOperationBusMasterWrite;\r
- break;\r
-\r
- case TO_DEVICE:\r
- DirectionFlag = EfiPciIoOperationBusMasterRead;\r
- break;\r
-\r
- default:\r
- *DevAddrPtr = 0;\r
- //\r
- // any non zero indicates error!\r
- //\r
- return ;\r
- }\r
- //\r
- // find an unused map_list entry\r
- //\r
- for (Index = 0; Index < MAX_MAP_LENGTH; Index++) {\r
- if (Snp->MapList[Index].VirtualAddress == 0) {\r
- break;\r
- }\r
- }\r
-\r
- if (Index >= MAX_MAP_LENGTH) {\r
- DEBUG ((EFI_D_INFO, "SNP maplist is FULL\n"));\r
- *DevAddrPtr = 0;\r
- return ;\r
- }\r
-\r
- Snp->MapList[Index].VirtualAddress = (EFI_PHYSICAL_ADDRESS) CpuAddr;\r
-\r
- Status = Snp->PciIo->Map (\r
- Snp->PciIo,\r
- DirectionFlag,\r
- (VOID *) (UINTN) CpuAddr,\r
- &BuffSize,\r
- DevAddrPtr,\r
- &(Snp->MapList[Index].MapCookie)\r
- );\r
- if (Status != EFI_SUCCESS) {\r
- *DevAddrPtr = 0;\r
- Snp->MapList[Index].VirtualAddress = 0;\r
- }\r
-\r
- return ;\r
-}\r
-\r
-/**\r
- Unmap an address that was previously mapped using map callback.\r
-\r
- This is a callback routine supplied to UNDI at undi_start time.\r
-\r
- @param UniqueId This was supplied to UNDI at Undi_Start, SNP uses this to\r
- store. Undi interface context (Undi does not read or write\r
- this variable).\r
- @param CpuAddr Virtual address that was mapped.\r
- @param NumBytes Size of memory mapped.\r
- @param Direction Direction of data flow for this memory's usage:\r
- cpu->device, device->cpu or both ways.\r
- @param DeviceAddr The mapped device address.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-SnpUndi32CallbackUnmap (\r
- IN UINT64 UniqueId,\r
- IN UINT64 CpuAddr,\r
- IN UINT32 NumBytes,\r
- IN UINT32 Direction,\r
- IN UINT64 DeviceAddr\r
- )\r
-{\r
- SNP_DRIVER *Snp;\r
- UINT16 Index;\r
-\r
- Snp = (SNP_DRIVER *) (UINTN) UniqueId;\r
-\r
- for (Index = 0; Index < MAX_MAP_LENGTH; Index++) {\r
- if (Snp->MapList[Index].VirtualAddress == CpuAddr) {\r
- break;\r
- }\r
- }\r
-\r
- if (Index >= MAX_MAP_LENGTH) {\r
- DEBUG ((EFI_D_ERROR, "SNP could not find a mapping, failed to unmap.\n"));\r
- return ;\r
- }\r
-\r
- Snp->PciIo->Unmap (Snp->PciIo, Snp->MapList[Index].MapCookie);\r
- Snp->MapList[Index].VirtualAddress = 0;\r
- Snp->MapList[Index].MapCookie = NULL;\r
- return ;\r
-}\r
-\r
-/**\r
- Synchronize the virtual buffer contents with the mapped buffer contents.\r
-\r
- This is a callback routine supplied to UNDI at undi_start time. The virtual\r
- and mapped buffers need not correspond to the same physical memory (especially\r
- if the virtual address is > 4GB). Depending on the direction for which the\r
- buffer is mapped, undi will need to synchronize their contents whenever it\r
- writes to/reads from the buffer using either the cpu address or the device\r
- address.\r
- EFI does not provide a sync call since virt=physical, we should just do the\r
- synchronization ourselves here.\r
-\r
- @param UniqueId This was supplied to UNDI at Undi_Start, SNP uses this to\r
- store Undi interface context (Undi does not read or write\r
- this variable).\r
- @param CpuAddr Virtual address that was mapped.\r
- @param NumBytes Size of memory mapped.\r
- @param Direction Direction of data flow for this memory's usage:\r
- cpu->device, device->cpu or both ways.\r
- @param DeviceAddr The mapped device address.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-SnpUndi32CallbackSync (\r
- IN UINT64 UniqueId,\r
- IN UINT64 CpuAddr,\r
- IN UINT32 NumBytes,\r
- IN UINT32 Direction,\r
- IN UINT64 DeviceAddr\r
- )\r
-{\r
- if ((CpuAddr == 0) || (DeviceAddr == 0) || (NumBytes == 0)) {\r
- return ;\r
-\r
- }\r
-\r
- switch (Direction) {\r
- case FROM_DEVICE:\r
- CopyMem ((UINT8 *) (UINTN) CpuAddr, (UINT8 *) (UINTN) DeviceAddr, NumBytes);\r
- break;\r
-\r
- case TO_DEVICE:\r
- CopyMem ((UINT8 *) (UINTN) DeviceAddr, (UINT8 *) (UINTN) CpuAddr, NumBytes);\r
- break;\r
- }\r
-\r
- return ;\r
-}\r