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