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