2020-09-30 17:12:29 +02:00

483 lines
14 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) 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;
}