3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: hal/halx86/generic/halinit.c
5 * PURPOSE: HAL Entrypoint and Initialization
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
15 /* GLOBALS *******************************************************************/
17 /* Share with Mm headers? */
18 #define MM_HAL_VA_START (PVOID)0xFFC00000
19 #define MM_HAL_HEAP_START (PVOID)((ULONG_PTR)MM_HAL_VA_START + (1024 * 1024))
21 BOOLEAN HalpPciLockSettings
;
22 ULONG HalpUsedAllocDescriptors
;
23 MEMORY_ALLOCATION_DESCRIPTOR HalpAllocationDescriptorArray
[64];
24 PVOID HalpHeapStart
= MM_HAL_HEAP_START
;
26 /* PRIVATE FUNCTIONS *********************************************************/
30 HalpAllocPhysicalMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
35 ULONG UsedDescriptors
, Alignment
, PhysicalAddress
;
36 PFN_NUMBER MaxPage
, BasePage
;
37 PLIST_ENTRY NextEntry
;
38 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock
, NewBlock
, FreeBlock
;
40 /* Highest page we'll go */
41 MaxPage
= MaxAddress
>> PAGE_SHIFT
;
43 /* We need at least two blocks */
44 if ((HalpUsedAllocDescriptors
+ 2) > 64) return 0;
46 /* Remember how many we have now */
47 UsedDescriptors
= HalpUsedAllocDescriptors
;
49 /* Loop the loader block memory descriptors */
50 NextEntry
= LoaderBlock
->MemoryDescriptorListHead
.Flink
;
51 while (NextEntry
!= &LoaderBlock
->MemoryDescriptorListHead
)
54 MdBlock
= CONTAINING_RECORD(NextEntry
,
55 MEMORY_ALLOCATION_DESCRIPTOR
,
58 /* No alignment by default */
61 /* Unless requested, in which case we use a 64KB block alignment */
62 if (Aligned
) Alignment
= ((MdBlock
->BasePage
+ 0x0F) & ~0x0F) - MdBlock
->BasePage
;
64 /* Search for free memory */
65 if ((MdBlock
->MemoryType
== LoaderFree
) ||
66 (MdBlock
->MemoryType
== MemoryFirmwareTemporary
))
68 /* Make sure the page is within bounds, including alignment */
69 BasePage
= MdBlock
->BasePage
;
71 (MdBlock
->PageCount
>= PageCount
+ Alignment
) &&
72 (BasePage
+ PageCount
+ Alignment
< MaxPage
))
75 /* We found an address */
76 PhysicalAddress
= (BasePage
+ Alignment
) << PAGE_SHIFT
;
82 NextEntry
= NextEntry
->Flink
;
85 /* If we didn't find anything, get out of here */
86 if (NextEntry
== &LoaderBlock
->MemoryDescriptorListHead
) return 0;
88 /* Okay, now get a descriptor */
89 NewBlock
= &HalpAllocationDescriptorArray
[HalpUsedAllocDescriptors
];
90 NewBlock
->PageCount
= PageCount
;
91 NewBlock
->BasePage
= MdBlock
->BasePage
+ Alignment
;
92 NewBlock
->MemoryType
= LoaderHALCachedMemory
;
96 HalpUsedAllocDescriptors
= UsedDescriptors
;
98 /* Check if we had any alignment */
101 /* Check if we had leftovers */
102 if ((MdBlock
->PageCount
- Alignment
) != PageCount
)
104 /* Get the next descriptor */
105 FreeBlock
= &HalpAllocationDescriptorArray
[UsedDescriptors
];
106 FreeBlock
->PageCount
= MdBlock
->PageCount
- Alignment
- PageCount
;
107 FreeBlock
->BasePage
= MdBlock
->BasePage
+ Alignment
+ PageCount
;
110 HalpUsedAllocDescriptors
++;
112 /* Insert it into the list */
113 InsertHeadList(&MdBlock
->ListEntry
, &FreeBlock
->ListEntry
);
116 /* Use this descriptor */
117 NewBlock
->PageCount
= Alignment
;
118 InsertHeadList(&MdBlock
->ListEntry
, &NewBlock
->ListEntry
);
122 /* Consume memory from this block */
123 MdBlock
->BasePage
+= PageCount
;
124 MdBlock
->PageCount
-= PageCount
;
126 /* Insert the descriptor */
127 InsertTailList(&MdBlock
->ListEntry
, &NewBlock
->ListEntry
);
129 /* Remove the entry if the whole block was allocated */
130 if (!MdBlock
->PageCount
== 0) RemoveEntryList(&MdBlock
->ListEntry
);
133 /* Return the address */
134 return PhysicalAddress
;
139 HalpMapPhysicalMemory64(IN PHYSICAL_ADDRESS PhysicalAddress
,
142 PHARDWARE_PTE PointerPte
;
144 PVOID VirtualAddress
, BaseAddress
;
146 /* Start at the current HAL heap base */
147 BaseAddress
= HalpHeapStart
;
149 /* Loop until we have all the pages required */
150 while (UsedPages
< PageCount
)
152 /* Begin a new loop cycle */
154 VirtualAddress
= BaseAddress
;
156 /* If this overflows past the HAL heap, it means there's no space */
157 if (BaseAddress
== NULL
) return NULL
;
159 /* Loop until we have all the pages required in a single run */
160 while (UsedPages
< PageCount
)
162 /* Get the PTE for this address and check if it's available */
163 PointerPte
= HalAddressToPte(VirtualAddress
);
164 if (*(PULONG
)PointerPte
)
166 /* PTE has data, skip it and start with a new base address */
167 BaseAddress
= (PVOID
)((ULONG_PTR
)VirtualAddress
+ PAGE_SIZE
);
171 /* PTE is available, keep going on this run */
172 VirtualAddress
= (PVOID
)((ULONG_PTR
)VirtualAddress
+ PAGE_SIZE
);
177 /* Take the base address of the page plus the actual offset in the address */
178 VirtualAddress
= (PVOID
)((ULONG_PTR
)BaseAddress
+
179 BYTE_OFFSET(PhysicalAddress
.LowPart
));
181 /* If we are starting at the heap, move the heap */
182 if (BaseAddress
== HalpHeapStart
)
184 /* Past this allocation */
185 HalpHeapStart
= (PVOID
)((ULONG_PTR
)BaseAddress
+ (PageCount
* PAGE_SIZE
));
188 /* Loop pages that can be mapped */
191 /* Fill out the PTE */
192 PointerPte
= HalAddressToPte(BaseAddress
);
193 PointerPte
->PageFrameNumber
= PhysicalAddress
.QuadPart
>> PAGE_SHIFT
;
194 PointerPte
->Valid
= 1;
195 PointerPte
->Write
= 1;
197 /* Move to the next address */
198 PhysicalAddress
.QuadPart
+= PAGE_SIZE
;
199 BaseAddress
= (PVOID
)((ULONG_PTR
)BaseAddress
+ PAGE_SIZE
);
202 /* Flush the TLB and return the address */
204 return VirtualAddress
;
209 HalpUnmapVirtualAddress(IN PVOID VirtualAddress
,
212 PHARDWARE_PTE PointerPte
;
215 /* Only accept valid addresses */
216 if (VirtualAddress
< MM_HAL_VA_START
) return;
218 /* Align it down to page size */
219 VirtualAddress
= (PVOID
)((ULONG_PTR
)VirtualAddress
& ~(PAGE_SIZE
- 1));
222 PointerPte
= HalAddressToPte(VirtualAddress
);
223 for (i
= 0; i
< PageCount
; i
++)
225 *(PULONG
)PointerPte
= 0;
232 /* Put the heap back */
233 if (HalpHeapStart
> VirtualAddress
) HalpHeapStart
= VirtualAddress
;
238 HalpGetParameters(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
242 /* Make sure we have a loader block and command line */
243 if ((LoaderBlock
) && (LoaderBlock
->LoadOptions
))
245 /* Read the command line */
246 CommandLine
= LoaderBlock
->LoadOptions
;
248 /* Check if PCI is locked */
249 if (strstr(CommandLine
, "PCILOCK")) HalpPciLockSettings
= TRUE
;
251 /* Check for initial breakpoint */
252 if (strstr(CommandLine
, "BREAK")) DbgBreakPoint();
256 /* FUNCTIONS *****************************************************************/
263 HalInitSystem(IN ULONG BootPhase
,
264 IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
266 PKPRCB Prcb
= KeGetCurrentPrcb();
268 /* Check the boot phase */
271 /* Phase 0... save bus type */
272 HalpBusType
= LoaderBlock
->u
.I386
.MachineType
& 0xFF;
274 /* Get command-line parameters */
275 HalpGetParameters(LoaderBlock
);
277 /* Checked HAL requires checked kernel */
279 if (!(Prcb
->BuildType
& PRCB_BUILD_DEBUG
))
281 /* No match, bugcheck */
282 KeBugCheckEx(MISMATCHED_HAL
, 2, Prcb
->BuildType
, 1, 0);
285 /* Release build requires release HAL */
286 if (Prcb
->BuildType
& PRCB_BUILD_DEBUG
)
288 /* No match, bugcheck */
289 KeBugCheckEx(MISMATCHED_HAL
, 2, Prcb
->BuildType
, 0, 0);
294 /* SMP HAL requires SMP kernel */
295 if (Prcb
->BuildType
& PRCB_BUILD_UNIPROCESSOR
)
297 /* No match, bugcheck */
298 KeBugCheckEx(MISMATCHED_HAL
, 2, Prcb
->BuildType
, 0, 0);
302 /* Validate the PRCB */
303 if (Prcb
->MajorVersion
!= PRCB_MAJOR_VERSION
)
305 /* Validation failed, bugcheck */
306 KeBugCheckEx(MISMATCHED_HAL
, 1, Prcb
->MajorVersion
, 1, 0);
310 /* Initialize the PICs */
311 HalpInitializePICs(TRUE
);
314 /* Force initial PIC state */
315 KfRaiseIrql(KeGetCurrentIrql());
317 /* Initialize CMOS lock */
318 KeInitializeSpinLock(&HalpSystemHardwareLock
);
320 /* Initialize CMOS */
321 HalpInitializeCmos();
323 /* Fill out the dispatch tables */
324 HalQuerySystemInformation
= HaliQuerySystemInformation
;
325 HalSetSystemInformation
= HaliSetSystemInformation
;
326 HalInitPnpDriver
= NULL
; // FIXME: TODO
328 HalGetDmaAdapter
= HalpGetDmaAdapter
;
330 HalGetDmaAdapter
= NULL
;
332 HalGetInterruptTranslator
= NULL
; // FIXME: TODO
334 HalResetDisplay
= HalpBiosDisplayReset
;
336 HalResetDisplay
= NULL
;
338 HalHaltSystem
= HaliHaltSystem
;
341 HalpRegisterVector(IDT_INTERNAL
,
342 PRIMARY_VECTOR_BASE
+ 2,
343 PRIMARY_VECTOR_BASE
+ 2,
346 /* Setup I/O space */
347 HalpDefaultIoSpace
.Next
= HalpAddressUsageList
;
348 HalpAddressUsageList
= &HalpDefaultIoSpace
;
350 /* Setup busy waiting */
351 HalpCalibrateStallExecution();
354 /* Initialize the clock */
355 HalpInitializeClock();
359 * We could be rebooting with a pending profile interrupt,
360 * so clear it here before interrupts are enabled
362 HalStopProfileInterrupt(ProfileTime
);
364 /* Do some HAL-specific initialization */
365 HalpInitPhase0(LoaderBlock
);
367 else if (BootPhase
== 1)
369 /* Initialize bus handlers */
370 HalpInitBusHandler();
374 HalpEnableInterruptHandler(IDT_DEVICE
,
382 HalpEnableInterruptHandler(IDT_DEVICE
,
384 PRIMARY_VECTOR_BASE
+ 8,
386 HalpProfileInterrupt
,
389 /* Initialize DMA. NT does this in Phase 0 */
393 /* Do some HAL-specific initialization */
397 /* All done, return */