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