]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
MdeModulePkg/NonDiscoverablePciDeviceDxe: Fix VS2010/2012 build failure
[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
16296a12
AB
18#include <Library/DxeServicesTableLib.h>\r
19\r
a42e6d44
AB
20#include <IndustryStandard/Acpi.h>\r
21\r
22#include <Protocol/PciRootBridgeIo.h>\r
23\r
24typedef struct {\r
25 EFI_PHYSICAL_ADDRESS AllocAddress;\r
26 VOID *HostAddress;\r
27 EFI_PCI_IO_PROTOCOL_OPERATION Operation;\r
28 UINTN NumberOfBytes;\r
29} NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO;\r
30\r
31//\r
32// Get the resource associated with BAR number 'BarIndex'.\r
33//\r
34STATIC\r
35EFI_STATUS\r
36GetBarResource (\r
37 IN NON_DISCOVERABLE_PCI_DEVICE *Dev,\r
38 IN UINT8 BarIndex,\r
39 OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptor\r
40 )\r
41{\r
42 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;\r
43\r
44 if (BarIndex < Dev->BarOffset) {\r
45 return EFI_NOT_FOUND;\r
46 }\r
47\r
8b78de74 48 BarIndex -= (UINT8)Dev->BarOffset;\r
a42e6d44
AB
49\r
50 for (Desc = Dev->Device->Resources;\r
51 Desc->Desc != ACPI_END_TAG_DESCRIPTOR;\r
52 Desc = (VOID *)((UINT8 *)Desc + Desc->Len + 3)) {\r
53\r
54 if (BarIndex == 0) {\r
55 *Descriptor = Desc;\r
56 return EFI_SUCCESS;\r
57 }\r
58\r
59 BarIndex -= 1;\r
60 }\r
61 return EFI_NOT_FOUND;\r
62}\r
63\r
64STATIC\r
65EFI_STATUS\r
8b78de74 66EFIAPI\r
a42e6d44
AB
67PciIoPollMem (\r
68 IN EFI_PCI_IO_PROTOCOL *This,\r
69 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
70 IN UINT8 BarIndex,\r
71 IN UINT64 Offset,\r
72 IN UINT64 Mask,\r
73 IN UINT64 Value,\r
74 IN UINT64 Delay,\r
75 OUT UINT64 *Result\r
76 )\r
77{\r
78 ASSERT (FALSE);\r
79 return EFI_UNSUPPORTED;\r
80}\r
81\r
82STATIC\r
83EFI_STATUS\r
8b78de74 84EFIAPI\r
a42e6d44
AB
85PciIoPollIo (\r
86 IN EFI_PCI_IO_PROTOCOL *This,\r
87 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
88 IN UINT8 BarIndex,\r
89 IN UINT64 Offset,\r
90 IN UINT64 Mask,\r
91 IN UINT64 Value,\r
92 IN UINT64 Delay,\r
93 OUT UINT64 *Result\r
94 )\r
95{\r
96 ASSERT (FALSE);\r
97 return EFI_UNSUPPORTED;\r
98}\r
99\r
100STATIC\r
101EFI_STATUS\r
8b78de74 102EFIAPI\r
a42e6d44
AB
103PciIoMemRW (\r
104 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
105 IN UINTN Count,\r
106 IN UINTN DstStride,\r
107 IN VOID *Dst,\r
108 IN UINTN SrcStride,\r
109 OUT CONST VOID *Src\r
110 )\r
111{\r
112 volatile UINT8 *Dst8;\r
113 volatile UINT16 *Dst16;\r
114 volatile UINT32 *Dst32;\r
115 volatile CONST UINT8 *Src8;\r
116 volatile CONST UINT16 *Src16;\r
117 volatile CONST UINT32 *Src32;\r
118\r
119 //\r
120 // Loop for each iteration and move the data\r
121 //\r
122 switch (Width & 0x3) {\r
123 case EfiPciWidthUint8:\r
124 Dst8 = (UINT8 *)Dst;\r
125 Src8 = (UINT8 *)Src;\r
126 for (;Count > 0; Count--, Dst8 += DstStride, Src8 += SrcStride) {\r
127 *Dst8 = *Src8;\r
128 }\r
129 break;\r
130 case EfiPciWidthUint16:\r
131 Dst16 = (UINT16 *)Dst;\r
132 Src16 = (UINT16 *)Src;\r
133 for (;Count > 0; Count--, Dst16 += DstStride, Src16 += SrcStride) {\r
134 *Dst16 = *Src16;\r
135 }\r
136 break;\r
137 case EfiPciWidthUint32:\r
138 Dst32 = (UINT32 *)Dst;\r
139 Src32 = (UINT32 *)Src;\r
140 for (;Count > 0; Count--, Dst32 += DstStride, Src32 += SrcStride) {\r
141 *Dst32 = *Src32;\r
142 }\r
143 break;\r
144 default:\r
145 return EFI_INVALID_PARAMETER;\r
146 }\r
147\r
148 return EFI_SUCCESS;\r
149}\r
150\r
151STATIC\r
152EFI_STATUS\r
8b78de74 153EFIAPI\r
a42e6d44
AB
154PciIoMemRead (\r
155 IN EFI_PCI_IO_PROTOCOL *This,\r
156 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
157 IN UINT8 BarIndex,\r
158 IN UINT64 Offset,\r
159 IN UINTN Count,\r
160 IN OUT VOID *Buffer\r
161 )\r
162{\r
163 NON_DISCOVERABLE_PCI_DEVICE *Dev;\r
164 UINTN AlignMask;\r
165 VOID *Address;\r
166 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;\r
167 EFI_STATUS Status;\r
168\r
169 if (Buffer == NULL) {\r
170 return EFI_INVALID_PARAMETER;\r
171 }\r
172\r
173 Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);\r
174\r
175 //\r
176 // Only allow accesses to the BARs we emulate\r
177 //\r
178 Status = GetBarResource (Dev, BarIndex, &Desc);\r
179 if (EFI_ERROR (Status)) {\r
180 return Status;\r
181 }\r
182\r
183 if (Offset + (Count << (Width & 0x3)) > Desc->AddrLen) {\r
184 return EFI_UNSUPPORTED;\r
185 }\r
186\r
187 Address = (VOID *)(UINTN)(Desc->AddrRangeMin + Offset);\r
188 AlignMask = (1 << (Width & 0x03)) - 1;\r
189 if ((UINTN)Address & AlignMask) {\r
190 return EFI_INVALID_PARAMETER;\r
191 }\r
192\r
193 switch (Width) {\r
82bf462e
HW
194 case EfiPciIoWidthUint8:\r
195 case EfiPciIoWidthUint16:\r
196 case EfiPciIoWidthUint32:\r
197 case EfiPciIoWidthUint64:\r
a42e6d44
AB
198 return PciIoMemRW (Width, Count, 1, Buffer, 1, Address);\r
199\r
82bf462e
HW
200 case EfiPciIoWidthFifoUint8:\r
201 case EfiPciIoWidthFifoUint16:\r
202 case EfiPciIoWidthFifoUint32:\r
203 case EfiPciIoWidthFifoUint64:\r
a42e6d44
AB
204 return PciIoMemRW (Width, Count, 1, Buffer, 0, Address);\r
205\r
82bf462e
HW
206 case EfiPciIoWidthFillUint8:\r
207 case EfiPciIoWidthFillUint16:\r
208 case EfiPciIoWidthFillUint32:\r
209 case EfiPciIoWidthFillUint64:\r
a42e6d44
AB
210 return PciIoMemRW (Width, Count, 0, Buffer, 1, Address);\r
211\r
212 default:\r
213 break;\r
214 }\r
215 return EFI_INVALID_PARAMETER;\r
216}\r
217\r
218STATIC\r
219EFI_STATUS\r
8b78de74 220EFIAPI\r
a42e6d44
AB
221PciIoMemWrite (\r
222 IN EFI_PCI_IO_PROTOCOL *This,\r
223 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
224 IN UINT8 BarIndex,\r
225 IN UINT64 Offset,\r
226 IN UINTN Count,\r
227 IN OUT VOID *Buffer\r
228 )\r
229{\r
230 NON_DISCOVERABLE_PCI_DEVICE *Dev;\r
231 UINTN AlignMask;\r
232 VOID *Address;\r
233 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;\r
234 EFI_STATUS Status;\r
235\r
236 if (Buffer == NULL) {\r
237 return EFI_INVALID_PARAMETER;\r
238 }\r
239\r
240 Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);\r
241\r
242 //\r
243 // Only allow accesses to the BARs we emulate\r
244 //\r
245 Status = GetBarResource (Dev, BarIndex, &Desc);\r
246 if (EFI_ERROR (Status)) {\r
247 return Status;\r
248 }\r
249\r
250 if (Offset + (Count << (Width & 0x3)) > Desc->AddrLen) {\r
251 return EFI_UNSUPPORTED;\r
252 }\r
253\r
254 Address = (VOID *)(UINTN)(Desc->AddrRangeMin + Offset);\r
255 AlignMask = (1 << (Width & 0x03)) - 1;\r
256 if ((UINTN)Address & AlignMask) {\r
257 return EFI_INVALID_PARAMETER;\r
258 }\r
259\r
260 switch (Width) {\r
82bf462e
HW
261 case EfiPciIoWidthUint8:\r
262 case EfiPciIoWidthUint16:\r
263 case EfiPciIoWidthUint32:\r
264 case EfiPciIoWidthUint64:\r
a42e6d44
AB
265 return PciIoMemRW (Width, Count, 1, Address, 1, Buffer);\r
266\r
82bf462e
HW
267 case EfiPciIoWidthFifoUint8:\r
268 case EfiPciIoWidthFifoUint16:\r
269 case EfiPciIoWidthFifoUint32:\r
270 case EfiPciIoWidthFifoUint64:\r
a42e6d44
AB
271 return PciIoMemRW (Width, Count, 0, Address, 1, Buffer);\r
272\r
82bf462e
HW
273 case EfiPciIoWidthFillUint8:\r
274 case EfiPciIoWidthFillUint16:\r
275 case EfiPciIoWidthFillUint32:\r
276 case EfiPciIoWidthFillUint64:\r
a42e6d44
AB
277 return PciIoMemRW (Width, Count, 1, Address, 0, Buffer);\r
278\r
279 default:\r
280 break;\r
281 }\r
282 return EFI_INVALID_PARAMETER;\r
283}\r
284\r
285STATIC\r
286EFI_STATUS\r
8b78de74 287EFIAPI\r
a42e6d44
AB
288PciIoIoRead (\r
289 IN EFI_PCI_IO_PROTOCOL *This,\r
290 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
291 IN UINT8 BarIndex,\r
292 IN UINT64 Offset,\r
293 IN UINTN Count,\r
294 IN OUT VOID *Buffer\r
295 )\r
296{\r
297 ASSERT (FALSE);\r
298 return EFI_UNSUPPORTED;\r
299}\r
300\r
301STATIC\r
302EFI_STATUS\r
8b78de74 303EFIAPI\r
a42e6d44
AB
304PciIoIoWrite (\r
305 IN EFI_PCI_IO_PROTOCOL *This,\r
306 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
307 IN UINT8 BarIndex,\r
308 IN UINT64 Offset,\r
309 IN UINTN Count,\r
310 IN OUT VOID *Buffer\r
311 )\r
312{\r
313 ASSERT (FALSE);\r
314 return EFI_UNSUPPORTED;\r
315}\r
316\r
317STATIC\r
318EFI_STATUS\r
8b78de74 319EFIAPI\r
a42e6d44
AB
320PciIoPciRead (\r
321 IN EFI_PCI_IO_PROTOCOL *This,\r
322 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
323 IN UINT32 Offset,\r
324 IN UINTN Count,\r
325 IN OUT VOID *Buffer\r
326 )\r
327{\r
328 NON_DISCOVERABLE_PCI_DEVICE *Dev;\r
329 VOID *Address;\r
330 UINTN Length;\r
331\r
332 if (Width < 0 || Width >= EfiPciIoWidthMaximum || Buffer == NULL) {\r
333 return EFI_INVALID_PARAMETER;\r
334 }\r
335\r
336 Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);\r
337 Address = (UINT8 *)&Dev->ConfigSpace + Offset;\r
338 Length = Count << ((UINTN)Width & 0x3);\r
339\r
340 if (Offset + Length > sizeof (Dev->ConfigSpace)) {\r
341 //\r
342 // Read all zeroes for config space accesses beyond the first\r
343 // 64 bytes\r
344 //\r
345 Length -= sizeof (Dev->ConfigSpace) - Offset;\r
346 ZeroMem ((UINT8 *)Buffer + sizeof (Dev->ConfigSpace) - Offset, Length);\r
347\r
348 Count -= Length >> ((UINTN)Width & 0x3);\r
349 }\r
350 return PciIoMemRW (Width, Count, 1, Buffer, 1, Address);\r
351}\r
352\r
353STATIC\r
354EFI_STATUS\r
8b78de74 355EFIAPI\r
a42e6d44
AB
356PciIoPciWrite (\r
357 IN EFI_PCI_IO_PROTOCOL *This,\r
358 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
359 IN UINT32 Offset,\r
360 IN UINTN Count,\r
361 IN OUT VOID *Buffer\r
362 )\r
363{\r
364 NON_DISCOVERABLE_PCI_DEVICE *Dev;\r
365 VOID *Address;\r
366\r
367 if (Width < 0 || Width >= EfiPciIoWidthMaximum || Buffer == NULL) {\r
368 return EFI_INVALID_PARAMETER;\r
369 }\r
370\r
371 Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);\r
372 Address = (UINT8 *)&Dev->ConfigSpace + Offset;\r
373\r
374 if (Offset + (Count << ((UINTN)Width & 0x3)) > sizeof (Dev->ConfigSpace)) {\r
375 return EFI_UNSUPPORTED;\r
376 }\r
377\r
378 return PciIoMemRW (Width, Count, 1, Address, 1, Buffer);\r
379}\r
380\r
381STATIC\r
382EFI_STATUS\r
8b78de74 383EFIAPI\r
a42e6d44
AB
384PciIoCopyMem (\r
385 IN EFI_PCI_IO_PROTOCOL *This,\r
386 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
387 IN UINT8 DestBarIndex,\r
388 IN UINT64 DestOffset,\r
389 IN UINT8 SrcBarIndex,\r
390 IN UINT64 SrcOffset,\r
391 IN UINTN Count\r
392 )\r
393{\r
394 ASSERT (FALSE);\r
395 return EFI_UNSUPPORTED;\r
396}\r
397\r
398STATIC\r
399EFI_STATUS\r
8b78de74 400EFIAPI\r
a42e6d44
AB
401CoherentPciIoMap (\r
402 IN EFI_PCI_IO_PROTOCOL *This,\r
403 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,\r
404 IN VOID *HostAddress,\r
405 IN OUT UINTN *NumberOfBytes,\r
406 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
407 OUT VOID **Mapping\r
408 )\r
409{\r
410 NON_DISCOVERABLE_PCI_DEVICE *Dev;\r
411 EFI_STATUS Status;\r
412 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo;\r
413\r
414 //\r
415 // If HostAddress exceeds 4 GB, and this device does not support 64-bit DMA\r
416 // addressing, we need to allocate a bounce buffer and copy over the data.\r
417 //\r
418 Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);\r
419 if ((Dev->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0 &&\r
420 (UINTN)HostAddress + *NumberOfBytes > SIZE_4GB) {\r
421\r
422 //\r
423 // Bounce buffering is not possible for consistent mappings\r
424 //\r
425 if (Operation == EfiPciIoOperationBusMasterCommonBuffer) {\r
426 return EFI_UNSUPPORTED;\r
427 }\r
428\r
429 MapInfo = AllocatePool (sizeof *MapInfo);\r
430 if (MapInfo == NULL) {\r
431 return EFI_OUT_OF_RESOURCES;\r
432 }\r
433\r
434 MapInfo->AllocAddress = MAX_UINT32;\r
435 MapInfo->HostAddress = HostAddress;\r
436 MapInfo->Operation = Operation;\r
437 MapInfo->NumberOfBytes = *NumberOfBytes;\r
438\r
439 Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData,\r
440 EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes),\r
441 &MapInfo->AllocAddress);\r
442 if (EFI_ERROR (Status)) {\r
443 //\r
444 // If we fail here, it is likely because the system has no memory below\r
445 // 4 GB to begin with. There is not much we can do about that other than\r
446 // fail the map request.\r
447 //\r
448 FreePool (MapInfo);\r
449 return EFI_DEVICE_ERROR;\r
450 }\r
451 if (Operation == EfiPciIoOperationBusMasterRead) {\r
452 gBS->CopyMem ((VOID *)(UINTN)MapInfo->AllocAddress, HostAddress,\r
453 *NumberOfBytes);\r
454 }\r
455 *DeviceAddress = MapInfo->AllocAddress;\r
456 *Mapping = MapInfo;\r
457 } else {\r
458 *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;\r
459 *Mapping = NULL;\r
460 }\r
461 return EFI_SUCCESS;\r
462}\r
463\r
464STATIC\r
465EFI_STATUS\r
8b78de74 466EFIAPI\r
a42e6d44
AB
467CoherentPciIoUnmap (\r
468 IN EFI_PCI_IO_PROTOCOL *This,\r
469 IN VOID *Mapping\r
470 )\r
471{\r
472 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo;\r
473\r
474 MapInfo = Mapping;\r
475 if (MapInfo != NULL) {\r
476 if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) {\r
477 gBS->CopyMem (MapInfo->HostAddress, (VOID *)(UINTN)MapInfo->AllocAddress,\r
478 MapInfo->NumberOfBytes);\r
479 }\r
480 gBS->FreePages (MapInfo->AllocAddress,\r
481 EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes));\r
482 FreePool (MapInfo);\r
483 }\r
484 return EFI_SUCCESS;\r
485}\r
486\r
487STATIC\r
488EFI_STATUS\r
8b78de74 489EFIAPI\r
a42e6d44
AB
490CoherentPciIoAllocateBuffer (\r
491 IN EFI_PCI_IO_PROTOCOL *This,\r
492 IN EFI_ALLOCATE_TYPE Type,\r
493 IN EFI_MEMORY_TYPE MemoryType,\r
494 IN UINTN Pages,\r
495 OUT VOID **HostAddress,\r
496 IN UINT64 Attributes\r
497 )\r
498{\r
499 NON_DISCOVERABLE_PCI_DEVICE *Dev;\r
500 EFI_PHYSICAL_ADDRESS AllocAddress;\r
501 EFI_ALLOCATE_TYPE AllocType;\r
502 EFI_STATUS Status;\r
503\r
504 if ((Attributes & ~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE |\r
505 EFI_PCI_ATTRIBUTE_MEMORY_CACHED)) != 0) {\r
506 return EFI_UNSUPPORTED;\r
507 }\r
508\r
509 //\r
510 // Allocate below 4 GB if the dual address cycle attribute has not\r
511 // been set. If the system has no memory available below 4 GB, there\r
512 // is little we can do except propagate the error.\r
513 //\r
514 Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);\r
515 if ((Dev->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0) {\r
516 AllocAddress = MAX_UINT32;\r
517 AllocType = AllocateMaxAddress;\r
518 } else {\r
519 AllocType = AllocateAnyPages;\r
520 }\r
521\r
522 Status = gBS->AllocatePages (AllocType, MemoryType, Pages, &AllocAddress);\r
523 if (!EFI_ERROR (Status)) {\r
524 *HostAddress = (VOID *)(UINTN)AllocAddress;\r
525 }\r
526 return Status;\r
527}\r
528\r
529STATIC\r
530EFI_STATUS\r
8b78de74 531EFIAPI\r
a42e6d44
AB
532CoherentPciIoFreeBuffer (\r
533 IN EFI_PCI_IO_PROTOCOL *This,\r
534 IN UINTN Pages,\r
535 IN VOID *HostAddress\r
536 )\r
537{\r
538 FreePages (HostAddress, Pages);\r
539 return EFI_SUCCESS;\r
540}\r
541\r
16296a12
AB
542STATIC\r
543EFI_STATUS\r
544EFIAPI\r
545NonCoherentPciIoFreeBuffer (\r
546 IN EFI_PCI_IO_PROTOCOL *This,\r
547 IN UINTN Pages,\r
548 IN VOID *HostAddress\r
549 )\r
550{\r
551 NON_DISCOVERABLE_PCI_DEVICE *Dev;\r
552 LIST_ENTRY *Entry;\r
553 EFI_STATUS Status;\r
554 NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc;\r
555 BOOLEAN Found;\r
556\r
557 Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);\r
558\r
559 Found = FALSE;\r
1525ff38 560 Alloc = NULL;\r
16296a12
AB
561\r
562 //\r
563 // Find the uncached allocation list entry associated\r
564 // with this allocation\r
565 //\r
566 for (Entry = Dev->UncachedAllocationList.ForwardLink;\r
567 Entry != &Dev->UncachedAllocationList;\r
568 Entry = Entry->ForwardLink) {\r
569\r
570 Alloc = BASE_CR (Entry, NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION, List);\r
571 if (Alloc->HostAddress == HostAddress && Alloc->NumPages == Pages) {\r
572 //\r
573 // We are freeing the exact allocation we were given\r
574 // before by AllocateBuffer()\r
575 //\r
576 Found = TRUE;\r
577 break;\r
578 }\r
579 }\r
580\r
581 if (!Found) {\r
582 ASSERT_EFI_ERROR (EFI_NOT_FOUND);\r
583 return EFI_NOT_FOUND;\r
584 }\r
585\r
586 RemoveEntryList (&Alloc->List);\r
587\r
588 Status = gDS->SetMemorySpaceAttributes (\r
589 (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,\r
590 EFI_PAGES_TO_SIZE (Pages),\r
591 Alloc->Attributes);\r
592 if (EFI_ERROR (Status)) {\r
593 goto FreeAlloc;\r
594 }\r
595\r
596 //\r
597 // If we fail to restore the original attributes, it is better to leak the\r
598 // memory than to return it to the heap\r
599 //\r
600 FreePages (HostAddress, Pages);\r
601\r
602FreeAlloc:\r
603 FreePool (Alloc);\r
604 return Status;\r
605}\r
606\r
607STATIC\r
608EFI_STATUS\r
609EFIAPI\r
610NonCoherentPciIoAllocateBuffer (\r
611 IN EFI_PCI_IO_PROTOCOL *This,\r
612 IN EFI_ALLOCATE_TYPE Type,\r
613 IN EFI_MEMORY_TYPE MemoryType,\r
614 IN UINTN Pages,\r
615 OUT VOID **HostAddress,\r
616 IN UINT64 Attributes\r
617 )\r
618{\r
619 NON_DISCOVERABLE_PCI_DEVICE *Dev;\r
620 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;\r
621 EFI_STATUS Status;\r
622 UINT64 MemType;\r
623 NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc;\r
624 VOID *AllocAddress;\r
625\r
626 Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);\r
627\r
628 Status = CoherentPciIoAllocateBuffer (This, Type, MemoryType, Pages,\r
629 &AllocAddress, Attributes);\r
630 if (EFI_ERROR (Status)) {\r
631 return Status;\r
632 }\r
633\r
634 Status = gDS->GetMemorySpaceDescriptor (\r
635 (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress,\r
636 &GcdDescriptor);\r
637 if (EFI_ERROR (Status)) {\r
638 goto FreeBuffer;\r
639 }\r
640\r
641 if ((GcdDescriptor.Capabilities & (EFI_MEMORY_WC | EFI_MEMORY_UC)) == 0) {\r
642 Status = EFI_UNSUPPORTED;\r
643 goto FreeBuffer;\r
644 }\r
645\r
646 //\r
647 // Set the preferred memory attributes\r
648 //\r
649 if ((Attributes & EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE) != 0 ||\r
650 (GcdDescriptor.Capabilities & EFI_MEMORY_UC) == 0) {\r
651 //\r
652 // Use write combining if it was requested, or if it is the only\r
653 // type supported by the region.\r
654 //\r
655 MemType = EFI_MEMORY_WC;\r
656 } else {\r
657 MemType = EFI_MEMORY_UC;\r
658 }\r
659\r
660 Alloc = AllocatePool (sizeof *Alloc);\r
661 if (Alloc == NULL) {\r
662 goto FreeBuffer;\r
663 }\r
664\r
665 Alloc->HostAddress = AllocAddress;\r
666 Alloc->NumPages = Pages;\r
667 Alloc->Attributes = GcdDescriptor.Attributes;\r
668\r
669 //\r
670 // Record this allocation in the linked list, so we\r
671 // can restore the memory space attributes later\r
672 //\r
673 InsertHeadList (&Dev->UncachedAllocationList, &Alloc->List);\r
674\r
675 Status = gDS->SetMemorySpaceAttributes (\r
676 (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress,\r
677 EFI_PAGES_TO_SIZE (Pages),\r
678 MemType);\r
679 if (EFI_ERROR (Status)) {\r
680 goto RemoveList;\r
681 }\r
682\r
683 Status = mCpu->FlushDataCache (\r
684 mCpu,\r
685 (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress,\r
686 EFI_PAGES_TO_SIZE (Pages),\r
687 EfiCpuFlushTypeInvalidate);\r
688 if (EFI_ERROR (Status)) {\r
689 goto RemoveList;\r
690 }\r
691\r
692 *HostAddress = AllocAddress;\r
693\r
694 return EFI_SUCCESS;\r
695\r
696RemoveList:\r
697 RemoveEntryList (&Alloc->List);\r
698 FreePool (Alloc);\r
699\r
700FreeBuffer:\r
701 CoherentPciIoFreeBuffer (This, Pages, AllocAddress);\r
702 return Status;\r
703}\r
704\r
705STATIC\r
706EFI_STATUS\r
707EFIAPI\r
708NonCoherentPciIoMap (\r
709 IN EFI_PCI_IO_PROTOCOL *This,\r
710 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,\r
711 IN VOID *HostAddress,\r
712 IN OUT UINTN *NumberOfBytes,\r
713 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
714 OUT VOID **Mapping\r
715 )\r
716{\r
717 NON_DISCOVERABLE_PCI_DEVICE *Dev;\r
718 EFI_STATUS Status;\r
719 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo;\r
720 UINTN AlignMask;\r
721 VOID *AllocAddress;\r
722 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;\r
723 BOOLEAN Bounce;\r
724\r
725 MapInfo = AllocatePool (sizeof *MapInfo);\r
726 if (MapInfo == NULL) {\r
727 return EFI_OUT_OF_RESOURCES;\r
728 }\r
729\r
730 MapInfo->HostAddress = HostAddress;\r
731 MapInfo->Operation = Operation;\r
732 MapInfo->NumberOfBytes = *NumberOfBytes;\r
733\r
734 Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);\r
735\r
736 //\r
737 // If this device does not support 64-bit DMA addressing, we need to allocate\r
738 // a bounce buffer and copy over the data in case HostAddress >= 4 GB.\r
739 //\r
740 Bounce = ((Dev->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0 &&\r
741 (UINTN)HostAddress + *NumberOfBytes > SIZE_4GB);\r
742\r
743 if (!Bounce) {\r
744 switch (Operation) {\r
745 case EfiPciIoOperationBusMasterRead:\r
746 case EfiPciIoOperationBusMasterWrite:\r
747 //\r
748 // For streaming DMA, it is sufficient if the buffer is aligned to\r
749 // the CPUs DMA buffer alignment.\r
750 //\r
751 AlignMask = mCpu->DmaBufferAlignment - 1;\r
752 if ((((UINTN) HostAddress | *NumberOfBytes) & AlignMask) == 0) {\r
753 break;\r
754 }\r
755 // fall through\r
756\r
757 case EfiPciIoOperationBusMasterCommonBuffer:\r
758 //\r
759 // Check whether the host address refers to an uncached mapping.\r
760 //\r
761 Status = gDS->GetMemorySpaceDescriptor (\r
762 (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,\r
763 &GcdDescriptor);\r
764 if (EFI_ERROR (Status) ||\r
765 (GcdDescriptor.Attributes & (EFI_MEMORY_WB|EFI_MEMORY_WT)) != 0) {\r
766 Bounce = TRUE;\r
767 }\r
768 break;\r
769\r
770 default:\r
771 ASSERT (FALSE);\r
772 }\r
773 }\r
774\r
775 if (Bounce) {\r
776 if (Operation == EfiPciIoOperationBusMasterCommonBuffer) {\r
777 Status = EFI_DEVICE_ERROR;\r
778 goto FreeMapInfo;\r
779 }\r
780\r
781 Status = NonCoherentPciIoAllocateBuffer (This, AllocateAnyPages,\r
782 EfiBootServicesData, EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes),\r
783 &AllocAddress, EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE);\r
784 if (EFI_ERROR (Status)) {\r
785 goto FreeMapInfo;\r
786 }\r
787 MapInfo->AllocAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress;\r
788 if (Operation == EfiPciIoOperationBusMasterRead) {\r
789 gBS->CopyMem (AllocAddress, HostAddress, *NumberOfBytes);\r
790 }\r
791 *DeviceAddress = MapInfo->AllocAddress;\r
792 } else {\r
793 MapInfo->AllocAddress = 0;\r
794 *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;\r
795\r
796 //\r
797 // We are not using a bounce buffer: the mapping is sufficiently\r
798 // aligned to allow us to simply flush the caches. Note that cleaning\r
799 // the caches is necessary for both data directions:\r
800 // - for bus master read, we want the latest data to be present\r
801 // in main memory\r
802 // - for bus master write, we don't want any stale dirty cachelines that\r
803 // may be written back unexpectedly, and clobber the data written to\r
804 // main memory by the device.\r
805 //\r
806 mCpu->FlushDataCache (mCpu, (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,\r
807 *NumberOfBytes, EfiCpuFlushTypeWriteBack);\r
808 }\r
809\r
810 *Mapping = MapInfo;\r
811 return EFI_SUCCESS;\r
812\r
813FreeMapInfo:\r
814 FreePool (MapInfo);\r
815\r
816 return Status;\r
817}\r
818\r
819STATIC\r
820EFI_STATUS\r
821EFIAPI\r
822NonCoherentPciIoUnmap (\r
823 IN EFI_PCI_IO_PROTOCOL *This,\r
824 IN VOID *Mapping\r
825 )\r
826{\r
827 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo;\r
828\r
829 if (Mapping == NULL) {\r
830 return EFI_DEVICE_ERROR;\r
831 }\r
832\r
833 MapInfo = Mapping;\r
834 if (MapInfo->AllocAddress != 0) {\r
835 //\r
836 // We are using a bounce buffer: copy back the data if necessary,\r
837 // and free the buffer.\r
838 //\r
839 if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) {\r
840 gBS->CopyMem (MapInfo->HostAddress, (VOID *)(UINTN)MapInfo->AllocAddress,\r
841 MapInfo->NumberOfBytes);\r
842 }\r
843 NonCoherentPciIoFreeBuffer (This,\r
844 EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes),\r
845 (VOID *)(UINTN)MapInfo->AllocAddress);\r
846 } else {\r
847 //\r
848 // We are *not* using a bounce buffer: if this is a bus master write,\r
849 // we have to invalidate the caches so the CPU will see the uncached\r
850 // data written by the device.\r
851 //\r
852 if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) {\r
853 mCpu->FlushDataCache (mCpu,\r
854 (EFI_PHYSICAL_ADDRESS)(UINTN)MapInfo->HostAddress,\r
855 MapInfo->NumberOfBytes, EfiCpuFlushTypeInvalidate);\r
856 }\r
857 }\r
858 FreePool (MapInfo);\r
859 return EFI_SUCCESS;\r
860}\r
a42e6d44
AB
861\r
862STATIC\r
863EFI_STATUS\r
8b78de74 864EFIAPI\r
a42e6d44
AB
865PciIoFlush (\r
866 IN EFI_PCI_IO_PROTOCOL *This\r
867 )\r
868{\r
869 return EFI_SUCCESS;\r
870}\r
871\r
872STATIC\r
873EFI_STATUS\r
8b78de74 874EFIAPI\r
a42e6d44
AB
875PciIoGetLocation (\r
876 IN EFI_PCI_IO_PROTOCOL *This,\r
877 OUT UINTN *SegmentNumber,\r
878 OUT UINTN *BusNumber,\r
879 OUT UINTN *DeviceNumber,\r
880 OUT UINTN *FunctionNumber\r
881 )\r
882{\r
883 if (SegmentNumber == NULL ||\r
884 BusNumber == NULL ||\r
885 DeviceNumber == NULL ||\r
886 FunctionNumber == NULL) {\r
887 return EFI_INVALID_PARAMETER;\r
888 }\r
889\r
890 *SegmentNumber = 0;\r
891 *BusNumber = 0xff;\r
892 *DeviceNumber = 0;\r
893 *FunctionNumber = 0;\r
894\r
895 return EFI_SUCCESS;\r
896}\r
897\r
898STATIC\r
899EFI_STATUS\r
8b78de74 900EFIAPI\r
a42e6d44
AB
901PciIoAttributes (\r
902 IN EFI_PCI_IO_PROTOCOL *This,\r
903 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,\r
904 IN UINT64 Attributes,\r
905 OUT UINT64 *Result OPTIONAL\r
906 )\r
907{\r
908 NON_DISCOVERABLE_PCI_DEVICE *Dev;\r
909 BOOLEAN Enable;\r
910\r
911 Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);\r
912\r
913 Enable = FALSE;\r
914 switch (Operation) {\r
915 case EfiPciIoAttributeOperationGet:\r
916 if (Result == NULL) {\r
917 return EFI_INVALID_PARAMETER;\r
918 }\r
919 *Result = Dev->Attributes;\r
920 break;\r
921\r
922 case EfiPciIoAttributeOperationSupported:\r
923 if (Result == NULL) {\r
924 return EFI_INVALID_PARAMETER;\r
925 }\r
926 *Result = EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;\r
927 break;\r
928\r
929 case EfiPciIoAttributeOperationEnable:\r
930 Attributes |= Dev->Attributes;\r
931 case EfiPciIoAttributeOperationSet:\r
932 Enable = ((~Dev->Attributes & Attributes) & EFI_PCI_DEVICE_ENABLE) != 0;\r
933 Dev->Attributes = Attributes;\r
934 break;\r
935\r
936 case EfiPciIoAttributeOperationDisable:\r
937 Dev->Attributes &= ~Attributes;\r
938 break;\r
939\r
940 default:\r
941 return EFI_INVALID_PARAMETER;\r
942 };\r
943\r
944 //\r
945 // If we're setting any of the EFI_PCI_DEVICE_ENABLE bits, perform\r
946 // the device specific initialization now.\r
947 //\r
948 if (Enable && !Dev->Enabled && Dev->Device->Initialize != NULL) {\r
949 Dev->Device->Initialize (Dev->Device);\r
950 Dev->Enabled = TRUE;\r
951 }\r
952 return EFI_SUCCESS;\r
953}\r
954\r
955STATIC\r
956EFI_STATUS\r
8b78de74 957EFIAPI\r
a42e6d44
AB
958PciIoGetBarAttributes (\r
959 IN EFI_PCI_IO_PROTOCOL *This,\r
960 IN UINT8 BarIndex,\r
961 OUT UINT64 *Supports OPTIONAL,\r
962 OUT VOID **Resources OPTIONAL\r
963 )\r
964{\r
965 NON_DISCOVERABLE_PCI_DEVICE *Dev;\r
966 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor, *BarDesc;\r
967 EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
968 EFI_STATUS Status;\r
969\r
970 if (Supports == NULL && Resources == NULL) {\r
971 return EFI_INVALID_PARAMETER;\r
972 }\r
973\r
974 Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);\r
975\r
976 Status = GetBarResource (Dev, BarIndex, &BarDesc);\r
977 if (EFI_ERROR (Status)) {\r
978 return Status;\r
979 }\r
980\r
981 //\r
982 // Don't expose any configurable attributes for our emulated BAR\r
983 //\r
984 if (Supports != NULL) {\r
985 *Supports = 0;\r
986 }\r
987\r
988 if (Resources != NULL) {\r
989 Descriptor = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +\r
990 sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
991 if (Descriptor == NULL) {\r
992 return EFI_OUT_OF_RESOURCES;\r
993 }\r
994\r
995 CopyMem (Descriptor, BarDesc, sizeof *Descriptor);\r
996\r
997 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);\r
998 End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
999 End->Checksum = 0;\r
1000\r
1001 *Resources = Descriptor;\r
1002 }\r
1003 return EFI_SUCCESS;\r
1004}\r
1005\r
1006STATIC\r
1007EFI_STATUS\r
8b78de74 1008EFIAPI\r
a42e6d44
AB
1009PciIoSetBarAttributes (\r
1010 IN EFI_PCI_IO_PROTOCOL *This,\r
1011 IN UINT64 Attributes,\r
1012 IN UINT8 BarIndex,\r
1013 IN OUT UINT64 *Offset,\r
1014 IN OUT UINT64 *Length\r
1015 )\r
1016{\r
1017 ASSERT (FALSE);\r
1018 return EFI_UNSUPPORTED;\r
1019}\r
1020\r
1021STATIC CONST EFI_PCI_IO_PROTOCOL PciIoTemplate =\r
1022{\r
1023 PciIoPollMem,\r
1024 PciIoPollIo,\r
1025 { PciIoMemRead, PciIoMemWrite },\r
1026 { PciIoIoRead, PciIoIoWrite },\r
1027 { PciIoPciRead, PciIoPciWrite },\r
1028 PciIoCopyMem,\r
1029 CoherentPciIoMap,\r
1030 CoherentPciIoUnmap,\r
1031 CoherentPciIoAllocateBuffer,\r
1032 CoherentPciIoFreeBuffer,\r
1033 PciIoFlush,\r
1034 PciIoGetLocation,\r
1035 PciIoAttributes,\r
1036 PciIoGetBarAttributes,\r
1037 PciIoSetBarAttributes,\r
1038 0,\r
1039 0\r
1040};\r
1041\r
1042VOID\r
1043InitializePciIoProtocol (\r
1044 NON_DISCOVERABLE_PCI_DEVICE *Dev\r
1045 )\r
1046{\r
1047 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;\r
1048 INTN Idx;\r
1049\r
16296a12
AB
1050 InitializeListHead (&Dev->UncachedAllocationList);\r
1051\r
a42e6d44
AB
1052 Dev->ConfigSpace.Hdr.VendorId = PCI_ID_VENDOR_UNKNOWN;\r
1053 Dev->ConfigSpace.Hdr.DeviceId = PCI_ID_DEVICE_DONTCARE;\r
1054\r
1055 // Copy protocol structure\r
1056 CopyMem(&Dev->PciIo, &PciIoTemplate, sizeof PciIoTemplate);\r
1057\r
16296a12
AB
1058 if (Dev->Device->DmaType == NonDiscoverableDeviceDmaTypeNonCoherent) {\r
1059 Dev->PciIo.AllocateBuffer = NonCoherentPciIoAllocateBuffer;\r
1060 Dev->PciIo.FreeBuffer = NonCoherentPciIoFreeBuffer;\r
1061 Dev->PciIo.Map = NonCoherentPciIoMap;\r
1062 Dev->PciIo.Unmap = NonCoherentPciIoUnmap;\r
1063 }\r
1064\r
a42e6d44
AB
1065 if (CompareGuid (Dev->Device->Type, &gEdkiiNonDiscoverableAhciDeviceGuid)) {\r
1066 Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_MASS_STORAGE_AHCI;\r
1067 Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_MASS_STORAGE_SATADPA;\r
1068 Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_MASS_STORAGE;\r
1069 Dev->BarOffset = 5;\r
1070 } else if (CompareGuid (Dev->Device->Type,\r
1071 &gEdkiiNonDiscoverableEhciDeviceGuid)) {\r
1072 Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_EHCI;\r
1073 Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_SERIAL_USB;\r
1074 Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_SERIAL;\r
1075 Dev->BarOffset = 0;\r
1076 } else if (CompareGuid (Dev->Device->Type,\r
1077 &gEdkiiNonDiscoverableNvmeDeviceGuid)) {\r
1078 Dev->ConfigSpace.Hdr.ClassCode[0] = 0x2; // PCI_IF_NVMHCI\r
1079 Dev->ConfigSpace.Hdr.ClassCode[1] = 0x8; // PCI_CLASS_MASS_STORAGE_NVM\r
1080 Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_MASS_STORAGE;\r
1081 Dev->BarOffset = 0;\r
1082 } else if (CompareGuid (Dev->Device->Type,\r
1083 &gEdkiiNonDiscoverableOhciDeviceGuid)) {\r
1084 Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_OHCI;\r
1085 Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_SERIAL_USB;\r
1086 Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_SERIAL;\r
1087 Dev->BarOffset = 0;\r
1088 } else if (CompareGuid (Dev->Device->Type,\r
1089 &gEdkiiNonDiscoverableSdhciDeviceGuid)) {\r
1090 Dev->ConfigSpace.Hdr.ClassCode[0] = 0x0; // don't care\r
1091 Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_SUBCLASS_SD_HOST_CONTROLLER;\r
1092 Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_SYSTEM_PERIPHERAL;\r
1093 Dev->BarOffset = 0;\r
1094 } else if (CompareGuid (Dev->Device->Type,\r
1095 &gEdkiiNonDiscoverableXhciDeviceGuid)) {\r
1096 Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_XHCI;\r
1097 Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_SERIAL_USB;\r
1098 Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_SERIAL;\r
1099 Dev->BarOffset = 0;\r
1100 } else if (CompareGuid (Dev->Device->Type,\r
1101 &gEdkiiNonDiscoverableUhciDeviceGuid)) {\r
1102 Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_UHCI;\r
1103 Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_SERIAL_USB;\r
1104 Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_SERIAL;\r
1105 Dev->BarOffset = 0;\r
1106 } else if (CompareGuid (Dev->Device->Type,\r
1107 &gEdkiiNonDiscoverableUfsDeviceGuid)) {\r
1108 Dev->ConfigSpace.Hdr.ClassCode[0] = 0x0; // don't care\r
1109 Dev->ConfigSpace.Hdr.ClassCode[1] = 0x9; // UFS controller subclass;\r
1110 Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_MASS_STORAGE;\r
1111 Dev->BarOffset = 0;\r
1112 } else {\r
1113 ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);\r
1114 }\r
1115\r
1116 //\r
1117 // Iterate over the resources to populate the virtual BARs\r
1118 //\r
1119 Idx = Dev->BarOffset;\r
1120 for (Desc = Dev->Device->Resources, Dev->BarCount = 0;\r
1121 Desc->Desc != ACPI_END_TAG_DESCRIPTOR;\r
1122 Desc = (VOID *)((UINT8 *)Desc + Desc->Len + 3)) {\r
1123\r
1124 ASSERT (Desc->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
1125 ASSERT (Desc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM);\r
1126\r
1127 if (Idx >= PCI_MAX_BARS ||\r
1128 (Idx == PCI_MAX_BARS - 1 && Desc->AddrSpaceGranularity == 64)) {\r
1129 DEBUG ((DEBUG_ERROR,\r
1130 "%a: resource count exceeds number of emulated BARs\n",\r
1131 __FUNCTION__));\r
1132 ASSERT (FALSE);\r
1133 break;\r
1134 }\r
1135\r
1136 Dev->ConfigSpace.Device.Bar[Idx] = (UINT32)Desc->AddrRangeMin;\r
1137 Dev->BarCount++;\r
1138\r
1139 if (Desc->AddrSpaceGranularity == 64) {\r
1140 Dev->ConfigSpace.Device.Bar[Idx] |= 0x4;\r
1141 Dev->ConfigSpace.Device.Bar[++Idx] = (UINT32)RShiftU64 (\r
1142 Desc->AddrRangeMin, 32);\r
1143 }\r
1144 }\r
1145}\r