]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/SnpDxe/Callback.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Universal / Network / SnpDxe / Callback.c
CommitLineData
fb0b259e 1/** @file\r
c4a7d208 2 This file contains the callback routines for undi3.1.\r
fb0b259e 3 the callback routines for Undi3.1 have an extra parameter UniqueId which\r
4 stores the interface context for the NIC that snp is trying to talk.\r
5\r
c4a7d208 6Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
9d510e61 7SPDX-License-Identifier: BSD-2-Clause-Patent\r
5e7e4fad 8\r
fb0b259e 9**/\r
5e7e4fad 10\r
11#include "Snp.h"\r
12\r
4cda7726 13/**\r
9c9f5859 14 Acquire or release a lock of the exclusive access to a critical section of the\r
15 code/data.\r
16\r
4cda7726 17 This is a callback routine supplied to UNDI3.1 at undi_start time.\r
f3816027 18 New callbacks for 3.1: there won't be a virtual2physical callback for UNDI 3.1\r
9c9f5859 19 because undi3.1 uses the MemMap call to map the required address by itself!\r
4cda7726 20\r
9c9f5859 21 @param UniqueId This was supplied to UNDI at Undi_Start, SNP uses this to\r
f3816027 22 store Undi interface context (Undi does not read or write\r
23 this variable).\r
9c9f5859 24 @param Enable Non-zero indicates acquire; Zero indicates release.\r
f3816027 25\r
4cda7726 26**/\r
5e7e4fad 27VOID\r
9c9f5859 28EFIAPI\r
4cda7726 29SnpUndi32CallbackBlock (\r
5e7e4fad 30 IN UINT64 UniqueId,\r
31 IN UINT32 Enable\r
32 )\r
5e7e4fad 33{\r
4cda7726 34 SNP_DRIVER *Snp;\r
5e7e4fad 35\r
4cda7726 36 Snp = (SNP_DRIVER *) (UINTN) UniqueId;\r
5e7e4fad 37 //\r
38 // tcpip was calling snp at tpl_notify and when we acquire a lock that was\r
39 // created at a lower level (TPL_CALLBACK) it gives an assert!\r
40 //\r
41 if (Enable != 0) {\r
4cda7726 42 EfiAcquireLock (&Snp->Lock);\r
5e7e4fad 43 } else {\r
4cda7726 44 EfiReleaseLock (&Snp->Lock);\r
5e7e4fad 45 }\r
46}\r
47\r
4cda7726 48/**\r
f3816027 49 Delay MicroSeconds of micro seconds.\r
9c9f5859 50\r
4cda7726 51 This is a callback routine supplied to UNDI at undi_start time.\r
4cda7726 52\r
53 @param UniqueId This was supplied to UNDI at Undi_Start, SNP uses this to\r
f3816027 54 store Undi interface context (Undi does not read or write\r
55 this variable).\r
9c9f5859 56 @param MicroSeconds Number of micro seconds to pause, ususlly multiple of 10.\r
f3816027 57\r
4cda7726 58**/\r
5e7e4fad 59VOID\r
9c9f5859 60EFIAPI\r
4cda7726 61SnpUndi32CallbackDelay (\r
5e7e4fad 62 IN UINT64 UniqueId,\r
63 IN UINT64 MicroSeconds\r
64 )\r
5e7e4fad 65{\r
66 if (MicroSeconds != 0) {\r
67 gBS->Stall ((UINTN) MicroSeconds);\r
68 }\r
69}\r
70\r
4cda7726 71/**\r
9c9f5859 72 IO routine for UNDI3.1.\r
73\r
4cda7726 74 This is a callback routine supplied to UNDI at undi_start time.\r
9c9f5859 75\r
76 @param UniqueId This was supplied to UNDI at Undi_Start, SNP uses this\r
77 to store Undi interface context (Undi does not read or\r
78 write this variable).\r
f3816027 79 @param ReadOrWrite Indicates read or write, IO or Memory.\r
80 @param NumBytes Number of bytes to read or write.\r
4cda7726 81 @param MemOrPortAddr IO or memory address to read from or write to.\r
f3816027 82 @param BufferPtr Memory location to read into or that contains the bytes\r
9c9f5859 83 to write.\r
f3816027 84\r
4cda7726 85**/\r
5e7e4fad 86VOID\r
9c9f5859 87EFIAPI\r
4cda7726 88SnpUndi32CallbackMemio (\r
89 IN UINT64 UniqueId,\r
90 IN UINT8 ReadOrWrite,\r
91 IN UINT8 NumBytes,\r
92 IN UINT64 MemOrPortAddr,\r
93 IN OUT UINT64 BufferPtr\r
5e7e4fad 94 )\r
5e7e4fad 95{\r
4cda7726 96 SNP_DRIVER *Snp;\r
5e7e4fad 97 EFI_PCI_IO_PROTOCOL_WIDTH Width;\r
98\r
4cda7726 99 Snp = (SNP_DRIVER *) (UINTN) UniqueId;\r
5e7e4fad 100\r
101 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 0;\r
102 switch (NumBytes) {\r
103 case 2:\r
104 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 1;\r
105 break;\r
106\r
107 case 4:\r
108 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 2;\r
109 break;\r
110\r
111 case 8:\r
112 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 3;\r
113 break;\r
114 }\r
115\r
116 switch (ReadOrWrite) {\r
117 case PXE_IO_READ:\r
4cda7726 118 Snp->PciIo->Io.Read (\r
119 Snp->PciIo,\r
120 Width,\r
121 Snp->IoBarIndex, // BAR 1 (for 32bit regs), IO base address\r
122 MemOrPortAddr,\r
123 1, // count\r
124 (VOID *) (UINTN) BufferPtr\r
125 );\r
5e7e4fad 126 break;\r
127\r
128 case PXE_IO_WRITE:\r
4cda7726 129 Snp->PciIo->Io.Write (\r
130 Snp->PciIo,\r
131 Width,\r
132 Snp->IoBarIndex, // BAR 1 (for 32bit regs), IO base address\r
133 MemOrPortAddr,\r
134 1, // count\r
135 (VOID *) (UINTN) BufferPtr\r
136 );\r
5e7e4fad 137 break;\r
138\r
139 case PXE_MEM_READ:\r
4cda7726 140 Snp->PciIo->Mem.Read (\r
141 Snp->PciIo,\r
5e7e4fad 142 Width,\r
4cda7726 143 Snp->MemoryBarIndex, // BAR 0, Memory base address\r
144 MemOrPortAddr,\r
5e7e4fad 145 1, // count\r
4cda7726 146 (VOID *) (UINTN) BufferPtr\r
5e7e4fad 147 );\r
148 break;\r
149\r
150 case PXE_MEM_WRITE:\r
4cda7726 151 Snp->PciIo->Mem.Write (\r
152 Snp->PciIo,\r
5e7e4fad 153 Width,\r
4cda7726 154 Snp->MemoryBarIndex, // BAR 0, Memory base address\r
155 MemOrPortAddr,\r
5e7e4fad 156 1, // count\r
4cda7726 157 (VOID *) (UINTN) BufferPtr\r
5e7e4fad 158 );\r
159 break;\r
160 }\r
161\r
162 return ;\r
163}\r
164\r
4cda7726 165/**\r
9c9f5859 166 Map a CPU address to a device address.\r
f3816027 167\r
4cda7726 168 This is a callback routine supplied to UNDI at undi_start time.\r
4cda7726 169\r
f3816027 170 @param UniqueId This was supplied to UNDI at Undi_Start, SNP uses this to\r
171 store Undi interface context (Undi does not read or write\r
172 this variable).\r
173 @param CpuAddr Virtual address to be mapped.\r
174 @param NumBytes Size of memory to be mapped.\r
175 @param Direction Direction of data flow for this memory's usage:\r
176 cpu->device, device->cpu or both ways.\r
177 @param DeviceAddrPtr Pointer to return the mapped device address.\r
4cda7726 178\r
179**/\r
5e7e4fad 180VOID\r
9c9f5859 181EFIAPI\r
4cda7726 182SnpUndi32CallbackMap (\r
5e7e4fad 183 IN UINT64 UniqueId,\r
184 IN UINT64 CpuAddr,\r
185 IN UINT32 NumBytes,\r
186 IN UINT32 Direction,\r
187 IN OUT UINT64 DeviceAddrPtr\r
188 )\r
5e7e4fad 189{\r
190 EFI_PHYSICAL_ADDRESS *DevAddrPtr;\r
191 EFI_PCI_IO_PROTOCOL_OPERATION DirectionFlag;\r
192 UINTN BuffSize;\r
4cda7726 193 SNP_DRIVER *Snp;\r
5e7e4fad 194 UINTN Index;\r
195 EFI_STATUS Status;\r
196\r
197 BuffSize = (UINTN) NumBytes;\r
4cda7726 198 Snp = (SNP_DRIVER *) (UINTN) UniqueId;\r
5e7e4fad 199 DevAddrPtr = (EFI_PHYSICAL_ADDRESS *) (UINTN) DeviceAddrPtr;\r
200\r
201 if (CpuAddr == 0) {\r
202 *DevAddrPtr = 0;\r
203 return ;\r
204 }\r
205\r
206 switch (Direction) {\r
207 case TO_AND_FROM_DEVICE:\r
208 DirectionFlag = EfiPciIoOperationBusMasterCommonBuffer;\r
209 break;\r
210\r
211 case FROM_DEVICE:\r
212 DirectionFlag = EfiPciIoOperationBusMasterWrite;\r
213 break;\r
214\r
215 case TO_DEVICE:\r
216 DirectionFlag = EfiPciIoOperationBusMasterRead;\r
217 break;\r
218\r
219 default:\r
220 *DevAddrPtr = 0;\r
221 //\r
222 // any non zero indicates error!\r
223 //\r
224 return ;\r
225 }\r
226 //\r
227 // find an unused map_list entry\r
228 //\r
229 for (Index = 0; Index < MAX_MAP_LENGTH; Index++) {\r
4cda7726 230 if (Snp->MapList[Index].VirtualAddress == 0) {\r
5e7e4fad 231 break;\r
232 }\r
233 }\r
234\r
235 if (Index >= MAX_MAP_LENGTH) {\r
236 DEBUG ((EFI_D_INFO, "SNP maplist is FULL\n"));\r
237 *DevAddrPtr = 0;\r
238 return ;\r
239 }\r
240\r
4cda7726 241 Snp->MapList[Index].VirtualAddress = (EFI_PHYSICAL_ADDRESS) CpuAddr;\r
5e7e4fad 242\r
4cda7726 243 Status = Snp->PciIo->Map (\r
244 Snp->PciIo,\r
245 DirectionFlag,\r
246 (VOID *) (UINTN) CpuAddr,\r
247 &BuffSize,\r
248 DevAddrPtr,\r
249 &(Snp->MapList[Index].MapCookie)\r
250 );\r
5e7e4fad 251 if (Status != EFI_SUCCESS) {\r
4cda7726 252 *DevAddrPtr = 0;\r
253 Snp->MapList[Index].VirtualAddress = 0;\r
5e7e4fad 254 }\r
255\r
256 return ;\r
257}\r
258\r
4cda7726 259/**\r
9c9f5859 260 Unmap an address that was previously mapped using map callback.\r
261\r
4cda7726 262 This is a callback routine supplied to UNDI at undi_start time.\r
4cda7726 263\r
9c9f5859 264 @param UniqueId This was supplied to UNDI at Undi_Start, SNP uses this to\r
f3816027 265 store. Undi interface context (Undi does not read or write\r
266 this variable).\r
267 @param CpuAddr Virtual address that was mapped.\r
268 @param NumBytes Size of memory mapped.\r
9c9f5859 269 @param Direction Direction of data flow for this memory's usage:\r
f3816027 270 cpu->device, device->cpu or both ways.\r
271 @param DeviceAddr The mapped device address.\r
4cda7726 272\r
273**/\r
5e7e4fad 274VOID\r
9c9f5859 275EFIAPI\r
4cda7726 276SnpUndi32CallbackUnmap (\r
5e7e4fad 277 IN UINT64 UniqueId,\r
278 IN UINT64 CpuAddr,\r
279 IN UINT32 NumBytes,\r
280 IN UINT32 Direction,\r
281 IN UINT64 DeviceAddr\r
282 )\r
5e7e4fad 283{\r
4cda7726 284 SNP_DRIVER *Snp;\r
5e7e4fad 285 UINT16 Index;\r
286\r
4cda7726 287 Snp = (SNP_DRIVER *) (UINTN) UniqueId;\r
5e7e4fad 288\r
289 for (Index = 0; Index < MAX_MAP_LENGTH; Index++) {\r
4cda7726 290 if (Snp->MapList[Index].VirtualAddress == CpuAddr) {\r
5e7e4fad 291 break;\r
292 }\r
293 }\r
294\r
f3816027 295 if (Index >= MAX_MAP_LENGTH) {\r
5e7e4fad 296 DEBUG ((EFI_D_ERROR, "SNP could not find a mapping, failed to unmap.\n"));\r
297 return ;\r
298 }\r
299\r
4cda7726 300 Snp->PciIo->Unmap (Snp->PciIo, Snp->MapList[Index].MapCookie);\r
301 Snp->MapList[Index].VirtualAddress = 0;\r
302 Snp->MapList[Index].MapCookie = NULL;\r
5e7e4fad 303 return ;\r
304}\r
305\r
9c9f5859 306/**\r
307 Synchronize the virtual buffer contents with the mapped buffer contents.\r
308\r
f3816027 309 This is a callback routine supplied to UNDI at undi_start time. The virtual\r
9c9f5859 310 and mapped buffers need not correspond to the same physical memory (especially\r
311 if the virtual address is > 4GB). Depending on the direction for which the\r
312 buffer is mapped, undi will need to synchronize their contents whenever it\r
313 writes to/reads from the buffer using either the cpu address or the device\r
314 address.\r
315 EFI does not provide a sync call since virt=physical, we should just do the\r
316 synchronization ourselves here.\r
317\r
318 @param UniqueId This was supplied to UNDI at Undi_Start, SNP uses this to\r
f3816027 319 store Undi interface context (Undi does not read or write\r
320 this variable).\r
321 @param CpuAddr Virtual address that was mapped.\r
322 @param NumBytes Size of memory mapped.\r
323 @param Direction Direction of data flow for this memory's usage:\r
4cda7726 324 cpu->device, device->cpu or both ways.\r
f3816027 325 @param DeviceAddr The mapped device address.\r
4cda7726 326\r
327**/\r
5e7e4fad 328VOID\r
9c9f5859 329EFIAPI\r
4cda7726 330SnpUndi32CallbackSync (\r
331 IN UINT64 UniqueId,\r
332 IN UINT64 CpuAddr,\r
333 IN UINT32 NumBytes,\r
334 IN UINT32 Direction,\r
335 IN UINT64 DeviceAddr\r
5e7e4fad 336 )\r
5e7e4fad 337{\r
338 if ((CpuAddr == 0) || (DeviceAddr == 0) || (NumBytes == 0)) {\r
339 return ;\r
340\r
341 }\r
342\r
343 switch (Direction) {\r
344 case FROM_DEVICE:\r
345 CopyMem ((UINT8 *) (UINTN) CpuAddr, (UINT8 *) (UINTN) DeviceAddr, NumBytes);\r
346 break;\r
347\r
348 case TO_DEVICE:\r
349 CopyMem ((UINT8 *) (UINTN) DeviceAddr, (UINT8 *) (UINTN) CpuAddr, NumBytes);\r
350 break;\r
351 }\r
352\r
353 return ;\r
354}\r