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