]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Compatibility/DeviceIoToPciRootBridgeIoThunk/DeviceIoToPciRootBridgeIoThunk.c
add in DeviceIoToPciRootBridgeIoThunk.
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / DeviceIoToPciRootBridgeIoThunk / DeviceIoToPciRootBridgeIoThunk.c
CommitLineData
fd4ae733 1/** @file\r
2Module Layer Device I/O on top of PCI Root Bridge I/O (Segment 0)\r
3\r
4Device I/O is on list of deprecated protocols for UEFI 2.0 and later.\r
5This module module layers Device I/O on top of PCI Root Bridge I/O (Segment 0)\r
6 Use if:\r
7 There are no R8.x modules present that produces Device I/O\r
8 EFI drivers included that consume Device I/O\r
9 Platform required to support EFI drivers that consume Device I/O\r
10 Platform required to support EFI applications that consume Device I/O\r
11\r
12Copyright (c) 2008 Intel Corporation. <BR>\r
13All rights reserved. This program and the accompanying materials\r
14are licensed and made available under the terms and conditions of the BSD License\r
15which accompanies this distribution. The full text of the license may be found at\r
16http://opensource.org/licenses/bsd-license.php\r
17\r
18THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
19WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
20\r
21**/\r
22\r
23#include <PiDxe.h>\r
24#include <IndustryStandard/Pci22.h>\r
25#include <Protocol/DeviceIo.h>\r
26#include <Protocol/PciRootBridgeIo.h>\r
27#include <Library/BaseLib.h>\r
28#include <Library/BaseMemoryLib.h>\r
29#include <Library/DebugLib.h>\r
30#include <Library/UefiBootServicesTableLib.h>\r
31#include <Library/UefiDriverEntryPoint.h>\r
32#include <Library/UefiLib.h>\r
33#include <Library/MemoryAllocationLib.h>\r
34#include <Library/DevicePathLib.h>\r
35\r
36\r
37/**\r
38 Perform reading memory mapped I/O space of device.\r
39\r
40 @param This A pointer to EFI_DEVICE_IO protocol instance.\r
41 @param Width Width of I/O operations.\r
42 @param Address The base address of I/O operations.\r
43 @param Count The number of I/O operations to perform. Bytes\r
44 moves is Width size * Count, starting at Address.\r
45 @param Buffer The destination buffer to store results.\r
46\r
47 @retval EFI_SUCCESS The data was read from the device.\r
48 @retval EFI_INVALID_PARAMETER Width is invalid.\r
49 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of\r
50 resources.\r
51\r
52**/\r
53EFI_STATUS\r
54EFIAPI\r
55DeviceIoMemRead (\r
56 IN EFI_DEVICE_IO_PROTOCOL *This,\r
57 IN EFI_IO_WIDTH Width,\r
58 IN UINT64 Address,\r
59 IN UINTN Count,\r
60 IN OUT VOID *Buffer\r
61 )\r
62;\r
63\r
64\r
65/**\r
66 Perform writing memory mapped I/O space of device.\r
67\r
68 @param This A pointer to EFI_DEVICE_IO protocol instance.\r
69 @param Width Width of I/O operations.\r
70 @param Address The base address of I/O operations.\r
71 @param Count The number of I/O operations to perform. Bytes\r
72 moves is Width size * Count, starting at Address.\r
73 @param Buffer The source buffer of data to be written.\r
74\r
75 @retval EFI_SUCCESS The data was written to the device.\r
76 @retval EFI_INVALID_PARAMETER Width is invalid.\r
77 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of\r
78 resources.\r
79\r
80**/\r
81EFI_STATUS\r
82EFIAPI\r
83DeviceIoMemWrite (\r
84 IN EFI_DEVICE_IO_PROTOCOL *This,\r
85 IN EFI_IO_WIDTH Width,\r
86 IN UINT64 Address,\r
87 IN UINTN Count,\r
88 IN OUT VOID *Buffer\r
89 )\r
90;\r
91\r
92/**\r
93 Perform reading I/O space of device.\r
94\r
95 @param This A pointer to EFI_DEVICE_IO protocol instance.\r
96 @param Width Width of I/O operations.\r
97 @param Address The base address of I/O operations.\r
98 @param Count The number of I/O operations to perform. Bytes\r
99 moves is Width size * Count, starting at Address.\r
100 @param Buffer The destination buffer to store results.\r
101\r
102 @retval EFI_SUCCESS The data was read from the device.\r
103 @retval EFI_INVALID_PARAMETER Width is invalid.\r
104 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of\r
105 resources.\r
106\r
107**/\r
108EFI_STATUS\r
109EFIAPI\r
110DeviceIoIoRead (\r
111 IN EFI_DEVICE_IO_PROTOCOL *This,\r
112 IN EFI_IO_WIDTH Width,\r
113 IN UINT64 Address,\r
114 IN UINTN Count,\r
115 IN OUT VOID *Buffer\r
116 )\r
117;\r
118\r
119/**\r
120 Perform writing I/O space of device.\r
121\r
122 @param This A pointer to EFI_DEVICE_IO protocol instance.\r
123 @param Width Width of I/O operations.\r
124 @param Address The base address of I/O operations.\r
125 @param Count The number of I/O operations to perform. Bytes\r
126 moves is Width size * Count, starting at Address.\r
127 @param Buffer The source buffer of data to be written.\r
128\r
129 @retval EFI_SUCCESS The data was written to the device.\r
130 @retval EFI_INVALID_PARAMETER Width is invalid.\r
131 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of\r
132 resources.\r
133\r
134**/\r
135EFI_STATUS\r
136EFIAPI\r
137DeviceIoIoWrite (\r
138 IN EFI_DEVICE_IO_PROTOCOL *This,\r
139 IN EFI_IO_WIDTH Width,\r
140 IN UINT64 Address,\r
141 IN UINTN Count,\r
142 IN OUT VOID *Buffer\r
143 )\r
144;\r
145\r
146/**\r
147 Perform reading PCI configuration space of device\r
148\r
149 @param This A pointer to EFI_DEVICE_IO protocol instance.\r
150 @param Width Width of I/O operations.\r
151 @param Address The base address of I/O operations.\r
152 @param Count The number of I/O operations to perform. Bytes\r
153 moves is Width size * Count, starting at Address.\r
154 @param Buffer The destination buffer to store results.\r
155\r
156 @retval EFI_SUCCESS The data was read from the device.\r
157 @retval EFI_INVALID_PARAMETER Width is invalid.\r
158 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of\r
159 resources.\r
160\r
161**/\r
162EFI_STATUS\r
163EFIAPI\r
164DeviceIoPciRead (\r
165 IN EFI_DEVICE_IO_PROTOCOL *This,\r
166 IN EFI_IO_WIDTH Width,\r
167 IN UINT64 Address,\r
168 IN UINTN Count,\r
169 IN OUT VOID *Buffer\r
170 )\r
171;\r
172\r
173/**\r
174 Perform writing PCI configuration space of device.\r
175\r
176 @param This A pointer to EFI_DEVICE_IO protocol instance.\r
177 @param Width Width of I/O operations.\r
178 @param Address The base address of I/O operations.\r
179 @param Count The number of I/O operations to perform. Bytes\r
180 moves is Width size * Count, starting at Address.\r
181 @param Buffer The source buffer of data to be written.\r
182\r
183 @retval EFI_SUCCESS The data was written to the device.\r
184 @retval EFI_INVALID_PARAMETER Width is invalid.\r
185 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of\r
186 resources.\r
187\r
188**/\r
189EFI_STATUS\r
190EFIAPI\r
191DeviceIoPciWrite (\r
192 IN EFI_DEVICE_IO_PROTOCOL *This,\r
193 IN EFI_IO_WIDTH Width,\r
194 IN UINT64 Address,\r
195 IN UINTN Count,\r
196 IN OUT VOID *Buffer\r
197 )\r
198;\r
199\r
200/**\r
201 Provides an EFI Device Path for a PCI device with the given PCI configuration space address.\r
202\r
203 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
204 @param Address The PCI configuration space address of the device\r
205 whose Device Path is going to be returned.\r
206 @param PciDevicePath A pointer to the pointer for the EFI Device Path\r
207 for PciAddress. Memory for the Device Path is\r
208 allocated from the pool.\r
209\r
210 @retval EFI_SUCCESS The PciDevicePath returns a pointer to a valid EFI\r
211 Device Path.\r
212 @retval EFI_UNSUPPORTED The PciAddress does not map to a valid EFI Device\r
213 Path.\r
214 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack\r
215 of resources.\r
216\r
217**/\r
218EFI_STATUS\r
219EFIAPI\r
220DeviceIoPciDevicePath (\r
221 IN EFI_DEVICE_IO_PROTOCOL *This,\r
222 IN UINT64 Address,\r
223 IN OUT EFI_DEVICE_PATH_PROTOCOL **PciDevicePath\r
224 )\r
225;\r
226\r
227/**\r
228 Provides the device-specific addresses needed to access system memory.\r
229\r
230 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
231 @param Operation Indicates if the bus master is going to read or\r
232 write to system memory.\r
233 @param HostAddress The system memory address to map to the device.\r
234 @param NumberOfBytes On input the number of bytes to map. On output the\r
235 number of bytes that were mapped.\r
236 @param DeviceAddress The resulting map address for the bus master\r
237 device to use to access the hosts HostAddress.\r
238 @param Mapping A resulting value to pass to Unmap().\r
239\r
240 @retval EFI_SUCCESS The range was mapped for the returned\r
241 NumberOfBytes.\r
242 @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined.\r
243 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common\r
244 buffer.\r
245 @retval EFI_DEVICE_ERROR The system hardware could not map the requested\r
246 address.\r
247 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack\r
248 of resources.\r
249\r
250**/\r
251EFI_STATUS\r
252EFIAPI\r
253DeviceIoMap (\r
254 IN EFI_DEVICE_IO_PROTOCOL *This,\r
255 IN EFI_IO_OPERATION_TYPE Operation,\r
256 IN EFI_PHYSICAL_ADDRESS *HostAddress,\r
257 IN OUT UINTN *NumberOfBytes,\r
258 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
259 OUT VOID **Mapping\r
260 )\r
261;\r
262\r
263/**\r
264 Completes the Map() operation and releases any corresponding resources.\r
265\r
266 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
267 @param Mapping The mapping value returned from Map().\r
268\r
269 @retval EFI_SUCCESS The range was unmapped.\r
270 @retval EFI_DEVICE_ERROR The data was not committed to the target system\r
271 memory.\r
272\r
273**/\r
274EFI_STATUS\r
275EFIAPI\r
276DeviceIoUnmap (\r
277 IN EFI_DEVICE_IO_PROTOCOL *This,\r
278 IN VOID *Mapping\r
279 )\r
280;\r
281\r
282/**\r
283 Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.\r
284\r
285 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
286 @param Type The type allocation to perform.\r
287 @param MemoryType The type of memory to allocate,\r
288 EfiBootServicesData or EfiRuntimeServicesData.\r
289 @param Pages The number of pages to allocate.\r
290 @param PhysicalAddress A pointer to store the base address of the\r
291 allocated range.\r
292\r
293 @retval EFI_SUCCESS The requested memory pages were allocated.\r
294 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.\r
295 @retval EFI_INVALID_PARAMETER The requested memory type is invalid.\r
296 @retval EFI_UNSUPPORTED The requested PhysicalAddress is not supported on\r
297 this platform.\r
298\r
299**/\r
300EFI_STATUS\r
301EFIAPI\r
302DeviceIoAllocateBuffer (\r
303 IN EFI_DEVICE_IO_PROTOCOL *This,\r
304 IN EFI_ALLOCATE_TYPE Type,\r
305 IN EFI_MEMORY_TYPE MemoryType,\r
306 IN UINTN Pages,\r
307 IN OUT EFI_PHYSICAL_ADDRESS *PhysicalAddress\r
308 )\r
309;\r
310\r
311/**\r
312 Flushes any posted write data to the device.\r
313\r
314 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
315\r
316 @retval EFI_SUCCESS The buffers were flushed.\r
317 @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware\r
318 error.\r
319\r
320**/\r
321EFI_STATUS\r
322EFIAPI\r
323DeviceIoFlush (\r
324 IN EFI_DEVICE_IO_PROTOCOL *This\r
325 )\r
326;\r
327\r
328/**\r
329 Frees pages that were allocated with AllocateBuffer().\r
330\r
331 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
332 @param Pages The number of pages to free.\r
333 @param HostAddress The base address of the range to free.\r
334\r
335 @retval EFI_SUCCESS The requested memory pages were freed.\r
336 @retval EFI_NOT_FOUND The requested memory pages were not allocated with\r
337 AllocateBuffer().\r
338 @retval EFI_INVALID_PARAMETER HostAddress is not page aligned or Pages is\r
339 invalid.\r
340\r
341**/\r
342EFI_STATUS\r
343EFIAPI\r
344DeviceIoFreeBuffer (\r
345 IN EFI_DEVICE_IO_PROTOCOL *This,\r
346 IN UINTN Pages,\r
347 IN EFI_PHYSICAL_ADDRESS HostAddress\r
348 )\r
349;\r
350\r
351\r
352#define DEVICE_IO_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('D', 'e', 'I', 'O')\r
353\r
354typedef struct {\r
355 UINTN Signature;\r
356 EFI_DEVICE_IO_PROTOCOL DeviceIo;\r
357 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
358 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
359 UINT16 PrimaryBus;\r
360 UINT16 SubordinateBus;\r
361} DEVICE_IO_PRIVATE_DATA;\r
362\r
363#define DEVICE_IO_PRIVATE_DATA_FROM_THIS(a) CR (a, DEVICE_IO_PRIVATE_DATA, DeviceIo, DEVICE_IO_PRIVATE_DATA_SIGNATURE)\r
364\r
365#define MAX_COMMON_BUFFER 0x00000000FFFFFFFF\r
366\r
367\r
368EFI_EVENT mPciRootBridgeIoRegistration;\r
369\r
370//\r
371// Device Io Volume Protocol template\r
372//\r
373DEVICE_IO_PRIVATE_DATA gDeviceIoPrivateDataTemplate = {\r
374 DEVICE_IO_PRIVATE_DATA_SIGNATURE,\r
375 {\r
376 {\r
377 DeviceIoMemRead,\r
378 DeviceIoMemWrite\r
379 },\r
380 {\r
381 DeviceIoIoRead,\r
382 DeviceIoIoWrite \r
383 },\r
384 {\r
385 DeviceIoPciRead,\r
386 DeviceIoPciWrite, \r
387 },\r
388 DeviceIoMap,\r
389 DeviceIoPciDevicePath,\r
390 DeviceIoUnmap,\r
391 DeviceIoAllocateBuffer,\r
392 DeviceIoFlush,\r
393 DeviceIoFreeBuffer\r
394 },\r
395 NULL, // PciRootBridgeIo\r
396 NULL, // DevicePath\r
397 0, // PrimaryBus\r
398 255 // SubordinateBus\r
399};\r
400\r
401VOID\r
402EFIAPI\r
403PciRootBridgeIoNotificationEvent (\r
404 IN EFI_EVENT Event,\r
405 IN VOID *Context\r
406 )\r
407{\r
408 EFI_STATUS Status;\r
409 UINTN BufferSize;\r
410 EFI_HANDLE Handle;\r
411 DEVICE_IO_PRIVATE_DATA *Private;\r
412 EFI_DEVICE_IO_PROTOCOL *DeviceIo;\r
413 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
414\r
415 while (TRUE) {\r
416 BufferSize = sizeof (Handle);\r
417 Status = gBS->LocateHandle (\r
418 ByRegisterNotify,\r
419 &gEfiPciRootBridgeIoProtocolGuid,\r
420 mPciRootBridgeIoRegistration,\r
421 &BufferSize,\r
422 &Handle\r
423 );\r
424 if (EFI_ERROR (Status)) {\r
425 //\r
426 // Exit Path of While Loop....\r
427 //\r
428 break;\r
429 }\r
430\r
431 //\r
432 // Skip this handle if the Device Io Protocol is already installed\r
433 //\r
434 Status = gBS->HandleProtocol (\r
435 Handle,\r
436 &gEfiDeviceIoProtocolGuid,\r
437 (VOID **)&DeviceIo\r
438 );\r
439 if (!EFI_ERROR (Status)) {\r
440 continue;\r
441 }\r
442\r
443 //\r
444 // Retrieve the Pci Root Bridge IO Protocol\r
445 //\r
446 Status = gBS->HandleProtocol (\r
447 Handle,\r
448 &gEfiPciRootBridgeIoProtocolGuid,\r
449 (VOID **)&PciRootBridgeIo\r
450 );\r
451 ASSERT_EFI_ERROR (Status);\r
452\r
453 //\r
454 // We only install Device IO for PCI bus in Segment 0\r
455 //\r
456 if (PciRootBridgeIo->SegmentNumber != 0) {\r
457 continue;\r
458 }\r
459\r
460 //\r
461 // Allocate private data structure\r
462 //\r
463 Private = AllocateCopyPool (sizeof (DEVICE_IO_PRIVATE_DATA), &gDeviceIoPrivateDataTemplate);\r
464 if (Private == NULL) {\r
465 continue;\r
466 }\r
467\r
468 Status = gBS->HandleProtocol (\r
469 Handle,\r
470 &gEfiDevicePathProtocolGuid,\r
471 (VOID **) &Private->DevicePath\r
472 );\r
473\r
474 //\r
475 // Install Device Io onto same handle\r
476 //\r
477 Status = gBS->InstallMultipleProtocolInterfaces (\r
478 &Handle,\r
479 &gEfiDeviceIoProtocolGuid,\r
480 &Private->DeviceIo,\r
481 NULL\r
482 );\r
483 ASSERT_EFI_ERROR (Status);\r
484 }\r
485}\r
486\r
487/**\r
488 The user Entry Point for DXE driver. The user code starts with this function\r
489 as the real entry point for the image goes into a library that calls this \r
490 function.\r
491\r
492 @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
493 @param[in] SystemTable A pointer to the EFI System Table.\r
494 \r
495 @retval EFI_SUCCESS The entry point is executed successfully.\r
496 @retval other Some error occurs when executing this entry point.\r
497\r
498**/\r
499EFI_STATUS\r
500EFIAPI\r
501InitializeDeviceIo (\r
502 IN EFI_HANDLE ImageHandle,\r
503 IN EFI_SYSTEM_TABLE *SystemTable\r
504 )\r
505{\r
506 EfiCreateProtocolNotifyEvent (\r
507 &gEfiPciRootBridgeIoProtocolGuid,\r
508 TPL_CALLBACK,\r
509 PciRootBridgeIoNotificationEvent,\r
510 NULL,\r
511 &mPciRootBridgeIoRegistration\r
512 );\r
513 return EFI_SUCCESS;\r
514}\r
515\r
516\r
517/**\r
518 Perform reading memory mapped I/O space of device.\r
519\r
520 @param This A pointer to EFI_DEVICE_IO protocol instance.\r
521 @param Width Width of I/O operations.\r
522 @param Address The base address of I/O operations.\r
523 @param Count The number of I/O operations to perform. Bytes\r
524 moves is Width size * Count, starting at Address.\r
525 @param Buffer The destination buffer to store results.\r
526\r
527 @retval EFI_SUCCESS The data was read from the device.\r
528 @retval EFI_INVALID_PARAMETER Width is invalid.\r
529 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of\r
530 resources.\r
531\r
532**/\r
533EFI_STATUS\r
534EFIAPI\r
535DeviceIoMemRead (\r
536 IN EFI_DEVICE_IO_PROTOCOL *This,\r
537 IN EFI_IO_WIDTH Width,\r
538 IN UINT64 Address,\r
539 IN UINTN Count,\r
540 IN OUT VOID *Buffer\r
541 )\r
542{\r
543 EFI_STATUS Status;\r
544 DEVICE_IO_PRIVATE_DATA *Private;\r
545\r
546 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
547\r
548 if (Width > MMIO_COPY_UINT64) {\r
549 return EFI_INVALID_PARAMETER;\r
550 }\r
551 if (Width >= MMIO_COPY_UINT8) {\r
552 Width = Width - MMIO_COPY_UINT8;\r
553 Status = Private->PciRootBridgeIo->CopyMem (\r
554 Private->PciRootBridgeIo,\r
555 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
556 (UINT64) (UINTN) Buffer,\r
557 Address,\r
558 Count\r
559 );\r
560 } else {\r
561 Status = Private->PciRootBridgeIo->Mem.Read (\r
562 Private->PciRootBridgeIo,\r
563 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
564 Address,\r
565 Count,\r
566 Buffer\r
567 );\r
568 }\r
569\r
570 return Status;\r
571}\r
572\r
573\r
574\r
575\r
576/**\r
577 Perform writing memory mapped I/O space of device.\r
578\r
579 @param This A pointer to EFI_DEVICE_IO protocol instance.\r
580 @param Width Width of I/O operations.\r
581 @param Address The base address of I/O operations.\r
582 @param Count The number of I/O operations to perform. Bytes\r
583 moves is Width size * Count, starting at Address.\r
584 @param Buffer The source buffer of data to be written.\r
585\r
586 @retval EFI_SUCCESS The data was written to the device.\r
587 @retval EFI_INVALID_PARAMETER Width is invalid.\r
588 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of\r
589 resources.\r
590\r
591**/\r
592EFI_STATUS\r
593EFIAPI\r
594DeviceIoMemWrite (\r
595 IN EFI_DEVICE_IO_PROTOCOL *This,\r
596 IN EFI_IO_WIDTH Width,\r
597 IN UINT64 Address,\r
598 IN UINTN Count,\r
599 IN OUT VOID *Buffer\r
600 )\r
601{\r
602 EFI_STATUS Status;\r
603 DEVICE_IO_PRIVATE_DATA *Private;\r
604\r
605 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
606\r
607 if (Width > MMIO_COPY_UINT64) {\r
608 return EFI_INVALID_PARAMETER;\r
609 }\r
610 if (Width >= MMIO_COPY_UINT8) {\r
611 Width = Width - MMIO_COPY_UINT8;\r
612 Status = Private->PciRootBridgeIo->CopyMem (\r
613 Private->PciRootBridgeIo,\r
614 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
615 Address,\r
616 (UINT64) (UINTN) Buffer,\r
617 Count\r
618 );\r
619 } else {\r
620 Status = Private->PciRootBridgeIo->Mem.Write (\r
621 Private->PciRootBridgeIo,\r
622 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
623 Address,\r
624 Count,\r
625 Buffer\r
626 );\r
627 }\r
628\r
629 return Status;\r
630}\r
631\r
632\r
633/**\r
634 Perform reading I/O space of device.\r
635\r
636 @param This A pointer to EFI_DEVICE_IO protocol instance.\r
637 @param Width Width of I/O operations.\r
638 @param Address The base address of I/O operations.\r
639 @param Count The number of I/O operations to perform. Bytes\r
640 moves is Width size * Count, starting at Address.\r
641 @param Buffer The destination buffer to store results.\r
642\r
643 @retval EFI_SUCCESS The data was read from the device.\r
644 @retval EFI_INVALID_PARAMETER Width is invalid.\r
645 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of\r
646 resources.\r
647\r
648**/\r
649EFI_STATUS\r
650EFIAPI\r
651DeviceIoIoRead (\r
652 IN EFI_DEVICE_IO_PROTOCOL *This,\r
653 IN EFI_IO_WIDTH Width,\r
654 IN UINT64 Address,\r
655 IN UINTN Count,\r
656 IN OUT VOID *Buffer\r
657 )\r
658{\r
659 EFI_STATUS Status;\r
660 DEVICE_IO_PRIVATE_DATA *Private;\r
661\r
662 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
663\r
664 if (Width >= MMIO_COPY_UINT8) {\r
665 return EFI_INVALID_PARAMETER;\r
666 }\r
667\r
668 Status = Private->PciRootBridgeIo->Io.Read (\r
669 Private->PciRootBridgeIo,\r
670 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
671 Address,\r
672 Count,\r
673 Buffer\r
674 );\r
675\r
676 return Status;\r
677}\r
678\r
679\r
680/**\r
681 Perform writing I/O space of device.\r
682\r
683 @param This A pointer to EFI_DEVICE_IO protocol instance.\r
684 @param Width Width of I/O operations.\r
685 @param Address The base address of I/O operations.\r
686 @param Count The number of I/O operations to perform. Bytes\r
687 moves is Width size * Count, starting at Address.\r
688 @param Buffer The source buffer of data to be written.\r
689\r
690 @retval EFI_SUCCESS The data was written to the device.\r
691 @retval EFI_INVALID_PARAMETER Width is invalid.\r
692 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of\r
693 resources.\r
694\r
695**/\r
696EFI_STATUS\r
697EFIAPI\r
698DeviceIoIoWrite (\r
699 IN EFI_DEVICE_IO_PROTOCOL *This,\r
700 IN EFI_IO_WIDTH Width,\r
701 IN UINT64 Address,\r
702 IN UINTN Count,\r
703 IN OUT VOID *Buffer\r
704 )\r
705{\r
706 EFI_STATUS Status;\r
707 DEVICE_IO_PRIVATE_DATA *Private;\r
708\r
709 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
710\r
711 if (Width >= MMIO_COPY_UINT8) {\r
712 return EFI_INVALID_PARAMETER;\r
713 }\r
714\r
715 Status = Private->PciRootBridgeIo->Io.Write (\r
716 Private->PciRootBridgeIo,\r
717 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
718 Address,\r
719 Count,\r
720 Buffer\r
721 );\r
722\r
723 return Status;\r
724}\r
725\r
726\r
727/**\r
728 Perform reading PCI configuration space of device\r
729\r
730 @param This A pointer to EFI_DEVICE_IO protocol instance.\r
731 @param Width Width of I/O operations.\r
732 @param Address The base address of I/O operations.\r
733 @param Count The number of I/O operations to perform. Bytes\r
734 moves is Width size * Count, starting at Address.\r
735 @param Buffer The destination buffer to store results.\r
736\r
737 @retval EFI_SUCCESS The data was read from the device.\r
738 @retval EFI_INVALID_PARAMETER Width is invalid.\r
739 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of\r
740 resources.\r
741\r
742**/\r
743EFI_STATUS\r
744EFIAPI\r
745DeviceIoPciRead (\r
746 IN EFI_DEVICE_IO_PROTOCOL *This,\r
747 IN EFI_IO_WIDTH Width,\r
748 IN UINT64 Address,\r
749 IN UINTN Count,\r
750 IN OUT VOID *Buffer\r
751 )\r
752{\r
753 EFI_STATUS Status;\r
754 DEVICE_IO_PRIVATE_DATA *Private;\r
755\r
756 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
757\r
758 if (Width < 0 || Width >= MMIO_COPY_UINT8) {\r
759 return EFI_INVALID_PARAMETER;\r
760 }\r
761\r
762 Status = Private->PciRootBridgeIo->Pci.Read (\r
763 Private->PciRootBridgeIo,\r
764 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
765 Address,\r
766 Count,\r
767 Buffer\r
768 );\r
769\r
770 return Status;\r
771}\r
772\r
773\r
774/**\r
775 Perform writing PCI configuration space of device.\r
776\r
777 @param This A pointer to EFI_DEVICE_IO protocol instance.\r
778 @param Width Width of I/O operations.\r
779 @param Address The base address of I/O operations.\r
780 @param Count The number of I/O operations to perform. Bytes\r
781 moves is Width size * Count, starting at Address.\r
782 @param Buffer The source buffer of data to be written.\r
783\r
784 @retval EFI_SUCCESS The data was written to the device.\r
785 @retval EFI_INVALID_PARAMETER Width is invalid.\r
786 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of\r
787 resources.\r
788\r
789**/\r
790EFI_STATUS\r
791EFIAPI\r
792DeviceIoPciWrite (\r
793 IN EFI_DEVICE_IO_PROTOCOL *This,\r
794 IN EFI_IO_WIDTH Width,\r
795 IN UINT64 Address,\r
796 IN UINTN Count,\r
797 IN OUT VOID *Buffer\r
798 )\r
799{\r
800 EFI_STATUS Status;\r
801 DEVICE_IO_PRIVATE_DATA *Private;\r
802\r
803 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
804\r
805 if (Width < 0 || Width >= MMIO_COPY_UINT8) {\r
806 return EFI_INVALID_PARAMETER;\r
807 }\r
808\r
809 Status = Private->PciRootBridgeIo->Pci.Write (\r
810 Private->PciRootBridgeIo,\r
811 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
812 Address,\r
813 Count,\r
814 Buffer\r
815 );\r
816\r
817 return Status;\r
818}\r
819\r
820\r
821/**\r
822 Append a PCI device path node to another device path.\r
823\r
824 @param Private A pointer to DEVICE_IO_PRIVATE_DATA instance.\r
825 @param Bus PCI bus number of the device.\r
826 @param Device PCI device number of the device.\r
827 @param Function PCI function number of the device.\r
828 @param DevicePath Original device path which will be appended a PCI\r
829 device path node.\r
830 @param BridgePrimaryBus Primary bus number of the bridge.\r
831 @param BridgeSubordinateBus Subordinate bus number of the bridge.\r
832\r
833 @return Pointer to the appended PCI device path.\r
834\r
835**/\r
836EFI_DEVICE_PATH_PROTOCOL *\r
837AppendPciDevicePath (\r
838 IN DEVICE_IO_PRIVATE_DATA *Private,\r
839 IN UINT8 Bus,\r
840 IN UINT8 Device,\r
841 IN UINT8 Function,\r
842 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
843 IN OUT UINT16 *BridgePrimaryBus,\r
844 IN OUT UINT16 *BridgeSubordinateBus\r
845 )\r
846{\r
847 UINT16 ThisBus;\r
848 UINT8 ThisDevice;\r
849 UINT8 ThisFunc;\r
850 UINT64 Address;\r
851 PCI_TYPE01 PciBridge;\r
852 PCI_TYPE01 *PciPtr;\r
853 EFI_DEVICE_PATH_PROTOCOL *ReturnDevicePath;\r
854 PCI_DEVICE_PATH PciNode;\r
855\r
856 PciPtr = &PciBridge;\r
857 for (ThisBus = *BridgePrimaryBus; ThisBus <= *BridgeSubordinateBus; ThisBus++) {\r
858 for (ThisDevice = 0; ThisDevice <= PCI_MAX_DEVICE; ThisDevice++) {\r
859 for (ThisFunc = 0; ThisFunc <= PCI_MAX_FUNC; ThisFunc++) {\r
860 Address = EFI_PCI_ADDRESS (ThisBus, ThisDevice, ThisFunc, 0);\r
861 ZeroMem (PciPtr, sizeof (PCI_TYPE01));\r
862 Private->DeviceIo.Pci.Read (\r
863 &Private->DeviceIo,\r
864 IO_UINT32,\r
865 Address,\r
866 1,\r
867 &(PciPtr->Hdr.VendorId)\r
868 );\r
869 if ((PciPtr->Hdr.VendorId == 0xffff) && (ThisFunc == 0)) {\r
870 break;\r
871 }\r
872 if (PciPtr->Hdr.VendorId == 0xffff) {\r
873 continue;\r
874 } else {\r
875 Private->DeviceIo.Pci.Read (\r
876 &Private->DeviceIo,\r
877 IO_UINT32,\r
878 Address,\r
879 sizeof (PCI_TYPE01) / sizeof (UINT32),\r
880 PciPtr\r
881 );\r
882 if (IS_PCI_BRIDGE (PciPtr)) {\r
883 if (Bus >= PciPtr->Bridge.SecondaryBus && Bus <= PciPtr->Bridge.SubordinateBus) {\r
884\r
885 PciNode.Header.Type = HARDWARE_DEVICE_PATH;\r
886 PciNode.Header.SubType = HW_PCI_DP;\r
887 SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));\r
888\r
889 PciNode.Device = ThisDevice;\r
890 PciNode.Function = ThisFunc;\r
891 ReturnDevicePath = AppendDevicePathNode (DevicePath, &PciNode.Header);\r
892\r
893 *BridgePrimaryBus = PciPtr->Bridge.SecondaryBus;\r
894 *BridgeSubordinateBus = PciPtr->Bridge.SubordinateBus;\r
895 return ReturnDevicePath;\r
896 }\r
897 }\r
898 if (ThisFunc == 0 && !(PciPtr->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION)) {\r
899 //\r
900 // Skip sub functions, this is not a multi function device\r
901 //\r
902 ThisFunc = 8;\r
903 }\r
904 }\r
905 }\r
906 }\r
907 }\r
908\r
909 ZeroMem (&PciNode, sizeof (PciNode));\r
910 PciNode.Header.Type = HARDWARE_DEVICE_PATH;\r
911 PciNode.Header.SubType = HW_PCI_DP;\r
912 SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));\r
913 PciNode.Device = Device;\r
914 PciNode.Function = Function;\r
915\r
916 ReturnDevicePath = AppendDevicePathNode (DevicePath, &PciNode.Header);\r
917\r
918 *BridgePrimaryBus = 0xffff;\r
919 *BridgeSubordinateBus = 0xffff;\r
920 return ReturnDevicePath;\r
921}\r
922\r
923\r
924/**\r
925 Provides an EFI Device Path for a PCI device with the given PCI configuration space address.\r
926\r
927 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
928 @param Address The PCI configuration space address of the device\r
929 whose Device Path is going to be returned.\r
930 @param PciDevicePath A pointer to the pointer for the EFI Device Path\r
931 for PciAddress. Memory for the Device Path is\r
932 allocated from the pool.\r
933\r
934 @retval EFI_SUCCESS The PciDevicePath returns a pointer to a valid EFI\r
935 Device Path.\r
936 @retval EFI_UNSUPPORTED The PciAddress does not map to a valid EFI Device\r
937 Path.\r
938 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack\r
939 of resources.\r
940\r
941**/\r
942EFI_STATUS\r
943EFIAPI\r
944DeviceIoPciDevicePath (\r
945 IN EFI_DEVICE_IO_PROTOCOL *This,\r
946 IN UINT64 Address,\r
947 IN OUT EFI_DEVICE_PATH_PROTOCOL **PciDevicePath\r
948 )\r
949{\r
950 DEVICE_IO_PRIVATE_DATA *Private;\r
951 UINT16 PrimaryBus;\r
952 UINT16 SubordinateBus;\r
953 UINT8 Bus;\r
954 UINT8 Device;\r
955 UINT8 Func;\r
956\r
957 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
958\r
959 Bus = (UINT8) (((UINT32) Address >> 24) & 0xff);\r
960 Device = (UINT8) (((UINT32) Address >> 16) & 0xff);\r
961 Func = (UINT8) (((UINT32) Address >> 8) & 0xff);\r
962\r
963 if (Bus < Private->PrimaryBus || Bus > Private->SubordinateBus) {\r
964 return EFI_UNSUPPORTED;\r
965 }\r
966\r
967 *PciDevicePath = Private->DevicePath;\r
968 PrimaryBus = Private->PrimaryBus;\r
969 SubordinateBus = Private->SubordinateBus;\r
970 do {\r
971 *PciDevicePath = AppendPciDevicePath (\r
972 Private,\r
973 Bus,\r
974 Device,\r
975 Func,\r
976 *PciDevicePath,\r
977 &PrimaryBus,\r
978 &SubordinateBus\r
979 );\r
980 if (*PciDevicePath == NULL) {\r
981 return EFI_OUT_OF_RESOURCES;\r
982 }\r
983 } while (PrimaryBus != 0xffff);\r
984\r
985 return EFI_SUCCESS;\r
986}\r
987\r
988\r
989/**\r
990 Provides the device-specific addresses needed to access system memory.\r
991\r
992 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
993 @param Operation Indicates if the bus master is going to read or\r
994 write to system memory.\r
995 @param HostAddress The system memory address to map to the device.\r
996 @param NumberOfBytes On input the number of bytes to map. On output the\r
997 number of bytes that were mapped.\r
998 @param DeviceAddress The resulting map address for the bus master\r
999 device to use to access the hosts HostAddress.\r
1000 @param Mapping A resulting value to pass to Unmap().\r
1001\r
1002 @retval EFI_SUCCESS The range was mapped for the returned\r
1003 NumberOfBytes.\r
1004 @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined.\r
1005 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common\r
1006 buffer.\r
1007 @retval EFI_DEVICE_ERROR The system hardware could not map the requested\r
1008 address.\r
1009 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack\r
1010 of resources.\r
1011\r
1012**/\r
1013EFI_STATUS\r
1014EFIAPI\r
1015DeviceIoMap (\r
1016 IN EFI_DEVICE_IO_PROTOCOL *This,\r
1017 IN EFI_IO_OPERATION_TYPE Operation,\r
1018 IN EFI_PHYSICAL_ADDRESS *HostAddress,\r
1019 IN OUT UINTN *NumberOfBytes,\r
1020 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
1021 OUT VOID **Mapping\r
1022 )\r
1023{\r
1024 EFI_STATUS Status;\r
1025 DEVICE_IO_PRIVATE_DATA *Private;\r
1026\r
1027 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
1028\r
1029 if (Operation < 0 || Operation > EfiBusMasterCommonBuffer) {\r
1030 return EFI_INVALID_PARAMETER;\r
1031 }\r
1032\r
1033 if (((UINTN) (*HostAddress) != (*HostAddress)) && Operation == EfiBusMasterCommonBuffer) {\r
1034 return EFI_UNSUPPORTED;\r
1035 }\r
1036\r
1037 Status = Private->PciRootBridgeIo->Map (\r
1038 Private->PciRootBridgeIo,\r
1039 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,\r
1040 (VOID *) (UINTN) (*HostAddress),\r
1041 NumberOfBytes,\r
1042 DeviceAddress,\r
1043 Mapping\r
1044 );\r
1045\r
1046 return Status;\r
1047}\r
1048\r
1049\r
1050/**\r
1051 Completes the Map() operation and releases any corresponding resources.\r
1052\r
1053 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
1054 @param Mapping The mapping value returned from Map().\r
1055\r
1056 @retval EFI_SUCCESS The range was unmapped.\r
1057 @retval EFI_DEVICE_ERROR The data was not committed to the target system\r
1058 memory.\r
1059\r
1060**/\r
1061EFI_STATUS\r
1062EFIAPI\r
1063DeviceIoUnmap (\r
1064 IN EFI_DEVICE_IO_PROTOCOL *This,\r
1065 IN VOID *Mapping\r
1066 )\r
1067{\r
1068 EFI_STATUS Status;\r
1069 DEVICE_IO_PRIVATE_DATA *Private;\r
1070\r
1071 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
1072\r
1073 Status = Private->PciRootBridgeIo->Unmap (\r
1074 Private->PciRootBridgeIo,\r
1075 Mapping\r
1076 );\r
1077\r
1078 return Status;\r
1079}\r
1080\r
1081\r
1082/**\r
1083 Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.\r
1084\r
1085 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
1086 @param Type The type allocation to perform.\r
1087 @param MemoryType The type of memory to allocate,\r
1088 EfiBootServicesData or EfiRuntimeServicesData.\r
1089 @param Pages The number of pages to allocate.\r
1090 @param PhysicalAddress A pointer to store the base address of the\r
1091 allocated range.\r
1092\r
1093 @retval EFI_SUCCESS The requested memory pages were allocated.\r
1094 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.\r
1095 @retval EFI_INVALID_PARAMETER The requested memory type is invalid.\r
1096 @retval EFI_UNSUPPORTED The requested PhysicalAddress is not supported on\r
1097 this platform.\r
1098\r
1099**/\r
1100EFI_STATUS\r
1101EFIAPI\r
1102DeviceIoAllocateBuffer (\r
1103 IN EFI_DEVICE_IO_PROTOCOL *This,\r
1104 IN EFI_ALLOCATE_TYPE Type,\r
1105 IN EFI_MEMORY_TYPE MemoryType,\r
1106 IN UINTN Pages,\r
1107 IN OUT EFI_PHYSICAL_ADDRESS *PhysicalAddress\r
1108 )\r
1109{\r
1110 EFI_STATUS Status;\r
1111 EFI_PHYSICAL_ADDRESS HostAddress;\r
1112\r
1113 HostAddress = *PhysicalAddress;\r
1114\r
1115 if ((MemoryType != EfiBootServicesData) && (MemoryType != EfiRuntimeServicesData)) {\r
1116 return EFI_INVALID_PARAMETER;\r
1117 }\r
1118\r
1119 if ((Type >= MaxAllocateType) || (Type < AllocateAnyPages)) {\r
1120 return EFI_INVALID_PARAMETER;\r
1121 }\r
1122\r
1123 if ((Type == AllocateAddress) && (HostAddress + EFI_PAGES_TO_SIZE (Pages) - 1 > MAX_COMMON_BUFFER)) {\r
1124 return EFI_UNSUPPORTED;\r
1125 }\r
1126\r
1127 if ((AllocateAnyPages == Type) || (AllocateMaxAddress == Type && HostAddress > MAX_COMMON_BUFFER)) {\r
1128 Type = AllocateMaxAddress;\r
1129 HostAddress = MAX_COMMON_BUFFER;\r
1130 }\r
1131\r
1132 Status = gBS->AllocatePages (\r
1133 Type,\r
1134 MemoryType,\r
1135 Pages,\r
1136 &HostAddress\r
1137 );\r
1138 if (EFI_ERROR (Status)) {\r
1139 return Status;\r
1140 }\r
1141\r
1142\r
1143 *PhysicalAddress = HostAddress;\r
1144\r
1145 return EFI_SUCCESS;\r
1146}\r
1147\r
1148\r
1149/**\r
1150 Flushes any posted write data to the device.\r
1151\r
1152 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
1153\r
1154 @retval EFI_SUCCESS The buffers were flushed.\r
1155 @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware\r
1156 error.\r
1157\r
1158**/\r
1159EFI_STATUS\r
1160EFIAPI\r
1161DeviceIoFlush (\r
1162 IN EFI_DEVICE_IO_PROTOCOL *This\r
1163 )\r
1164{\r
1165 EFI_STATUS Status;\r
1166 DEVICE_IO_PRIVATE_DATA *Private;\r
1167\r
1168 Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
1169\r
1170 Status = Private->PciRootBridgeIo->Flush (Private->PciRootBridgeIo);\r
1171\r
1172 return Status;\r
1173}\r
1174\r
1175\r
1176/**\r
1177 Frees pages that were allocated with AllocateBuffer().\r
1178\r
1179 @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
1180 @param Pages The number of pages to free.\r
1181 @param HostAddress The base address of the range to free.\r
1182\r
1183 @retval EFI_SUCCESS The requested memory pages were freed.\r
1184 @retval EFI_NOT_FOUND The requested memory pages were not allocated with\r
1185 AllocateBuffer().\r
1186 @retval EFI_INVALID_PARAMETER HostAddress is not page aligned or Pages is\r
1187 invalid.\r
1188\r
1189**/\r
1190EFI_STATUS\r
1191EFIAPI\r
1192DeviceIoFreeBuffer (\r
1193 IN EFI_DEVICE_IO_PROTOCOL *This,\r
1194 IN UINTN Pages,\r
1195 IN EFI_PHYSICAL_ADDRESS HostAddress\r
1196 )\r
1197{\r
1198 if (((HostAddress & EFI_PAGE_MASK) != 0) || (Pages <= 0)) {\r
1199 return EFI_INVALID_PARAMETER;\r
1200 }\r
1201\r
1202 return gBS->FreePages (HostAddress, Pages);\r
1203}\r
1204\r