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