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