]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
FatPkg: Fix format issues in dec/inf/dsc files
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / NonDiscoverablePciDeviceDxe / NonDiscoverablePciDeviceIo.c
CommitLineData
a42e6d44
AB
1/** @file\r
2\r
3 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
4 Copyright (c) 2016, Linaro, Ltd. All rights reserved.<BR>\r
5\r
6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "NonDiscoverablePciDeviceIo.h"\r
17\r
18#include <IndustryStandard/Acpi.h>\r
19\r
20#include <Protocol/PciRootBridgeIo.h>\r
21\r
22typedef struct {\r
23 EFI_PHYSICAL_ADDRESS AllocAddress;\r
24 VOID *HostAddress;\r
25 EFI_PCI_IO_PROTOCOL_OPERATION Operation;\r
26 UINTN NumberOfBytes;\r
27} NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO;\r
28\r
29//\r
30// Get the resource associated with BAR number 'BarIndex'.\r
31//\r
32STATIC\r
33EFI_STATUS\r
34GetBarResource (\r
35 IN NON_DISCOVERABLE_PCI_DEVICE *Dev,\r
36 IN UINT8 BarIndex,\r
37 OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptor\r
38 )\r
39{\r
40 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;\r
41\r
42 if (BarIndex < Dev->BarOffset) {\r
43 return EFI_NOT_FOUND;\r
44 }\r
45\r
46 BarIndex -= Dev->BarOffset;\r
47\r
48 for (Desc = Dev->Device->Resources;\r
49 Desc->Desc != ACPI_END_TAG_DESCRIPTOR;\r
50 Desc = (VOID *)((UINT8 *)Desc + Desc->Len + 3)) {\r
51\r
52 if (BarIndex == 0) {\r
53 *Descriptor = Desc;\r
54 return EFI_SUCCESS;\r
55 }\r
56\r
57 BarIndex -= 1;\r
58 }\r
59 return EFI_NOT_FOUND;\r
60}\r
61\r
62STATIC\r
63EFI_STATUS\r
64PciIoPollMem (\r
65 IN EFI_PCI_IO_PROTOCOL *This,\r
66 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
67 IN UINT8 BarIndex,\r
68 IN UINT64 Offset,\r
69 IN UINT64 Mask,\r
70 IN UINT64 Value,\r
71 IN UINT64 Delay,\r
72 OUT UINT64 *Result\r
73 )\r
74{\r
75 ASSERT (FALSE);\r
76 return EFI_UNSUPPORTED;\r
77}\r
78\r
79STATIC\r
80EFI_STATUS\r
81PciIoPollIo (\r
82 IN EFI_PCI_IO_PROTOCOL *This,\r
83 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
84 IN UINT8 BarIndex,\r
85 IN UINT64 Offset,\r
86 IN UINT64 Mask,\r
87 IN UINT64 Value,\r
88 IN UINT64 Delay,\r
89 OUT UINT64 *Result\r
90 )\r
91{\r
92 ASSERT (FALSE);\r
93 return EFI_UNSUPPORTED;\r
94}\r
95\r
96STATIC\r
97EFI_STATUS\r
98PciIoMemRW (\r
99 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
100 IN UINTN Count,\r
101 IN UINTN DstStride,\r
102 IN VOID *Dst,\r
103 IN UINTN SrcStride,\r
104 OUT CONST VOID *Src\r
105 )\r
106{\r
107 volatile UINT8 *Dst8;\r
108 volatile UINT16 *Dst16;\r
109 volatile UINT32 *Dst32;\r
110 volatile CONST UINT8 *Src8;\r
111 volatile CONST UINT16 *Src16;\r
112 volatile CONST UINT32 *Src32;\r
113\r
114 //\r
115 // Loop for each iteration and move the data\r
116 //\r
117 switch (Width & 0x3) {\r
118 case EfiPciWidthUint8:\r
119 Dst8 = (UINT8 *)Dst;\r
120 Src8 = (UINT8 *)Src;\r
121 for (;Count > 0; Count--, Dst8 += DstStride, Src8 += SrcStride) {\r
122 *Dst8 = *Src8;\r
123 }\r
124 break;\r
125 case EfiPciWidthUint16:\r
126 Dst16 = (UINT16 *)Dst;\r
127 Src16 = (UINT16 *)Src;\r
128 for (;Count > 0; Count--, Dst16 += DstStride, Src16 += SrcStride) {\r
129 *Dst16 = *Src16;\r
130 }\r
131 break;\r
132 case EfiPciWidthUint32:\r
133 Dst32 = (UINT32 *)Dst;\r
134 Src32 = (UINT32 *)Src;\r
135 for (;Count > 0; Count--, Dst32 += DstStride, Src32 += SrcStride) {\r
136 *Dst32 = *Src32;\r
137 }\r
138 break;\r
139 default:\r
140 return EFI_INVALID_PARAMETER;\r
141 }\r
142\r
143 return EFI_SUCCESS;\r
144}\r
145\r
146STATIC\r
147EFI_STATUS\r
148PciIoMemRead (\r
149 IN EFI_PCI_IO_PROTOCOL *This,\r
150 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
151 IN UINT8 BarIndex,\r
152 IN UINT64 Offset,\r
153 IN UINTN Count,\r
154 IN OUT VOID *Buffer\r
155 )\r
156{\r
157 NON_DISCOVERABLE_PCI_DEVICE *Dev;\r
158 UINTN AlignMask;\r
159 VOID *Address;\r
160 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;\r
161 EFI_STATUS Status;\r
162\r
163 if (Buffer == NULL) {\r
164 return EFI_INVALID_PARAMETER;\r
165 }\r
166\r
167 Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);\r
168\r
169 //\r
170 // Only allow accesses to the BARs we emulate\r
171 //\r
172 Status = GetBarResource (Dev, BarIndex, &Desc);\r
173 if (EFI_ERROR (Status)) {\r
174 return Status;\r
175 }\r
176\r
177 if (Offset + (Count << (Width & 0x3)) > Desc->AddrLen) {\r
178 return EFI_UNSUPPORTED;\r
179 }\r
180\r
181 Address = (VOID *)(UINTN)(Desc->AddrRangeMin + Offset);\r
182 AlignMask = (1 << (Width & 0x03)) - 1;\r
183 if ((UINTN)Address & AlignMask) {\r
184 return EFI_INVALID_PARAMETER;\r
185 }\r
186\r
187 switch (Width) {\r
188 case EfiPciWidthUint8:\r
189 case EfiPciWidthUint16:\r
190 case EfiPciWidthUint32:\r
191 case EfiPciWidthUint64:\r
192 return PciIoMemRW (Width, Count, 1, Buffer, 1, Address);\r
193\r
194 case EfiPciWidthFifoUint8:\r
195 case EfiPciWidthFifoUint16:\r
196 case EfiPciWidthFifoUint32:\r
197 case EfiPciWidthFifoUint64:\r
198 return PciIoMemRW (Width, Count, 1, Buffer, 0, Address);\r
199\r
200 case EfiPciWidthFillUint8:\r
201 case EfiPciWidthFillUint16:\r
202 case EfiPciWidthFillUint32:\r
203 case EfiPciWidthFillUint64:\r
204 return PciIoMemRW (Width, Count, 0, Buffer, 1, Address);\r
205\r
206 default:\r
207 break;\r
208 }\r
209 return EFI_INVALID_PARAMETER;\r
210}\r
211\r
212STATIC\r
213EFI_STATUS\r
214PciIoMemWrite (\r
215 IN EFI_PCI_IO_PROTOCOL *This,\r
216 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
217 IN UINT8 BarIndex,\r
218 IN UINT64 Offset,\r
219 IN UINTN Count,\r
220 IN OUT VOID *Buffer\r
221 )\r
222{\r
223 NON_DISCOVERABLE_PCI_DEVICE *Dev;\r
224 UINTN AlignMask;\r
225 VOID *Address;\r
226 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;\r
227 EFI_STATUS Status;\r
228\r
229 if (Buffer == NULL) {\r
230 return EFI_INVALID_PARAMETER;\r
231 }\r
232\r
233 Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);\r
234\r
235 //\r
236 // Only allow accesses to the BARs we emulate\r
237 //\r
238 Status = GetBarResource (Dev, BarIndex, &Desc);\r
239 if (EFI_ERROR (Status)) {\r
240 return Status;\r
241 }\r
242\r
243 if (Offset + (Count << (Width & 0x3)) > Desc->AddrLen) {\r
244 return EFI_UNSUPPORTED;\r
245 }\r
246\r
247 Address = (VOID *)(UINTN)(Desc->AddrRangeMin + Offset);\r
248 AlignMask = (1 << (Width & 0x03)) - 1;\r
249 if ((UINTN)Address & AlignMask) {\r
250 return EFI_INVALID_PARAMETER;\r
251 }\r
252\r
253 switch (Width) {\r
254 case EfiPciWidthUint8:\r
255 case EfiPciWidthUint16:\r
256 case EfiPciWidthUint32:\r
257 case EfiPciWidthUint64:\r
258 return PciIoMemRW (Width, Count, 1, Address, 1, Buffer);\r
259\r
260 case EfiPciWidthFifoUint8:\r
261 case EfiPciWidthFifoUint16:\r
262 case EfiPciWidthFifoUint32:\r
263 case EfiPciWidthFifoUint64:\r
264 return PciIoMemRW (Width, Count, 0, Address, 1, Buffer);\r
265\r
266 case EfiPciWidthFillUint8:\r
267 case EfiPciWidthFillUint16:\r
268 case EfiPciWidthFillUint32:\r
269 case EfiPciWidthFillUint64:\r
270 return PciIoMemRW (Width, Count, 1, Address, 0, Buffer);\r
271\r
272 default:\r
273 break;\r
274 }\r
275 return EFI_INVALID_PARAMETER;\r
276}\r
277\r
278STATIC\r
279EFI_STATUS\r
280PciIoIoRead (\r
281 IN EFI_PCI_IO_PROTOCOL *This,\r
282 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
283 IN UINT8 BarIndex,\r
284 IN UINT64 Offset,\r
285 IN UINTN Count,\r
286 IN OUT VOID *Buffer\r
287 )\r
288{\r
289 ASSERT (FALSE);\r
290 return EFI_UNSUPPORTED;\r
291}\r
292\r
293STATIC\r
294EFI_STATUS\r
295PciIoIoWrite (\r
296 IN EFI_PCI_IO_PROTOCOL *This,\r
297 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
298 IN UINT8 BarIndex,\r
299 IN UINT64 Offset,\r
300 IN UINTN Count,\r
301 IN OUT VOID *Buffer\r
302 )\r
303{\r
304 ASSERT (FALSE);\r
305 return EFI_UNSUPPORTED;\r
306}\r
307\r
308STATIC\r
309EFI_STATUS\r
310PciIoPciRead (\r
311 IN EFI_PCI_IO_PROTOCOL *This,\r
312 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
313 IN UINT32 Offset,\r
314 IN UINTN Count,\r
315 IN OUT VOID *Buffer\r
316 )\r
317{\r
318 NON_DISCOVERABLE_PCI_DEVICE *Dev;\r
319 VOID *Address;\r
320 UINTN Length;\r
321\r
322 if (Width < 0 || Width >= EfiPciIoWidthMaximum || Buffer == NULL) {\r
323 return EFI_INVALID_PARAMETER;\r
324 }\r
325\r
326 Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);\r
327 Address = (UINT8 *)&Dev->ConfigSpace + Offset;\r
328 Length = Count << ((UINTN)Width & 0x3);\r
329\r
330 if (Offset + Length > sizeof (Dev->ConfigSpace)) {\r
331 //\r
332 // Read all zeroes for config space accesses beyond the first\r
333 // 64 bytes\r
334 //\r
335 Length -= sizeof (Dev->ConfigSpace) - Offset;\r
336 ZeroMem ((UINT8 *)Buffer + sizeof (Dev->ConfigSpace) - Offset, Length);\r
337\r
338 Count -= Length >> ((UINTN)Width & 0x3);\r
339 }\r
340 return PciIoMemRW (Width, Count, 1, Buffer, 1, Address);\r
341}\r
342\r
343STATIC\r
344EFI_STATUS\r
345PciIoPciWrite (\r
346 IN EFI_PCI_IO_PROTOCOL *This,\r
347 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
348 IN UINT32 Offset,\r
349 IN UINTN Count,\r
350 IN OUT VOID *Buffer\r
351 )\r
352{\r
353 NON_DISCOVERABLE_PCI_DEVICE *Dev;\r
354 VOID *Address;\r
355\r
356 if (Width < 0 || Width >= EfiPciIoWidthMaximum || Buffer == NULL) {\r
357 return EFI_INVALID_PARAMETER;\r
358 }\r
359\r
360 Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);\r
361 Address = (UINT8 *)&Dev->ConfigSpace + Offset;\r
362\r
363 if (Offset + (Count << ((UINTN)Width & 0x3)) > sizeof (Dev->ConfigSpace)) {\r
364 return EFI_UNSUPPORTED;\r
365 }\r
366\r
367 return PciIoMemRW (Width, Count, 1, Address, 1, Buffer);\r
368}\r
369\r
370STATIC\r
371EFI_STATUS\r
372PciIoCopyMem (\r
373 IN EFI_PCI_IO_PROTOCOL *This,\r
374 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
375 IN UINT8 DestBarIndex,\r
376 IN UINT64 DestOffset,\r
377 IN UINT8 SrcBarIndex,\r
378 IN UINT64 SrcOffset,\r
379 IN UINTN Count\r
380 )\r
381{\r
382 ASSERT (FALSE);\r
383 return EFI_UNSUPPORTED;\r
384}\r
385\r
386STATIC\r
387EFI_STATUS\r
388CoherentPciIoMap (\r
389 IN EFI_PCI_IO_PROTOCOL *This,\r
390 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,\r
391 IN VOID *HostAddress,\r
392 IN OUT UINTN *NumberOfBytes,\r
393 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
394 OUT VOID **Mapping\r
395 )\r
396{\r
397 NON_DISCOVERABLE_PCI_DEVICE *Dev;\r
398 EFI_STATUS Status;\r
399 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo;\r
400\r
401 //\r
402 // If HostAddress exceeds 4 GB, and this device does not support 64-bit DMA\r
403 // addressing, we need to allocate a bounce buffer and copy over the data.\r
404 //\r
405 Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);\r
406 if ((Dev->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0 &&\r
407 (UINTN)HostAddress + *NumberOfBytes > SIZE_4GB) {\r
408\r
409 //\r
410 // Bounce buffering is not possible for consistent mappings\r
411 //\r
412 if (Operation == EfiPciIoOperationBusMasterCommonBuffer) {\r
413 return EFI_UNSUPPORTED;\r
414 }\r
415\r
416 MapInfo = AllocatePool (sizeof *MapInfo);\r
417 if (MapInfo == NULL) {\r
418 return EFI_OUT_OF_RESOURCES;\r
419 }\r
420\r
421 MapInfo->AllocAddress = MAX_UINT32;\r
422 MapInfo->HostAddress = HostAddress;\r
423 MapInfo->Operation = Operation;\r
424 MapInfo->NumberOfBytes = *NumberOfBytes;\r
425\r
426 Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData,\r
427 EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes),\r
428 &MapInfo->AllocAddress);\r
429 if (EFI_ERROR (Status)) {\r
430 //\r
431 // If we fail here, it is likely because the system has no memory below\r
432 // 4 GB to begin with. There is not much we can do about that other than\r
433 // fail the map request.\r
434 //\r
435 FreePool (MapInfo);\r
436 return EFI_DEVICE_ERROR;\r
437 }\r
438 if (Operation == EfiPciIoOperationBusMasterRead) {\r
439 gBS->CopyMem ((VOID *)(UINTN)MapInfo->AllocAddress, HostAddress,\r
440 *NumberOfBytes);\r
441 }\r
442 *DeviceAddress = MapInfo->AllocAddress;\r
443 *Mapping = MapInfo;\r
444 } else {\r
445 *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;\r
446 *Mapping = NULL;\r
447 }\r
448 return EFI_SUCCESS;\r
449}\r
450\r
451STATIC\r
452EFI_STATUS\r
453CoherentPciIoUnmap (\r
454 IN EFI_PCI_IO_PROTOCOL *This,\r
455 IN VOID *Mapping\r
456 )\r
457{\r
458 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo;\r
459\r
460 MapInfo = Mapping;\r
461 if (MapInfo != NULL) {\r
462 if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) {\r
463 gBS->CopyMem (MapInfo->HostAddress, (VOID *)(UINTN)MapInfo->AllocAddress,\r
464 MapInfo->NumberOfBytes);\r
465 }\r
466 gBS->FreePages (MapInfo->AllocAddress,\r
467 EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes));\r
468 FreePool (MapInfo);\r
469 }\r
470 return EFI_SUCCESS;\r
471}\r
472\r
473STATIC\r
474EFI_STATUS\r
475CoherentPciIoAllocateBuffer (\r
476 IN EFI_PCI_IO_PROTOCOL *This,\r
477 IN EFI_ALLOCATE_TYPE Type,\r
478 IN EFI_MEMORY_TYPE MemoryType,\r
479 IN UINTN Pages,\r
480 OUT VOID **HostAddress,\r
481 IN UINT64 Attributes\r
482 )\r
483{\r
484 NON_DISCOVERABLE_PCI_DEVICE *Dev;\r
485 EFI_PHYSICAL_ADDRESS AllocAddress;\r
486 EFI_ALLOCATE_TYPE AllocType;\r
487 EFI_STATUS Status;\r
488\r
489 if ((Attributes & ~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE |\r
490 EFI_PCI_ATTRIBUTE_MEMORY_CACHED)) != 0) {\r
491 return EFI_UNSUPPORTED;\r
492 }\r
493\r
494 //\r
495 // Allocate below 4 GB if the dual address cycle attribute has not\r
496 // been set. If the system has no memory available below 4 GB, there\r
497 // is little we can do except propagate the error.\r
498 //\r
499 Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);\r
500 if ((Dev->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0) {\r
501 AllocAddress = MAX_UINT32;\r
502 AllocType = AllocateMaxAddress;\r
503 } else {\r
504 AllocType = AllocateAnyPages;\r
505 }\r
506\r
507 Status = gBS->AllocatePages (AllocType, MemoryType, Pages, &AllocAddress);\r
508 if (!EFI_ERROR (Status)) {\r
509 *HostAddress = (VOID *)(UINTN)AllocAddress;\r
510 }\r
511 return Status;\r
512}\r
513\r
514STATIC\r
515EFI_STATUS\r
516CoherentPciIoFreeBuffer (\r
517 IN EFI_PCI_IO_PROTOCOL *This,\r
518 IN UINTN Pages,\r
519 IN VOID *HostAddress\r
520 )\r
521{\r
522 FreePages (HostAddress, Pages);\r
523 return EFI_SUCCESS;\r
524}\r
525\r
526\r
527STATIC\r
528EFI_STATUS\r
529PciIoFlush (\r
530 IN EFI_PCI_IO_PROTOCOL *This\r
531 )\r
532{\r
533 return EFI_SUCCESS;\r
534}\r
535\r
536STATIC\r
537EFI_STATUS\r
538PciIoGetLocation (\r
539 IN EFI_PCI_IO_PROTOCOL *This,\r
540 OUT UINTN *SegmentNumber,\r
541 OUT UINTN *BusNumber,\r
542 OUT UINTN *DeviceNumber,\r
543 OUT UINTN *FunctionNumber\r
544 )\r
545{\r
546 if (SegmentNumber == NULL ||\r
547 BusNumber == NULL ||\r
548 DeviceNumber == NULL ||\r
549 FunctionNumber == NULL) {\r
550 return EFI_INVALID_PARAMETER;\r
551 }\r
552\r
553 *SegmentNumber = 0;\r
554 *BusNumber = 0xff;\r
555 *DeviceNumber = 0;\r
556 *FunctionNumber = 0;\r
557\r
558 return EFI_SUCCESS;\r
559}\r
560\r
561STATIC\r
562EFI_STATUS\r
563PciIoAttributes (\r
564 IN EFI_PCI_IO_PROTOCOL *This,\r
565 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,\r
566 IN UINT64 Attributes,\r
567 OUT UINT64 *Result OPTIONAL\r
568 )\r
569{\r
570 NON_DISCOVERABLE_PCI_DEVICE *Dev;\r
571 BOOLEAN Enable;\r
572\r
573 Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);\r
574\r
575 Enable = FALSE;\r
576 switch (Operation) {\r
577 case EfiPciIoAttributeOperationGet:\r
578 if (Result == NULL) {\r
579 return EFI_INVALID_PARAMETER;\r
580 }\r
581 *Result = Dev->Attributes;\r
582 break;\r
583\r
584 case EfiPciIoAttributeOperationSupported:\r
585 if (Result == NULL) {\r
586 return EFI_INVALID_PARAMETER;\r
587 }\r
588 *Result = EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;\r
589 break;\r
590\r
591 case EfiPciIoAttributeOperationEnable:\r
592 Attributes |= Dev->Attributes;\r
593 case EfiPciIoAttributeOperationSet:\r
594 Enable = ((~Dev->Attributes & Attributes) & EFI_PCI_DEVICE_ENABLE) != 0;\r
595 Dev->Attributes = Attributes;\r
596 break;\r
597\r
598 case EfiPciIoAttributeOperationDisable:\r
599 Dev->Attributes &= ~Attributes;\r
600 break;\r
601\r
602 default:\r
603 return EFI_INVALID_PARAMETER;\r
604 };\r
605\r
606 //\r
607 // If we're setting any of the EFI_PCI_DEVICE_ENABLE bits, perform\r
608 // the device specific initialization now.\r
609 //\r
610 if (Enable && !Dev->Enabled && Dev->Device->Initialize != NULL) {\r
611 Dev->Device->Initialize (Dev->Device);\r
612 Dev->Enabled = TRUE;\r
613 }\r
614 return EFI_SUCCESS;\r
615}\r
616\r
617STATIC\r
618EFI_STATUS\r
619PciIoGetBarAttributes (\r
620 IN EFI_PCI_IO_PROTOCOL *This,\r
621 IN UINT8 BarIndex,\r
622 OUT UINT64 *Supports OPTIONAL,\r
623 OUT VOID **Resources OPTIONAL\r
624 )\r
625{\r
626 NON_DISCOVERABLE_PCI_DEVICE *Dev;\r
627 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor, *BarDesc;\r
628 EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
629 EFI_STATUS Status;\r
630\r
631 if (Supports == NULL && Resources == NULL) {\r
632 return EFI_INVALID_PARAMETER;\r
633 }\r
634\r
635 Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);\r
636\r
637 Status = GetBarResource (Dev, BarIndex, &BarDesc);\r
638 if (EFI_ERROR (Status)) {\r
639 return Status;\r
640 }\r
641\r
642 //\r
643 // Don't expose any configurable attributes for our emulated BAR\r
644 //\r
645 if (Supports != NULL) {\r
646 *Supports = 0;\r
647 }\r
648\r
649 if (Resources != NULL) {\r
650 Descriptor = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +\r
651 sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
652 if (Descriptor == NULL) {\r
653 return EFI_OUT_OF_RESOURCES;\r
654 }\r
655\r
656 CopyMem (Descriptor, BarDesc, sizeof *Descriptor);\r
657\r
658 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);\r
659 End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
660 End->Checksum = 0;\r
661\r
662 *Resources = Descriptor;\r
663 }\r
664 return EFI_SUCCESS;\r
665}\r
666\r
667STATIC\r
668EFI_STATUS\r
669PciIoSetBarAttributes (\r
670 IN EFI_PCI_IO_PROTOCOL *This,\r
671 IN UINT64 Attributes,\r
672 IN UINT8 BarIndex,\r
673 IN OUT UINT64 *Offset,\r
674 IN OUT UINT64 *Length\r
675 )\r
676{\r
677 ASSERT (FALSE);\r
678 return EFI_UNSUPPORTED;\r
679}\r
680\r
681STATIC CONST EFI_PCI_IO_PROTOCOL PciIoTemplate =\r
682{\r
683 PciIoPollMem,\r
684 PciIoPollIo,\r
685 { PciIoMemRead, PciIoMemWrite },\r
686 { PciIoIoRead, PciIoIoWrite },\r
687 { PciIoPciRead, PciIoPciWrite },\r
688 PciIoCopyMem,\r
689 CoherentPciIoMap,\r
690 CoherentPciIoUnmap,\r
691 CoherentPciIoAllocateBuffer,\r
692 CoherentPciIoFreeBuffer,\r
693 PciIoFlush,\r
694 PciIoGetLocation,\r
695 PciIoAttributes,\r
696 PciIoGetBarAttributes,\r
697 PciIoSetBarAttributes,\r
698 0,\r
699 0\r
700};\r
701\r
702VOID\r
703InitializePciIoProtocol (\r
704 NON_DISCOVERABLE_PCI_DEVICE *Dev\r
705 )\r
706{\r
707 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;\r
708 INTN Idx;\r
709\r
710 Dev->ConfigSpace.Hdr.VendorId = PCI_ID_VENDOR_UNKNOWN;\r
711 Dev->ConfigSpace.Hdr.DeviceId = PCI_ID_DEVICE_DONTCARE;\r
712\r
713 // Copy protocol structure\r
714 CopyMem(&Dev->PciIo, &PciIoTemplate, sizeof PciIoTemplate);\r
715\r
716 if (CompareGuid (Dev->Device->Type, &gEdkiiNonDiscoverableAhciDeviceGuid)) {\r
717 Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_MASS_STORAGE_AHCI;\r
718 Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_MASS_STORAGE_SATADPA;\r
719 Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_MASS_STORAGE;\r
720 Dev->BarOffset = 5;\r
721 } else if (CompareGuid (Dev->Device->Type,\r
722 &gEdkiiNonDiscoverableEhciDeviceGuid)) {\r
723 Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_EHCI;\r
724 Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_SERIAL_USB;\r
725 Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_SERIAL;\r
726 Dev->BarOffset = 0;\r
727 } else if (CompareGuid (Dev->Device->Type,\r
728 &gEdkiiNonDiscoverableNvmeDeviceGuid)) {\r
729 Dev->ConfigSpace.Hdr.ClassCode[0] = 0x2; // PCI_IF_NVMHCI\r
730 Dev->ConfigSpace.Hdr.ClassCode[1] = 0x8; // PCI_CLASS_MASS_STORAGE_NVM\r
731 Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_MASS_STORAGE;\r
732 Dev->BarOffset = 0;\r
733 } else if (CompareGuid (Dev->Device->Type,\r
734 &gEdkiiNonDiscoverableOhciDeviceGuid)) {\r
735 Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_OHCI;\r
736 Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_SERIAL_USB;\r
737 Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_SERIAL;\r
738 Dev->BarOffset = 0;\r
739 } else if (CompareGuid (Dev->Device->Type,\r
740 &gEdkiiNonDiscoverableSdhciDeviceGuid)) {\r
741 Dev->ConfigSpace.Hdr.ClassCode[0] = 0x0; // don't care\r
742 Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_SUBCLASS_SD_HOST_CONTROLLER;\r
743 Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_SYSTEM_PERIPHERAL;\r
744 Dev->BarOffset = 0;\r
745 } else if (CompareGuid (Dev->Device->Type,\r
746 &gEdkiiNonDiscoverableXhciDeviceGuid)) {\r
747 Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_XHCI;\r
748 Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_SERIAL_USB;\r
749 Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_SERIAL;\r
750 Dev->BarOffset = 0;\r
751 } else if (CompareGuid (Dev->Device->Type,\r
752 &gEdkiiNonDiscoverableUhciDeviceGuid)) {\r
753 Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_UHCI;\r
754 Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_SERIAL_USB;\r
755 Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_SERIAL;\r
756 Dev->BarOffset = 0;\r
757 } else if (CompareGuid (Dev->Device->Type,\r
758 &gEdkiiNonDiscoverableUfsDeviceGuid)) {\r
759 Dev->ConfigSpace.Hdr.ClassCode[0] = 0x0; // don't care\r
760 Dev->ConfigSpace.Hdr.ClassCode[1] = 0x9; // UFS controller subclass;\r
761 Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_MASS_STORAGE;\r
762 Dev->BarOffset = 0;\r
763 } else {\r
764 ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);\r
765 }\r
766\r
767 //\r
768 // Iterate over the resources to populate the virtual BARs\r
769 //\r
770 Idx = Dev->BarOffset;\r
771 for (Desc = Dev->Device->Resources, Dev->BarCount = 0;\r
772 Desc->Desc != ACPI_END_TAG_DESCRIPTOR;\r
773 Desc = (VOID *)((UINT8 *)Desc + Desc->Len + 3)) {\r
774\r
775 ASSERT (Desc->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
776 ASSERT (Desc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM);\r
777\r
778 if (Idx >= PCI_MAX_BARS ||\r
779 (Idx == PCI_MAX_BARS - 1 && Desc->AddrSpaceGranularity == 64)) {\r
780 DEBUG ((DEBUG_ERROR,\r
781 "%a: resource count exceeds number of emulated BARs\n",\r
782 __FUNCTION__));\r
783 ASSERT (FALSE);\r
784 break;\r
785 }\r
786\r
787 Dev->ConfigSpace.Device.Bar[Idx] = (UINT32)Desc->AddrRangeMin;\r
788 Dev->BarCount++;\r
789\r
790 if (Desc->AddrSpaceGranularity == 64) {\r
791 Dev->ConfigSpace.Device.Bar[Idx] |= 0x4;\r
792 Dev->ConfigSpace.Device.Bar[++Idx] = (UINT32)RShiftU64 (\r
793 Desc->AddrRangeMin, 32);\r
794 }\r
795 }\r
796}\r