[NTOS]: Check registry for our CardList, check if the PCI hardware matches any entry...
[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 /* Not yet implemented */
344 if (!WarningsGiven[0]++) DbgPrint("HAL: Not checking for PCI Chipset Hacks. Your hardware may malfunction!\n");
345 *HackFlags = 0;
346 return STATUS_UNSUCCESSFUL;
347 }
348
349 BOOLEAN
350 NTAPI
351 HalpIsRecognizedCard(IN PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo,
352 IN PPCI_COMMON_CONFIG PciData,
353 IN ULONG Flags)
354 {
355 ULONG ElementCount, i;
356 PPCI_CARD_DESCRIPTOR CardDescriptor;
357
358 /* How many PCI Cards that we know about? */
359 ElementCount = PciRegistryInfo->ElementCount;
360 if (!ElementCount) return FALSE;
361
362 /* Loop all descriptors */
363 CardDescriptor = &PciRegistryInfo->CardList[0];
364 for (i = 0; i < ElementCount; i++, CardDescriptor++)
365 {
366 /* Check for flag match */
367 if (CardDescriptor->Flags != Flags) continue;
368
369 /* Check for VID-PID match */
370 if ((CardDescriptor->VendorID != PciData->VendorID) ||
371 (CardDescriptor->DeviceID != PciData->DeviceID))
372 {
373 /* Skip */
374 continue;
375 }
376
377 /* Check for revision match, if requested */
378 if ((CardDescriptor->Flags & HALP_CHECK_CARD_REVISION_ID) &&
379 (CardDescriptor->RevisionID != PciData->RevisionID))
380 {
381 /* Skip */
382 continue;
383 }
384
385 /* Check what kind of device this is */
386 switch (PCI_CONFIGURATION_TYPE(PciData))
387 {
388 /* CardBUS Bridge */
389 case PCI_CARDBUS_BRIDGE_TYPE:
390
391 /* This means the real device header is in the device-specific data */
392 PciData = (PPCI_COMMON_CONFIG)PciData->DeviceSpecific;
393
394 /* Normal PCI device */
395 case PCI_DEVICE_TYPE:
396
397 /* Check for subvendor match, if requested */
398 if ((CardDescriptor->Flags & HALP_CHECK_CARD_SUBVENDOR_ID) &&
399 (CardDescriptor->SubsystemVendorID != PciData->u.type0.SubVendorID))
400 {
401 /* Skip */
402 continue;
403 }
404
405 /* Check for subsystem match, if requested */
406 if ((CardDescriptor->Flags & HALP_CHECK_CARD_SUBSYSTEM_ID) &&
407 (CardDescriptor->SubsystemID != PciData->u.type0.SubSystemID))
408 {
409 /* Skip */
410 continue;
411 }
412
413 /* You made it! */
414 return TRUE;
415
416 /* PCI Bridge -- don't bother */
417 case PCI_BRIDGE_TYPE:
418 default:
419
420 /* Recognize it */
421 return TRUE;
422 }
423 }
424
425 /* This means the card isn't recognized */
426 return FALSE;
427 }
428
429 BOOLEAN
430 NTAPI
431 HalpIsIdeDevice(IN PPCI_COMMON_CONFIG PciData)
432 {
433 /* Simple test first */
434 if ((PciData->BaseClass == PCI_CLASS_MASS_STORAGE_CTLR) &&
435 (PciData->SubClass == PCI_SUBCLASS_MSC_IDE_CTLR))
436 {
437 /* The device is nice enough to admit it */
438 return TRUE;
439 }
440
441 /* Symphony 82C101 */
442 if (PciData->VendorID == 0x1C1C) return TRUE;
443
444 /* ALi MS4803 or M5219 */
445 if ((PciData->VendorID == 0x10B9) &&
446 ((PciData->DeviceID == 0x5215) || (PciData->DeviceID == 0x5219)))
447 {
448 return TRUE;
449 }
450
451 /* Appian Technology */
452 if ((PciData->VendorID == 0x1097) && (PciData->DeviceID == 0x38)) return TRUE;
453
454 /* Compaq Triflex Dual EIDE Controller */
455 if ((PciData->VendorID == 0xE11) && (PciData->DeviceID == 0xAE33)) return TRUE;
456
457 /* Micron PC Tech RZ1000 */
458 if ((PciData->VendorID == 0x1042) && (PciData->DeviceID == 0x1000)) return TRUE;
459
460 /* SiS 85C601 or 5513 [IDE] */
461 if ((PciData->VendorID == 0x1039) &&
462 ((PciData->DeviceID == 0x601) || (PciData->DeviceID == 0x5513)))
463 {
464 return TRUE;
465 }
466
467 /* Symphony Labs W83769F */
468 if ((PciData->VendorID == 0x10AD) &&
469 ((PciData->DeviceID == 0x1) || (PciData->DeviceID == 0x150)))
470 {
471 return TRUE;
472 }
473
474 /* UMC UM8673F */
475 if ((PciData->VendorID == 0x1060) && (PciData->DeviceID == 0x101)) return TRUE;
476
477 /* You've survived */
478 return FALSE;
479 }
480
481 BOOLEAN
482 NTAPI
483 HalpGetPciBridgeConfig(IN ULONG PciType,
484 IN PUCHAR MaxPciBus)
485 {
486 /* Not yet implemented */
487 if (!WarningsGiven[3]++) DbgPrint("HAL: Not checking for PCI-to-PCI Bridges. Your hardware may malfunction!\n");
488 return FALSE;
489 }
490
491 VOID
492 NTAPI
493 HalpFixupPciSupportedRanges(IN ULONG MaxBuses)
494 {
495 /* Not yet implemented */
496 if (!WarningsGiven[4]++) DbgPrint("HAL: Not adjusting Bridge-to-Child PCI Address Ranges. Your hardware may malfunction!\n");
497 }
498 #endif
499
500 VOID
501 NTAPI
502 HalpInitializePciBus(VOID)
503 {
504 #ifndef _MINIHAL_
505 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo;
506 UCHAR PciType;
507 PCI_SLOT_NUMBER PciSlot;
508 ULONG i, j, k;
509 UCHAR DataBuffer[PCI_COMMON_HDR_LENGTH];
510 PPCI_COMMON_CONFIG PciData = (PPCI_COMMON_CONFIG)DataBuffer;
511 PBUS_HANDLER BusHandler;
512 ULONG HackFlags;
513 BOOLEAN ExtendedAddressDecoding = FALSE;
514
515 /* Query registry information */
516 PciRegistryInfo = HalpQueryPciRegistryInfo();
517 if (!PciRegistryInfo) return;
518
519 /* Initialize the PCI configuration lock */
520 KeInitializeSpinLock(&HalpPCIConfigLock);
521
522 /* Get the type and free the info structure */
523 PciType = PciRegistryInfo->HardwareMechanism & 0xF;
524
525 /* Check if this is a type 2 PCI bus with at least one bus */
526 if ((PciRegistryInfo->NoBuses) && (PciType == 2))
527 {
528 /* Setup the PCI slot */
529 PciSlot.u.bits.Reserved = 0;
530 PciSlot.u.bits.FunctionNumber = 0;
531
532 /* Loop all slots */
533 for (i = 0; i < 32; i++)
534 {
535 /* Try to setup a Type 2 PCI slot */
536 PciType = 2;
537 BusHandler = HalpAllocateAndInitPciBusHandler(2, 0, TRUE);
538 if (!BusHandler) break;
539
540 /* Now check if it's valid */
541 if (HalpIsValidPCIDevice(BusHandler, PciSlot)) break;
542
543 /* Heh, the BIOS lied... try Type 1 */
544 PciType = 1;
545 BusHandler = HalpAllocateAndInitPciBusHandler(1, 0, TRUE);
546 if (!BusHandler) break;
547
548 /* Now check if it's valid */
549 if (HalpIsValidPCIDevice(BusHandler, PciSlot)) break;
550
551 /* Keep trying */
552 PciType = 2;
553 }
554
555 /* Now allocate the correct kind of handler */
556 HalpAllocateAndInitPciBusHandler(PciType, 0, FALSE);
557 }
558
559 /* Okay, now loop all PCI bridges */
560 do
561 {
562 /* Loop all PCI buses */
563 for (i = 0; i < PciRegistryInfo->NoBuses; i++)
564 {
565 /* Check if we have a handler for it */
566 if (!HalHandlerForBus(PCIBus, i))
567 {
568 /* Allocate it */
569 HalpAllocateAndInitPciBusHandler(PciType, i, FALSE);
570 }
571 }
572 /* Go to the next bridge */
573 } while (HalpGetPciBridgeConfig(PciType, &PciRegistryInfo->NoBuses));
574
575 /* Now build correct address range informaiton */
576 HalpFixupPciSupportedRanges(PciRegistryInfo->NoBuses);
577
578 /* Loop every bus */
579 PciSlot.u.bits.Reserved = 0;
580 for (i = 0; i < PciRegistryInfo->NoBuses; i++)
581 {
582 /* Get the bus handler */
583 BusHandler = HalHandlerForBus(PCIBus, i);
584
585 /* Loop every device */
586 for (j = 0; j < 32; j++)
587 {
588 /* Loop every function */
589 PciSlot.u.bits.DeviceNumber = j;
590 for (k = 0; k < 8; k++)
591 {
592 /* Build the final slot structure */
593 PciSlot.u.bits.FunctionNumber = k;
594
595 /* Read the configuration information */
596 HalpReadPCIConfig(BusHandler,
597 PciSlot,
598 PciData,
599 0,
600 PCI_COMMON_HDR_LENGTH);
601
602 /* Skip if this is an invalid function */
603 if (PciData->VendorID == PCI_INVALID_VENDORID) continue;
604
605 /* Check if this is a Cardbus bridge */
606 if (PCI_CONFIGURATION_TYPE(PciData) == PCI_CARDBUS_BRIDGE_TYPE)
607 {
608 /* Not supported */
609 DbgPrint("HAL: Your machine has a PCI Cardbus Bridge. This is not supported!\n");
610 continue;
611 }
612
613 /* Check if this is a PCI device */
614 if (PCI_CONFIGURATION_TYPE(PciData) != PCI_BRIDGE_TYPE)
615 {
616 /* Check if it has an interrupt pin and line registered */
617 if ((PciData->u.type1.InterruptPin) &&
618 (PciData->u.type1.InterruptLine))
619 {
620 /* Check if this interrupt line is connected to the bus */
621 if (PciData->u.type1.InterruptLine < 16)
622 {
623 /* Is this an IDE device? */
624 DbgPrint("HAL: Found PCI device with IRQ line\n");
625 if (!HalpIsIdeDevice(PciData))
626 {
627 /* We'll mask out this interrupt then */
628 DbgPrint("HAL: Device is not an IDE Device. Should be masking IRQ %d! This is not supported!\n",
629 PciData->u.type1.InterruptLine);
630 HalpPciIrqMask |= (1 << PciData->u.type1.InterruptLine);
631 }
632 }
633 }
634 }
635
636 /* Check for broken Intel chips */
637 if (PciData->VendorID == 0x8086)
638 {
639 /* Check for broken 82830 PCI controller */
640 if ((PciData->DeviceID == 0x04A3) &&
641 (PciData->RevisionID < 0x11))
642 {
643 /* Skip */
644 DbgPrint("HAL: Your machine has a broken Intel 82430 PCI Controller. This is not supported!\n");
645 continue;
646 }
647
648 /* Check for broken 82378 PCI-to-ISA Bridge */
649 if ((PciData->DeviceID == 0x0484) &&
650 (PciData->RevisionID <= 3))
651 {
652 /* Skip */
653 DbgPrint("HAL: Your machine has a broken Intel 82378 PCI-to-ISA Bridge. This is not supported!\n");
654 continue;
655 }
656
657 /* Check for broken 82450 PCI Bridge */
658 if ((PciData->DeviceID == 0x84C4) &&
659 (PciData->RevisionID <= 4))
660 {
661 DbgPrint("HAL: Your machine has an Intel Orion 82450 PCI Bridge. This is not supported!\n");
662 continue;
663 }
664 }
665
666 /* Do we know this card? */
667 if (!ExtendedAddressDecoding)
668 {
669 /* Check for it */
670 if (HalpIsRecognizedCard(PciRegistryInfo,
671 PciData,
672 HALP_CARD_FEATURE_FULL_DECODE))
673 {
674 /* We'll do chipset checks later */
675 DbgPrint("HAL: Recognized a PCI Card with Extended Address Decoding. This is not supported!\n");
676 ExtendedAddressDecoding = TRUE;
677 }
678 }
679
680 /* Check if this is a USB controller */
681 if ((PciData->BaseClass == PCI_CLASS_SERIAL_BUS_CTLR) &&
682 (PciData->SubClass == PCI_SUBCLASS_SB_USB))
683 {
684 /* Check if this is an OHCI controller */
685 if (PciData->ProgIf == 0x10)
686 {
687 DbgPrint("HAL: Your machine has an OHCI (USB) PCI Expansion Card. This is not supported!\n");
688 continue;
689 }
690
691 /* Check for Intel UHCI controller */
692 if (PciData->VendorID == 0x8086)
693 {
694 DbgPrint("HAL: Your machine has an Intel UHCI (USB) Controller. This is not supported!\n");
695 continue;
696 }
697
698 /* Check for VIA UHCI controller */
699 if (PciData->VendorID == 0x1106)
700 {
701 DbgPrint("HAL: Your machine has a VIA UHCI (USB) Controller. This is not supported!\n");
702 continue;
703 }
704 }
705
706 /* Now check the registry for chipset hacks */
707 if (NT_SUCCESS(HalpGetChipHacks(PciData->VendorID,
708 PciData->DeviceID,
709 PciData->RevisionID,
710 &HackFlags)))
711 {
712 /* Check for hibernate-disable */
713 if (HackFlags & HAL_PCI_CHIP_HACK_DISABLE_HIBERNATE)
714 {
715 DbgPrint("HAL: Your machine has a broken PCI device which is incompatible with hibernation. This is not supported!\n");
716 continue;
717 }
718
719 /* Check for USB controllers that generate SMIs */
720 if (HackFlags & HAL_PCI_CHIP_HACK_USB_SMI_DISABLE)
721 {
722 DbgPrint("HAL: Your machine has a USB controller which generates SMIs. This is not supported!\n");
723 continue;
724 }
725 }
726 }
727 }
728 }
729
730 /* Initialize NMI Crash Flag */
731 HalpGetNMICrashFlag();
732
733 /* Free the registry data */
734 ExFreePool(PciRegistryInfo);
735
736 /* Tell PnP if this hard supports correct decoding */
737 HalpMarkChipsetDecode(ExtendedAddressDecoding);
738 DPRINT1("PCI BUS Setup complete\n");
739 #endif
740 }
741
742 VOID
743 NTAPI
744 HalpInitBusHandlers(VOID)
745 {
746 /* Register the HAL Bus Handler support */
747 HalpRegisterInternalBusHandlers();
748 }
749
750 VOID
751 NTAPI
752 HalpRegisterKdSupportFunctions(VOID)
753 {
754 /* Register PCI Device Functions */
755 KdSetupPciDeviceForDebugging = HalpSetupPciDeviceForDebugging;
756 KdReleasePciDeviceforDebugging = HalpReleasePciDeviceForDebugging;
757
758 /* Register memory functions */
759 #ifndef _MINIHAL_
760 KdMapPhysicalMemory64 = HalpMapPhysicalMemory64;
761 KdUnmapVirtualAddress = HalpUnmapVirtualAddress;
762 #endif
763
764 /* Register ACPI stub */
765 KdCheckPowerButton = HalpCheckPowerButton;
766 }
767
768 NTSTATUS
769 NTAPI
770 HalpAssignSlotResources(IN PUNICODE_STRING RegistryPath,
771 IN PUNICODE_STRING DriverClassName,
772 IN PDRIVER_OBJECT DriverObject,
773 IN PDEVICE_OBJECT DeviceObject,
774 IN INTERFACE_TYPE BusType,
775 IN ULONG BusNumber,
776 IN ULONG SlotNumber,
777 IN OUT PCM_RESOURCE_LIST *AllocatedResources)
778 {
779 BUS_HANDLER BusHandler;
780 PAGED_CODE();
781
782 /* Only PCI is supported */
783 if (BusType != PCIBus) return STATUS_NOT_IMPLEMENTED;
784
785 /* Setup fake PCI Bus handler */
786 RtlCopyMemory(&BusHandler, &HalpFakePciBusHandler, sizeof(BUS_HANDLER));
787 BusHandler.BusNumber = BusNumber;
788
789 /* Call the PCI function */
790 return HalpAssignPCISlotResources(&BusHandler,
791 &BusHandler,
792 RegistryPath,
793 DriverClassName,
794 DriverObject,
795 DeviceObject,
796 SlotNumber,
797 AllocatedResources);
798 }
799
800 BOOLEAN
801 NTAPI
802 HalpTranslateBusAddress(IN INTERFACE_TYPE InterfaceType,
803 IN ULONG BusNumber,
804 IN PHYSICAL_ADDRESS BusAddress,
805 IN OUT PULONG AddressSpace,
806 OUT PPHYSICAL_ADDRESS TranslatedAddress)
807 {
808 /* Translation is easy */
809 TranslatedAddress->QuadPart = BusAddress.QuadPart;
810 return TRUE;
811 }
812
813 ULONG
814 NTAPI
815 HalpGetSystemInterruptVector_Acpi(IN ULONG BusNumber,
816 IN ULONG BusInterruptLevel,
817 IN ULONG BusInterruptVector,
818 OUT PKIRQL Irql,
819 OUT PKAFFINITY Affinity)
820 {
821 ULONG Vector = IRQ2VECTOR(BusInterruptLevel);
822 *Irql = (KIRQL)VECTOR2IRQL(Vector);
823 *Affinity = 0xFFFFFFFF;
824 return Vector;
825 }
826
827 BOOLEAN
828 NTAPI
829 HalpFindBusAddressTranslation(IN PHYSICAL_ADDRESS BusAddress,
830 IN OUT PULONG AddressSpace,
831 OUT PPHYSICAL_ADDRESS TranslatedAddress,
832 IN OUT PULONG_PTR Context,
833 IN BOOLEAN NextBus)
834 {
835 /* Make sure we have a context */
836 if (!Context) return FALSE;
837
838 /* If we have data in the context, then this shouldn't be a new lookup */
839 if ((*Context) && (NextBus == TRUE)) return FALSE;
840
841 /* Return bus data */
842 TranslatedAddress->QuadPart = BusAddress.QuadPart;
843
844 /* Set context value and return success */
845 *Context = 1;
846 return TRUE;
847 }
848
849 /* PUBLIC FUNCTIONS **********************************************************/
850
851 /*
852 * @implemented
853 */
854 NTSTATUS
855 NTAPI
856 HalAdjustResourceList(IN PCM_RESOURCE_LIST Resources)
857 {
858 /* Deprecated, return success */
859 return STATUS_SUCCESS;
860 }
861
862 /*
863 * @implemented
864 */
865 NTSTATUS
866 NTAPI
867 HalAssignSlotResources(IN PUNICODE_STRING RegistryPath,
868 IN PUNICODE_STRING DriverClassName,
869 IN PDRIVER_OBJECT DriverObject,
870 IN PDEVICE_OBJECT DeviceObject,
871 IN INTERFACE_TYPE BusType,
872 IN ULONG BusNumber,
873 IN ULONG SlotNumber,
874 IN OUT PCM_RESOURCE_LIST *AllocatedResources)
875 {
876 /* Check the bus type */
877 if (BusType != PCIBus)
878 {
879 /* Call our internal handler */
880 return HalpAssignSlotResources(RegistryPath,
881 DriverClassName,
882 DriverObject,
883 DeviceObject,
884 BusType,
885 BusNumber,
886 SlotNumber,
887 AllocatedResources);
888 }
889 else
890 {
891 /* Call the PCI registered function */
892 return HalPciAssignSlotResources(RegistryPath,
893 DriverClassName,
894 DriverObject,
895 DeviceObject,
896 PCIBus,
897 BusNumber,
898 SlotNumber,
899 AllocatedResources);
900 }
901 }
902
903 /*
904 * @implemented
905 */
906 ULONG
907 NTAPI
908 HalGetBusData(IN BUS_DATA_TYPE BusDataType,
909 IN ULONG BusNumber,
910 IN ULONG SlotNumber,
911 IN PVOID Buffer,
912 IN ULONG Length)
913 {
914 /* Call the extended function */
915 return HalGetBusDataByOffset(BusDataType,
916 BusNumber,
917 SlotNumber,
918 Buffer,
919 0,
920 Length);
921 }
922
923 /*
924 * @implemented
925 */
926 ULONG
927 NTAPI
928 HalGetBusDataByOffset(IN BUS_DATA_TYPE BusDataType,
929 IN ULONG BusNumber,
930 IN ULONG SlotNumber,
931 IN PVOID Buffer,
932 IN ULONG Offset,
933 IN ULONG Length)
934 {
935 BUS_HANDLER BusHandler;
936
937 /* Look as the bus type */
938 if (BusDataType == Cmos)
939 {
940 /* Call CMOS Function */
941 return HalpGetCmosData(0, SlotNumber, Buffer, Length);
942 }
943 else if (BusDataType == EisaConfiguration)
944 {
945 /* FIXME: TODO */
946 ASSERT(FALSE);
947 }
948 else if ((BusDataType == PCIConfiguration) &&
949 (HalpPCIConfigInitialized) &&
950 ((BusNumber >= HalpMinPciBus) && (BusNumber <= HalpMaxPciBus)))
951 {
952 /* Setup fake PCI Bus handler */
953 RtlCopyMemory(&BusHandler, &HalpFakePciBusHandler, sizeof(BUS_HANDLER));
954 BusHandler.BusNumber = BusNumber;
955
956 /* Call PCI function */
957 return HalpGetPCIData(&BusHandler,
958 &BusHandler,
959 *(PPCI_SLOT_NUMBER)&SlotNumber,
960 Buffer,
961 Offset,
962 Length);
963 }
964
965 /* Invalid bus */
966 return 0;
967 }
968
969 /*
970 * @implemented
971 */
972 ULONG
973 NTAPI
974 HalGetInterruptVector(IN INTERFACE_TYPE InterfaceType,
975 IN ULONG BusNumber,
976 IN ULONG BusInterruptLevel,
977 IN ULONG BusInterruptVector,
978 OUT PKIRQL Irql,
979 OUT PKAFFINITY Affinity)
980 {
981 /* Call the system bus translator */
982 return HalpGetSystemInterruptVector_Acpi(BusNumber,
983 BusInterruptLevel,
984 BusInterruptVector,
985 Irql,
986 Affinity);
987 }
988
989 /*
990 * @implemented
991 */
992 ULONG
993 NTAPI
994 HalSetBusData(IN BUS_DATA_TYPE BusDataType,
995 IN ULONG BusNumber,
996 IN ULONG SlotNumber,
997 IN PVOID Buffer,
998 IN ULONG Length)
999 {
1000 /* Call the extended function */
1001 return HalSetBusDataByOffset(BusDataType,
1002 BusNumber,
1003 SlotNumber,
1004 Buffer,
1005 0,
1006 Length);
1007 }
1008
1009 /*
1010 * @implemented
1011 */
1012 ULONG
1013 NTAPI
1014 HalSetBusDataByOffset(IN BUS_DATA_TYPE BusDataType,
1015 IN ULONG BusNumber,
1016 IN ULONG SlotNumber,
1017 IN PVOID Buffer,
1018 IN ULONG Offset,
1019 IN ULONG Length)
1020 {
1021 BUS_HANDLER BusHandler;
1022
1023 /* Look as the bus type */
1024 if (BusDataType == Cmos)
1025 {
1026 /* Call CMOS Function */
1027 return HalpSetCmosData(0, SlotNumber, Buffer, Length);
1028 }
1029 else if ((BusDataType == PCIConfiguration) && (HalpPCIConfigInitialized))
1030 {
1031 /* Setup fake PCI Bus handler */
1032 RtlCopyMemory(&BusHandler, &HalpFakePciBusHandler, sizeof(BUS_HANDLER));
1033 BusHandler.BusNumber = BusNumber;
1034
1035 /* Call PCI function */
1036 return HalpSetPCIData(&BusHandler,
1037 &BusHandler,
1038 *(PPCI_SLOT_NUMBER)&SlotNumber,
1039 Buffer,
1040 Offset,
1041 Length);
1042 }
1043
1044 /* Invalid bus */
1045 return 0;
1046 }
1047
1048 /*
1049 * @implemented
1050 */
1051 BOOLEAN
1052 NTAPI
1053 HalTranslateBusAddress(IN INTERFACE_TYPE InterfaceType,
1054 IN ULONG BusNumber,
1055 IN PHYSICAL_ADDRESS BusAddress,
1056 IN OUT PULONG AddressSpace,
1057 OUT PPHYSICAL_ADDRESS TranslatedAddress)
1058 {
1059 /* Look as the bus type */
1060 if (InterfaceType == PCIBus)
1061 {
1062 /* Call the PCI registered function */
1063 return HalPciTranslateBusAddress(PCIBus,
1064 BusNumber,
1065 BusAddress,
1066 AddressSpace,
1067 TranslatedAddress);
1068 }
1069 else
1070 {
1071 /* Translation is easy */
1072 TranslatedAddress->QuadPart = BusAddress.QuadPart;
1073 return TRUE;
1074 }
1075 }
1076
1077 /* EOF */