BOOLEAN KdPortInitialize ( PDEBUG_PARAMETERS DebugParameters, PLOADER_PARAMETER_BLOCK LoaderBlock, BOOLEAN Initialize ) /*++ Routine Description: This routine initializes the serial port used by the kernel debugger and must be called during system initialization. Arguments: DebugParameter - Supplies a pointer to the debug port parameters. LoaderBlock - Supplies a pointer to the loader parameter block. Initialize - Specifies a boolean value that determines whether the debug port is initialized or just the debug port parameters are captured. Return Value: A value of TRUE is returned is the port was successfully initialized. Otherwise, a value of FALSE is returned. --*/ { PCONFIGURATION_COMPONENT_DATA ConfigurationEntry; UCHAR DataByte; PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor; PCM_SERIAL_DEVICE_DATA DeviceData; ULONG KdPortEntry; PCM_PARTIAL_RESOURCE_LIST List; ULONG MatchKey; ULONG BaudRate; ULONG BaudClock; // // Find the configuration information for the first serial port. // if (LoaderBlock != NULL) { MatchKey = 0; ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot, ControllerClass, SerialController, &MatchKey); } else { ConfigurationEntry = NULL; } if (DebugParameters->BaudRate != 0) { BaudRate = DebugParameters->BaudRate; } else { BaudRate = 19200; } // // If the serial configuration entry was found, then set baud clock // for 8000000. // BaudClock = 8000000; if (ConfigurationEntry != NULL) { List = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData; Descriptor = &List->PartialDescriptors[List->Count]; DeviceData = (PCM_SERIAL_DEVICE_DATA)Descriptor; if ((DeviceData->BaudClock == 1843200) || (DeviceData->BaudClock == 4233600) || (DeviceData->BaudClock == 8000000)) { BaudClock = DeviceData->BaudClock; } } HalpGetDivisorFromBaud( BaudClock, BaudRate, &HalpBaudRateDivisor ); // // If the debugger is not being enabled, then return. // if (Initialize == FALSE) { return TRUE; } // // Map the serial port into the system virtual address space by loading // a TB entry. // HalpPte[0].PFN = SP_PHYSICAL_BASE >> PAGE_SHIFT; HalpPte[0].G = 1; HalpPte[0].V = 1; HalpPte[0].D = 1; #if defined(R3000) // // Set the TB entry and set the noncached bit in the PTE that will // map the serial controller. // KdPortEntry = KDPORT_ENTRY; HalpPte[0].N = 1; #endif #if defined(R4000) // // Allocate a TB entry, set the uncached policy in the PTE that will // map the serial controller, and initialize the second PTE. // KdPortEntry = HalpAllocateTbEntry(); HalpPte[0].C = UNCACHED_POLICY; HalpPte[1].PFN = 0; HalpPte[1].G = 1; HalpPte[1].V = 0; HalpPte[1].D = 0; HalpPte[1].C = 0; #endif KdComPortInUse=(PUCHAR)SERIAL0_PHYSICAL_BASE; // // Map the serial controller through a fixed TB entry. // KeFillFixedEntryTb((PHARDWARE_PTE)&HalpPte[0], (PVOID)SP_VIRTUAL_BASE, KdPortEntry); // // Clear the divisor latch, clear all interrupt enables, and reset and // disable the FIFO's. // WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, 0x0); WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, 0x0); DataByte = 0; ((PSP_FIFO_CONTROL)(&DataByte))->ReceiveFifoReset = 1; ((PSP_FIFO_CONTROL)(&DataByte))->TransmitFifoReset = 1; WRITE_REGISTER_UCHAR(&SP_WRITE->FifoControl, DataByte); // // Set the divisor latch and set the baud rate to 19200 baud. // ((PSP_LINE_CONTROL)(&DataByte))->DivisorLatch = 1; WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte); WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, (UCHAR)(HalpBaudRateDivisor&0xff)); WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, (UCHAR)(HalpBaudRateDivisor>>8)); // // Clear the divisor latch and set the character size to eight bits // with one stop bit and no parity checking. // DataByte = 0; ((PSP_LINE_CONTROL)(&DataByte))->CharacterSize = EIGHT_BITS; WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte); // // Set data terminal ready and request to send. // DataByte = 0; ((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady = 1; ((PSP_MODEM_CONTROL)(&DataByte))->RequestToSend = 1; WRITE_REGISTER_UCHAR(&SP_WRITE->ModemControl, DataByte); // // Free the TB entry if one was allocated. // #if defined(R4000) HalpFreeTbEntry(); #endif return TRUE; }
NTSTATUS CmpInitializeHardwareConfiguration( IN PLOADER_PARAMETER_BLOCK LoaderBlock ) /*++ Routine Description: This routine creates \\Registry\Machine\Hardware node in the registry and calls SetupTree routine to put the hardware information to the registry. Arguments: LoaderBlock - supplies a pointer to the LoaderBlock passed in from the OS Loader. Returns: NTSTATUS code for sucess or reason of failure. --*/ { NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE BaseHandle; PCONFIGURATION_COMPONENT_DATA ConfigurationRoot; ULONG Disposition; ConfigurationRoot = (PCONFIGURATION_COMPONENT_DATA)LoaderBlock->ConfigurationRoot; if (ConfigurationRoot) { #ifdef _X86_ // // The following strings found in the registry identify obscure, // yet market dominant, non PC/AT compatible i386 machine in Japan. // #define MACHINE_TYPE_FUJITSU_FMR_NAME_A "FUJITSU FMR-" #define MACHINE_TYPE_NEC_PC98_NAME_A "NEC PC-98" { PCONFIGURATION_COMPONENT_DATA SystemNode; ULONG JapanMachineId; // // For Japan, we have to special case some non PC/AT machines, so // determine at this time what kind of platform we are on: // // NEC PC9800 Compatibles/Fujitsu FM-R Compatibles/IBM PC/AT Compatibles // // Default is PC/AT compatible. // JapanMachineId = MACHINE_TYPE_PC_AT_COMPATIBLE; // // Find the hardware description node // SystemNode = KeFindConfigurationEntry(ConfigurationRoot, SystemClass, MaximumType, NULL); // // Did we find something? // if (SystemNode) { // // Check platform from identifier string // if (RtlCompareMemory(SystemNode->ComponentEntry.Identifier, MACHINE_TYPE_NEC_PC98_NAME_A, sizeof(MACHINE_TYPE_NEC_PC98_NAME_A) - 1) == sizeof(MACHINE_TYPE_NEC_PC98_NAME_A) - 1) { // // we are running on NEC PC-9800 comaptibles. // JapanMachineId = MACHINE_TYPE_PC_9800_COMPATIBLE; SetNEC_98; } else if (RtlCompareMemory(SystemNode->ComponentEntry.Identifier, MACHINE_TYPE_FUJITSU_FMR_NAME_A, sizeof(MACHINE_TYPE_FUJITSU_FMR_NAME_A) - 1) == sizeof(MACHINE_TYPE_FUJITSU_FMR_NAME_A) - 1) { // // we are running on Fujitsu FMR comaptibles. // JapanMachineId = MACHINE_TYPE_FMR_COMPATIBLE; } } // // Now 'or' this value into the kernel global. // KeI386MachineType |= JapanMachineId; } #endif //_X86_ // // Create \\Registry\Machine\Hardware\DeviceMap // InitializeObjectAttributes( &ObjectAttributes, &CmRegistryMachineHardwareDeviceMapName, 0, (HANDLE)NULL, NULL ); ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE; Status = NtCreateKey( // Paht may already exist &BaseHandle, KEY_READ | KEY_WRITE, &ObjectAttributes, TITLE_INDEX_VALUE, NULL, 0, &Disposition ); if (!NT_SUCCESS(Status)) { return(Status); } NtClose(BaseHandle); ASSERT(Disposition == REG_CREATED_NEW_KEY); // // Create \\Registry\Machine\Hardware\Description and use the // returned handle as the BaseHandle to build the hardware tree. // InitializeObjectAttributes( &ObjectAttributes, &CmRegistryMachineHardwareDescriptionName, 0, (HANDLE)NULL, NULL ); ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE; Status = NtCreateKey( // Path may already exist &BaseHandle, KEY_READ | KEY_WRITE, &ObjectAttributes, TITLE_INDEX_VALUE, NULL, 0, &Disposition ); if (!NT_SUCCESS(Status)) { return(Status); } ASSERT(Disposition == REG_CREATED_NEW_KEY); // // Allocate 16K bytes memory from paged pool for constructing // configuration data for controller component. // NOTE: The configuration Data for controller component // usually takes less than 100 bytes. But on EISA machine, the // EISA configuration information takes more than 10K and up to // 64K. I believe 16K is the reasonable number to handler 99.9% // of the machines. Therefore, 16K is the initial value. // CmpConfigurationData = (PCM_FULL_RESOURCE_DESCRIPTOR)ExAllocatePool( PagedPool, CmpConfigurationAreaSize ); if (CmpConfigurationData == NULL) { return(STATUS_INSUFFICIENT_RESOURCES); } // // Call SetupConfigurationTree routine to go over each component // of the tree and add component information to registry database. // Status = CmpSetupConfigurationTree(ConfigurationRoot, BaseHandle, -1, (ULONG)-1 ); ExFreePool((PVOID)CmpConfigurationData); NtClose(BaseHandle); return(Status); } else { return(STATUS_SUCCESS); } }
BOOLEAN KdPortInitialize ( PDEBUG_PARAMETERS DebugParameters, PLOADER_PARAMETER_BLOCK LoaderBlock, BOOLEAN Initialize ) /*++ Routine Description: This routine initializes the serial port used by the kernel debugger and must be called during system initialization. Arguments: DebugParameter - Supplies a pointer to the debug port parameters. LoaderBlock - Supplies a pointer to the loader parameter block. Initialize - Specifies a boolean value that determines whether the debug port is initialized or just the debug port parameters are captured. Return Value: A value of TRUE is returned is the port was successfully initialized. Otherwise, a value of FALSE is returned. --*/ { PCONFIGURATION_COMPONENT_DATA ConfigurationEntry; UCHAR DataByte; PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor; PCM_SERIAL_DEVICE_DATA DeviceData; PCM_PARTIAL_RESOURCE_LIST List; ULONG MatchKey; ULONG BaudRate; ULONG BaudClock; // // Find the configuration information for the first serial port. // if (LoaderBlock != NULL) { MatchKey = 0; ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot, ControllerClass, SerialController, &MatchKey); } else { ConfigurationEntry = NULL; } if (DebugParameters->BaudRate != 0) { BaudRate = DebugParameters->BaudRate; } else { BaudRate = 19200; } // // If the serial configuration entry was not found or the frequency // specified is not supported, then default the baud clock to 800000. // BaudClock = 8000000; if (ConfigurationEntry != NULL) { List = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData; Descriptor = &List->PartialDescriptors[List->Count]; DeviceData = (PCM_SERIAL_DEVICE_DATA)Descriptor; if ((DeviceData->BaudClock == 1843200) || (DeviceData->BaudClock == 4233600) || (DeviceData->BaudClock == 8000000)) { BaudClock = DeviceData->BaudClock; } } HalpGetDivisorFromBaud( BaudClock, BaudRate, &HalpBaudRateDivisor ); // // If the debugger is not being enabled, then return. // if (Initialize == FALSE) { return TRUE; } KdComPortInUse=(PUCHAR)SERIAL0_PHYSICAL_BASE; // // Clear the divisor latch, clear all interrupt enables, and reset and // disable the FIFO's. // WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, 0x0); WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, 0x0); DataByte = 0; ((PSP_FIFO_CONTROL)(&DataByte))->ReceiveFifoReset = 1; ((PSP_FIFO_CONTROL)(&DataByte))->TransmitFifoReset = 1; WRITE_REGISTER_UCHAR(&SP_WRITE->FifoControl, DataByte); // // Set the divisor latch and set the baud rate. // ((PSP_LINE_CONTROL)(&DataByte))->DivisorLatch = 1; WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte); WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer,(UCHAR)(HalpBaudRateDivisor&0xFF)); WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable,(UCHAR)(HalpBaudRateDivisor>>8)); // // Clear the divisor latch and set the character size to eight bits // with one stop bit and no parity checking. // DataByte = 0; ((PSP_LINE_CONTROL)(&DataByte))->CharacterSize = EIGHT_BITS; WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte); // // Set data terminal ready and request to send. // DataByte = 0; ((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady = 1; ((PSP_MODEM_CONTROL)(&DataByte))->RequestToSend = 1; WRITE_REGISTER_UCHAR(&SP_WRITE->ModemControl, DataByte); // // Free the TB entry if one was allocated. // return TRUE; }
BOOLEAN HalpInitializeDisplay0 ( IN PLOADER_PARAMETER_BLOCK LoaderBlock ) /*++ Routine Description: This routine maps the video memory and control registers into the user part of the idle process address space, initializes the video control registers, and clears the video screen. Arguments: LoaderBlock - Supplies a pointer to the loader parameter block. Return Value: If the initialization is successfully completed, than a value of TRUE is returned. Otherwise, a value of FALSE is returned. --*/ { PCONFIGURATION_COMPONENT_DATA ConfigurationEntry; PVIDEO_BOARD_INFO VideoBoard; LONG Index; ULONG MatchKey; // // Find the configuration entry for the first display controller. // MatchKey = 0; ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot, ControllerClass, DisplayController, &MatchKey); if (ConfigurationEntry == NULL) { return FALSE; } // // Determine which video controller is present in the system. // N.B. Be carefull with debug prints during Phase 0, it // will kill the initial break point request from the debugger ... // for( Index=0, VideoBoard = KnownVideoBoards; Index < numVideoBoards; Index++, VideoBoard++) { if (!strcmp( ConfigurationEntry->ComponentEntry.Identifier, VideoBoard->FirmwareString )) { HalpVideoBoard = VideoBoard->VideoBoard; HalpVideoChip = VideoBoard->VideoChip; HalpDisplayControllerSetup = VideoBoard->ControllerSetup; break; } } if (Index >= numVideoBoards) { HalpVideoBoard = VIDEO_BOARD_UNKNOWN; HalpVideoChip = VIDEO_CHIP_UNKNOWN; HalpDisplayControllerSetup = HalpDoNoSetup; // // let's see, if the bios emulator can initialize the card .... // HalpDisplayWidth = 80; HalpDisplayText = 25; return TRUE; } // // Initialize the display controller. // HalpDisplayControllerSetup(); HalpFirstBoot = FALSE; return TRUE; }