1 /*
2 * PROJECT: ReactOS HAL
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: hal/halx86/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 CODE_SEG("INIT")
16 PBUS_HANDLER
17 NTAPI
18 HalpAllocateAndInitPciBusHandler(
19 IN ULONG PciType,
20 IN ULONG BusNo,
21 IN BOOLEAN TestAllocation
22 );
23
24 CODE_SEG("INIT")
25 VOID
26 NTAPI
27 HalpFixupPciSupportedRanges(
28 IN ULONG BusCount
29 );
30
31 CODE_SEG("INIT")
32 NTSTATUS
33 NTAPI
34 HalpGetChipHacks(
35 IN USHORT VendorId,
36 IN USHORT DeviceId,
37 IN UCHAR RevisionId,
38 IN PULONG HackFlags
39 );
40
41 CODE_SEG("INIT")
42 BOOLEAN
43 NTAPI
44 HalpGetPciBridgeConfig(
45 IN ULONG PciType,
46 IN PUCHAR BusCount
47 );
48
49 CODE_SEG("INIT")
50 BOOLEAN
51 NTAPI
52 HalpIsBridgeDevice(
53 IN PPCI_COMMON_CONFIG PciData
54 );
55
56 CODE_SEG("INIT")
57 BOOLEAN
58 NTAPI
59 HalpIsIdeDevice(
60 IN PPCI_COMMON_CONFIG PciData
61 );
62
63 CODE_SEG("INIT")
64 BOOLEAN
65 NTAPI
66 HalpIsRecognizedCard(
67 IN PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo,
68 IN PPCI_COMMON_CONFIG PciData,
69 IN ULONG Flags
70 );
71
72 CODE_SEG("INIT")
73 BOOLEAN
74 NTAPI
75 HalpIsValidPCIDevice(
76 IN PBUS_HANDLER BusHandler,
77 IN PCI_SLOT_NUMBER Slot
78 );
79
80 CODE_SEG("INIT")
81 NTSTATUS
82 NTAPI
83 HalpMarkChipsetDecode(
84 IN BOOLEAN OverrideEnable
85 );
86
87 CODE_SEG("INIT")
88 VOID
89 NTAPI
90 HalpRegisterInternalBusHandlers(
91 VOID
92 );
93
94 CODE_SEG("INIT")
95 VOID
96 NTAPI
97 ShowSize(
98 IN ULONG Size
99 );
100
101 /* GLOBALS ********************************************************************/
102
103 extern KSPIN_LOCK HalpPCIConfigLock;
104 ULONG HalpPciIrqMask;
105
106 /* PRIVATE FUNCTIONS **********************************************************/
107
108 PBUS_HANDLER
109 NTAPI
HalpAllocateBusHandler(IN INTERFACE_TYPE InterfaceType,IN BUS_DATA_TYPE BusDataType,IN ULONG BusNumber,IN INTERFACE_TYPE ParentBusInterfaceType,IN ULONG ParentBusNumber,IN ULONG BusSpecificData)110 HalpAllocateBusHandler(IN INTERFACE_TYPE InterfaceType,
111 IN BUS_DATA_TYPE BusDataType,
112 IN ULONG BusNumber,
113 IN INTERFACE_TYPE ParentBusInterfaceType,
114 IN ULONG ParentBusNumber,
115 IN ULONG BusSpecificData)
116 {
117 PBUS_HANDLER Bus;
118
119 /* Register the bus handler */
120 HalRegisterBusHandler(InterfaceType,
121 BusDataType,
122 BusNumber,
123 ParentBusInterfaceType,
124 ParentBusNumber,
125 BusSpecificData,
126 NULL,
127 &Bus);
128 if (!Bus)
129 {
130 return NULL;
131 }
132
133 /* Check for a valid interface */
134 if (InterfaceType != InterfaceTypeUndefined)
135 {
136 /* Allocate address ranges and zero them out */
137 Bus->BusAddresses = ExAllocatePoolWithTag(NonPagedPoolMustSucceed,
138 sizeof(SUPPORTED_RANGES),
139 TAG_HAL);
140 RtlZeroMemory(Bus->BusAddresses, sizeof(SUPPORTED_RANGES));
141
142 /* Build the data structure */
143 Bus->BusAddresses->Version = HAL_SUPPORTED_RANGE_VERSION;
144 Bus->BusAddresses->Dma.Limit = 7;
145 Bus->BusAddresses->Memory.Limit = 0xFFFFFFFF;
146 Bus->BusAddresses->IO.Limit = 0xFFFF;
147 Bus->BusAddresses->IO.SystemAddressSpace = 1;
148 Bus->BusAddresses->PrefetchMemory.Base = 1;
149 }
150
151 /* Return the bus address */
152 return Bus;
153 }
154
155 #ifndef _MINIHAL_
156 CODE_SEG("INIT")
157 VOID
158 NTAPI
HalpRegisterInternalBusHandlers(VOID)159 HalpRegisterInternalBusHandlers(VOID)
160 {
161 PBUS_HANDLER Bus;
162
163 /* Only do processor 1 */
164 if (KeGetCurrentPrcb()->Number) return;
165
166 /* Register root support */
167 HalpInitBusHandler();
168
169 /* Allocate the system bus */
170 Bus = HalpAllocateBusHandler(Internal,
171 ConfigurationSpaceUndefined,
172 0,
173 InterfaceTypeUndefined,
174 0,
175 0);
176 if (Bus)
177 {
178 /* Set it up */
179 Bus->GetInterruptVector = HalpGetSystemInterruptVector;
180 Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
181 }
182
183 /* Allocate the CMOS bus */
184 Bus = HalpAllocateBusHandler(InterfaceTypeUndefined,
185 Cmos,
186 0,
187 InterfaceTypeUndefined,
188 0,
189 0);
190 if (Bus)
191 {
192 /* Set it up */
193 Bus->GetBusData = HalpcGetCmosData;
194 Bus->SetBusData = HalpcSetCmosData;
195 }
196
197 /* Allocate the CMOS bus */
198 Bus = HalpAllocateBusHandler(InterfaceTypeUndefined,
199 Cmos,
200 1,
201 InterfaceTypeUndefined,
202 0,
203 0);
204 if (Bus)
205 {
206 /* Set it up */
207 Bus->GetBusData = HalpcGetCmosData;
208 Bus->SetBusData = HalpcSetCmosData;
209 }
210
211 /* Allocate ISA bus */
212 Bus = HalpAllocateBusHandler(Isa,
213 ConfigurationSpaceUndefined,
214 0,
215 Internal,
216 0,
217 0);
218 if (Bus)
219 {
220 /* Set it up */
221 Bus->GetBusData = HalpNoBusData;
222 Bus->BusAddresses->Memory.Limit = 0xFFFFFF;
223 Bus->TranslateBusAddress = HalpTranslateIsaBusAddress;
224 }
225
226 /* No support for EISA or MCA */
227 ASSERT(HalpBusType == MACHINE_TYPE_ISA);
228 }
229 #endif // _MINIHAL_
230
231 #ifndef _MINIHAL_
232 CODE_SEG("INIT")
233 NTSTATUS
234 NTAPI
HalpMarkChipsetDecode(BOOLEAN OverrideEnable)235 HalpMarkChipsetDecode(BOOLEAN OverrideEnable)
236 {
237 NTSTATUS Status;
238 UNICODE_STRING KeyString;
239 ULONG Data = OverrideEnable;
240 HANDLE KeyHandle, Handle;
241
242 /* Open CCS key */
243 RtlInitUnicodeString(&KeyString,
244 L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET");
245 Status = HalpOpenRegistryKey(&Handle, 0, &KeyString, KEY_ALL_ACCESS, FALSE);
246 if (NT_SUCCESS(Status))
247 {
248 /* Open PNP Bios key */
249 RtlInitUnicodeString(&KeyString, L"Control\\Biosinfo\\PNPBios");
250 Status = HalpOpenRegistryKey(&KeyHandle,
251 Handle,
252 &KeyString,
253 KEY_ALL_ACCESS,
254 TRUE);
255
256 /* Close root key */
257 ZwClose(Handle);
258
259 /* Check if PNP BIOS key exists */
260 if (NT_SUCCESS(Status))
261 {
262 /* Set the override value */
263 RtlInitUnicodeString(&KeyString, L"FullDecodeChipsetOverride");
264 Status = ZwSetValueKey(KeyHandle,
265 &KeyString,
266 0,
267 REG_DWORD,
268 &Data,
269 sizeof(Data));
270
271 /* Close subkey */
272 ZwClose(KeyHandle);
273 }
274 }
275
276 /* Return status */
277 return Status;
278 }
279
280 CODE_SEG("INIT")
281 PBUS_HANDLER
282 NTAPI
HalpAllocateAndInitPciBusHandler(IN ULONG PciType,IN ULONG BusNo,IN BOOLEAN TestAllocation)283 HalpAllocateAndInitPciBusHandler(IN ULONG PciType,
284 IN ULONG BusNo,
285 IN BOOLEAN TestAllocation)
286 {
287 PBUS_HANDLER Bus;
288 PPCIPBUSDATA BusData;
289
290 /* Allocate the bus handler */
291 Bus = HalpAllocateBusHandler(PCIBus,
292 PCIConfiguration,
293 BusNo,
294 Internal,
295 0,
296 sizeof(PCIPBUSDATA));
297
298 /* Set it up */
299 Bus->GetBusData = HalpGetPCIData;
300 Bus->SetBusData = HalpSetPCIData;
301 Bus->GetInterruptVector = HalpGetPCIIntOnISABus;
302 Bus->AdjustResourceList = HalpAdjustPCIResourceList;
303 Bus->AssignSlotResources = HalpAssignPCISlotResources;
304 Bus->BusAddresses->Dma.Limit = 0;
305
306 /* Get our custom bus data */
307 BusData = (PPCIPBUSDATA)Bus->BusData;
308
309 /* Setup custom bus data */
310 BusData->CommonData.Tag = PCI_DATA_TAG;
311 BusData->CommonData.Version = PCI_DATA_VERSION;
312 BusData->CommonData.ReadConfig = HalpReadPCIConfig;
313 BusData->CommonData.WriteConfig = HalpWritePCIConfig;
314 BusData->CommonData.Pin2Line = HalpPCIPin2ISALine;
315 BusData->CommonData.Line2Pin = HalpPCIISALine2Pin;
316 BusData->MaxDevice = PCI_MAX_DEVICES;
317 BusData->GetIrqRange = HalpGetISAFixedPCIIrq;
318
319 /* Initialize the bitmap */
320 RtlInitializeBitMap(&BusData->DeviceConfigured, BusData->ConfiguredBits, 256);
321
322 /* Check the type of PCI bus */
323 switch (PciType)
324 {
325 /* Type 1 PCI Bus */
326 case 1:
327
328 /* Copy the Type 1 handler data */
329 RtlCopyMemory(&PCIConfigHandler,
330 &PCIConfigHandlerType1,
331 sizeof(PCIConfigHandler));
332
333 /* Set correct I/O Ports */
334 BusData->Config.Type1.Address = PCI_TYPE1_ADDRESS_PORT;
335 BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT;
336 break;
337
338 /* Type 2 PCI Bus */
339 case 2:
340
341 /* Copy the Type 1 handler data */
342 RtlCopyMemory(&PCIConfigHandler,
343 &PCIConfigHandlerType2,
344 sizeof (PCIConfigHandler));
345
346 /* Set correct I/O Ports */
347 BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT;
348 BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT;
349 BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE;
350
351 /* Only 16 devices supported, not 32 */
352 BusData->MaxDevice = 16;
353 break;
354
355 default:
356
357 /* Invalid type */
358 DbgPrint("HAL: Unknown PCI type\n");
359 }
360
361 /* Return the bus handler */
362 return Bus;
363 }
364
365 CODE_SEG("INIT")
366 BOOLEAN
367 NTAPI
HalpIsValidPCIDevice(IN PBUS_HANDLER BusHandler,IN PCI_SLOT_NUMBER Slot)368 HalpIsValidPCIDevice(IN PBUS_HANDLER BusHandler,
369 IN PCI_SLOT_NUMBER Slot)
370 {
371 UCHAR DataBuffer[PCI_COMMON_HDR_LENGTH];
372 PPCI_COMMON_CONFIG PciHeader = (PVOID)DataBuffer;
373 ULONG i;
374 ULONG_PTR Address;
375
376 /* Read the PCI header */
377 HalpReadPCIConfig(BusHandler, Slot, PciHeader, 0, PCI_COMMON_HDR_LENGTH);
378
379 /* Make sure it's a valid device */
380 if ((PciHeader->VendorID == PCI_INVALID_VENDORID) ||
381 (PCI_CONFIGURATION_TYPE(PciHeader) != PCI_DEVICE_TYPE))
382 {
383 /* Bail out */
384 return FALSE;
385 }
386
387 /* Make sure interrupt numbers make sense */
388 if (((PciHeader->u.type0.InterruptPin) &&
389 (PciHeader->u.type0.InterruptPin > 4)) ||
390 (PciHeader->u.type0.InterruptLine & 0x70))
391 {
392 /* Bail out */
393 return FALSE;
394 }
395
396 /* Now scan PCI BARs */
397 for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
398 {
399 /* Check what kind of address it is */
400 Address = PciHeader->u.type0.BaseAddresses[i];
401 if (Address & PCI_ADDRESS_IO_SPACE)
402 {
403 /* Highest I/O port is 65535 */
404 if (Address > 0xFFFF) return FALSE;
405 }
406 else
407 {
408 /* MMIO should be higher than 0x80000 */
409 if ((Address > 0xF) && (Address < 0x80000)) return FALSE;
410 }
411
412 /* Is this a 64-bit address? */
413 if (!(Address & PCI_ADDRESS_IO_SPACE) &&
414 ((Address & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT))
415 {
416 /* Check the next-next entry, since this one 64-bits wide */
417 i++;
418 }
419 }
420
421 /* Header, interrupt and address data all make sense */
422 return TRUE;
423 }
424
425 static BOOLEAN WarningsGiven[5];
426
427 CODE_SEG("INIT")
428 NTSTATUS
429 NTAPI
HalpGetChipHacks(IN USHORT VendorId,IN USHORT DeviceId,IN UCHAR RevisionId,IN PULONG HackFlags)430 HalpGetChipHacks(IN USHORT VendorId,
431 IN USHORT DeviceId,
432 IN UCHAR RevisionId,
433 IN PULONG HackFlags)
434 {
435 UNICODE_STRING KeyName, ValueName;
436 NTSTATUS Status;
437 OBJECT_ATTRIBUTES ObjectAttributes;
438 HANDLE KeyHandle;
439 WCHAR Buffer[32];
440 KEY_VALUE_PARTIAL_INFORMATION PartialInfo;
441 ULONG ResultLength;
442
443 /* Setup the object attributes for the key */
444 RtlInitUnicodeString(&KeyName,
445 L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\"
446 L"Control\\HAL");
447 InitializeObjectAttributes(&ObjectAttributes,
448 &KeyName,
449 OBJ_CASE_INSENSITIVE,
450 NULL,
451 NULL);
452
453 /* Open the key */
454 Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
455 if (!NT_SUCCESS(Status)) return Status;
456
457 /* Query value */
458 swprintf(Buffer, L"%04X%04X", VendorId, DeviceId);
459 RtlInitUnicodeString(&ValueName, Buffer);
460 Status = ZwQueryValueKey(KeyHandle,
461 &ValueName,
462 KeyValuePartialInformation,
463 &PartialInfo,
464 sizeof(PartialInfo),
465 &ResultLength);
466 if (NT_SUCCESS(Status))
467 {
468 /* Return the flags */
469 DbgPrint("\tFound HackFlags for your chipset\n");
470 *HackFlags = *(PULONG)PartialInfo.Data;
471 DbgPrint("\t\tHack Flags: %lx (Hack Revision: %lx-Your Revision: %lx)\n",
472 *HackFlags, HALP_REVISION_FROM_HACK_FLAGS(*HackFlags), RevisionId);
473
474 /* Does it apply to this revision? */
475 if ((RevisionId) && (RevisionId >= (HALP_REVISION_FROM_HACK_FLAGS(*HackFlags))))
476 {
477 /* Read the revision flags */
478 *HackFlags = HALP_REVISION_HACK_FLAGS(*HackFlags);
479 }
480
481 /* Throw out revision data */
482 *HackFlags = HALP_HACK_FLAGS(*HackFlags);
483 if (!*HackFlags) DbgPrint("\tNo HackFlags for your chipset's revision!\n");
484 }
485
486 /* Close the handle and return */
487 ZwClose(KeyHandle);
488 return Status;
489 }
490
491 CODE_SEG("INIT")
492 BOOLEAN
493 NTAPI
HalpIsRecognizedCard(IN PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo,IN PPCI_COMMON_CONFIG PciData,IN ULONG Flags)494 HalpIsRecognizedCard(IN PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo,
495 IN PPCI_COMMON_CONFIG PciData,
496 IN ULONG Flags)
497 {
498 ULONG ElementCount, i;
499 PPCI_CARD_DESCRIPTOR CardDescriptor;
500
501 /* How many PCI Cards that we know about? */
502 ElementCount = PciRegistryInfo->ElementCount;
503 if (!ElementCount) return FALSE;
504
505 /* Loop all descriptors */
506 CardDescriptor = &PciRegistryInfo->CardList[0];
507 for (i = 0; i < ElementCount; i++, CardDescriptor++)
508 {
509 /* Check for flag match */
510 if (CardDescriptor->Flags != Flags) continue;
511
512 /* Check for VID-PID match */
513 if ((CardDescriptor->VendorID != PciData->VendorID) ||
514 (CardDescriptor->DeviceID != PciData->DeviceID))
515 {
516 /* Skip */
517 continue;
518 }
519
520 /* Check for revision match, if requested */
521 if ((CardDescriptor->Flags & HALP_CHECK_CARD_REVISION_ID) &&
522 (CardDescriptor->RevisionID != PciData->RevisionID))
523 {
524 /* Skip */
525 continue;
526 }
527
528 /* Check what kind of device this is */
529 switch (PCI_CONFIGURATION_TYPE(PciData))
530 {
531 /* CardBUS Bridge */
532 case PCI_CARDBUS_BRIDGE_TYPE:
533
534 /* This means the real device header is in the device-specific data */
535 PciData = (PPCI_COMMON_CONFIG)PciData->DeviceSpecific;
536
537 /* Normal PCI device */
538 case PCI_DEVICE_TYPE:
539
540 /* Check for subvendor match, if requested */
541 if ((CardDescriptor->Flags & HALP_CHECK_CARD_SUBVENDOR_ID) &&
542 (CardDescriptor->SubsystemVendorID != PciData->u.type0.SubVendorID))
543 {
544 /* Skip */
545 continue;
546 }
547
548 /* Check for subsystem match, if requested */
549 if ((CardDescriptor->Flags & HALP_CHECK_CARD_SUBSYSTEM_ID) &&
550 (CardDescriptor->SubsystemID != PciData->u.type0.SubSystemID))
551 {
552 /* Skip */
553 continue;
554 }
555
556 /* You made it! */
557 return TRUE;
558
559 /* PCI Bridge -- don't bother */
560 case PCI_BRIDGE_TYPE:
561 default:
562
563 /* Recognize it */
564 return TRUE;
565 }
566 }
567
568 /* This means the card isn't recognized */
569 return FALSE;
570 }
571
572 CODE_SEG("INIT")
573 BOOLEAN
574 NTAPI
HalpIsIdeDevice(IN PPCI_COMMON_CONFIG PciData)575 HalpIsIdeDevice(IN PPCI_COMMON_CONFIG PciData)
576 {
577 /* Simple test first */
578 if ((PciData->BaseClass == PCI_CLASS_MASS_STORAGE_CTLR) &&
579 (PciData->SubClass == PCI_SUBCLASS_MSC_IDE_CTLR))
580 {
581 /* The device is nice enough to admit it */
582 return TRUE;
583 }
584
585 /* Symphony 82C101 */
586 if (PciData->VendorID == 0x1C1C) return TRUE;
587
588 /* ALi MS4803 or M5219 */
589 if ((PciData->VendorID == 0x10B9) &&
590 ((PciData->DeviceID == 0x5215) || (PciData->DeviceID == 0x5219)))
591 {
592 return TRUE;
593 }
594
595 /* Appian Technology */
596 if ((PciData->VendorID == 0x1097) && (PciData->DeviceID == 0x38)) return TRUE;
597
598 /* Compaq Triflex Dual EIDE Controller */
599 if ((PciData->VendorID == 0xE11) && (PciData->DeviceID == 0xAE33)) return TRUE;
600
601 /* Micron PC Tech RZ1000 */
602 if ((PciData->VendorID == 0x1042) && (PciData->DeviceID == 0x1000)) return TRUE;
603
604 /* SiS 85C601 or 5513 [IDE] */
605 if ((PciData->VendorID == 0x1039) &&
606 ((PciData->DeviceID == 0x601) || (PciData->DeviceID == 0x5513)))
607 {
608 return TRUE;
609 }
610
611 /* Symphony Labs W83769F */
612 if ((PciData->VendorID == 0x10AD) &&
613 ((PciData->DeviceID == 0x1) || (PciData->DeviceID == 0x150)))
614 {
615 return TRUE;
616 }
617
618 /* UMC UM8673F */
619 if ((PciData->VendorID == 0x1060) && (PciData->DeviceID == 0x101)) return TRUE;
620
621 /* You've survived */
622 return FALSE;
623 }
624
625 CODE_SEG("INIT")
626 BOOLEAN
627 NTAPI
HalpIsBridgeDevice(IN PPCI_COMMON_CONFIG PciData)628 HalpIsBridgeDevice(IN PPCI_COMMON_CONFIG PciData)
629 {
630 /* Either this is a PCI-to-PCI Bridge, or a CardBUS Bridge */
631 return (((PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE) &&
632 (PciData->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
633 (PciData->SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI)) ||
634 ((PCI_CONFIGURATION_TYPE(PciData) == PCI_CARDBUS_BRIDGE_TYPE) &&
635 (PciData->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
636 (PciData->SubClass == PCI_SUBCLASS_BR_CARDBUS)));
637 }
638
639 CODE_SEG("INIT")
640 BOOLEAN
641 NTAPI
HalpGetPciBridgeConfig(IN ULONG PciType,IN PUCHAR BusCount)642 HalpGetPciBridgeConfig(IN ULONG PciType,
643 IN PUCHAR BusCount)
644 {
645 PCI_SLOT_NUMBER PciSlot;
646 ULONG i, j, k;
647 UCHAR DataBuffer[PCI_COMMON_HDR_LENGTH];
648 PPCI_COMMON_CONFIG PciData = (PPCI_COMMON_CONFIG)DataBuffer;
649 PBUS_HANDLER BusHandler;
650
651 /* Loop PCI buses */
652 PciSlot.u.bits.Reserved = 0;
653 for (i = 0; i < *BusCount; i++)
654 {
655 /* Get the bus handler */
656 BusHandler = HalHandlerForBus(PCIBus, i);
657
658 /* Loop every device */
659 for (j = 0; j < PCI_MAX_DEVICES; j++)
660 {
661 /* Loop every function */
662 PciSlot.u.bits.DeviceNumber = j;
663 for (k = 0; k < PCI_MAX_FUNCTION; k++)
664 {
665 /* Build the final slot structure */
666 PciSlot.u.bits.FunctionNumber = k;
667
668 /* Read the configuration information */
669 HalpReadPCIConfig(BusHandler,
670 PciSlot,
671 PciData,
672 0,
673 PCI_COMMON_HDR_LENGTH);
674
675 /* Skip if this is an invalid function */
676 if (PciData->VendorID == PCI_INVALID_VENDORID) continue;
677
678 /* Make sure that this is a PCI bridge or a cardbus bridge */
679 if (!HalpIsBridgeDevice(PciData)) continue;
680
681 /* Not supported */
682 if (!WarningsGiven[2]++)
683 DPRINT1("Your machine has a PCI-to-PCI or CardBUS Bridge. PCI devices may fail!\n");
684 continue;
685 }
686 }
687 }
688
689 /* If we exited the loop, then there's no bridge to worry about */
690 return FALSE;
691 }
692
693 CODE_SEG("INIT")
694 VOID
695 NTAPI
HalpFixupPciSupportedRanges(IN ULONG BusCount)696 HalpFixupPciSupportedRanges(IN ULONG BusCount)
697 {
698 ULONG i;
699 PBUS_HANDLER Bus, ParentBus;
700
701 /* Loop all buses */
702 for (i = 0; i < BusCount; i++)
703 {
704 /* Get PCI bus handler */
705 Bus = HalHandlerForBus(PCIBus, i);
706
707 /* Loop all parent buses */
708 ParentBus = Bus->ParentHandler;
709 while (ParentBus)
710 {
711 /* Should merge addresses */
712 if (!WarningsGiven[0]++)
713 DPRINT1("Found parent bus (indicating PCI Bridge). PCI devices may fail!\n");
714
715 /* Check the next parent */
716 ParentBus = ParentBus->ParentHandler;
717 }
718 }
719
720 /* Loop all buses again */
721 for (i = 0; i < BusCount; i++)
722 {
723 /* Get PCI bus handler */
724 Bus = HalHandlerForBus(PCIBus, i);
725
726 /* Check if this is a PCI 2.2 Bus with Subtractive Decode */
727 if (!((PPCIPBUSDATA)Bus->BusData)->Subtractive)
728 {
729 /* Loop all parent buses */
730 ParentBus = Bus->ParentHandler;
731 while (ParentBus)
732 {
733 /* But check only PCI parent buses specifically */
734 if (ParentBus->InterfaceType == PCIBus)
735 {
736 /* Should trim addresses */
737 if (!WarningsGiven[1]++)
738 DPRINT1("Found parent PCI Bus (indicating PCI-to-PCI Bridge). PCI devices may fail!\n");
739 }
740
741 /* Check the next parent */
742 ParentBus = ParentBus->ParentHandler;
743 }
744 }
745 }
746
747 /* Loop buses one last time */
748 for (i = 0; i < BusCount; i++)
749 {
750 /* Get the PCI bus handler */
751 Bus = HalHandlerForBus(PCIBus, i);
752
753 /* Sort and combine (trim) bus address range information */
754 DPRINT("Warning: Bus addresses not being optimized!\n");
755 }
756 }
757
758 CODE_SEG("INIT")
759 VOID
760 NTAPI
ShowSize(ULONG x)761 ShowSize(ULONG x)
762 {
763 if (!x) return;
764 DbgPrint(" [size=");
765 if (x < 1024)
766 {
767 DbgPrint("%d", (int) x);
768 }
769 else if (x < 1048576)
770 {
771 DbgPrint("%dK", (int)(x / 1024));
772 }
773 else if (x < 0x80000000)
774 {
775 DbgPrint("%dM", (int)(x / 1048576));
776 }
777 else
778 {
779 DbgPrint("%d", x);
780 }
781 DbgPrint("]");
782 }
783
784 /*
785 * These includes are required to define
786 * the ClassTable and VendorTable arrays.
787 */
788 #define NEWLINE "\n" // "\r\n"
789 #include "pci_classes.h"
790 #include "pci_vendors.h"
791 CODE_SEG("INIT")
792 VOID
793 NTAPI
HalpDebugPciDumpBus(IN PBUS_HANDLER BusHandler,IN PCI_SLOT_NUMBER PciSlot,IN ULONG i,IN ULONG j,IN ULONG k,IN PPCI_COMMON_CONFIG PciData)794 HalpDebugPciDumpBus(IN PBUS_HANDLER BusHandler,
795 IN PCI_SLOT_NUMBER PciSlot,
796 IN ULONG i,
797 IN ULONG j,
798 IN ULONG k,
799 IN PPCI_COMMON_CONFIG PciData)
800 {
801 PCHAR p, ClassName, Boundary, SubClassName, VendorName, ProductName, SubVendorName;
802 UCHAR HeaderType;
803 ULONG Length;
804 CHAR LookupString[16] = "";
805 CHAR bSubClassName[64] = "Unknown";
806 CHAR bVendorName[64] = "";
807 CHAR bProductName[128] = "Unknown device";
808 CHAR bSubVendorName[128] = "Unknown";
809 ULONG Size, Mem, b;
810
811 HeaderType = (PciData->HeaderType & ~PCI_MULTIFUNCTION);
812
813 /* Isolate the class name */
814 sprintf(LookupString, "C %02x ", PciData->BaseClass);
815 ClassName = strstr((PCHAR)ClassTable, LookupString);
816 if (ClassName)
817 {
818 /* Isolate the subclass name */
819 ClassName += strlen("C 00 ");
820 Boundary = strstr(ClassName, NEWLINE "C ");
821 sprintf(LookupString, NEWLINE "\t%02x ", PciData->SubClass);
822 SubClassName = strstr(ClassName, LookupString);
823 if (Boundary && SubClassName > Boundary)
824 {
825 SubClassName = NULL;
826 }
827 if (!SubClassName)
828 {
829 SubClassName = ClassName;
830 }
831 else
832 {
833 SubClassName += strlen(NEWLINE "\t00 ");
834 }
835 /* Copy the subclass into our buffer */
836 p = strpbrk(SubClassName, NEWLINE);
837 Length = p - SubClassName;
838 Length = min(Length, sizeof(bSubClassName) - 1);
839 strncpy(bSubClassName, SubClassName, Length);
840 bSubClassName[Length] = '\0';
841 }
842
843 /* Isolate the vendor name */
844 sprintf(LookupString, NEWLINE "%04x ", PciData->VendorID);
845 VendorName = strstr((PCHAR)VendorTable, LookupString);
846 if (VendorName)
847 {
848 /* Copy the vendor name into our buffer */
849 VendorName += strlen(NEWLINE "0000 ");
850 p = strpbrk(VendorName, NEWLINE);
851 Length = p - VendorName;
852 Length = min(Length, sizeof(bVendorName) - 1);
853 strncpy(bVendorName, VendorName, Length);
854 bVendorName[Length] = '\0';
855 p += strlen(NEWLINE);
856 while (*p == '\t' || *p == '#')
857 {
858 p = strpbrk(p, NEWLINE);
859 p += strlen(NEWLINE);
860 }
861 Boundary = p;
862
863 /* Isolate the product name */
864 sprintf(LookupString, "\t%04x ", PciData->DeviceID);
865 ProductName = strstr(VendorName, LookupString);
866 if (Boundary && ProductName >= Boundary)
867 {
868 ProductName = NULL;
869 }
870 if (ProductName)
871 {
872 /* Copy the product name into our buffer */
873 ProductName += strlen("\t0000 ");
874 p = strpbrk(ProductName, NEWLINE);
875 Length = p - ProductName;
876 Length = min(Length, sizeof(bProductName) - 1);
877 strncpy(bProductName, ProductName, Length);
878 bProductName[Length] = '\0';
879 p += strlen(NEWLINE);
880 while ((*p == '\t' && *(p + 1) == '\t') || *p == '#')
881 {
882 p = strpbrk(p, NEWLINE);
883 p += strlen(NEWLINE);
884 }
885 Boundary = p;
886 SubVendorName = NULL;
887
888 if (HeaderType == PCI_DEVICE_TYPE)
889 {
890 /* Isolate the subvendor and subsystem name */
891 sprintf(LookupString,
892 "\t\t%04x %04x ",
893 PciData->u.type0.SubVendorID,
894 PciData->u.type0.SubSystemID);
895 SubVendorName = strstr(ProductName, LookupString);
896 if (Boundary && SubVendorName >= Boundary)
897 {
898 SubVendorName = NULL;
899 }
900 }
901 if (SubVendorName)
902 {
903 /* Copy the subvendor name into our buffer */
904 SubVendorName += strlen("\t\t0000 0000 ");
905 p = strpbrk(SubVendorName, NEWLINE);
906 Length = p - SubVendorName;
907 Length = min(Length, sizeof(bSubVendorName) - 1);
908 strncpy(bSubVendorName, SubVendorName, Length);
909 bSubVendorName[Length] = '\0';
910 }
911 }
912 }
913
914 /* Print out the data */
915 DbgPrint("%02x:%02x.%x %s [%02x%02x]: %s %s [%04x:%04x] (rev %02x)\n",
916 i,
917 j,
918 k,
919 bSubClassName,
920 PciData->BaseClass,
921 PciData->SubClass,
922 bVendorName,
923 bProductName,
924 PciData->VendorID,
925 PciData->DeviceID,
926 PciData->RevisionID);
927
928 if (HeaderType == PCI_DEVICE_TYPE)
929 {
930 DbgPrint("\tSubsystem: %s [%04x:%04x]\n",
931 bSubVendorName,
932 PciData->u.type0.SubVendorID,
933 PciData->u.type0.SubSystemID);
934 }
935
936 /* Print out and decode flags */
937 DbgPrint("\tFlags:");
938 if (PciData->Command & PCI_ENABLE_BUS_MASTER) DbgPrint(" bus master,");
939 if (PciData->Status & PCI_STATUS_66MHZ_CAPABLE) DbgPrint(" 66MHz,");
940 if ((PciData->Status & PCI_STATUS_DEVSEL) == 0x000) DbgPrint(" fast devsel,");
941 if ((PciData->Status & PCI_STATUS_DEVSEL) == 0x200) DbgPrint(" medium devsel,");
942 if ((PciData->Status & PCI_STATUS_DEVSEL) == 0x400) DbgPrint(" slow devsel,");
943 if ((PciData->Status & PCI_STATUS_DEVSEL) == 0x600) DbgPrint(" unknown devsel,");
944 DbgPrint(" latency %d", PciData->LatencyTimer);
945 if (PciData->u.type0.InterruptPin != 0 &&
946 PciData->u.type0.InterruptLine != 0 &&
947 PciData->u.type0.InterruptLine != 0xFF) DbgPrint(", IRQ %02d", PciData->u.type0.InterruptLine);
948 else if (PciData->u.type0.InterruptPin != 0) DbgPrint(", IRQ assignment required");
949 DbgPrint("\n");
950
951 if (HeaderType == PCI_BRIDGE_TYPE)
952 {
953 DbgPrint("\tBridge:");
954 DbgPrint(" primary bus %d,", PciData->u.type1.PrimaryBus);
955 DbgPrint(" secondary bus %d,", PciData->u.type1.SecondaryBus);
956 DbgPrint(" subordinate bus %d,", PciData->u.type1.SubordinateBus);
957 DbgPrint(" secondary latency %d", PciData->u.type1.SecondaryLatency);
958 DbgPrint("\n");
959 }
960
961 /* Scan addresses */
962 Size = 0;
963 for (b = 0; b < (HeaderType == PCI_DEVICE_TYPE ? PCI_TYPE0_ADDRESSES : PCI_TYPE1_ADDRESSES); b++)
964 {
965 /* Check for a BAR */
966 if (HeaderType != PCI_CARDBUS_BRIDGE_TYPE)
967 Mem = PciData->u.type0.BaseAddresses[b];
968 else
969 Mem = 0;
970 if (Mem)
971 {
972 ULONG PciBar = 0xFFFFFFFF;
973
974 HalpWritePCIConfig(BusHandler,
975 PciSlot,
976 &PciBar,
977 FIELD_OFFSET(PCI_COMMON_HEADER, u.type0.BaseAddresses[b]),
978 sizeof(ULONG));
979 HalpReadPCIConfig(BusHandler,
980 PciSlot,
981 &PciBar,
982 FIELD_OFFSET(PCI_COMMON_HEADER, u.type0.BaseAddresses[b]),
983 sizeof(ULONG));
984 HalpWritePCIConfig(BusHandler,
985 PciSlot,
986 &Mem,
987 FIELD_OFFSET(PCI_COMMON_HEADER, u.type0.BaseAddresses[b]),
988 sizeof(ULONG));
989
990 /* Decode the address type */
991 if (PciBar & PCI_ADDRESS_IO_SPACE)
992 {
993 /* Guess the size */
994 Size = 1 << 2;
995 while (!(PciBar & Size) && (Size)) Size <<= 1;
996
997 /* Print it out */
998 DbgPrint("\tI/O ports at %04lx", Mem & PCI_ADDRESS_IO_ADDRESS_MASK);
999 ShowSize(Size);
1000 }
1001 else
1002 {
1003 /* Guess the size */
1004 Size = 1 << 4;
1005 while (!(PciBar & Size) && (Size)) Size <<= 1;
1006
1007 /* Print it out */
1008 DbgPrint("\tMemory at %08lx (%d-bit, %sprefetchable)",
1009 Mem & PCI_ADDRESS_MEMORY_ADDRESS_MASK,
1010 (Mem & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_32BIT ? 32 : 64,
1011 (Mem & PCI_ADDRESS_MEMORY_PREFETCHABLE) ? "" : "non-");
1012 ShowSize(Size);
1013 }
1014 DbgPrint("\n");
1015 }
1016 }
1017 }
1018 #endif
1019
1020 CODE_SEG("INIT")
1021 VOID
1022 NTAPI
HalpInitializePciBus(VOID)1023 HalpInitializePciBus(VOID)
1024 {
1025 #ifndef _MINIHAL_
1026 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo;
1027 UCHAR PciType;
1028 PCI_SLOT_NUMBER PciSlot;
1029 ULONG i, j, k;
1030 UCHAR DataBuffer[PCI_COMMON_HDR_LENGTH];
1031 PPCI_COMMON_CONFIG PciData = (PPCI_COMMON_CONFIG)DataBuffer;
1032 PBUS_HANDLER BusHandler;
1033 ULONG HackFlags;
1034 BOOLEAN ExtendedAddressDecoding = FALSE;
1035 NTSTATUS Status;
1036
1037 /* Query registry information */
1038 PciRegistryInfo = HalpQueryPciRegistryInfo();
1039 if (!PciRegistryInfo) return;
1040
1041 /* Initialize the PCI configuration lock */
1042 KeInitializeSpinLock(&HalpPCIConfigLock);
1043
1044 /* Get the type and free the info structure */
1045 PciType = PciRegistryInfo->HardwareMechanism & 0xF;
1046
1047 /* Check if this is a type 2 PCI bus with at least one bus */
1048 if ((PciRegistryInfo->NoBuses) && (PciType == 2))
1049 {
1050 /* Setup the PCI slot */
1051 PciSlot.u.bits.Reserved = 0;
1052 PciSlot.u.bits.FunctionNumber = 0;
1053
1054 /* Loop all slots */
1055 for (i = 0; i < 32; i++)
1056 {
1057 /* Try to setup a Type 2 PCI slot */
1058 PciType = 2;
1059 BusHandler = HalpAllocateAndInitPciBusHandler(2, 0, TRUE);
1060 if (!BusHandler) break;
1061
1062 /* Now check if it's valid */
1063 if (HalpIsValidPCIDevice(BusHandler, PciSlot)) break;
1064
1065 /* Heh, the BIOS lied... try Type 1 */
1066 PciType = 1;
1067 BusHandler = HalpAllocateAndInitPciBusHandler(1, 0, TRUE);
1068 if (!BusHandler) break;
1069
1070 /* Now check if it's valid */
1071 if (HalpIsValidPCIDevice(BusHandler, PciSlot)) break;
1072
1073 /* Keep trying */
1074 PciType = 2;
1075 }
1076
1077 /* Now allocate the correct kind of handler */
1078 HalpAllocateAndInitPciBusHandler(PciType, 0, FALSE);
1079 }
1080
1081 /* Okay, now loop all PCI bridges */
1082 do
1083 {
1084 /* Loop all PCI buses */
1085 for (i = 0; i < PciRegistryInfo->NoBuses; i++)
1086 {
1087 /* Check if we have a handler for it */
1088 if (!HalHandlerForBus(PCIBus, i))
1089 {
1090 /* Allocate it */
1091 HalpAllocateAndInitPciBusHandler(PciType, i, FALSE);
1092 }
1093 }
1094 /* Go to the next bridge */
1095 } while (HalpGetPciBridgeConfig(PciType, &PciRegistryInfo->NoBuses));
1096
1097 /* Now build correct address range informaiton */
1098 HalpFixupPciSupportedRanges(PciRegistryInfo->NoBuses);
1099
1100 /* Loop every bus */
1101 DbgPrint("\n====== PCI BUS HARDWARE DETECTION =======\n\n");
1102 PciSlot.u.bits.Reserved = 0;
1103 for (i = 0; i < PciRegistryInfo->NoBuses; i++)
1104 {
1105 /* Get the bus handler */
1106 BusHandler = HalHandlerForBus(PCIBus, i);
1107
1108 /* Loop every device */
1109 for (j = 0; j < 32; j++)
1110 {
1111 /* Loop every function */
1112 PciSlot.u.bits.DeviceNumber = j;
1113 for (k = 0; k < 8; k++)
1114 {
1115 /* Build the final slot structure */
1116 PciSlot.u.bits.FunctionNumber = k;
1117
1118 /* Read the configuration information */
1119 HalpReadPCIConfig(BusHandler,
1120 PciSlot,
1121 PciData,
1122 0,
1123 PCI_COMMON_HDR_LENGTH);
1124
1125 /* Skip if this is an invalid function */
1126 if (PciData->VendorID == PCI_INVALID_VENDORID) continue;
1127
1128 /* Print out the entry */
1129 HalpDebugPciDumpBus(BusHandler, PciSlot, i, j, k, PciData);
1130
1131 /* Check if this is a Cardbus bridge */
1132 if (PCI_CONFIGURATION_TYPE(PciData) == PCI_CARDBUS_BRIDGE_TYPE)
1133 {
1134 /* Not supported */
1135 DbgPrint("\tDevice is a PCI Cardbus Bridge. It will not work!\n");
1136 continue;
1137 }
1138
1139 /* Check if this is a PCI device */
1140 if (PCI_CONFIGURATION_TYPE(PciData) != PCI_BRIDGE_TYPE)
1141 {
1142 /* Check if it has an interrupt pin and line registered */
1143 if ((PciData->u.type1.InterruptPin) &&
1144 (PciData->u.type1.InterruptLine))
1145 {
1146 /* Check if this interrupt line is connected to the bus */
1147 if (PciData->u.type1.InterruptLine < 16)
1148 {
1149 /* Is this an IDE device? */
1150 if (!HalpIsIdeDevice(PciData))
1151 {
1152 /* We'll mask out this interrupt then */
1153 DbgPrint("\tDevice is using IRQ %d! ISA Cards using that IRQ may fail!\n",
1154 PciData->u.type1.InterruptLine);
1155 HalpPciIrqMask |= (1 << PciData->u.type1.InterruptLine);
1156 }
1157 }
1158 }
1159 }
1160
1161 /* Check for broken Intel chips */
1162 if (PciData->VendorID == 0x8086)
1163 {
1164 /* Check for broken 82830 PCI controller */
1165 if ((PciData->DeviceID == 0x04A3) &&
1166 (PciData->RevisionID < 0x11))
1167 {
1168 /* Skip */
1169 DbgPrint("\tDevice is a broken Intel 82430 PCI Controller. It will not work!\n\n");
1170 continue;
1171 }
1172
1173 /* Check for broken 82378 PCI-to-ISA Bridge */
1174 if ((PciData->DeviceID == 0x0484) &&
1175 (PciData->RevisionID <= 3))
1176 {
1177 /* Skip */
1178 DbgPrint("\tDevice is a broken Intel 82378 PCI-to-ISA Bridge. It will not work!\n\n");
1179 continue;
1180 }
1181
1182 /* Check for broken 82450 PCI Bridge */
1183 if ((PciData->DeviceID == 0x84C4) &&
1184 (PciData->RevisionID <= 4))
1185 {
1186 DbgPrint("\tDevice is a Intel Orion 82450 PCI Bridge. It will not work!\n\n");
1187 continue;
1188 }
1189 }
1190
1191 /* Do we know this card? */
1192 if (!ExtendedAddressDecoding)
1193 {
1194 /* Check for it */
1195 if (HalpIsRecognizedCard(PciRegistryInfo,
1196 PciData,
1197 HALP_CARD_FEATURE_FULL_DECODE))
1198 {
1199 /* We'll do chipset checks later */
1200 DbgPrint("\tDevice has Extended Address Decoding. It may fail to work on older BIOSes!\n");
1201 ExtendedAddressDecoding = TRUE;
1202 }
1203 }
1204
1205 /* Now check the registry for chipset hacks */
1206 Status = HalpGetChipHacks(PciData->VendorID,
1207 PciData->DeviceID,
1208 PciData->RevisionID,
1209 &HackFlags);
1210 if (NT_SUCCESS(Status))
1211 {
1212 /* Check for broken ACPI routing */
1213 if (HackFlags & HAL_PCI_CHIP_HACK_DISABLE_ACPI_IRQ_ROUTING)
1214 {
1215 DbgPrint("This chipset has broken ACPI IRQ Routing! Be aware!\n\n");
1216 continue;
1217 }
1218
1219 /* Check for broken ACPI timer */
1220 if (HackFlags & HAL_PCI_CHIP_HACK_BROKEN_ACPI_TIMER)
1221 {
1222 DbgPrint("This chipset has a broken ACPI timer! Be aware!\n\n");
1223 continue;
1224 }
1225
1226 /* Check for hibernate-disable */
1227 if (HackFlags & HAL_PCI_CHIP_HACK_DISABLE_HIBERNATE)
1228 {
1229 DbgPrint("This chipset has a broken PCI device which is incompatible with hibernation. Be aware!\n\n");
1230 continue;
1231 }
1232
1233 /* Check for USB controllers that generate SMIs */
1234 if (HackFlags & HAL_PCI_CHIP_HACK_USB_SMI_DISABLE)
1235 {
1236 DbgPrint("This chipset has a USB controller which generates SMIs. ReactOS will likely fail to boot!\n\n");
1237 continue;
1238 }
1239 }
1240
1241 /* Terminate the entry */
1242 DbgPrint("\n");
1243 }
1244 }
1245 }
1246
1247 /* Initialize NMI Crash Flag */
1248 HalpGetNMICrashFlag();
1249
1250 /* Free the registry data */
1251 ExFreePoolWithTag(PciRegistryInfo, TAG_HAL);
1252
1253 /* Tell PnP if this hard supports correct decoding */
1254 HalpMarkChipsetDecode(ExtendedAddressDecoding);
1255 DbgPrint("====== PCI BUS DETECTION COMPLETE =======\n\n");
1256 #endif
1257 }
1258
1259 #ifndef _MINIHAL_
1260 CODE_SEG("INIT")
1261 VOID
1262 NTAPI
HalpInitBusHandlers(VOID)1263 HalpInitBusHandlers(VOID)
1264 {
1265 /* Register the HAL Bus Handler support */
1266 HalpRegisterInternalBusHandlers();
1267 }
1268
1269 CODE_SEG("INIT")
1270 VOID
1271 NTAPI
HalpRegisterKdSupportFunctions(VOID)1272 HalpRegisterKdSupportFunctions(VOID)
1273 {
1274 /* Register PCI Device Functions */
1275 KdSetupPciDeviceForDebugging = HalpSetupPciDeviceForDebugging;
1276 KdReleasePciDeviceforDebugging = HalpReleasePciDeviceForDebugging;
1277
1278 /* Register memory functions */
1279 #ifndef _MINIHAL_
1280 #if (NTDDI_VERSION >= NTDDI_VISTA)
1281 KdMapPhysicalMemory64 = HalpMapPhysicalMemory64Vista;
1282 KdUnmapVirtualAddress = HalpUnmapVirtualAddressVista;
1283 #else
1284 KdMapPhysicalMemory64 = HalpMapPhysicalMemory64;
1285 KdUnmapVirtualAddress = HalpUnmapVirtualAddress;
1286 #endif
1287 #endif
1288
1289 /* Register ACPI stub */
1290 KdCheckPowerButton = HalpCheckPowerButton;
1291 }
1292 #endif // _MINIHAL_
1293
1294 NTSTATUS
1295 NTAPI
HalpAssignSlotResources(IN PUNICODE_STRING RegistryPath,IN PUNICODE_STRING DriverClassName,IN PDRIVER_OBJECT DriverObject,IN PDEVICE_OBJECT DeviceObject,IN INTERFACE_TYPE BusType,IN ULONG BusNumber,IN ULONG SlotNumber,IN OUT PCM_RESOURCE_LIST * AllocatedResources)1296 HalpAssignSlotResources(IN PUNICODE_STRING RegistryPath,
1297 IN PUNICODE_STRING DriverClassName,
1298 IN PDRIVER_OBJECT DriverObject,
1299 IN PDEVICE_OBJECT DeviceObject,
1300 IN INTERFACE_TYPE BusType,
1301 IN ULONG BusNumber,
1302 IN ULONG SlotNumber,
1303 IN OUT PCM_RESOURCE_LIST *AllocatedResources)
1304 {
1305 PBUS_HANDLER Handler;
1306 NTSTATUS Status;
1307 PAGED_CODE();
1308 DPRINT1("Slot assignment for %d on bus %u\n", BusType, BusNumber);
1309
1310 /* Find the handler */
1311 Handler = HalReferenceHandlerForBus(BusType, BusNumber);
1312 if (!Handler) return STATUS_NOT_FOUND;
1313
1314 /* Do the assignment */
1315 Status = Handler->AssignSlotResources(Handler,
1316 Handler,
1317 RegistryPath,
1318 DriverClassName,
1319 DriverObject,
1320 DeviceObject,
1321 SlotNumber,
1322 AllocatedResources);
1323
1324 /* Dereference the handler and return */
1325 HalDereferenceBusHandler(Handler);
1326 return Status;
1327 }
1328
1329 BOOLEAN
1330 NTAPI
HaliFindBusAddressTranslation(IN PHYSICAL_ADDRESS BusAddress,IN OUT PULONG AddressSpace,OUT PPHYSICAL_ADDRESS TranslatedAddress,IN OUT PULONG_PTR Context,IN BOOLEAN NextBus)1331 HaliFindBusAddressTranslation(IN PHYSICAL_ADDRESS BusAddress,
1332 IN OUT PULONG AddressSpace,
1333 OUT PPHYSICAL_ADDRESS TranslatedAddress,
1334 IN OUT PULONG_PTR Context,
1335 IN BOOLEAN NextBus)
1336 {
1337 PHAL_BUS_HANDLER BusHandler;
1338 PBUS_HANDLER Handler;
1339 PLIST_ENTRY NextEntry;
1340
1341 /* Make sure we have a context */
1342 if (!Context)
1343 return FALSE;
1344
1345 /* If we have data in the context, then this shouldn't be a new lookup */
1346 if ((*Context != 0) && (NextBus != FALSE))
1347 return FALSE;
1348
1349 /* Find the bus handler */
1350 Handler = HalpContextToBusHandler(*Context);
1351 if (!Handler)
1352 return FALSE;
1353
1354 /* Check if this is an ongoing lookup */
1355 if (NextBus)
1356 {
1357 /* Get the HAL bus handler */
1358 BusHandler = CONTAINING_RECORD(Handler, HAL_BUS_HANDLER, Handler);
1359 NextEntry = &BusHandler->AllHandlers;
1360
1361 /* Get the next one if we were already with one */
1362 if (*Context)
1363 NextEntry = NextEntry->Flink;
1364
1365 /* Start scanning */
1366 while (TRUE)
1367 {
1368 /* Check if this is the last one */
1369 if (NextEntry == &HalpAllBusHandlers)
1370 {
1371 /* Quit */
1372 *Context = 1;
1373 return FALSE;
1374 }
1375
1376 /* Call this translator */
1377 BusHandler = CONTAINING_RECORD(NextEntry, HAL_BUS_HANDLER, AllHandlers);
1378 if (HalTranslateBusAddress(BusHandler->Handler.InterfaceType,
1379 BusHandler->Handler.BusNumber,
1380 BusAddress,
1381 AddressSpace,
1382 TranslatedAddress))
1383 {
1384 break;
1385 }
1386
1387 /* Try the next one */
1388 NextEntry = NextEntry->Flink;
1389 }
1390
1391 /* If we made it, we're done */
1392 *Context = (ULONG_PTR)&BusHandler->Handler;
1393 return TRUE;
1394 }
1395
1396 /* Try the first one through */
1397 if (!HalTranslateBusAddress(Handler->InterfaceType,
1398 Handler->BusNumber,
1399 BusAddress,
1400 AddressSpace,
1401 TranslatedAddress))
1402 {
1403 return FALSE;
1404 }
1405
1406 /* Remember for next time */
1407 *Context = (ULONG_PTR)Handler;
1408 return TRUE;
1409 }
1410
1411 BOOLEAN
1412 NTAPI
HaliTranslateBusAddress(IN INTERFACE_TYPE InterfaceType,IN ULONG BusNumber,IN PHYSICAL_ADDRESS BusAddress,IN OUT PULONG AddressSpace,OUT PPHYSICAL_ADDRESS TranslatedAddress)1413 HaliTranslateBusAddress(IN INTERFACE_TYPE InterfaceType,
1414 IN ULONG BusNumber,
1415 IN PHYSICAL_ADDRESS BusAddress,
1416 IN OUT PULONG AddressSpace,
1417 OUT PPHYSICAL_ADDRESS TranslatedAddress)
1418 {
1419 PBUS_HANDLER Handler;
1420 BOOLEAN Status;
1421
1422 /* Find the handler */
1423 Handler = HalReferenceHandlerForBus(InterfaceType, BusNumber);
1424 if (!(Handler) || !(Handler->TranslateBusAddress))
1425 {
1426 DPRINT1("No translator Interface: %x, Bus: %x, Handler: %p, BusAddress: %x!\n", InterfaceType, BusNumber, Handler, BusAddress);
1427 return FALSE;
1428 }
1429
1430 /* Do the assignment */
1431 Status = Handler->TranslateBusAddress(Handler,
1432 Handler,
1433 BusAddress,
1434 AddressSpace,
1435 TranslatedAddress);
1436
1437 /* Dereference the handler and return */
1438 HalDereferenceBusHandler(Handler);
1439 return Status;
1440 }
1441
1442 /* PUBLIC FUNCTIONS **********************************************************/
1443
1444 #ifndef _MINIHAL_
1445 /*
1446 * @implemented
1447 */
1448 NTSTATUS
1449 NTAPI
HalAdjustResourceList(IN PIO_RESOURCE_REQUIREMENTS_LIST * ResourceList)1450 HalAdjustResourceList(IN PIO_RESOURCE_REQUIREMENTS_LIST *ResourceList)
1451 {
1452 PBUS_HANDLER Handler;
1453 ULONG Status;
1454 PAGED_CODE();
1455
1456 /* Find the handler */
1457 Handler = HalReferenceHandlerForBus((*ResourceList)->InterfaceType,
1458 (*ResourceList)->BusNumber);
1459 if (!Handler) return STATUS_SUCCESS;
1460
1461 /* Do the assignment */
1462 Status = Handler->AdjustResourceList(Handler,
1463 Handler,
1464 ResourceList);
1465
1466 /* Dereference the handler and return */
1467 HalDereferenceBusHandler(Handler);
1468 return Status;
1469 }
1470 #endif // _MINIHAL_
1471
1472 /*
1473 * @implemented
1474 */
1475 NTSTATUS
1476 NTAPI
HalAssignSlotResources(IN PUNICODE_STRING RegistryPath,IN PUNICODE_STRING DriverClassName,IN PDRIVER_OBJECT DriverObject,IN PDEVICE_OBJECT DeviceObject,IN INTERFACE_TYPE BusType,IN ULONG BusNumber,IN ULONG SlotNumber,IN OUT PCM_RESOURCE_LIST * AllocatedResources)1477 HalAssignSlotResources(IN PUNICODE_STRING RegistryPath,
1478 IN PUNICODE_STRING DriverClassName,
1479 IN PDRIVER_OBJECT DriverObject,
1480 IN PDEVICE_OBJECT DeviceObject,
1481 IN INTERFACE_TYPE BusType,
1482 IN ULONG BusNumber,
1483 IN ULONG SlotNumber,
1484 IN OUT PCM_RESOURCE_LIST *AllocatedResources)
1485 {
1486 PAGED_CODE();
1487
1488 /* Check the bus type */
1489 if (BusType != PCIBus)
1490 {
1491 /* Call our internal handler */
1492 return HalpAssignSlotResources(RegistryPath,
1493 DriverClassName,
1494 DriverObject,
1495 DeviceObject,
1496 BusType,
1497 BusNumber,
1498 SlotNumber,
1499 AllocatedResources);
1500 }
1501 else
1502 {
1503 /* Call the PCI registered function */
1504 return HalPciAssignSlotResources(RegistryPath,
1505 DriverClassName,
1506 DriverObject,
1507 DeviceObject,
1508 PCIBus,
1509 BusNumber,
1510 SlotNumber,
1511 AllocatedResources);
1512 }
1513 }
1514
1515 #ifndef _MINIHAL_
1516 /*
1517 * @implemented
1518 */
1519 ULONG
1520 NTAPI
HalGetBusData(IN BUS_DATA_TYPE BusDataType,IN ULONG BusNumber,IN ULONG SlotNumber,IN PVOID Buffer,IN ULONG Length)1521 HalGetBusData(IN BUS_DATA_TYPE BusDataType,
1522 IN ULONG BusNumber,
1523 IN ULONG SlotNumber,
1524 IN PVOID Buffer,
1525 IN ULONG Length)
1526 {
1527 /* Call the extended function */
1528 return HalGetBusDataByOffset(BusDataType,
1529 BusNumber,
1530 SlotNumber,
1531 Buffer,
1532 0,
1533 Length);
1534 }
1535 #endif // _MINIHAL_
1536
1537 /*
1538 * @implemented
1539 */
1540 ULONG
1541 NTAPI
HalGetBusDataByOffset(IN BUS_DATA_TYPE BusDataType,IN ULONG BusNumber,IN ULONG SlotNumber,IN PVOID Buffer,IN ULONG Offset,IN ULONG Length)1542 HalGetBusDataByOffset(IN BUS_DATA_TYPE BusDataType,
1543 IN ULONG BusNumber,
1544 IN ULONG SlotNumber,
1545 IN PVOID Buffer,
1546 IN ULONG Offset,
1547 IN ULONG Length)
1548 {
1549 PBUS_HANDLER Handler;
1550 ULONG Status;
1551
1552 /* Find the handler */
1553 Handler = HaliReferenceHandlerForConfigSpace(BusDataType, BusNumber);
1554 if (!Handler) return 0;
1555
1556 /* Do the assignment */
1557 Status = Handler->GetBusData(Handler,
1558 Handler,
1559 SlotNumber,
1560 Buffer,
1561 Offset,
1562 Length);
1563
1564 /* Dereference the handler and return */
1565 HalDereferenceBusHandler(Handler);
1566 return Status;
1567 }
1568
1569 #ifndef _MINIHAL_
1570 /*
1571 * @implemented
1572 */
1573 ULONG
1574 NTAPI
HalGetInterruptVector(IN INTERFACE_TYPE InterfaceType,IN ULONG BusNumber,IN ULONG BusInterruptLevel,IN ULONG BusInterruptVector,OUT PKIRQL Irql,OUT PKAFFINITY Affinity)1575 HalGetInterruptVector(IN INTERFACE_TYPE InterfaceType,
1576 IN ULONG BusNumber,
1577 IN ULONG BusInterruptLevel,
1578 IN ULONG BusInterruptVector,
1579 OUT PKIRQL Irql,
1580 OUT PKAFFINITY Affinity)
1581 {
1582 PBUS_HANDLER Handler;
1583 ULONG Vector;
1584 PAGED_CODE();
1585
1586 /* Defaults */
1587 *Irql = 0;
1588 *Affinity = 0;
1589
1590 /* Find the handler */
1591 Handler = HalReferenceHandlerForBus(InterfaceType, BusNumber);
1592 if (!Handler) return 0;
1593
1594 /* Do the assignment */
1595 Vector = Handler->GetInterruptVector(Handler,
1596 Handler,
1597 BusInterruptLevel,
1598 BusInterruptVector,
1599 Irql,
1600 Affinity);
1601 if ((Vector != IRQ2VECTOR(BusInterruptLevel)) ||
1602 (*Irql != VECTOR2IRQL(IRQ2VECTOR(BusInterruptLevel))))
1603 {
1604 DPRINT1("Returning IRQL %lx, Vector %lx for Level/Vector: %lx/%lx\n",
1605 *Irql, Vector, BusInterruptLevel, BusInterruptVector);
1606 DPRINT1("Old HAL would've returned IRQL %lx and Vector %lx\n",
1607 VECTOR2IRQL(IRQ2VECTOR(BusInterruptLevel)),
1608 IRQ2VECTOR(BusInterruptLevel));
1609 }
1610
1611 /* Dereference the handler and return */
1612 HalDereferenceBusHandler(Handler);
1613 return Vector;
1614 }
1615
1616 /*
1617 * @implemented
1618 */
1619 ULONG
1620 NTAPI
HalSetBusData(IN BUS_DATA_TYPE BusDataType,IN ULONG BusNumber,IN ULONG SlotNumber,IN PVOID Buffer,IN ULONG Length)1621 HalSetBusData(IN BUS_DATA_TYPE BusDataType,
1622 IN ULONG BusNumber,
1623 IN ULONG SlotNumber,
1624 IN PVOID Buffer,
1625 IN ULONG Length)
1626 {
1627 /* Call the extended function */
1628 return HalSetBusDataByOffset(BusDataType,
1629 BusNumber,
1630 SlotNumber,
1631 Buffer,
1632 0,
1633 Length);
1634 }
1635
1636 /*
1637 * @implemented
1638 */
1639 ULONG
1640 NTAPI
HalSetBusDataByOffset(IN BUS_DATA_TYPE BusDataType,IN ULONG BusNumber,IN ULONG SlotNumber,IN PVOID Buffer,IN ULONG Offset,IN ULONG Length)1641 HalSetBusDataByOffset(IN BUS_DATA_TYPE BusDataType,
1642 IN ULONG BusNumber,
1643 IN ULONG SlotNumber,
1644 IN PVOID Buffer,
1645 IN ULONG Offset,
1646 IN ULONG Length)
1647 {
1648 PBUS_HANDLER Handler;
1649 ULONG Status;
1650
1651 /* Find the handler */
1652 Handler = HaliReferenceHandlerForConfigSpace(BusDataType, BusNumber);
1653 if (!Handler) return 0;
1654
1655 /* Do the assignment */
1656 Status = Handler->SetBusData(Handler,
1657 Handler,
1658 SlotNumber,
1659 Buffer,
1660 Offset,
1661 Length);
1662
1663 /* Dereference the handler and return */
1664 HalDereferenceBusHandler(Handler);
1665 return Status;
1666 }
1667 #endif // _MINIHAL_
1668
1669 /*
1670 * @implemented
1671 */
1672 BOOLEAN
1673 NTAPI
HalTranslateBusAddress(IN INTERFACE_TYPE InterfaceType,IN ULONG BusNumber,IN PHYSICAL_ADDRESS BusAddress,IN OUT PULONG AddressSpace,OUT PPHYSICAL_ADDRESS TranslatedAddress)1674 HalTranslateBusAddress(IN INTERFACE_TYPE InterfaceType,
1675 IN ULONG BusNumber,
1676 IN PHYSICAL_ADDRESS BusAddress,
1677 IN OUT PULONG AddressSpace,
1678 OUT PPHYSICAL_ADDRESS TranslatedAddress)
1679 {
1680 /* Look as the bus type */
1681 if (InterfaceType == PCIBus)
1682 {
1683 /* Call the PCI registered function */
1684 return HalPciTranslateBusAddress(PCIBus,
1685 BusNumber,
1686 BusAddress,
1687 AddressSpace,
1688 TranslatedAddress);
1689 }
1690 else
1691 {
1692 /* Call the bus handler */
1693 return HaliTranslateBusAddress(InterfaceType,
1694 BusNumber,
1695 BusAddress,
1696 AddressSpace,
1697 TranslatedAddress);
1698 }
1699 }
1700
1701 /* EOF */
1702