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