2606ea24f783f3582917e95d51dd7b3d391667ff
[reactos.git] / reactos / hal / halx86 / generic / legacy / bussupp.c
1 /*
2 * PROJECT: ReactOS HAL
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: hal/halx86/generic/legacy/bussupp.c
5 * PURPOSE: HAL Legacy Bus Support Code
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <hal.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* GLOBALS ********************************************************************/
16
17 extern KSPIN_LOCK HalpPCIConfigLock;
18 ULONG HalpPciIrqMask;
19
20 /* PRIVATE FUNCTIONS **********************************************************/
21
22 PBUS_HANDLER
23 NTAPI
24 HalpAllocateBusHandler(IN INTERFACE_TYPE InterfaceType,
25 IN BUS_DATA_TYPE BusDataType,
26 IN ULONG BusNumber,
27 IN INTERFACE_TYPE ParentBusInterfaceType,
28 IN ULONG ParentBusNumber,
29 IN ULONG BusSpecificData)
30 {
31 PBUS_HANDLER Bus;
32
33 /* Register the bus handler */
34 HalRegisterBusHandler(InterfaceType,
35 BusDataType,
36 BusNumber,
37 ParentBusInterfaceType,
38 ParentBusNumber,
39 BusSpecificData,
40 NULL,
41 &Bus);
42 if (!Bus) return NULL;
43
44 /* Check for a valid interface */
45 if (InterfaceType != InterfaceTypeUndefined)
46 {
47 /* Allocate address ranges and zero them out */
48 Bus->BusAddresses = ExAllocatePoolWithTag(NonPagedPool,
49 sizeof(SUPPORTED_RANGES),
50 ' laH');
51 RtlZeroMemory(Bus->BusAddresses, sizeof(SUPPORTED_RANGES));
52
53 /* Build the data structure */
54 Bus->BusAddresses->Version = HAL_SUPPORTED_RANGE_VERSION;
55 Bus->BusAddresses->Dma.Limit = 7;
56 Bus->BusAddresses->Memory.Limit = 0xFFFFFFFF;
57 Bus->BusAddresses->IO.Limit = 0xFFFF;
58 Bus->BusAddresses->IO.SystemAddressSpace = 1;
59 Bus->BusAddresses->PrefetchMemory.Base = 1;
60 }
61
62 /* Return the bus address */
63 return Bus;
64 }
65
66 VOID
67 NTAPI
68 HalpRegisterInternalBusHandlers(VOID)
69 {
70 PBUS_HANDLER Bus;
71
72 /* Only do processor 1 */
73 if (KeGetCurrentPrcb()->Number) return;
74
75 /* Register root support */
76 HalpInitBusHandler();
77
78 /* Allocate the system bus */
79 Bus = HalpAllocateBusHandler(Internal,
80 ConfigurationSpaceUndefined,
81 0,
82 InterfaceTypeUndefined,
83 0,
84 0);
85 DPRINT1("Registering Internal Bus: %p\n", Bus);
86 if (Bus)
87 {
88 /* Set it up */
89 Bus->GetInterruptVector = HalpGetSystemInterruptVector;
90 Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
91 }
92
93 /* Allocate the CMOS bus */
94 Bus = HalpAllocateBusHandler(InterfaceTypeUndefined,
95 Cmos,
96 0,
97 InterfaceTypeUndefined,
98 0,
99 0);
100 DPRINT1("Registering CMOS Bus: %p\n", Bus);
101 if (Bus)
102 {
103 /* Set it up */
104 Bus->GetBusData = HalpcGetCmosData;
105 Bus->SetBusData = HalpcSetCmosData;
106 }
107
108 /* Allocate the CMOS bus */
109 Bus = HalpAllocateBusHandler(InterfaceTypeUndefined,
110 Cmos,
111 1,
112 InterfaceTypeUndefined,
113 0,
114 0);
115 DPRINT1("Registering CMOS Bus: %p\n", Bus);
116 if (Bus)
117 {
118 /* Set it up */
119 Bus->GetBusData = HalpcGetCmosData;
120 Bus->SetBusData = HalpcSetCmosData;
121 }
122
123 /* Allocate ISA bus */
124 Bus = HalpAllocateBusHandler(Isa,
125 ConfigurationSpaceUndefined,
126 0,
127 Internal,
128 0,
129 0);
130 DPRINT1("Registering ISA Bus: %p\n", Bus);
131 if (Bus)
132 {
133 /* Set it up */
134 Bus->GetBusData = HalpNoBusData;
135 Bus->BusAddresses->Memory.Limit = 0xFFFFFF;
136 Bus->TranslateBusAddress = HalpTranslateIsaBusAddress;
137 }
138
139 /* No support for EISA or MCA */
140 ASSERT(HalpBusType == MACHINE_TYPE_ISA);
141 }
142
143 #ifndef _MINIHAL_
144 NTSTATUS
145 NTAPI
146 HalpMarkChipsetDecode(BOOLEAN OverrideEnable)
147 {
148 NTSTATUS Status;
149 UNICODE_STRING KeyString;
150 ULONG Data = OverrideEnable;
151 HANDLE KeyHandle, Handle;
152
153 /* Open CCS key */
154 RtlInitUnicodeString(&KeyString,
155 L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET");
156 Status = HalpOpenRegistryKey(&Handle, 0, &KeyString, KEY_ALL_ACCESS, FALSE);
157 if (NT_SUCCESS(Status))
158 {
159 /* Open PNP Bios key */
160 RtlInitUnicodeString(&KeyString, L"Control\\Biosinfo\\PNPBios");
161 Status = HalpOpenRegistryKey(&KeyHandle,
162 Handle,
163 &KeyString,
164 KEY_ALL_ACCESS,
165 TRUE);
166
167 /* Close root key */
168 ZwClose(Handle);
169
170 /* Check if PNP BIOS key exists */
171 if (NT_SUCCESS(Status))
172 {
173 /* Set the override value */
174 RtlInitUnicodeString(&KeyString, L"FullDecodeChipsetOverride");
175 Status = ZwSetValueKey(KeyHandle,
176 &KeyString,
177 0,
178 REG_DWORD,
179 &Data,
180 sizeof(Data));
181
182 /* Close subkey */
183 ZwClose(KeyHandle);
184 }
185 }
186
187 /* Return status */
188 return Status;
189 }
190
191 PBUS_HANDLER
192 NTAPI
193 HalpAllocateAndInitPciBusHandler(IN ULONG PciType,
194 IN ULONG BusNo,
195 IN BOOLEAN TestAllocation)
196 {
197 PBUS_HANDLER Bus;
198 PPCIPBUSDATA BusData;
199
200 /* Allocate the bus handler */
201 Bus = HalpAllocateBusHandler(PCIBus,
202 PCIConfiguration,
203 BusNo,
204 Internal,
205 0,
206 sizeof(PCIPBUSDATA));
207
208 /* Set it up */
209 Bus->GetBusData = (PGETSETBUSDATA)HalpGetPCIData;
210 Bus->SetBusData = (PGETSETBUSDATA)HalpSetPCIData;
211 Bus->GetInterruptVector = (PGETINTERRUPTVECTOR)HalpGetPCIIntOnISABus;
212 Bus->AdjustResourceList = (PADJUSTRESOURCELIST)HalpAdjustPCIResourceList;
213 Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES)HalpAssignPCISlotResources;
214 Bus->BusAddresses->Dma.Limit = 0;
215
216 /* Get our custom bus data */
217 BusData = (PPCIPBUSDATA)Bus->BusData;
218
219 /* Setup custom bus data */
220 BusData->CommonData.Tag = PCI_DATA_TAG;
221 BusData->CommonData.Version = PCI_DATA_VERSION;
222 BusData->CommonData.ReadConfig = (PciReadWriteConfig)HalpReadPCIConfig;
223 BusData->CommonData.WriteConfig = (PciReadWriteConfig)HalpWritePCIConfig;
224 BusData->CommonData.Pin2Line = (PciPin2Line)HalpPCIPin2ISALine;
225 BusData->CommonData.Line2Pin = (PciLine2Pin)HalpPCIISALine2Pin;
226 BusData->MaxDevice = PCI_MAX_DEVICES;
227 BusData->GetIrqRange = (PciIrqRange)HalpGetISAFixedPCIIrq;
228
229 /* Initialize the bitmap */
230 RtlInitializeBitMap(&BusData->DeviceConfigured, BusData->ConfiguredBits, 256);
231
232 /* Check the type of PCI bus */
233 switch (PciType)
234 {
235 /* Type 1 PCI Bus */
236 case 1:
237
238 /* Copy the Type 1 handler data */
239 RtlCopyMemory(&PCIConfigHandler,
240 &PCIConfigHandlerType1,
241 sizeof(PCIConfigHandler));
242
243 /* Set correct I/O Ports */
244 BusData->Config.Type1.Address = PCI_TYPE1_ADDRESS_PORT;
245 BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT;
246 break;
247
248 /* Type 2 PCI Bus */
249 case 2:
250
251 /* Copy the Type 1 handler data */
252 RtlCopyMemory(&PCIConfigHandler,
253 &PCIConfigHandlerType2,
254 sizeof (PCIConfigHandler));
255
256 /* Set correct I/O Ports */
257 BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT;
258 BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT;
259 BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE;
260
261 /* Only 16 devices supported, not 32 */
262 BusData->MaxDevice = 16;
263 break;
264
265 default:
266
267 /* Invalid type */
268 DbgPrint("HAL: Unnkown PCI type\n");
269 }
270
271 /* Return the bus handler */
272 return Bus;
273 }
274
275 BOOLEAN
276 NTAPI
277 HalpIsValidPCIDevice(IN PBUS_HANDLER BusHandler,
278 IN PCI_SLOT_NUMBER Slot)
279 {
280 UCHAR DataBuffer[PCI_COMMON_HDR_LENGTH];
281 PPCI_COMMON_CONFIG PciHeader = (PVOID)DataBuffer;
282 ULONG i;
283 ULONG_PTR Address;
284
285 /* Read the PCI header */
286 HalpReadPCIConfig(BusHandler, Slot, PciHeader, 0, PCI_COMMON_HDR_LENGTH);
287
288 /* Make sure it's a valid device */
289 if ((PciHeader->VendorID == PCI_INVALID_VENDORID) ||
290 (PCI_CONFIGURATION_TYPE(PciHeader) != PCI_DEVICE_TYPE))
291 {
292 /* Bail out */
293 return FALSE;
294 }
295
296 /* Make sure interrupt numbers make sense */
297 if (((PciHeader->u.type0.InterruptPin) &&
298 (PciHeader->u.type0.InterruptPin > 4)) ||
299 (PciHeader->u.type0.InterruptLine & 0x70))
300 {
301 /* Bail out */
302 return FALSE;
303 }
304
305 /* Now scan PCI BARs */
306 for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
307 {
308 /* Check what kind of address it is */
309 Address = PciHeader->u.type0.BaseAddresses[i];
310 if (Address & PCI_ADDRESS_IO_SPACE)
311 {
312 /* Highest I/O port is 65535 */
313 if (Address > 0xFFFF) return FALSE;
314 }
315 else
316 {
317 /* MMIO should be higher than 0x80000 */
318 if ((Address > 0xF) && (Address < 0x80000)) return FALSE;
319 }
320
321 /* Is this a 64-bit address? */
322 if (!(Address & PCI_ADDRESS_IO_SPACE) &&
323 ((Address & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT))
324 {
325 /* Check the next-next entry, since this one 64-bits wide */
326 i++;
327 }
328 }
329
330 /* Header, interrupt and address data all make sense */
331 return TRUE;
332 }
333
334 static BOOLEAN WarningsGiven[5];
335
336 NTSTATUS
337 NTAPI
338 HalpGetChipHacks(IN USHORT VendorId,
339 IN USHORT DeviceId,
340 IN UCHAR RevisionId,
341 IN PULONG HackFlags)
342 {
343 UNICODE_STRING KeyName, ValueName;
344 NTSTATUS Status;
345 OBJECT_ATTRIBUTES ObjectAttributes;
346 HANDLE KeyHandle;
347 WCHAR Buffer[32];
348 KEY_VALUE_PARTIAL_INFORMATION PartialInfo;
349 ULONG ResultLength;
350
351 /* Setup the object attributes for the key */
352 RtlInitUnicodeString(&KeyName,
353 L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\"
354 L"Control\\HAL");
355 InitializeObjectAttributes(&ObjectAttributes,
356 &KeyName,
357 OBJ_CASE_INSENSITIVE,
358 NULL,
359 NULL);
360
361 /* Open the key */
362 Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
363 if (!NT_SUCCESS(Status)) return Status;
364
365 /* Query value */
366 swprintf(Buffer, L"%04X%04X", VendorId, DeviceId);
367 RtlInitUnicodeString(&ValueName, Buffer);
368 Status = ZwQueryValueKey(KeyHandle,
369 &ValueName,
370 KeyValuePartialInformation,
371 &PartialInfo,
372 sizeof(PartialInfo),
373 &ResultLength);
374 if (NT_SUCCESS(Status))
375 {
376 /* Return the flags */
377 DPRINT1("Found HackFlags for your %lx:%lx device\n", VendorId, DeviceId);
378 *HackFlags = *(PULONG)PartialInfo.Data;
379 DPRINT1("Hack Flags: %lx (Hack Revision: %lx\tYour Revision: %lx)\n",
380 *HackFlags, HALP_REVISION_FROM_HACK_FLAGS(*HackFlags), RevisionId);
381
382 /* Does it apply to this revision? */
383 if ((RevisionId) && (RevisionId >= (HALP_REVISION_FROM_HACK_FLAGS(*HackFlags))))
384 {
385 /* Read the revision flags */
386 *HackFlags = HALP_REVISION_HACK_FLAGS(*HackFlags);
387 }
388
389 /* Throw out revision data */
390 *HackFlags = HALP_HACK_FLAGS(*HackFlags);
391 }
392
393 /* Close the handle and return */
394 ZwClose(KeyHandle);
395 return Status;
396 }
397
398 BOOLEAN
399 NTAPI
400 HalpIsRecognizedCard(IN PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo,
401 IN PPCI_COMMON_CONFIG PciData,
402 IN ULONG Flags)
403 {
404 ULONG ElementCount, i;
405 PPCI_CARD_DESCRIPTOR CardDescriptor;
406
407 /* How many PCI Cards that we know about? */
408 ElementCount = PciRegistryInfo->ElementCount;
409 if (!ElementCount) return FALSE;
410
411 /* Loop all descriptors */
412 CardDescriptor = &PciRegistryInfo->CardList[0];
413 for (i = 0; i < ElementCount; i++, CardDescriptor++)
414 {
415 /* Check for flag match */
416 if (CardDescriptor->Flags != Flags) continue;
417
418 /* Check for VID-PID match */
419 if ((CardDescriptor->VendorID != PciData->VendorID) ||
420 (CardDescriptor->DeviceID != PciData->DeviceID))
421 {
422 /* Skip */
423 continue;
424 }
425
426 /* Check for revision match, if requested */
427 if ((CardDescriptor->Flags & HALP_CHECK_CARD_REVISION_ID) &&
428 (CardDescriptor->RevisionID != PciData->RevisionID))
429 {
430 /* Skip */
431 continue;
432 }
433
434 /* Check what kind of device this is */
435 switch (PCI_CONFIGURATION_TYPE(PciData))
436 {
437 /* CardBUS Bridge */
438 case PCI_CARDBUS_BRIDGE_TYPE:
439
440 /* This means the real device header is in the device-specific data */
441 PciData = (PPCI_COMMON_CONFIG)PciData->DeviceSpecific;
442
443 /* Normal PCI device */
444 case PCI_DEVICE_TYPE:
445
446 /* Check for subvendor match, if requested */
447 if ((CardDescriptor->Flags & HALP_CHECK_CARD_SUBVENDOR_ID) &&
448 (CardDescriptor->SubsystemVendorID != PciData->u.type0.SubVendorID))
449 {
450 /* Skip */
451 continue;
452 }
453
454 /* Check for subsystem match, if requested */
455 if ((CardDescriptor->Flags & HALP_CHECK_CARD_SUBSYSTEM_ID) &&
456 (CardDescriptor->SubsystemID != PciData->u.type0.SubSystemID))
457 {
458 /* Skip */
459 continue;
460 }
461
462 /* You made it! */
463 return TRUE;
464
465 /* PCI Bridge -- don't bother */
466 case PCI_BRIDGE_TYPE:
467 default:
468
469 /* Recognize it */
470 return TRUE;
471 }
472 }
473
474 /* This means the card isn't recognized */
475 return FALSE;
476 }
477
478 BOOLEAN
479 NTAPI
480 HalpIsIdeDevice(IN PPCI_COMMON_CONFIG PciData)
481 {
482 /* Simple test first */
483 if ((PciData->BaseClass == PCI_CLASS_MASS_STORAGE_CTLR) &&
484 (PciData->SubClass == PCI_SUBCLASS_MSC_IDE_CTLR))
485 {
486 /* The device is nice enough to admit it */
487 return TRUE;
488 }
489
490 /* Symphony 82C101 */
491 if (PciData->VendorID == 0x1C1C) return TRUE;
492
493 /* ALi MS4803 or M5219 */
494 if ((PciData->VendorID == 0x10B9) &&
495 ((PciData->DeviceID == 0x5215) || (PciData->DeviceID == 0x5219)))
496 {
497 return TRUE;
498 }
499
500 /* Appian Technology */
501 if ((PciData->VendorID == 0x1097) && (PciData->DeviceID == 0x38)) return TRUE;
502
503 /* Compaq Triflex Dual EIDE Controller */
504 if ((PciData->VendorID == 0xE11) && (PciData->DeviceID == 0xAE33)) return TRUE;
505
506 /* Micron PC Tech RZ1000 */
507 if ((PciData->VendorID == 0x1042) && (PciData->DeviceID == 0x1000)) return TRUE;
508
509 /* SiS 85C601 or 5513 [IDE] */
510 if ((PciData->VendorID == 0x1039) &&
511 ((PciData->DeviceID == 0x601) || (PciData->DeviceID == 0x5513)))
512 {
513 return TRUE;
514 }
515
516 /* Symphony Labs W83769F */
517 if ((PciData->VendorID == 0x10AD) &&
518 ((PciData->DeviceID == 0x1) || (PciData->DeviceID == 0x150)))
519 {
520 return TRUE;
521 }
522
523 /* UMC UM8673F */
524 if ((PciData->VendorID == 0x1060) && (PciData->DeviceID == 0x101)) return TRUE;
525
526 /* You've survived */
527 return FALSE;
528 }
529
530 BOOLEAN
531 NTAPI
532 HalpGetPciBridgeConfig(IN ULONG PciType,
533 IN PUCHAR MaxPciBus)
534 {
535 /* Not yet implemented */
536 if (!WarningsGiven[2]++) DbgPrint("HAL: Not checking for PCI-to-PCI Bridges. Your hardware may malfunction!\n");
537 return FALSE;
538 }
539
540 VOID
541 NTAPI
542 HalpFixupPciSupportedRanges(IN ULONG BusCount)
543 {
544 ULONG i;
545 PBUS_HANDLER Bus, ParentBus;
546
547 /* Loop all buses */
548 for (i = 0; i < BusCount; i++)
549 {
550 /* Get PCI bus handler */
551 Bus = HalHandlerForBus(PCIBus, i);
552
553 /* Loop all parent buses */
554 ParentBus = Bus->ParentHandler;
555 while (ParentBus)
556 {
557 /* Should merge addresses */
558 if (!WarningsGiven[0]++) DPRINT1("Found parent bus (indicating PCI Bridge). This is not supported!\n");
559
560 /* Check the next parent */
561 ParentBus = ParentBus->ParentHandler;
562 }
563 }
564
565 /* Loop all buses again */
566 for (i = 0; i < BusCount; i++)
567 {
568 /* Get PCI bus handler */
569 Bus = HalHandlerForBus(PCIBus, i);
570
571 /* Check if this is a PCI 2.2 Bus with Subtractive Decode */
572 if (!((PPCIPBUSDATA)Bus->BusData)->Subtractive)
573 {
574 /* Loop all parent buses */
575 ParentBus = Bus->ParentHandler;
576 while (ParentBus)
577 {
578 /* But check only PCI parent buses specifically */
579 if (ParentBus->InterfaceType == PCIBus)
580 {
581 /* Should trim addresses */
582 if (!WarningsGiven[1]++) DPRINT1("Found parent PCI Bus (indicating PCI-to-PCI Bridge). This is not supported!\n");
583 }
584
585 /* Check the next parent */
586 ParentBus = ParentBus->ParentHandler;
587 }
588 }
589 }
590
591 /* Loop buses one last time */
592 for (i = 0; i < BusCount; i++)
593 {
594 /* Get the PCI bus handler */
595 Bus = HalHandlerForBus(PCIBus, i);
596
597 /* Sort and combine (trim) bus address range information */
598 DPRINT("Warning: Bus addresses not being optimized!\n");
599 }
600 }
601 #endif
602
603 VOID
604 NTAPI
605 HalpInitializePciBus(VOID)
606 {
607 #ifndef _MINIHAL_
608 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo;
609 UCHAR PciType;
610 PCI_SLOT_NUMBER PciSlot;
611 ULONG i, j, k;
612 UCHAR DataBuffer[PCI_COMMON_HDR_LENGTH];
613 PPCI_COMMON_CONFIG PciData = (PPCI_COMMON_CONFIG)DataBuffer;
614 PBUS_HANDLER BusHandler;
615 ULONG HackFlags;
616 BOOLEAN ExtendedAddressDecoding = FALSE;
617 NTSTATUS Status;
618
619 /* Query registry information */
620 PciRegistryInfo = HalpQueryPciRegistryInfo();
621 if (!PciRegistryInfo) return;
622
623 /* Initialize the PCI configuration lock */
624 KeInitializeSpinLock(&HalpPCIConfigLock);
625
626 /* Get the type and free the info structure */
627 PciType = PciRegistryInfo->HardwareMechanism & 0xF;
628
629 /* Check if this is a type 2 PCI bus with at least one bus */
630 if ((PciRegistryInfo->NoBuses) && (PciType == 2))
631 {
632 /* Setup the PCI slot */
633 PciSlot.u.bits.Reserved = 0;
634 PciSlot.u.bits.FunctionNumber = 0;
635
636 /* Loop all slots */
637 for (i = 0; i < 32; i++)
638 {
639 /* Try to setup a Type 2 PCI slot */
640 PciType = 2;
641 BusHandler = HalpAllocateAndInitPciBusHandler(2, 0, TRUE);
642 if (!BusHandler) break;
643
644 /* Now check if it's valid */
645 if (HalpIsValidPCIDevice(BusHandler, PciSlot)) break;
646
647 /* Heh, the BIOS lied... try Type 1 */
648 PciType = 1;
649 BusHandler = HalpAllocateAndInitPciBusHandler(1, 0, TRUE);
650 if (!BusHandler) break;
651
652 /* Now check if it's valid */
653 if (HalpIsValidPCIDevice(BusHandler, PciSlot)) break;
654
655 /* Keep trying */
656 PciType = 2;
657 }
658
659 /* Now allocate the correct kind of handler */
660 HalpAllocateAndInitPciBusHandler(PciType, 0, FALSE);
661 }
662
663 /* Okay, now loop all PCI bridges */
664 do
665 {
666 /* Loop all PCI buses */
667 for (i = 0; i < PciRegistryInfo->NoBuses; i++)
668 {
669 /* Check if we have a handler for it */
670 if (!HalHandlerForBus(PCIBus, i))
671 {
672 /* Allocate it */
673 HalpAllocateAndInitPciBusHandler(PciType, i, FALSE);
674 }
675 }
676 /* Go to the next bridge */
677 } while (HalpGetPciBridgeConfig(PciType, &PciRegistryInfo->NoBuses));
678
679 /* Now build correct address range informaiton */
680 HalpFixupPciSupportedRanges(PciRegistryInfo->NoBuses);
681
682 /* Loop every bus */
683 PciSlot.u.bits.Reserved = 0;
684 for (i = 0; i < PciRegistryInfo->NoBuses; i++)
685 {
686 /* Get the bus handler */
687 BusHandler = HalHandlerForBus(PCIBus, i);
688
689 /* Loop every device */
690 for (j = 0; j < 32; j++)
691 {
692 /* Loop every function */
693 PciSlot.u.bits.DeviceNumber = j;
694 for (k = 0; k < 8; k++)
695 {
696 /* Build the final slot structure */
697 PciSlot.u.bits.FunctionNumber = k;
698
699 /* Read the configuration information */
700 HalpReadPCIConfig(BusHandler,
701 PciSlot,
702 PciData,
703 0,
704 PCI_COMMON_HDR_LENGTH);
705
706 /* Skip if this is an invalid function */
707 if (PciData->VendorID == PCI_INVALID_VENDORID) continue;
708
709 /* Check if this is a Cardbus bridge */
710 if (PCI_CONFIGURATION_TYPE(PciData) == PCI_CARDBUS_BRIDGE_TYPE)
711 {
712 /* Not supported */
713 DbgPrint("HAL: Your machine has a PCI Cardbus Bridge. This is not supported!\n");
714 continue;
715 }
716
717 /* Check if this is a PCI device */
718 if (PCI_CONFIGURATION_TYPE(PciData) != PCI_BRIDGE_TYPE)
719 {
720 /* Check if it has an interrupt pin and line registered */
721 if ((PciData->u.type1.InterruptPin) &&
722 (PciData->u.type1.InterruptLine))
723 {
724 /* Check if this interrupt line is connected to the bus */
725 if (PciData->u.type1.InterruptLine < 16)
726 {
727 /* Is this an IDE device? */
728 if (!HalpIsIdeDevice(PciData))
729 {
730 /* We'll mask out this interrupt then */
731 DPRINT1("HAL: Device %lx:%lx is not an IDE Device. Should be masking IRQ %d! This is not supported!\n",
732 PciData->VendorID, PciData->DeviceID,
733 PciData->u.type1.InterruptLine);
734 HalpPciIrqMask |= (1 << PciData->u.type1.InterruptLine);
735 }
736 }
737 }
738 }
739
740 /* Check for broken Intel chips */
741 if (PciData->VendorID == 0x8086)
742 {
743 /* Check for broken 82830 PCI controller */
744 if ((PciData->DeviceID == 0x04A3) &&
745 (PciData->RevisionID < 0x11))
746 {
747 /* Skip */
748 DbgPrint("HAL: Your machine has a broken Intel 82430 PCI Controller. This is not supported!\n");
749 continue;
750 }
751
752 /* Check for broken 82378 PCI-to-ISA Bridge */
753 if ((PciData->DeviceID == 0x0484) &&
754 (PciData->RevisionID <= 3))
755 {
756 /* Skip */
757 DbgPrint("HAL: Your machine has a broken Intel 82378 PCI-to-ISA Bridge. This is not supported!\n");
758 continue;
759 }
760
761 /* Check for broken 82450 PCI Bridge */
762 if ((PciData->DeviceID == 0x84C4) &&
763 (PciData->RevisionID <= 4))
764 {
765 DbgPrint("HAL: Your machine has an Intel Orion 82450 PCI Bridge. This is not supported!\n");
766 continue;
767 }
768 }
769
770 /* Do we know this card? */
771 if (!ExtendedAddressDecoding)
772 {
773 /* Check for it */
774 if (HalpIsRecognizedCard(PciRegistryInfo,
775 PciData,
776 HALP_CARD_FEATURE_FULL_DECODE))
777 {
778 /* We'll do chipset checks later */
779 DPRINT1("Your %lx:%lx PCI device has Extended Address Decoding. This is not supported!\n",
780 PciData->VendorID, PciData->DeviceID);
781 ExtendedAddressDecoding = TRUE;
782 }
783 }
784
785 /* Check if this is a USB controller */
786 if ((PciData->BaseClass == PCI_CLASS_SERIAL_BUS_CTLR) &&
787 (PciData->SubClass == PCI_SUBCLASS_SB_USB))
788 {
789 /* Check if this is an OHCI controller */
790 if (PciData->ProgIf == 0x10)
791 {
792 DbgPrint("HAL: Your machine has an OHCI (USB) PCI Expansion Card. This is not supported!\n");
793 continue;
794 }
795
796 /* Check for Intel UHCI controller */
797 if (PciData->VendorID == 0x8086)
798 {
799 DbgPrint("HAL: Your machine has an Intel UHCI (USB) Controller. This is not supported!\n");
800 continue;
801 }
802
803 /* Check for VIA UHCI controller */
804 if (PciData->VendorID == 0x1106)
805 {
806 DbgPrint("HAL: Your machine has a VIA UHCI (USB) Controller. This is not supported!\n");
807 continue;
808 }
809 }
810
811 /* Now check the registry for chipset hacks */
812 Status = HalpGetChipHacks(PciData->VendorID,
813 PciData->DeviceID,
814 PciData->RevisionID,
815 &HackFlags);
816 if (NT_SUCCESS(Status))
817 {
818 /* Check for broken ACPI routing */
819 if (HackFlags & HAL_PCI_CHIP_HACK_DISABLE_ACPI_IRQ_ROUTING)
820 {
821 DPRINT1("Your hardware has broken ACPI IRQ Routing! This is not supported!\n");
822 continue;
823 }
824
825 /* Check for broken ACPI timer */
826 if (HackFlags & HAL_PCI_CHIP_HACK_BROKEN_ACPI_TIMER)
827 {
828 DPRINT1("Your hardware has a broken ACPI timer! This is not supported!\n");
829 continue;
830 }
831
832 /* Check for hibernate-disable */
833 if (HackFlags & HAL_PCI_CHIP_HACK_DISABLE_HIBERNATE)
834 {
835 DPRINT1("Your machine has a broken PCI device which is incompatible with hibernation. This is not supported!\n");
836 continue;
837 }
838
839 /* Check for USB controllers that generate SMIs */
840 if (HackFlags & HAL_PCI_CHIP_HACK_USB_SMI_DISABLE)
841 {
842 DPRINT1("Your machine has a USB controller which generates SMIs. This is not supported!\n");
843 continue;
844 }
845 }
846 }
847 }
848 }
849
850 /* Initialize NMI Crash Flag */
851 HalpGetNMICrashFlag();
852
853 /* Free the registry data */
854 ExFreePool(PciRegistryInfo);
855
856 /* Tell PnP if this hard supports correct decoding */
857 HalpMarkChipsetDecode(ExtendedAddressDecoding);
858 DPRINT1("PCI BUS Setup complete\n");
859 #endif
860 }
861
862 VOID
863 NTAPI
864 HalpInitBusHandlers(VOID)
865 {
866 /* Register the HAL Bus Handler support */
867 HalpRegisterInternalBusHandlers();
868 }
869
870 VOID
871 NTAPI
872 HalpRegisterKdSupportFunctions(VOID)
873 {
874 /* Register PCI Device Functions */
875 KdSetupPciDeviceForDebugging = HalpSetupPciDeviceForDebugging;
876 KdReleasePciDeviceforDebugging = HalpReleasePciDeviceForDebugging;
877
878 /* Register memory functions */
879 #ifndef _MINIHAL_
880 KdMapPhysicalMemory64 = HalpMapPhysicalMemory64;
881 KdUnmapVirtualAddress = HalpUnmapVirtualAddress;
882 #endif
883
884 /* Register ACPI stub */
885 KdCheckPowerButton = HalpCheckPowerButton;
886 }
887
888 NTSTATUS
889 NTAPI
890 HalpAssignSlotResources(IN PUNICODE_STRING RegistryPath,
891 IN PUNICODE_STRING DriverClassName,
892 IN PDRIVER_OBJECT DriverObject,
893 IN PDEVICE_OBJECT DeviceObject,
894 IN INTERFACE_TYPE BusType,
895 IN ULONG BusNumber,
896 IN ULONG SlotNumber,
897 IN OUT PCM_RESOURCE_LIST *AllocatedResources)
898 {
899 BUS_HANDLER BusHandler;
900 PAGED_CODE();
901
902 /* Only PCI is supported */
903 if (BusType != PCIBus) return STATUS_NOT_IMPLEMENTED;
904
905 /* Setup fake PCI Bus handler */
906 RtlCopyMemory(&BusHandler, &HalpFakePciBusHandler, sizeof(BUS_HANDLER));
907 BusHandler.BusNumber = BusNumber;
908
909 /* Call the PCI function */
910 return HalpAssignPCISlotResources(&BusHandler,
911 &BusHandler,
912 RegistryPath,
913 DriverClassName,
914 DriverObject,
915 DeviceObject,
916 SlotNumber,
917 AllocatedResources);
918 }
919
920 BOOLEAN
921 NTAPI
922 HalpTranslateBusAddress(IN INTERFACE_TYPE InterfaceType,
923 IN ULONG BusNumber,
924 IN PHYSICAL_ADDRESS BusAddress,
925 IN OUT PULONG AddressSpace,
926 OUT PPHYSICAL_ADDRESS TranslatedAddress)
927 {
928 /* Translation is easy */
929 TranslatedAddress->QuadPart = BusAddress.QuadPart;
930 return TRUE;
931 }
932
933 ULONG
934 NTAPI
935 HalpGetSystemInterruptVector_Acpi(IN ULONG BusNumber,
936 IN ULONG BusInterruptLevel,
937 IN ULONG BusInterruptVector,
938 OUT PKIRQL Irql,
939 OUT PKAFFINITY Affinity)
940 {
941 ULONG Vector = IRQ2VECTOR(BusInterruptLevel);
942 *Irql = (KIRQL)VECTOR2IRQL(Vector);
943 *Affinity = 0xFFFFFFFF;
944 return Vector;
945 }
946
947 BOOLEAN
948 NTAPI
949 HalpFindBusAddressTranslation(IN PHYSICAL_ADDRESS BusAddress,
950 IN OUT PULONG AddressSpace,
951 OUT PPHYSICAL_ADDRESS TranslatedAddress,
952 IN OUT PULONG_PTR Context,
953 IN BOOLEAN NextBus)
954 {
955 /* Make sure we have a context */
956 if (!Context) return FALSE;
957
958 /* If we have data in the context, then this shouldn't be a new lookup */
959 if ((*Context) && (NextBus == TRUE)) return FALSE;
960
961 /* Return bus data */
962 TranslatedAddress->QuadPart = BusAddress.QuadPart;
963
964 /* Set context value and return success */
965 *Context = 1;
966 return TRUE;
967 }
968
969 /* PUBLIC FUNCTIONS **********************************************************/
970
971 /*
972 * @implemented
973 */
974 NTSTATUS
975 NTAPI
976 HalAdjustResourceList(IN PCM_RESOURCE_LIST Resources)
977 {
978 /* Deprecated, return success */
979 return STATUS_SUCCESS;
980 }
981
982 /*
983 * @implemented
984 */
985 NTSTATUS
986 NTAPI
987 HalAssignSlotResources(IN PUNICODE_STRING RegistryPath,
988 IN PUNICODE_STRING DriverClassName,
989 IN PDRIVER_OBJECT DriverObject,
990 IN PDEVICE_OBJECT DeviceObject,
991 IN INTERFACE_TYPE BusType,
992 IN ULONG BusNumber,
993 IN ULONG SlotNumber,
994 IN OUT PCM_RESOURCE_LIST *AllocatedResources)
995 {
996 /* Check the bus type */
997 if (BusType != PCIBus)
998 {
999 /* Call our internal handler */
1000 return HalpAssignSlotResources(RegistryPath,
1001 DriverClassName,
1002 DriverObject,
1003 DeviceObject,
1004 BusType,
1005 BusNumber,
1006 SlotNumber,
1007 AllocatedResources);
1008 }
1009 else
1010 {
1011 /* Call the PCI registered function */
1012 return HalPciAssignSlotResources(RegistryPath,
1013 DriverClassName,
1014 DriverObject,
1015 DeviceObject,
1016 PCIBus,
1017 BusNumber,
1018 SlotNumber,
1019 AllocatedResources);
1020 }
1021 }
1022
1023 /*
1024 * @implemented
1025 */
1026 ULONG
1027 NTAPI
1028 HalGetBusData(IN BUS_DATA_TYPE BusDataType,
1029 IN ULONG BusNumber,
1030 IN ULONG SlotNumber,
1031 IN PVOID Buffer,
1032 IN ULONG Length)
1033 {
1034 /* Call the extended function */
1035 return HalGetBusDataByOffset(BusDataType,
1036 BusNumber,
1037 SlotNumber,
1038 Buffer,
1039 0,
1040 Length);
1041 }
1042
1043 /*
1044 * @implemented
1045 */
1046 ULONG
1047 NTAPI
1048 HalGetBusDataByOffset(IN BUS_DATA_TYPE BusDataType,
1049 IN ULONG BusNumber,
1050 IN ULONG SlotNumber,
1051 IN PVOID Buffer,
1052 IN ULONG Offset,
1053 IN ULONG Length)
1054 {
1055 BUS_HANDLER BusHandler;
1056
1057 /* Look as the bus type */
1058 if (BusDataType == Cmos)
1059 {
1060 /* Call CMOS Function */
1061 return HalpGetCmosData(0, SlotNumber, Buffer, Length);
1062 }
1063 else if (BusDataType == EisaConfiguration)
1064 {
1065 /* FIXME: TODO */
1066 ASSERT(FALSE);
1067 }
1068 else if ((BusDataType == PCIConfiguration) &&
1069 (HalpPCIConfigInitialized) &&
1070 ((BusNumber >= HalpMinPciBus) && (BusNumber <= HalpMaxPciBus)))
1071 {
1072 /* Setup fake PCI Bus handler */
1073 RtlCopyMemory(&BusHandler, &HalpFakePciBusHandler, sizeof(BUS_HANDLER));
1074 BusHandler.BusNumber = BusNumber;
1075
1076 /* Call PCI function */
1077 return HalpGetPCIData(&BusHandler,
1078 &BusHandler,
1079 *(PPCI_SLOT_NUMBER)&SlotNumber,
1080 Buffer,
1081 Offset,
1082 Length);
1083 }
1084
1085 /* Invalid bus */
1086 return 0;
1087 }
1088
1089 /*
1090 * @implemented
1091 */
1092 ULONG
1093 NTAPI
1094 HalGetInterruptVector(IN INTERFACE_TYPE InterfaceType,
1095 IN ULONG BusNumber,
1096 IN ULONG BusInterruptLevel,
1097 IN ULONG BusInterruptVector,
1098 OUT PKIRQL Irql,
1099 OUT PKAFFINITY Affinity)
1100 {
1101 /* Call the system bus translator */
1102 return HalpGetSystemInterruptVector_Acpi(BusNumber,
1103 BusInterruptLevel,
1104 BusInterruptVector,
1105 Irql,
1106 Affinity);
1107 }
1108
1109 /*
1110 * @implemented
1111 */
1112 ULONG
1113 NTAPI
1114 HalSetBusData(IN BUS_DATA_TYPE BusDataType,
1115 IN ULONG BusNumber,
1116 IN ULONG SlotNumber,
1117 IN PVOID Buffer,
1118 IN ULONG Length)
1119 {
1120 /* Call the extended function */
1121 return HalSetBusDataByOffset(BusDataType,
1122 BusNumber,
1123 SlotNumber,
1124 Buffer,
1125 0,
1126 Length);
1127 }
1128
1129 /*
1130 * @implemented
1131 */
1132 ULONG
1133 NTAPI
1134 HalSetBusDataByOffset(IN BUS_DATA_TYPE BusDataType,
1135 IN ULONG BusNumber,
1136 IN ULONG SlotNumber,
1137 IN PVOID Buffer,
1138 IN ULONG Offset,
1139 IN ULONG Length)
1140 {
1141 BUS_HANDLER BusHandler;
1142
1143 /* Look as the bus type */
1144 if (BusDataType == Cmos)
1145 {
1146 /* Call CMOS Function */
1147 return HalpSetCmosData(0, SlotNumber, Buffer, Length);
1148 }
1149 else if ((BusDataType == PCIConfiguration) && (HalpPCIConfigInitialized))
1150 {
1151 /* Setup fake PCI Bus handler */
1152 RtlCopyMemory(&BusHandler, &HalpFakePciBusHandler, sizeof(BUS_HANDLER));
1153 BusHandler.BusNumber = BusNumber;
1154
1155 /* Call PCI function */
1156 return HalpSetPCIData(&BusHandler,
1157 &BusHandler,
1158 *(PPCI_SLOT_NUMBER)&SlotNumber,
1159 Buffer,
1160 Offset,
1161 Length);
1162 }
1163
1164 /* Invalid bus */
1165 return 0;
1166 }
1167
1168 /*
1169 * @implemented
1170 */
1171 BOOLEAN
1172 NTAPI
1173 HalTranslateBusAddress(IN INTERFACE_TYPE InterfaceType,
1174 IN ULONG BusNumber,
1175 IN PHYSICAL_ADDRESS BusAddress,
1176 IN OUT PULONG AddressSpace,
1177 OUT PPHYSICAL_ADDRESS TranslatedAddress)
1178 {
1179 /* Look as the bus type */
1180 if (InterfaceType == PCIBus)
1181 {
1182 /* Call the PCI registered function */
1183 return HalPciTranslateBusAddress(PCIBus,
1184 BusNumber,
1185 BusAddress,
1186 AddressSpace,
1187 TranslatedAddress);
1188 }
1189 else
1190 {
1191 /* Translation is easy */
1192 TranslatedAddress->QuadPart = BusAddress.QuadPart;
1193 return TRUE;
1194 }
1195 }
1196
1197 /* EOF */