]>
Commit | Line | Data |
---|---|---|
878ddf1f | 1 | /*++\r |
3aaddf92 | 2 | Copyright (c) 2006, Intel Corporation\r |
3 | All rights reserved. This program and the accompanying materials\r | |
4 | are licensed and made available under the terms and conditions of the BSD License\r | |
5 | which accompanies this distribution. The full text of the license may be found at\r | |
6 | http://opensource.org/licenses/bsd-license.php\r | |
7 | \r | |
8 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r | |
9 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r | |
878ddf1f | 10 | \r |
11 | Module name:\r | |
12 | callback.c\r | |
13 | \r | |
14 | Abstract:\r | |
15 | This file contains two sets of callback routines for undi3.0 and undi3.1.\r | |
16 | the callback routines for Undi3.1 have an extra parameter UniqueId which\r | |
17 | stores the interface context for the NIC that snp is trying to talk..\r | |
18 | \r | |
19 | --*/\r | |
20 | \r | |
21 | \r | |
4cbd855e | 22 | #include "Snp.h"\r |
878ddf1f | 23 | \r |
24 | //\r | |
25 | // Global variables\r | |
26 | // these 2 global variables are used only for 3.0 undi. we could not place\r | |
27 | // them in the snp structure because we will not know which snp structure\r | |
28 | // in the callback context!\r | |
29 | //\r | |
30 | STATIC BOOLEAN mInitializeLock = TRUE;\r | |
31 | STATIC EFI_LOCK mLock;\r | |
32 | \r | |
33 | //\r | |
34 | // End Global variables\r | |
35 | //\r | |
878ddf1f | 36 | \r |
37 | VOID\r | |
38 | snp_undi32_callback_v2p_30 (\r | |
39 | IN UINT64 CpuAddr,\r | |
40 | IN OUT UINT64 DeviceAddrPtr\r | |
41 | )\r | |
42 | /*++\r | |
43 | \r | |
44 | Routine Description:\r | |
45 | This is a callback routine supplied to UNDI at undi_start time.\r | |
46 | UNDI call this routine with a virtual or CPU address that SNP provided\r | |
47 | to convert it to a physical or device address. Since EFI uses the identical\r | |
48 | mapping, this routine returns the physical address same as the virtual address\r | |
49 | for most of the addresses. an address above 4GB cannot generally be used as a\r | |
50 | device address, it needs to be mapped to a lower physical address. This routine\r | |
51 | does not call the map routine itself, but it assumes that the mapping was done\r | |
52 | at the time of providing the address to UNDI. This routine just looks up the\r | |
53 | address in a map table (which is the v2p structure chain)\r | |
54 | \r | |
55 | Arguments:\r | |
56 | CpuAddr - virtual address of a buffer\r | |
57 | DeviceAddrPtr - pointer to the physical address\r | |
58 | \r | |
59 | Returns:\r | |
60 | void - The DeviceAddrPtr will contain 0 in case of any error\r | |
61 | \r | |
62 | --*/\r | |
63 | {\r | |
64 | struct s_v2p *v2p;\r | |
65 | //\r | |
66 | // Do nothing if virtual address is zero or physical pointer is NULL.\r | |
67 | // No need to map if the virtual address is within 4GB limit since\r | |
68 | // EFI uses identical mapping\r | |
69 | //\r | |
70 | if ((CpuAddr == 0) || (DeviceAddrPtr == 0)) {\r | |
71 | DEBUG ((EFI_D_ERROR, "\nv2p: Null virtual address or physical pointer.\n"));\r | |
72 | return ;\r | |
73 | }\r | |
74 | \r | |
75 | if (CpuAddr < FOUR_GIGABYTES) {\r | |
76 | *(UINT64 *) (UINTN) DeviceAddrPtr = CpuAddr;\r | |
77 | return ;\r | |
78 | }\r | |
79 | //\r | |
80 | // SNP creates a vaddr tp paddr mapping at the time of calling undi with any\r | |
81 | // big address, this callback routine just looks up in the v2p list and\r | |
82 | // returns the physical address for any given virtual address.\r | |
83 | //\r | |
84 | if (find_v2p (&v2p, (VOID *) (UINTN) CpuAddr) != EFI_SUCCESS) {\r | |
85 | *(UINT64 *) (UINTN) DeviceAddrPtr = CpuAddr;\r | |
86 | } else {\r | |
87 | *(UINT64 *) (UINTN) DeviceAddrPtr = v2p->paddr;\r | |
88 | }\r | |
89 | }\r | |
90 | \r | |
91 | VOID\r | |
92 | snp_undi32_callback_block_30 (\r | |
93 | IN UINT32 Enable\r | |
94 | )\r | |
95 | /*++\r | |
96 | \r | |
97 | Routine Description:\r | |
98 | This is a callback routine supplied to UNDI at undi_start time.\r | |
99 | UNDI call this routine when it wants to have exclusive access to a critical\r | |
100 | section of the code/data\r | |
101 | \r | |
102 | Arguments:\r | |
103 | Enable - non-zero indicates acquire\r | |
104 | zero indicates release\r | |
105 | \r | |
106 | Returns:\r | |
107 | void\r | |
108 | --*/\r | |
109 | {\r | |
110 | //\r | |
111 | // tcpip was calling snp at tpl_notify and if we acquire a lock that was\r | |
112 | // created at a lower level (TPL_CALLBACK) it gives an assert!\r | |
113 | //\r | |
114 | if (mInitializeLock) {\r | |
115 | EfiInitializeLock (&mLock, EFI_TPL_NOTIFY);\r | |
116 | mInitializeLock = FALSE;\r | |
117 | }\r | |
118 | \r | |
119 | if (Enable != 0) {\r | |
120 | EfiAcquireLock (&mLock);\r | |
121 | } else {\r | |
122 | EfiReleaseLock (&mLock);\r | |
123 | }\r | |
124 | }\r | |
125 | \r | |
126 | VOID\r | |
127 | snp_undi32_callback_delay_30 (\r | |
128 | IN UINT64 MicroSeconds\r | |
129 | )\r | |
130 | /*++\r | |
131 | \r | |
132 | Routine Description:\r | |
133 | This is a callback routine supplied to UNDI at undi_start time.\r | |
134 | UNDI call this routine with the number of micro seconds when it wants to\r | |
135 | pause.\r | |
136 | \r | |
137 | Arguments:\r | |
138 | MicroSeconds - number of micro seconds to pause, ususlly multiple of 10\r | |
139 | \r | |
140 | Returns:\r | |
141 | void\r | |
142 | --*/\r | |
143 | {\r | |
144 | if (MicroSeconds != 0) {\r | |
145 | gBS->Stall ((UINTN) MicroSeconds);\r | |
146 | }\r | |
147 | }\r | |
148 | \r | |
149 | VOID\r | |
150 | snp_undi32_callback_memio_30 (\r | |
151 | IN UINT8 ReadOrWrite,\r | |
152 | IN UINT8 NumBytes,\r | |
153 | IN UINT64 Address,\r | |
154 | IN OUT UINT64 BufferAddr\r | |
155 | )\r | |
156 | /*++\r | |
157 | \r | |
158 | Routine Description:\r | |
159 | This is a callback routine supplied to UNDI at undi_start time.\r | |
160 | This is the IO routine for UNDI. This is not currently being used by UNDI3.0\r | |
161 | because Undi3.0 uses io/mem offsets relative to the beginning of the device\r | |
162 | io/mem address and so it needs to use the PCI_IO_FUNCTION that abstracts the\r | |
163 | start of the device's io/mem addresses. Since SNP cannot retrive the context\r | |
164 | of the undi3.0 interface it cannot use the PCI_IO_FUNCTION that specific for\r | |
165 | that NIC and uses one global IO functions structure, this does not work.\r | |
166 | This however works fine for EFI1.0 Undis because they use absolute addresses\r | |
167 | for io/mem access.\r | |
168 | \r | |
169 | Arguments:\r | |
170 | ReadOrWrite - indicates read or write, IO or Memory\r | |
171 | NumBytes - number of bytes to read or write\r | |
172 | Address - IO or memory address to read from or write to\r | |
173 | BufferAddr - memory location to read into or that contains the bytes\r | |
174 | to write\r | |
175 | \r | |
176 | Returns:\r | |
177 | \r | |
178 | --*/\r | |
179 | {\r | |
180 | EFI_PCI_IO_PROTOCOL_WIDTH Width;\r | |
181 | \r | |
182 | switch (NumBytes) {\r | |
183 | case 2:\r | |
1cc8ee78 | 184 | Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 1;\r |
878ddf1f | 185 | break;\r |
186 | \r | |
187 | case 4:\r | |
1cc8ee78 | 188 | Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 2;\r |
878ddf1f | 189 | break;\r |
190 | \r | |
191 | case 8:\r | |
1cc8ee78 | 192 | Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 3;\r |
878ddf1f | 193 | break;\r |
194 | \r | |
195 | default:\r | |
1cc8ee78 | 196 | Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 0;\r |
878ddf1f | 197 | }\r |
198 | \r | |
199 | switch (ReadOrWrite) {\r | |
200 | case PXE_IO_READ:\r | |
201 | mPciIoFncs->Io.Read (\r | |
202 | mPciIoFncs,\r | |
203 | Width,\r | |
204 | 1, // BAR 1, IO base address\r | |
205 | Address,\r | |
206 | 1, // count\r | |
207 | (VOID *) (UINTN) BufferAddr\r | |
208 | );\r | |
209 | break;\r | |
210 | \r | |
211 | case PXE_IO_WRITE:\r | |
212 | mPciIoFncs->Io.Write (\r | |
213 | mPciIoFncs,\r | |
214 | Width,\r | |
215 | 1, // BAR 1, IO base address\r | |
216 | Address,\r | |
217 | 1, // count\r | |
218 | (VOID *) (UINTN) BufferAddr\r | |
219 | );\r | |
220 | break;\r | |
221 | \r | |
222 | case PXE_MEM_READ:\r | |
223 | mPciIoFncs->Mem.Read (\r | |
224 | mPciIoFncs,\r | |
225 | Width,\r | |
226 | 0, // BAR 0, Memory base address\r | |
227 | Address,\r | |
228 | 1, // count\r | |
229 | (VOID *) (UINTN) BufferAddr\r | |
230 | );\r | |
231 | break;\r | |
232 | \r | |
233 | case PXE_MEM_WRITE:\r | |
234 | mPciIoFncs->Mem.Write (\r | |
235 | mPciIoFncs,\r | |
236 | Width,\r | |
237 | 0, // BAR 0, Memory base address\r | |
238 | Address,\r | |
239 | 1, // count\r | |
240 | (VOID *) (UINTN) BufferAddr\r | |
241 | );\r | |
242 | break;\r | |
243 | }\r | |
244 | \r | |
245 | return ;\r | |
246 | }\r | |
247 | //\r | |
248 | // New callbacks for 3.1:\r | |
249 | // there won't be a virtual2physical callback for UNDI 3.1 because undi3.1 uses\r | |
250 | // the MemMap call to map the required address by itself!\r | |
251 | //\r | |
252 | VOID\r | |
253 | snp_undi32_callback_block (\r | |
254 | IN UINT64 UniqueId,\r | |
255 | IN UINT32 Enable\r | |
256 | )\r | |
257 | /*++\r | |
258 | \r | |
259 | Routine Description:\r | |
260 | This is a callback routine supplied to UNDI3.1 at undi_start time.\r | |
261 | UNDI call this routine when it wants to have exclusive access to a critical\r | |
262 | section of the code/data\r | |
263 | \r | |
264 | Arguments:\r | |
265 | UniqueId - This was supplied to UNDI at Undi_Start, SNP uses this to store\r | |
266 | Undi interface context (Undi does not read or write this variable)\r | |
267 | Enable - non-zero indicates acquire\r | |
268 | zero indicates release\r | |
269 | \r | |
270 | Returns:\r | |
271 | void\r | |
272 | \r | |
273 | --*/\r | |
274 | {\r | |
275 | SNP_DRIVER *snp;\r | |
276 | \r | |
277 | snp = (SNP_DRIVER *) (UINTN) UniqueId;\r | |
278 | //\r | |
279 | // tcpip was calling snp at tpl_notify and when we acquire a lock that was\r | |
280 | // created at a lower level (TPL_CALLBACK) it gives an assert!\r | |
281 | //\r | |
282 | if (Enable != 0) {\r | |
283 | EfiAcquireLock (&snp->lock);\r | |
284 | } else {\r | |
285 | EfiReleaseLock (&snp->lock);\r | |
286 | }\r | |
287 | }\r | |
288 | \r | |
289 | VOID\r | |
290 | snp_undi32_callback_delay (\r | |
291 | IN UINT64 UniqueId,\r | |
292 | IN UINT64 MicroSeconds\r | |
293 | )\r | |
294 | /*++\r | |
295 | \r | |
296 | Routine Description:\r | |
297 | This is a callback routine supplied to UNDI at undi_start time.\r | |
298 | UNDI call this routine with the number of micro seconds when it wants to\r | |
299 | pause.\r | |
300 | \r | |
301 | Arguments:\r | |
302 | MicroSeconds - number of micro seconds to pause, ususlly multiple of 10\r | |
303 | \r | |
304 | Returns:\r | |
305 | void\r | |
306 | --*/\r | |
307 | {\r | |
308 | if (MicroSeconds != 0) {\r | |
309 | gBS->Stall ((UINTN) MicroSeconds);\r | |
310 | }\r | |
311 | }\r | |
312 | \r | |
313 | /*\r | |
314 | * IO routine for UNDI start CPB.\r | |
315 | */\r | |
316 | VOID\r | |
317 | snp_undi32_callback_memio (\r | |
318 | UINT64 UniqueId,\r | |
319 | UINT8 ReadOrWrite,\r | |
320 | UINT8 NumBytes,\r | |
321 | UINT64 Address,\r | |
322 | UINT64 BufferAddr\r | |
323 | )\r | |
324 | /*++\r | |
325 | \r | |
326 | Routine Description:\r | |
327 | This is a callback routine supplied to UNDI at undi_start time.\r | |
328 | This is the IO routine for UNDI3.1.\r | |
329 | \r | |
330 | Arguments:\r | |
331 | ReadOrWrite - indicates read or write, IO or Memory\r | |
332 | NumBytes - number of bytes to read or write\r | |
333 | Address - IO or memory address to read from or write to\r | |
334 | BufferAddr - memory location to read into or that contains the bytes\r | |
335 | to write\r | |
336 | \r | |
337 | Returns:\r | |
338 | \r | |
339 | --*/\r | |
340 | {\r | |
341 | SNP_DRIVER *snp;\r | |
342 | EFI_PCI_IO_PROTOCOL_WIDTH Width;\r | |
343 | \r | |
344 | snp = (SNP_DRIVER *) (UINTN) UniqueId;\r | |
345 | \r | |
1cc8ee78 | 346 | Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 0;\r |
878ddf1f | 347 | switch (NumBytes) {\r |
348 | case 2:\r | |
1cc8ee78 | 349 | Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 1;\r |
878ddf1f | 350 | break;\r |
351 | \r | |
352 | case 4:\r | |
1cc8ee78 | 353 | Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 2;\r |
878ddf1f | 354 | break;\r |
355 | \r | |
356 | case 8:\r | |
1cc8ee78 | 357 | Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 3;\r |
878ddf1f | 358 | break;\r |
359 | }\r | |
360 | \r | |
361 | switch (ReadOrWrite) {\r | |
362 | case PXE_IO_READ:\r | |
363 | snp->IoFncs->Io.Read (\r | |
364 | snp->IoFncs,\r | |
365 | Width,\r | |
366 | snp->IoBarIndex, // BAR 1 (for 32bit regs), IO base address\r | |
367 | Address,\r | |
368 | 1, // count\r | |
369 | (VOID *) (UINTN) BufferAddr\r | |
370 | );\r | |
371 | break;\r | |
372 | \r | |
373 | case PXE_IO_WRITE:\r | |
374 | snp->IoFncs->Io.Write (\r | |
375 | snp->IoFncs,\r | |
376 | Width,\r | |
377 | snp->IoBarIndex, // BAR 1 (for 32bit regs), IO base address\r | |
378 | Address,\r | |
379 | 1, // count\r | |
380 | (VOID *) (UINTN) BufferAddr\r | |
381 | );\r | |
382 | break;\r | |
383 | \r | |
384 | case PXE_MEM_READ:\r | |
385 | snp->IoFncs->Mem.Read (\r | |
386 | snp->IoFncs,\r | |
387 | Width,\r | |
388 | snp->MemoryBarIndex, // BAR 0, Memory base address\r | |
389 | Address,\r | |
390 | 1, // count\r | |
391 | (VOID *) (UINTN) BufferAddr\r | |
392 | );\r | |
393 | break;\r | |
394 | \r | |
395 | case PXE_MEM_WRITE:\r | |
396 | snp->IoFncs->Mem.Write (\r | |
397 | snp->IoFncs,\r | |
398 | Width,\r | |
399 | snp->MemoryBarIndex, // BAR 0, Memory base address\r | |
400 | Address,\r | |
401 | 1, // count\r | |
402 | (VOID *) (UINTN) BufferAddr\r | |
403 | );\r | |
404 | break;\r | |
405 | }\r | |
406 | \r | |
407 | return ;\r | |
408 | }\r | |
409 | \r | |
410 | VOID\r | |
411 | snp_undi32_callback_map (\r | |
412 | IN UINT64 UniqueId,\r | |
413 | IN UINT64 CpuAddr,\r | |
414 | IN UINT32 NumBytes,\r | |
415 | IN UINT32 Direction,\r | |
416 | IN OUT UINT64 DeviceAddrPtr\r | |
417 | )\r | |
418 | /*++\r | |
419 | \r | |
420 | Routine Description:\r | |
421 | This is a callback routine supplied to UNDI at undi_start time.\r | |
422 | UNDI call this routine when it has to map a CPU address to a device\r | |
423 | address.\r | |
424 | \r | |
425 | Arguments:\r | |
426 | UniqueId - This was supplied to UNDI at Undi_Start, SNP uses this to store\r | |
427 | Undi interface context (Undi does not read or write this variable)\r | |
428 | CpuAddr - Virtual address to be mapped!\r | |
429 | NumBytes - size of memory to be mapped\r | |
430 | Direction - direction of data flow for this memory's usage:\r | |
431 | cpu->device, device->cpu or both ways\r | |
432 | DeviceAddrPtr - pointer to return the mapped device address\r | |
433 | \r | |
434 | Returns:\r | |
435 | None\r | |
436 | \r | |
437 | --*/\r | |
438 | {\r | |
439 | EFI_PHYSICAL_ADDRESS *DevAddrPtr;\r | |
440 | EFI_PCI_IO_PROTOCOL_OPERATION DirectionFlag;\r | |
441 | UINTN BuffSize;\r | |
442 | SNP_DRIVER *snp;\r | |
443 | UINTN Index;\r | |
444 | EFI_STATUS Status;\r | |
445 | \r | |
446 | BuffSize = (UINTN) NumBytes;\r | |
447 | snp = (SNP_DRIVER *) (UINTN) UniqueId;\r | |
448 | DevAddrPtr = (EFI_PHYSICAL_ADDRESS *) (UINTN) DeviceAddrPtr;\r | |
449 | \r | |
450 | if (CpuAddr == 0) {\r | |
451 | *DevAddrPtr = 0;\r | |
452 | return ;\r | |
453 | }\r | |
454 | \r | |
455 | switch (Direction) {\r | |
456 | case TO_AND_FROM_DEVICE:\r | |
457 | DirectionFlag = EfiPciIoOperationBusMasterCommonBuffer;\r | |
458 | break;\r | |
459 | \r | |
460 | case FROM_DEVICE:\r | |
461 | DirectionFlag = EfiPciIoOperationBusMasterWrite;\r | |
462 | break;\r | |
463 | \r | |
464 | case TO_DEVICE:\r | |
465 | DirectionFlag = EfiPciIoOperationBusMasterRead;\r | |
466 | break;\r | |
467 | \r | |
468 | default:\r | |
469 | *DevAddrPtr = 0;\r | |
470 | //\r | |
471 | // any non zero indicates error!\r | |
472 | //\r | |
473 | return ;\r | |
474 | }\r | |
475 | //\r | |
476 | // find an unused map_list entry\r | |
477 | //\r | |
478 | for (Index = 0; Index < MAX_MAP_LENGTH; Index++) {\r | |
479 | if (snp->map_list[Index].virt == 0) {\r | |
480 | break;\r | |
481 | }\r | |
482 | }\r | |
483 | \r | |
484 | if (Index >= MAX_MAP_LENGTH) {\r | |
3aaddf92 | 485 | DEBUG ((EFI_D_INFO, "SNP maplist is FULL\n"));\r |
878ddf1f | 486 | *DevAddrPtr = 0;\r |
487 | return ;\r | |
488 | }\r | |
489 | \r | |
490 | snp->map_list[Index].virt = (EFI_PHYSICAL_ADDRESS) CpuAddr;\r | |
491 | \r | |
492 | Status = snp->IoFncs->Map (\r | |
493 | snp->IoFncs,\r | |
494 | DirectionFlag,\r | |
495 | (VOID *) (UINTN) CpuAddr,\r | |
496 | &BuffSize,\r | |
497 | DevAddrPtr,\r | |
498 | &(snp->map_list[Index].map_cookie)\r | |
499 | );\r | |
500 | if (Status != EFI_SUCCESS) {\r | |
501 | *DevAddrPtr = 0;\r | |
502 | snp->map_list[Index].virt = 0;\r | |
503 | }\r | |
504 | \r | |
505 | return ;\r | |
506 | }\r | |
507 | \r | |
508 | VOID\r | |
509 | snp_undi32_callback_unmap (\r | |
510 | IN UINT64 UniqueId,\r | |
511 | IN UINT64 CpuAddr,\r | |
512 | IN UINT32 NumBytes,\r | |
513 | IN UINT32 Direction,\r | |
514 | IN UINT64 DeviceAddr\r | |
515 | )\r | |
516 | /*++\r | |
517 | \r | |
518 | Routine Description:\r | |
519 | This is a callback routine supplied to UNDI at undi_start time.\r | |
520 | UNDI call this routine when it wants to unmap an address that was previously\r | |
521 | mapped using map callback\r | |
522 | \r | |
523 | Arguments:\r | |
524 | UniqueId - This was supplied to UNDI at Undi_Start, SNP uses this to store\r | |
525 | Undi interface context (Undi does not read or write this variable)\r | |
526 | CpuAddr - Virtual address that was mapped!\r | |
527 | NumBytes - size of memory mapped\r | |
528 | Direction- direction of data flow for this memory's usage:\r | |
529 | cpu->device, device->cpu or both ways\r | |
530 | DeviceAddr - the mapped device address\r | |
531 | \r | |
532 | Returns:\r | |
533 | \r | |
534 | --*/\r | |
535 | {\r | |
536 | SNP_DRIVER *snp;\r | |
537 | UINT16 Index;\r | |
538 | \r | |
539 | snp = (SNP_DRIVER *) (UINTN) UniqueId;\r | |
540 | \r | |
541 | for (Index = 0; Index < MAX_MAP_LENGTH; Index++) {\r | |
542 | if (snp->map_list[Index].virt == CpuAddr) {\r | |
543 | break;\r | |
544 | }\r | |
545 | }\r | |
546 | \r | |
547 | if (Index >= MAX_MAP_LENGTH)\r | |
548 | {\r | |
9cc655d5 | 549 | DEBUG ((EFI_D_ERROR, "SNP could not find a mapping, failed to unmap.\n"));\r |
878ddf1f | 550 | return ;\r |
551 | }\r | |
552 | \r | |
553 | snp->IoFncs->Unmap (snp->IoFncs, snp->map_list[Index].map_cookie);\r | |
554 | snp->map_list[Index].virt = 0;\r | |
555 | snp->map_list[Index].map_cookie = NULL;\r | |
556 | return ;\r | |
557 | }\r | |
558 | \r | |
559 | VOID\r | |
560 | snp_undi32_callback_sync (\r | |
561 | UINT64 UniqueId,\r | |
562 | UINT64 CpuAddr,\r | |
563 | UINT32 NumBytes,\r | |
564 | UINT32 Direction,\r | |
565 | UINT64 DeviceAddr\r | |
566 | )\r | |
567 | /*++\r | |
568 | \r | |
569 | Routine Description:\r | |
570 | This is a callback routine supplied to UNDI at undi_start time.\r | |
571 | UNDI call this routine when it wants synchronize the virtual buffer contents\r | |
572 | with the mapped buffer contents. The virtual and mapped buffers need not\r | |
573 | correspond to the same physical memory (especially if the virtual address is\r | |
574 | > 4GB). Depending on the direction for which the buffer is mapped, undi will\r | |
575 | need to synchronize their contents whenever it writes to/reads from the buffer\r | |
576 | using either the cpu address or the device address.\r | |
577 | \r | |
578 | EFI does not provide a sync call, since virt=physical, we sould just do\r | |
579 | the synchronization ourself here!\r | |
580 | \r | |
581 | Arguments:\r | |
582 | UniqueId - This was supplied to UNDI at Undi_Start, SNP uses this to store\r | |
583 | Undi interface context (Undi does not read or write this variable)\r | |
584 | CpuAddr - Virtual address that was mapped!\r | |
585 | NumBytes - size of memory mapped\r | |
586 | Direction- direction of data flow for this memory's usage:\r | |
587 | cpu->device, device->cpu or both ways\r | |
588 | DeviceAddr - the mapped device address\r | |
589 | \r | |
590 | Returns:\r | |
591 | \r | |
592 | --*/\r | |
593 | {\r | |
594 | if ((CpuAddr == 0) || (DeviceAddr == 0) || (NumBytes == 0)) {\r | |
595 | return ;\r | |
596 | \r | |
597 | }\r | |
598 | \r | |
599 | switch (Direction) {\r | |
600 | case FROM_DEVICE:\r | |
601 | CopyMem ((UINT8 *) (UINTN) CpuAddr, (UINT8 *) (UINTN) DeviceAddr, NumBytes);\r | |
602 | break;\r | |
603 | \r | |
604 | case TO_DEVICE:\r | |
605 | CopyMem ((UINT8 *) (UINTN) DeviceAddr, (UINT8 *) (UINTN) CpuAddr, NumBytes);\r | |
606 | break;\r | |
607 | }\r | |
608 | \r | |
609 | return ;\r | |
610 | }\r |