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