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