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