NT4/private/ntos/nthals/halcbus/i386/cbusmem.c
2020-09-30 17:12:29 +02:00

295 lines
7.7 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1992, 1993, 1994 Corollary Inc.
Module Name:
cbus_mem.c
Abstract:
This module implements the handling of additional memory
ranges to be freed to the MM subcomponent for the Corollary MP
architectures under Windows NT.
Author:
Landy Wang (landy@corollary.com) 26-Mar-1992
Environment:
Kernel mode only.
Revision History:
--*/
#include "halp.h"
#include "cbusrrd.h"
VOID
CbusMemoryFree(
IN ULONG Address,
IN ULONG Size
);
VOID
HalpAddMem (
IN PLOADER_PARAMETER_BLOCK LoaderBlock
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, CbusMemoryFree)
#pragma alloc_text(INIT, HalpAddMem)
#endif
#define MAX_MEMORY_RANGES 16
ULONG HalpMemoryIndex;
MEMORY_ALLOCATION_DESCRIPTOR HalpMemory [MAX_MEMORY_RANGES];
extern EXT_CFG_OVERRIDE_T CbusGlobal;
extern ADDRESS_USAGE HalpCbusMemoryHole;
extern ULONG CbusMemoryHoleIndex;
#define SIXTEEN_MB (BYTES_TO_PAGES(16 * 1024 * 1024))
VOID
CbusMemoryFree(
IN ULONG Address,
IN ULONG Size
)
/*++
Routine Description:
Add the specified memory range to our list of memory ranges to
give to MM later. Called each time we find a memory card during startup,
also called on Cbus1 systems when we add a jumpered range (between 8 and
16MB). ranges are jumpered via EISA config when the user has added a
dual-ported RAM card and wants to configure it into the middle of memory
(not including 640K-1MB, which is jumpered for free) somewhere.
Arguments:
Address - Supplies a start physical address in bytes of memory to free
Size - Supplies a length in bytes spanned by this range
Return Value:
None.
--*/
{
PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
ULONG Page;
ULONG Index;
ULONG Index2;
//
// add the card provided we have space.
//
if (HalpMemoryIndex >= MAX_MEMORY_RANGES)
return;
Page = BYTES_TO_PAGES(Address);
for (Index = 0; Index < HalpMemoryIndex; Index++) {
if (Page < HalpMemory[Index].BasePage) {
for (Index2 = HalpMemoryIndex+1; Index2 > Index; Index2--) {
HalpMemory[Index2] = HalpMemory[Index2 - 1];
}
break;
}
}
Descriptor = &HalpMemory[Index];
Descriptor->MemoryType = MemoryFree;
Descriptor->BasePage = Page;
Descriptor->PageCount = BYTES_TO_PAGES(Size);
HalpMemoryIndex++;
}
VOID
HalpAddMem (
IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
/*++
Routine Description:
This function adds any general-purpose memory (not found by
ntldr) to the memory descriptor lists for usage by the MM subcomponent.
Kernel mode only. Called from HalInitSystem() at Phase0 since
this must all happen before MmInitSystem happens at Phase0.
Arguments:
LoaderBlock data structure to add the memory to. Note that when
adding memory, no attempt is made to sort new entries numerically
into the list.
Return Value:
None.
--*/
{
PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
PLIST_ENTRY NewMd;
ULONG Index;
//
// first, scan the existing memory list checking for an entries
// memory holes added to this table via the BIOS E820 function.
// using the E820 memory function was the only way to have the
// uniprocessor HAL not use the 3GB - 4GB range (CSR space),
// and other memory memory holes, for PCI devices. however,
// using the E820 memory function to pass reserved ranges has the
// side-effect of causing NT to allocate page tables and page
// file size calculations based on the inclusion of these reserved
// memory ranges. so, the E820 memory function will continue
// to set this range, but the C-bus HAL will look for these reserved
// memory ranges and delete it before the page tables are allocated.
// note that these reserved memory ranges have been recorded in
// HalpCbusMemoryHole and passed to the NT kernel as resources
// reserved by the C-bus HAL.
//
NewMd = LoaderBlock->MemoryDescriptorListHead.Flink;
while (NewMd != &LoaderBlock->MemoryDescriptorListHead) {
Descriptor = CONTAINING_RECORD(NewMd, MEMORY_ALLOCATION_DESCRIPTOR,
ListEntry);
for (Index = 0; Index < CbusMemoryHoleIndex; Index++) {
if (Descriptor->BasePage == BYTES_TO_PAGES(HalpCbusMemoryHole.Element[Index].Start)) {
NewMd = &Descriptor->ListEntry;
RemoveEntryList(NewMd);
break;
}
}
NewMd = Descriptor->ListEntry.Flink;
}
//
// next, scan the existing memory list for memory above 16MB.
// if we find any, then we are running on a new BIOS
// which has already told the NT loader about all the memory in
// the system, so don't free it again now...
//
NewMd = LoaderBlock->MemoryDescriptorListHead.Flink;
while (NewMd != &LoaderBlock->MemoryDescriptorListHead) {
Descriptor = CONTAINING_RECORD(NewMd, MEMORY_ALLOCATION_DESCRIPTOR,
ListEntry);
if (Descriptor->BasePage + Descriptor->PageCount > SIXTEEN_MB) {
//
// our BIOS gave NT loader the memory already, so
// we can just bail right now...
//
return;
}
NewMd = Descriptor->ListEntry.Flink;
}
Descriptor = HalpMemory;
for (Index = 0; Index < HalpMemoryIndex; Index++, Descriptor++) {
NewMd = &Descriptor->ListEntry;
//
// any memory below 16MB has already been reported by the BIOS,
// so trim the request. this is because requests can arrive in
// the flavor of a memory board with 64MB (or more) on one board!
//
// note that Cbus1 "hole" memory is always reclaimed at the
// doubly-mapped address in high memory, never in low memory.
//
if (Descriptor->BasePage + Descriptor->PageCount <= SIXTEEN_MB) {
continue;
}
if (Descriptor->BasePage < SIXTEEN_MB) {
Descriptor->PageCount -= (SIXTEEN_MB-Descriptor->BasePage);
Descriptor->BasePage = SIXTEEN_MB;
}
InsertHeadList(&LoaderBlock->MemoryDescriptorListHead, NewMd);
}
}
#if 0
VOID
CbusMemoryThread()
{
//
// Loop looking for work to do
//
do {
//
// Wait until something is put in the queue. By specifying
// a wait mode of UserMode, the thread's kernel stack is
// swappable
//
Entry = KeRemoveQueue(&ExWorkerQueue[QueueType], WaitMode,
NULL);
WorkItem = CONTAINING_RECORD(Entry, WORK_QUEUE_ITEM, List);
//
// Execute the specified routine.
//
} while (1);
}
BOOLEAN
CbusCreateMemoryThread()
{
HANDLE Thread;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS Status;
//
// Create our memory scrubbing thread
//
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
Status = PsCreateSystemThread(&Thread,
THREAD_ALL_ACCESS,
&ObjectAttributes,
0L,
NULL,
CbusMemoryThread,
(PVOID)CriticalWorkQueue);
if (!NT_SUCCESS(Status)) {
return FALSE;
}
ExCriticalWorkerThreads++;
ZwClose(Thread);
return True;
}
#endif