VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/NetworkPkg/SnpDxe/Callback.c@ 99404

Last change on this file since 99404 was 99404, checked in by vboxsync, 20 months ago

Devices/EFI/FirmwareNew: Update to edk2-stable202302 and make it build, bugref:4643

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette