Merge r68232 to get Windows' rpcrt4.dll to work under ReactOS.
[reactos.git] / reactos / hal / halppc / generic / pci.c
1 /*
2 * PROJECT: ReactOS HAL
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: hal/halx86/generic/pci.c
5 * PURPOSE: PCI Bus Support (Configuration Space, Resource Allocation)
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <hal.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* GLOBALS *******************************************************************/
16
17 BOOLEAN HalpPCIConfigInitialized;
18 ULONG HalpMinPciBus, HalpMaxPciBus;
19 KSPIN_LOCK HalpPCIConfigLock;
20 PCI_CONFIG_HANDLER PCIConfigHandler;
21
22 /* PCI Operation Matrix */
23 UCHAR PCIDeref[4][4] =
24 {
25 {0, 1, 2, 2}, // ULONG-aligned offset
26 {1, 1, 1, 1}, // UCHAR-aligned offset
27 {2, 1, 2, 2}, // USHORT-aligned offset
28 {1, 1, 1, 1} // UCHAR-aligned offset
29 };
30
31 /* Type 1 PCI Bus */
32 PCI_CONFIG_HANDLER PCIConfigHandlerType1 =
33 {
34 /* Synchronization */
35 (FncSync)HalpPCISynchronizeType1,
36 (FncReleaseSync)HalpPCIReleaseSynchronzationType1,
37
38 /* Read */
39 {
40 (FncConfigIO)HalpPCIReadUlongType1,
41 (FncConfigIO)HalpPCIReadUcharType1,
42 (FncConfigIO)HalpPCIReadUshortType1
43 },
44
45 /* Write */
46 {
47 (FncConfigIO)HalpPCIWriteUlongType1,
48 (FncConfigIO)HalpPCIWriteUcharType1,
49 (FncConfigIO)HalpPCIWriteUshortType1
50 }
51 };
52
53 /* Type 2 PCI Bus */
54 PCI_CONFIG_HANDLER PCIConfigHandlerType2 =
55 {
56 /* Synchronization */
57 (FncSync)HalpPCISynchronizeType2,
58 (FncReleaseSync)HalpPCIReleaseSynchronzationType2,
59
60 /* Read */
61 {
62 (FncConfigIO)HalpPCIReadUlongType2,
63 (FncConfigIO)HalpPCIReadUcharType2,
64 (FncConfigIO)HalpPCIReadUshortType2
65 },
66
67 /* Write */
68 {
69 (FncConfigIO)HalpPCIWriteUlongType2,
70 (FncConfigIO)HalpPCIWriteUcharType2,
71 (FncConfigIO)HalpPCIWriteUshortType2
72 }
73 };
74
75 PCIPBUSDATA HalpFakePciBusData =
76 {
77 {
78 PCI_DATA_TAG,
79 PCI_DATA_VERSION,
80 HalpReadPCIConfig,
81 HalpWritePCIConfig,
82 NULL,
83 NULL,
84 {{{0}}},
85 {0, 0, 0, 0}
86 },
87 {{0}},
88 32,
89 };
90
91 BUS_HANDLER HalpFakePciBusHandler =
92 {
93 1,
94 PCIBus,
95 PCIConfiguration,
96 0,
97 NULL,
98 NULL,
99 &HalpFakePciBusData,
100 0,
101 {0, 0, 0, 0},
102 HalpGetPCIData,
103 HalpSetPCIData,
104 NULL,
105 HalpAssignPCISlotResources,
106 NULL,
107 NULL
108 };
109
110 /* TYPE 1 FUNCTIONS **********************************************************/
111
112 VOID
113 NTAPI
114 HalpPCISynchronizeType1(IN PBUS_HANDLER BusHandler,
115 IN PCI_SLOT_NUMBER Slot,
116 IN PKIRQL Irql,
117 IN PPCI_TYPE1_CFG_BITS PciCfg1)
118 {
119 /* Setup the PCI Configuration Register */
120 PciCfg1->u.AsULONG = 0;
121 PciCfg1->u.bits.BusNumber = BusHandler->BusNumber;
122 PciCfg1->u.bits.DeviceNumber = Slot.u.bits.DeviceNumber;
123 PciCfg1->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber;
124 PciCfg1->u.bits.Enable = TRUE;
125
126 /* Acquire the lock */
127 KeRaiseIrql(HIGH_LEVEL, Irql);
128 KiAcquireSpinLock(&HalpPCIConfigLock);
129 }
130
131 VOID
132 NTAPI
133 HalpPCIReleaseSynchronzationType1(IN PBUS_HANDLER BusHandler,
134 IN KIRQL Irql)
135 {
136 PCI_TYPE1_CFG_BITS PciCfg1;
137
138 /* Clear the PCI Configuration Register */
139 PciCfg1.u.AsULONG = 0;
140 WRITE_PORT_ULONG(((PPCIPBUSDATA)BusHandler->BusData)->Config.Type1.Address,
141 PciCfg1.u.AsULONG);
142
143 /* Release the lock */
144 KiReleaseSpinLock(&HalpPCIConfigLock);
145 KeLowerIrql(Irql);
146 }
147
148 TYPE1_READ(HalpPCIReadUcharType1, UCHAR)
149 TYPE1_READ(HalpPCIReadUshortType1, USHORT)
150 TYPE1_READ(HalpPCIReadUlongType1, ULONG)
151 TYPE1_WRITE(HalpPCIWriteUcharType1, UCHAR)
152 TYPE1_WRITE(HalpPCIWriteUshortType1, USHORT)
153 TYPE1_WRITE(HalpPCIWriteUlongType1, ULONG)
154
155 /* TYPE 2 FUNCTIONS **********************************************************/
156
157 VOID
158 NTAPI
159 HalpPCISynchronizeType2(IN PBUS_HANDLER BusHandler,
160 IN PCI_SLOT_NUMBER Slot,
161 IN PKIRQL Irql,
162 IN PPCI_TYPE2_ADDRESS_BITS PciCfg)
163 {
164 PCI_TYPE2_CSE_BITS PciCfg2Cse;
165 PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData;
166
167 /* Setup the configuration register */
168 PciCfg->u.AsUSHORT = 0;
169 PciCfg->u.bits.Agent = (USHORT)Slot.u.bits.DeviceNumber;
170 PciCfg->u.bits.AddressBase = (USHORT)BusData->Config.Type2.Base;
171
172 /* Acquire the lock */
173 KeRaiseIrql(HIGH_LEVEL, Irql);
174 KiAcquireSpinLock(&HalpPCIConfigLock);
175
176 /* Setup the CSE Register */
177 PciCfg2Cse.u.AsUCHAR = 0;
178 PciCfg2Cse.u.bits.Enable = TRUE;
179 PciCfg2Cse.u.bits.FunctionNumber = (UCHAR)Slot.u.bits.FunctionNumber;
180 PciCfg2Cse.u.bits.Key = -1;
181
182 /* Write the bus number and CSE */
183 WRITE_PORT_UCHAR(BusData->Config.Type2.Forward,
184 (UCHAR)BusHandler->BusNumber);
185 WRITE_PORT_UCHAR(BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR);
186 }
187
188 VOID
189 NTAPI
190 HalpPCIReleaseSynchronzationType2(IN PBUS_HANDLER BusHandler,
191 IN KIRQL Irql)
192 {
193 PCI_TYPE2_CSE_BITS PciCfg2Cse;
194 PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData;
195
196 /* Clear CSE and bus number */
197 PciCfg2Cse.u.AsUCHAR = 0;
198 WRITE_PORT_UCHAR(BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR);
199 WRITE_PORT_UCHAR(BusData->Config.Type2.Forward, 0);
200
201 /* Release the lock */
202 KiReleaseSpinLock(&HalpPCIConfigLock);
203 KeLowerIrql(Irql);
204 }
205
206 TYPE2_READ(HalpPCIReadUcharType2, UCHAR)
207 TYPE2_READ(HalpPCIReadUshortType2, USHORT)
208 TYPE2_READ(HalpPCIReadUlongType2, ULONG)
209 TYPE2_WRITE(HalpPCIWriteUcharType2, UCHAR)
210 TYPE2_WRITE(HalpPCIWriteUshortType2, USHORT)
211 TYPE2_WRITE(HalpPCIWriteUlongType2, ULONG)
212
213 /* PCI CONFIGURATION SPACE ***************************************************/
214
215 VOID
216 NTAPI
217 HalpPCIConfig(IN PBUS_HANDLER BusHandler,
218 IN PCI_SLOT_NUMBER Slot,
219 IN PUCHAR Buffer,
220 IN ULONG Offset,
221 IN ULONG Length,
222 IN FncConfigIO *ConfigIO)
223 {
224 KIRQL OldIrql;
225 ULONG i;
226 UCHAR State[20];
227
228 /* Synchronize the operation */
229 PCIConfigHandler.Synchronize(BusHandler, Slot, &OldIrql, State);
230
231 /* Loop every increment */
232 while (Length)
233 {
234 /* Find out the type of read/write we need to do */
235 i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
236
237 /* Do the read/write and return the number of bytes */
238 i = ConfigIO[i]((PPCIPBUSDATA)BusHandler->BusData,
239 State,
240 Buffer,
241 Offset);
242
243 /* Increment the buffer position and offset, and decrease the length */
244 Offset += i;
245 Buffer += i;
246 Length -= i;
247 }
248
249 /* Release the lock and PCI bus */
250 PCIConfigHandler.ReleaseSynchronzation(BusHandler, OldIrql);
251 }
252
253 VOID
254 NTAPI
255 HalpReadPCIConfig(IN PBUS_HANDLER BusHandler,
256 IN PCI_SLOT_NUMBER Slot,
257 IN PVOID Buffer,
258 IN ULONG Offset,
259 IN ULONG Length)
260 {
261 /* Validate the PCI Slot */
262 if (!HalpValidPCISlot(BusHandler, Slot))
263 {
264 /* Fill the buffer with invalid data */
265 RtlFillMemory(Buffer, Length, -1);
266 }
267 else
268 {
269 /* Send the request */
270 HalpPCIConfig(BusHandler,
271 Slot,
272 Buffer,
273 Offset,
274 Length,
275 PCIConfigHandler.ConfigRead);
276 }
277 }
278
279 VOID
280 NTAPI
281 HalpWritePCIConfig(IN PBUS_HANDLER BusHandler,
282 IN PCI_SLOT_NUMBER Slot,
283 IN PVOID Buffer,
284 IN ULONG Offset,
285 IN ULONG Length)
286 {
287 /* Validate the PCI Slot */
288 if (HalpValidPCISlot(BusHandler, Slot))
289 {
290 /* Send the request */
291 HalpPCIConfig(BusHandler,
292 Slot,
293 Buffer,
294 Offset,
295 Length,
296 PCIConfigHandler.ConfigWrite);
297 }
298 }
299
300 BOOLEAN
301 NTAPI
302 HalpValidPCISlot(IN PBUS_HANDLER BusHandler,
303 IN PCI_SLOT_NUMBER Slot)
304 {
305 PCI_SLOT_NUMBER MultiSlot;
306 PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData;
307 UCHAR HeaderType;
308 ULONG Device;
309
310 /* Simple validation */
311 if (Slot.u.bits.Reserved) return FALSE;
312 if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) return FALSE;
313
314 /* Function 0 doesn't need checking */
315 if (!Slot.u.bits.FunctionNumber) return TRUE;
316
317 /* Functions 0+ need Multi-Function support, so check the slot */
318 Device = Slot.u.bits.DeviceNumber;
319 MultiSlot = Slot;
320 MultiSlot.u.bits.FunctionNumber = 0;
321
322 /* Send function 0 request to get the header back */
323 HalpReadPCIConfig(BusHandler,
324 MultiSlot,
325 &HeaderType,
326 FIELD_OFFSET(PCI_COMMON_CONFIG, HeaderType),
327 sizeof(UCHAR));
328
329 /* Now make sure the header is multi-function */
330 if (!(HeaderType & PCI_MULTIFUNCTION) || (HeaderType == 0xFF)) return FALSE;
331 return TRUE;
332 }
333
334 /* HAL PCI CALLBACKS *********************************************************/
335
336 ULONG
337 NTAPI
338 HalpGetPCIData(IN PBUS_HANDLER BusHandler,
339 IN PBUS_HANDLER RootHandler,
340 IN PCI_SLOT_NUMBER Slot,
341 IN PUCHAR Buffer,
342 IN ULONG Offset,
343 IN ULONG Length)
344 {
345 UCHAR PciBuffer[PCI_COMMON_HDR_LENGTH];
346 PPCI_COMMON_CONFIG PciConfig = (PPCI_COMMON_CONFIG)PciBuffer;
347 ULONG Len = 0;
348
349 /* Normalize the length */
350 if (Length > sizeof(PCI_COMMON_CONFIG)) Length = sizeof(PCI_COMMON_CONFIG);
351
352 /* Check if this is a vendor-specific read */
353 if (Offset >= PCI_COMMON_HDR_LENGTH)
354 {
355 /* Read the header */
356 HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, sizeof(ULONG));
357
358 /* Make sure the vendor is valid */
359 if (PciConfig->VendorID == PCI_INVALID_VENDORID) return 0;
360 }
361 else
362 {
363 /* Read the entire header */
364 Len = PCI_COMMON_HDR_LENGTH;
365 HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, Len);
366
367 /* Validate the vendor ID */
368 if (PciConfig->VendorID == PCI_INVALID_VENDORID)
369 {
370 /* It's invalid, but we want to return this much */
371 PciConfig->VendorID = PCI_INVALID_VENDORID;
372 Len = sizeof(USHORT);
373 }
374
375 /* Now check if there's space left */
376 if (Len < Offset) return 0;
377
378 /* There is, so return what's after the offset and normalize */
379 Len -= Offset;
380 if (Len > Length) Len = Length;
381
382 /* Copy the data into the caller's buffer */
383 RtlMoveMemory(Buffer, PciBuffer + Offset, Len);
384
385 /* Update buffer and offset, decrement total length */
386 Offset += Len;
387 Buffer += Len;
388 Length -= Len;
389 }
390
391 /* Now we still have something to copy */
392 if (Length)
393 {
394 /* Check if it's vendor-specific data */
395 if (Offset >= PCI_COMMON_HDR_LENGTH)
396 {
397 /* Read it now */
398 HalpReadPCIConfig(BusHandler, Slot, Buffer, Offset, Length);
399 Len += Length;
400 }
401 }
402
403 /* Update the total length read */
404 return Len;
405 }
406
407 ULONG
408 NTAPI
409 HalpSetPCIData(IN PBUS_HANDLER BusHandler,
410 IN PBUS_HANDLER RootHandler,
411 IN PCI_SLOT_NUMBER Slot,
412 IN PUCHAR Buffer,
413 IN ULONG Offset,
414 IN ULONG Length)
415 {
416 UCHAR PciBuffer[PCI_COMMON_HDR_LENGTH];
417 PPCI_COMMON_CONFIG PciConfig = (PPCI_COMMON_CONFIG)PciBuffer;
418 ULONG Len = 0;
419
420 /* Normalize the length */
421 if (Length > sizeof(PCI_COMMON_CONFIG)) Length = sizeof(PCI_COMMON_CONFIG);
422
423 /* Check if this is a vendor-specific read */
424 if (Offset >= PCI_COMMON_HDR_LENGTH)
425 {
426 /* Read the header */
427 HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, sizeof(ULONG));
428
429 /* Make sure the vendor is valid */
430 if (PciConfig->VendorID == PCI_INVALID_VENDORID) return 0;
431 }
432 else
433 {
434 /* Read the entire header and validate the vendor ID */
435 Len = PCI_COMMON_HDR_LENGTH;
436 HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, Len);
437 if (PciConfig->VendorID == PCI_INVALID_VENDORID) return 0;
438
439 /* Return what's after the offset and normalize */
440 Len -= Offset;
441 if (Len > Length) Len = Length;
442
443 /* Copy the specific caller data */
444 RtlMoveMemory(PciBuffer + Offset, Buffer, Len);
445
446 /* Write the actual configuration data */
447 HalpWritePCIConfig(BusHandler, Slot, PciBuffer + Offset, Offset, Len);
448
449 /* Update buffer and offset, decrement total length */
450 Offset += Len;
451 Buffer += Len;
452 Length -= Len;
453 }
454
455 /* Now we still have something to copy */
456 if (Length)
457 {
458 /* Check if it's vendor-specific data */
459 if (Offset >= PCI_COMMON_HDR_LENGTH)
460 {
461 /* Read it now */
462 HalpWritePCIConfig(BusHandler, Slot, Buffer, Offset, Length);
463 Len += Length;
464 }
465 }
466
467 /* Update the total length read */
468 return Len;
469 }
470
471 NTSTATUS
472 NTAPI
473 HalpSetupPciDeviceForDebugging(IN PVOID LoaderBlock,
474 IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice)
475 {
476 DPRINT1("Unimplemented!\n");
477 return STATUS_NOT_IMPLEMENTED;
478 }
479
480 NTSTATUS
481 NTAPI
482 HalpReleasePciDeviceForDebugging(IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice)
483 {
484 DPRINT1("Unimplemented!\n");
485 return STATUS_NOT_IMPLEMENTED;
486 }
487
488 NTSTATUS
489 NTAPI
490 HalpAssignPCISlotResources(IN PBUS_HANDLER BusHandler,
491 IN PBUS_HANDLER RootHandler,
492 IN PUNICODE_STRING RegistryPath,
493 IN PUNICODE_STRING DriverClassName OPTIONAL,
494 IN PDRIVER_OBJECT DriverObject,
495 IN PDEVICE_OBJECT DeviceObject OPTIONAL,
496 IN ULONG Slot,
497 IN OUT PCM_RESOURCE_LIST *pAllocatedResources)
498 {
499 KeBugCheck(0);
500 return STATUS_SUCCESS;
501 }
502
503 ULONG
504 NTAPI
505 HaliPciInterfaceReadConfig(IN PBUS_HANDLER RootBusHandler,
506 IN ULONG BusNumber,
507 IN PCI_SLOT_NUMBER SlotNumber,
508 IN PVOID Buffer,
509 IN ULONG Offset,
510 IN ULONG Length)
511 {
512 BUS_HANDLER BusHandler;
513 PPCI_COMMON_CONFIG PciData = (PPCI_COMMON_CONFIG)Buffer;
514
515 /* Setup fake PCI Bus handler */
516 RtlCopyMemory(&BusHandler, &HalpFakePciBusHandler, sizeof(BUS_HANDLER));
517 BusHandler.BusNumber = BusNumber;
518
519 /* Read configuration data */
520 HalpReadPCIConfig(&BusHandler, SlotNumber, Buffer, Offset, Length);
521
522 /* Check if caller only wanted at least Vendor ID */
523 if (Length >= 2)
524 {
525 /* Validate it */
526 if (PciData->VendorID != PCI_INVALID_VENDORID)
527 {
528 /* Check if this is the new maximum bus number */
529 if (HalpMaxPciBus < BusHandler.BusNumber)
530 {
531 /* Set it */
532 HalpMaxPciBus = BusHandler.BusNumber;
533 }
534 }
535 }
536
537 /* Return length */
538 return Length;
539 }
540
541 PPCI_REGISTRY_INFO_INTERNAL
542 NTAPI
543 HalpQueryPciRegistryInfo(VOID)
544 {
545 WCHAR NameBuffer[8];
546 OBJECT_ATTRIBUTES ObjectAttributes;
547 UNICODE_STRING KeyName, ConfigName, IdentName;
548 HANDLE KeyHandle, BusKeyHandle;
549 NTSTATUS Status;
550 UCHAR KeyBuffer[sizeof(PPCI_REGISTRY_INFO) + 100];
551 PKEY_VALUE_FULL_INFORMATION ValueInfo = (PVOID)KeyBuffer;
552 ULONG ResultLength;
553 PWSTR Tag;
554 ULONG i;
555 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor;
556 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
557 PPCI_REGISTRY_INFO PciRegInfo;
558 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo;
559
560 /* Setup the object attributes for the key */
561 RtlInitUnicodeString(&KeyName,
562 L"\\Registry\\Machine\\Hardware\\Description\\"
563 L"System\\MultiFunctionAdapter");
564 InitializeObjectAttributes(&ObjectAttributes,
565 &KeyName,
566 OBJ_CASE_INSENSITIVE,
567 NULL,
568 NULL);
569
570 /* Open the key */
571 Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
572 if (!NT_SUCCESS(Status)) return NULL;
573
574 /* Setup the receiving string */
575 KeyName.Buffer = NameBuffer;
576 KeyName.MaximumLength = sizeof(NameBuffer);
577
578 /* Setup the configuration and identifier key names */
579 RtlInitUnicodeString(&ConfigName, L"ConfigurationData");
580 RtlInitUnicodeString(&IdentName, L"Identifier");
581
582 /* Keep looping for each ID */
583 for (i = 0; TRUE; i++)
584 {
585 /* Setup the key name */
586 RtlIntegerToUnicodeString(i, 10, &KeyName);
587 InitializeObjectAttributes(&ObjectAttributes,
588 &KeyName,
589 OBJ_CASE_INSENSITIVE,
590 KeyHandle,
591 NULL);
592
593 /* Open it */
594 Status = ZwOpenKey(&BusKeyHandle, KEY_READ, &ObjectAttributes);
595 if (!NT_SUCCESS(Status))
596 {
597 /* None left, fail */
598 ZwClose(KeyHandle);
599 return NULL;
600 }
601
602 /* Read the registry data */
603 Status = ZwQueryValueKey(BusKeyHandle,
604 &IdentName,
605 KeyValueFullInformation,
606 ValueInfo,
607 sizeof(KeyBuffer),
608 &ResultLength);
609 if (!NT_SUCCESS(Status))
610 {
611 /* Failed, try the next one */
612 ZwClose(BusKeyHandle);
613 continue;
614 }
615
616 /* Get the PCI Tag and validate it */
617 Tag = (PWSTR)((ULONG_PTR)ValueInfo + ValueInfo->DataOffset);
618 if ((Tag[0] != L'P') ||
619 (Tag[1] != L'C') ||
620 (Tag[2] != L'I') ||
621 (Tag[3]))
622 {
623 /* Not a valid PCI entry, skip it */
624 ZwClose(BusKeyHandle);
625 continue;
626 }
627
628 /* Now read our PCI structure */
629 Status = ZwQueryValueKey(BusKeyHandle,
630 &ConfigName,
631 KeyValueFullInformation,
632 ValueInfo,
633 sizeof(KeyBuffer),
634 &ResultLength);
635 ZwClose(BusKeyHandle);
636 if (!NT_SUCCESS(Status)) continue;
637
638 /* We read it OK! Get the actual resource descriptors */
639 FullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)
640 ((ULONG_PTR)ValueInfo + ValueInfo->DataOffset);
641 PartialDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
642 ((ULONG_PTR)FullDescriptor->
643 PartialResourceList.PartialDescriptors);
644
645 /* Check if this is our PCI Registry Information */
646 if (PartialDescriptor->Type == CmResourceTypeDeviceSpecific)
647 {
648 /* Close the key */
649 ZwClose(KeyHandle);
650
651 /* FIXME: Check PnP\PCI\CardList */
652
653 /* Get the PCI information */
654 PciRegInfo = (PPCI_REGISTRY_INFO)(PartialDescriptor + 1);
655
656 /* Allocate the return structure */
657 PciRegistryInfo = ExAllocatePoolWithTag(NonPagedPool,
658 sizeof(PCI_REGISTRY_INFO_INTERNAL),
659 ' laH');
660 if (!PciRegistryInfo) return NULL;
661
662 /* Fill it out */
663 PciRegistryInfo->HardwareMechanism = PciRegInfo->HardwareMechanism;
664 PciRegistryInfo->NoBuses = PciRegInfo->NoBuses;
665 PciRegistryInfo->MajorRevision = PciRegInfo->MajorRevision;
666 PciRegistryInfo->MinorRevision = PciRegInfo->MinorRevision;
667 PciRegistryInfo->ElementCount = 0;
668 }
669 }
670 }
671
672 VOID
673 NTAPI
674 HalpInitializePciStubs(VOID)
675 {
676 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo;
677 UCHAR PciType;
678 PPCIPBUSDATA BusData = (PPCIPBUSDATA)HalpFakePciBusHandler.BusData;
679 ULONG i;
680 PCI_SLOT_NUMBER j;
681 ULONG VendorId = 0;
682
683 /* Query registry information */
684 PciRegistryInfo = HalpQueryPciRegistryInfo();
685 if (!PciRegistryInfo)
686 {
687 /* Assume type 1 */
688 PciType = 1;
689 }
690 else
691 {
692 /* Get the type and free the info structure */
693 PciType = PciRegistryInfo->HardwareMechanism & 0xF;
694 ExFreePool(PciRegistryInfo);
695 }
696
697 /* Initialize the PCI lock */
698 KeInitializeSpinLock(&HalpPCIConfigLock);
699
700 /* Check the type of PCI bus */
701 switch (PciType)
702 {
703 /* Type 1 PCI Bus */
704 case 1:
705
706 /* Copy the Type 1 handler data */
707 RtlCopyMemory(&PCIConfigHandler,
708 &PCIConfigHandlerType1,
709 sizeof(PCIConfigHandler));
710
711 /* Set correct I/O Ports */
712 BusData->Config.Type1.Address = PCI_TYPE1_ADDRESS_PORT;
713 BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT;
714 break;
715
716 /* Type 2 PCI Bus */
717 case 2:
718
719 /* Copy the Type 1 handler data */
720 RtlCopyMemory(&PCIConfigHandler,
721 &PCIConfigHandlerType2,
722 sizeof (PCIConfigHandler));
723
724 /* Set correct I/O Ports */
725 BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT;
726 BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT;
727 BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE;
728
729 /* Only 16 devices supported, not 32 */
730 BusData->MaxDevice = 16;
731 break;
732
733 default:
734
735 /* Invalid type */
736 DbgPrint("HAL: Unnkown PCI type\n");
737 }
738
739 /* Loop all possible buses */
740 for (i = 0; i < 256; i++)
741 {
742 /* Loop all devices */
743 for (j.u.AsULONG = 0; j.u.AsULONG < 32; j.u.AsULONG++)
744 {
745 /* Query the interface */
746 if (HaliPciInterfaceReadConfig(NULL,
747 i,
748 j,
749 &VendorId,
750 0,
751 sizeof(ULONG)))
752 {
753 /* Validate the vendor ID */
754 if ((USHORT)VendorId != PCI_INVALID_VENDORID)
755 {
756 /* Set this as the maximum ID */
757 HalpMaxPciBus = i;
758 break;
759 }
760 }
761 }
762 }
763
764 /* We're done */
765 HalpPCIConfigInitialized = TRUE;
766 }
767
768 VOID
769 NTAPI
770 HalpInitializePciBus(VOID)
771 {
772 /* Initialize the stubs */
773 HalpInitializePciStubs();
774
775 /* FIXME: Initialize NMI Crash Flag */
776 }
777
778 /* EOF */