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