483 lines
14 KiB
C
483 lines
14 KiB
C
/*++
|
||
|
||
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;
|
||
}
|
||
|
||
|
||
|