mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
482 lines
14 KiB
482 lines
14 KiB
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
init.c
|
|
|
|
Abstract:
|
|
|
|
|
|
DriverEntry initialization code for pnp bios bus extender.
|
|
|
|
Author:
|
|
|
|
Shie-Lin Tzong (shielint) 21-Apr-1995
|
|
|
|
Environment:
|
|
|
|
Kernel mode only.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "busp.h"
|
|
|
|
NTSTATUS
|
|
MbInstallBusHandler (
|
|
IN PBUS_HANDLER MbBus
|
|
);
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(INIT,DriverEntry)
|
|
#pragma alloc_text(PAGE,MbAddBusDevices)
|
|
#pragma alloc_text(PAGE,MbInstallBusHandler)
|
|
#endif
|
|
|
|
|
|
NTSTATUS
|
|
DriverEntry(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine checks if mother board device info is accessible. If yes it
|
|
initializes its data structures and invokes h/w dependent initialization
|
|
routine.
|
|
|
|
Arguments:
|
|
|
|
DriverObject - specifies the driver object for the bus extender.
|
|
|
|
RegistryPath - supplies a pointer to a unicode string of the service key name in
|
|
the CurrentControlSet\Services key for the bus extender.
|
|
|
|
Return Value:
|
|
|
|
A NTSTATUS code to indicate the result of the initialization.
|
|
|
|
--*/
|
|
|
|
{
|
|
UNICODE_STRING unicodeString;
|
|
NTSTATUS status;
|
|
PVOID p;
|
|
ULONG length, count, i, bufferSize;
|
|
PDEVICE_HANDLER_OBJECT deviceHandler;
|
|
HAL_BUS_INFORMATION busInfo;
|
|
PCM_RESOURCE_LIST configuration = NULL;
|
|
ULONG deviceFlags;
|
|
|
|
//
|
|
// Verify Pnp BIOS is present - perform h/w dependent phase 0 initialization.
|
|
//
|
|
|
|
status = PbInitialize(0, NULL);
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((DEBUG_MESSAGE,"PnpBios: Pnp Bios data phase 0 Initialization failed.\n"));
|
|
return STATUS_NO_SUCH_DEVICE;
|
|
}
|
|
|
|
//
|
|
// Get pointers to the Hals callback objects. The one we are really interested
|
|
// in is Bus Check callback.
|
|
//
|
|
|
|
status = HalQuerySystemInformation (
|
|
HalCallbackInformation,
|
|
sizeof (MbpHalCallbacks),
|
|
&MbpHalCallbacks,
|
|
&length
|
|
);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((DEBUG_MESSAGE,"PnpBios: Failed to query Hal callbacks\n"));
|
|
return status;
|
|
}
|
|
|
|
//
|
|
// Initialize globals
|
|
//
|
|
|
|
MbpDriverObject = DriverObject;
|
|
ExInitializeWorkItem (&MbpWorkItem, MbpControlWorker, NULL);
|
|
KeInitializeSpinLock (&MbpSpinlock);
|
|
InitializeListHead (&MbpControlWorkerList);
|
|
InitializeListHead (&MbpCheckBusList);
|
|
ExInitializeFastMutex (&MbpMutex);
|
|
MbpDeviceHandlerObjectSize = *IoDeviceHandlerObjectSize;
|
|
|
|
for (i = 0; i < MAXIMUM_BUS_NUMBER; i++) {
|
|
MbpBusNumber[i] = (ULONG) -1;
|
|
}
|
|
|
|
//
|
|
// Initialize driver object add and detect device entries.
|
|
//
|
|
|
|
DriverObject->DriverExtension->AddDevice = MbAddBusDevices;
|
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = MbCreateClose;
|
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = MbCreateClose;
|
|
|
|
//
|
|
// Query the devices/buses currently controlled by the bus extender
|
|
//
|
|
|
|
status = IoQueryDeviceEnumInfo (&DriverObject->DriverExtension->ServiceKeyName, &count);
|
|
if (!NT_SUCCESS(status)) {
|
|
return status;
|
|
}
|
|
for (i = 0; i < count; i++) {
|
|
status = IoGetDeviceHandler(&DriverObject->DriverExtension->ServiceKeyName,
|
|
i,
|
|
&deviceHandler);
|
|
if (NT_SUCCESS(status)) {
|
|
bufferSize = sizeof(CM_RESOURCE_LIST);
|
|
tryAgain:
|
|
configuration = (PCM_RESOURCE_LIST)ExAllocatePool(PagedPool,
|
|
bufferSize
|
|
);
|
|
if (!configuration) {
|
|
IoReleaseDeviceHandler(deviceHandler);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
status = IoQueryDeviceConfiguration(deviceHandler,
|
|
&busInfo,
|
|
&deviceFlags,
|
|
configuration,
|
|
bufferSize, // buffer size
|
|
&length // Actual size
|
|
);
|
|
IoReleaseDeviceHandler(deviceHandler);
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
//
|
|
// We know we have two buses at most. If this is the first bus, we will add it
|
|
// and exit. We don't touch 2nd bus at init time. It should be enumerated
|
|
// later.
|
|
|
|
if (length >= MIN_DETECT_SIGNATURE_SIZE &&
|
|
configuration->List[0].BusNumber == 0 &&
|
|
configuration->List[0].InterfaceType == BUS_0_SIGNATURE) {
|
|
if (deviceFlags == DeviceStatusOK) {
|
|
MbAddBusDevices(&DriverObject->DriverExtension->ServiceKeyName, &i);
|
|
ExFreePool(configuration);
|
|
break;
|
|
}
|
|
}
|
|
} else if (status == STATUS_BUFFER_TOO_SMALL) {
|
|
ExFreePool(configuration);
|
|
bufferSize = length;
|
|
goto tryAgain;
|
|
}
|
|
ExFreePool(configuration);
|
|
}
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
MbAddBusDevices(
|
|
IN PUNICODE_STRING ServiceKeyName,
|
|
IN OUT PULONG InstanceNumber
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS status;
|
|
PBUS_HANDLER busHandler;
|
|
PCM_RESOURCE_LIST detectSignature;
|
|
UCHAR configuration[sizeof(CM_RESOURCE_LIST)];
|
|
UNICODE_STRING unicodeString;
|
|
WCHAR buffer[60];
|
|
ULONG VirtualBusNumber;
|
|
PDEVICE_HANDLER_OBJECT deviceHandler = NULL;
|
|
|
|
PAGED_CODE();
|
|
RtlZeroMemory(configuration, sizeof(CM_RESOURCE_LIST));
|
|
|
|
//
|
|
// Check if DriverEntry succeeded ...
|
|
//
|
|
|
|
if (!MbpDriverObject) {
|
|
return STATUS_NO_MORE_ENTRIES;
|
|
}
|
|
|
|
if (*InstanceNumber == PLUGPLAY_NO_INSTANCE) {
|
|
if (MbpBusNumber[0] == (ULONG) -1) {
|
|
|
|
//
|
|
// If bus handler for Pnp Bios bus 0 has not been installed,
|
|
// add this bus.
|
|
//
|
|
// Register bus handler for bus 0 - motherboard devices
|
|
//
|
|
|
|
status = HalRegisterBusHandler (
|
|
Internal,
|
|
-1,
|
|
(ULONG)-1,
|
|
Isa, // child of Isa bus # 0
|
|
0,
|
|
sizeof (MB_BUS_EXTENSION),
|
|
MbInstallBusHandler,
|
|
&busHandler
|
|
);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((DEBUG_MESSAGE,"PnpBios: Register Pnp bus 0 handler failed\n"));
|
|
return status;
|
|
}
|
|
|
|
//
|
|
// Register the bus with Pnp manager.
|
|
//
|
|
|
|
detectSignature = (PCM_RESOURCE_LIST)configuration;
|
|
detectSignature->Count = 1;
|
|
detectSignature->List[0].InterfaceType = BUS_0_SIGNATURE;
|
|
detectSignature->List[0].BusNumber = 0;
|
|
status = IoRegisterDetectedDevice (&MbpDriverObject->DriverExtension->ServiceKeyName,
|
|
detectSignature,
|
|
InstanceNumber);
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
//
|
|
// BUGBUG - unregister bus handler? How?
|
|
//
|
|
|
|
DebugPrint((DEBUG_BREAK,"PnpBios: Failed to register bus 0 to Pnp Mgr\n"));
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
} else {
|
|
|
|
//
|
|
// Enumerator should be able to find the docking station bus, if present,
|
|
// and should call this routine with a valid InstanceNumber. So, if after
|
|
// bus 0 is registered and enumerator calls this function again with
|
|
// *InstanceNumber == PLUGPLAY_NO_INSTANCE, it means there is no docking
|
|
// station bus - bus 1, we can simply return STATUS_NO_MORE_ENTRIES.
|
|
//
|
|
|
|
return STATUS_NO_MORE_ENTRIES;
|
|
}
|
|
} else {
|
|
|
|
if (MbpBusNumber[0] == (ULONG) -1) {
|
|
|
|
//
|
|
// If bus handler for Pnp Bios bus 0 has not been installed,
|
|
// add this bus.
|
|
//
|
|
// Register bus handler for bus 0 - motherboard devices
|
|
//
|
|
|
|
status = HalRegisterBusHandler (
|
|
Internal,
|
|
-1,
|
|
(ULONG)-1,
|
|
Isa, // child of Isa bus # 0
|
|
0,
|
|
sizeof (MB_BUS_EXTENSION),
|
|
MbInstallBusHandler,
|
|
&busHandler
|
|
);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((DEBUG_MESSAGE,"PnpBios: Register Pnp bus 0 handler failed\n"));
|
|
return status;
|
|
}
|
|
|
|
} else if (MbpBusNumber[1] == (ULONG) -1 && MbpBusExtension[0]->DockingStationDevice ) {
|
|
|
|
//
|
|
// If bus 1 has not been registered and docking station is present,
|
|
// Register bus handler for bus 1 - docking station devices
|
|
//
|
|
|
|
status = HalRegisterBusHandler (
|
|
Internal,
|
|
-1,
|
|
(ULONG)-1,
|
|
Internal,
|
|
MbpBusNumber[0],
|
|
sizeof (MB_BUS_EXTENSION),
|
|
MbInstallBusHandler,
|
|
&busHandler
|
|
);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((DEBUG_MESSAGE,"PnpBios: Register Pnp bus handler for bus 1 failed\n"));
|
|
return status;
|
|
}
|
|
} else {
|
|
return STATUS_NO_MORE_ENTRIES;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Call Pnp Io Mgr to register the new device object path
|
|
//
|
|
|
|
swprintf (buffer, rgzBIOSDeviceName, busHandler->BusNumber);
|
|
RtlInitUnicodeString (&unicodeString, buffer);
|
|
|
|
if (!NT_SUCCESS(status = IoGetDeviceHandler(&MbpDriverObject->DriverExtension->ServiceKeyName,
|
|
*InstanceNumber, &deviceHandler)) ||
|
|
!NT_SUCCESS(status = IoRegisterDevicePath(deviceHandler, &unicodeString, TRUE, NULL,
|
|
DeviceStatusOK))) {
|
|
|
|
//
|
|
// BUGBUG - unregister bus handler? How?
|
|
//
|
|
|
|
if (deviceHandler) {
|
|
DebugPrint((DEBUG_MESSAGE,"PnpBios: Register NT device path failed\n"));
|
|
IoReleaseDeviceHandler(deviceHandler);
|
|
} else {
|
|
DebugPrint((DEBUG_MESSAGE,"PnpBios: Unable to get device handler\n"));
|
|
}
|
|
}
|
|
|
|
IoReleaseDeviceHandler(deviceHandler);
|
|
|
|
//
|
|
// Perform initial bus check
|
|
//
|
|
|
|
MbpCheckBus(busHandler);
|
|
|
|
//
|
|
// Give non portable part of initialization another chance - phase 1 initialization.
|
|
//
|
|
|
|
PbInitialize(1, busHandler->DeviceObject);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
MbInstallBusHandler (
|
|
PBUS_HANDLER MbBus
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is invoked by Hal to initialize BUS_HANDLER structure and its
|
|
extension.
|
|
|
|
Arguments:
|
|
|
|
MbBus - spplies a pointer to Pnp BIOS bus handler's BUS_HANDLER structure.
|
|
|
|
Return Value:
|
|
|
|
A NTSTATUS code to indicate the result of the initialization.
|
|
|
|
--*/
|
|
|
|
{
|
|
WCHAR buffer[60];
|
|
UNICODE_STRING unicodeString;
|
|
PMB_DEVICE_EXTENSION deviceExtension;
|
|
PMB_BUS_EXTENSION busExtension;
|
|
NTSTATUS status;
|
|
PDEVICE_OBJECT deviceObject;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// Verify there's a parent handler
|
|
//
|
|
|
|
if (!MbBus->ParentHandler) {
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Create device object for Motherboard/PnpBios bus extender.
|
|
//
|
|
|
|
swprintf (buffer, rgzBIOSDeviceName, MbBus->BusNumber);
|
|
RtlInitUnicodeString (&unicodeString, buffer);
|
|
|
|
status = IoCreateDevice(
|
|
MbpDriverObject,
|
|
sizeof(MB_DEVICE_EXTENSION), // No device extension space
|
|
&unicodeString,
|
|
FILE_DEVICE_BUS_EXTENDER,
|
|
0,
|
|
FALSE,
|
|
&deviceObject
|
|
);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((DEBUG_MESSAGE,"PnpBios: Failed to create device object\n"));
|
|
return status;
|
|
}
|
|
|
|
// ===================================
|
|
// BUGBUG - need to find a solution
|
|
//
|
|
|
|
deviceObject->Flags &= ~0x80;
|
|
|
|
// ==================================
|
|
deviceExtension = (PMB_DEVICE_EXTENSION) deviceObject->DeviceExtension;
|
|
deviceExtension->BusHandler = MbBus;
|
|
|
|
//
|
|
// Initialize bus handlers
|
|
//
|
|
|
|
MbBus->DeviceObject = deviceObject;
|
|
MbBus->GetBusData = (PGETSETBUSDATA) MbGetBusData;
|
|
MbBus->SetBusData = (PGETSETBUSDATA) MbSetBusData;
|
|
MbBus->QueryBusSlots = (PQUERY_BUS_SLOTS) MbQueryBusSlots;
|
|
MbBus->DeviceControl = (PDEVICE_CONTROL) MbDeviceControl;
|
|
MbBus->ReferenceDeviceHandler = (PREFERENCE_DEVICE_HANDLER) MbpReferenceDeviceHandler;
|
|
MbBus->GetDeviceData = (PGET_SET_DEVICE_DATA) MbGetDeviceData;
|
|
MbBus->SetDeviceData = (PGET_SET_DEVICE_DATA) MbSetDeviceData;
|
|
|
|
//
|
|
// Intialize bus extension
|
|
//
|
|
|
|
busExtension = (PMB_BUS_EXTENSION)MbBus->BusData;
|
|
RtlZeroMemory(busExtension, sizeof(MB_BUS_EXTENSION));
|
|
busExtension->BusHandler = MbBus;
|
|
|
|
MbpBusNumber[MbpNextBusId] = MbBus->BusNumber;
|
|
MbpBusExtension[MbpNextBusId] = busExtension;
|
|
MbpNextBusId++;
|
|
|
|
InitializeListHead (&busExtension->CheckBus);
|
|
InitializeListHead (&busExtension->DeviceControl);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
|