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.
886 lines
21 KiB
886 lines
21 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
port.c
|
|
|
|
Abstract:
|
|
|
|
|
|
Author:
|
|
|
|
Shie-Lin Tzong (shielint) May-20-1995
|
|
|
|
Environment:
|
|
|
|
Kernel mode only.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "busp.h"
|
|
|
|
VOID
|
|
MbpInvalidateSlots (
|
|
IN PMB_BUS_EXTENSION BusExtension
|
|
);
|
|
|
|
VOID
|
|
MbpDeleteSlots (
|
|
IN PMB_BUS_EXTENSION BusExtension
|
|
);
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE,MbQueryBusSlots)
|
|
#pragma alloc_text(PAGE,MbpCheckBus)
|
|
#pragma alloc_text(PAGE,MbpReferenceDeviceHandler)
|
|
#endif
|
|
|
|
|
|
ULONG
|
|
MbGetBusData (
|
|
IN PBUS_HANDLER BusHandler,
|
|
IN PBUS_HANDLER RootHandler,
|
|
IN ULONG SlotNumber,
|
|
IN PUCHAR Buffer,
|
|
IN ULONG Offset,
|
|
IN ULONG Length
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The function returns the Pnp Bios data for a device.
|
|
|
|
Arguments:
|
|
|
|
BusHandler - supplies a pointer to the handler of the bus.
|
|
|
|
RootHandler - supplies a pointer to a BUS_HANDLER for the originating
|
|
request.
|
|
|
|
Buffer - Supplies the space to store the data.
|
|
|
|
Offset - Supplies the offset to the device data to start reading.
|
|
|
|
Length - Supplies a count in bytes of the maximum amount to return.
|
|
|
|
Return Value:
|
|
|
|
Returns the amount of data stored into the buffer.
|
|
|
|
--*/
|
|
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
ULONG
|
|
MbSetBusData (
|
|
IN PBUS_HANDLER BusHandler,
|
|
IN PBUS_HANDLER RootHandler,
|
|
IN ULONG SlotNumber,
|
|
IN PUCHAR Buffer,
|
|
IN ULONG Offset,
|
|
IN ULONG Length
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The function sets the Pnp Bios data for a device.
|
|
|
|
Arguments:
|
|
|
|
BusHandler - supplies a pointer to the handler of the bus.
|
|
|
|
RootHandler - supplies a pointer to a BUS_HANDLER for the originating
|
|
request.
|
|
|
|
Buffer - Supplies the space to store the data.
|
|
|
|
Offset - Supplies the offset to the device data to be set.
|
|
|
|
Length - Supplies a count in bytes of the maximum amount to return.
|
|
|
|
Return Value:
|
|
|
|
Returns the amount of data stored into the buffer.
|
|
|
|
--*/
|
|
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
ULONG
|
|
MbGetDeviceData (
|
|
IN struct _BUS_HANDLER *BusHandler,
|
|
IN struct _BUS_HANDLER *RootHandler,
|
|
IN PDEVICE_HANDLER_OBJECT DeviceHandler,
|
|
IN ULONG DataType,
|
|
IN PUCHAR Buffer,
|
|
IN ULONG Offset,
|
|
IN ULONG Length
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The function returns the Pnp Bios data for a device.
|
|
|
|
Arguments:
|
|
|
|
BusHandler - supplies a pointer to the handler of the bus.
|
|
|
|
RootHandler - supplies a pointer to a BUS_HANDLER for the originating
|
|
request.
|
|
|
|
DeviceHandler - supplies a pointer to a DEVICE_HANDLER_OBJECT
|
|
|
|
DataType - Specifies the type of device data desired.
|
|
|
|
Buffer - Supplies the space to store the data.
|
|
|
|
Offset - Supplies the offset to the device data to start reading.
|
|
|
|
Length - Supplies a count in bytes of the maximum amount to return.
|
|
|
|
Return Value:
|
|
|
|
Returns the amount of data stored into the buffer.
|
|
|
|
--*/
|
|
{
|
|
ULONG dataLength;
|
|
PDEVICE_DATA deviceData;
|
|
|
|
UNREFERENCED_PARAMETER ( DataType);
|
|
|
|
dataLength = 0;
|
|
deviceData = DeviceHandler2DeviceData (DeviceHandler);
|
|
|
|
//
|
|
// Verify caller has a valid DeviceHandler object
|
|
//
|
|
|
|
if (!(deviceData->Flags & DEVICE_FLAGS_VALID)) {
|
|
|
|
//
|
|
// Obsolete object, return no data
|
|
//
|
|
|
|
return dataLength;
|
|
}
|
|
|
|
//
|
|
// Get the device's data.
|
|
//
|
|
|
|
//
|
|
// Synchronize with other pnp bios service functions.
|
|
//
|
|
|
|
ExAcquireFastMutex(&MbpMutex);
|
|
|
|
dataLength = deviceData->BusDataLength;
|
|
if (Offset < dataLength) {
|
|
dataLength -= Offset;
|
|
if (dataLength > Length) {
|
|
dataLength = Length;
|
|
}
|
|
RtlMoveMemory(Buffer, (PUCHAR)deviceData->BusData + Offset, dataLength);
|
|
} else {
|
|
dataLength = 0;
|
|
}
|
|
|
|
ExReleaseFastMutex(&MbpMutex);
|
|
return dataLength;
|
|
}
|
|
|
|
ULONG
|
|
MbSetDeviceData (
|
|
IN struct _BUS_HANDLER *BusHandler,
|
|
IN struct _BUS_HANDLER *RootHandler,
|
|
IN PDEVICE_HANDLER_OBJECT DeviceHandler,
|
|
IN ULONG DataType,
|
|
IN PUCHAR Buffer,
|
|
IN ULONG Offset,
|
|
IN ULONG Length
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The function sets Pnp Bios data for a device.
|
|
|
|
Arguments:
|
|
|
|
BusHandler - supplies a pointer to the handler of the bus.
|
|
|
|
RootHandler - supplies a pointer to a BUS_HANDLER for the originating
|
|
request.
|
|
|
|
DeviceHandler - supplies a pointer to a DEVICE_HANDLER_OBJECT
|
|
|
|
DataType - Specifies the type of device data desired.
|
|
|
|
Buffer - Supplies the space to store the data.
|
|
|
|
Offset - Supplies the offset to the device data to start reading.
|
|
|
|
Length - Supplies a count in bytes of the maximum amount to return.
|
|
|
|
Return Value:
|
|
|
|
Returns the amount of data set.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// We don't let drivers change Pnp device data.
|
|
//
|
|
|
|
return 0;
|
|
}
|
|
|
|
NTSTATUS
|
|
MbQueryBusSlots (
|
|
IN PBUS_HANDLER BusHandler,
|
|
IN PBUS_HANDLER RootHandler,
|
|
IN ULONG BufferSize,
|
|
OUT PULONG SlotNumbers,
|
|
OUT PULONG ReturnedLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The function returns a list of currently available SlotNumber.
|
|
|
|
Arguments:
|
|
|
|
BusHandler - supplies a pointer to the handler of the bus.
|
|
|
|
RootHandler - supplies a pointer to a BUS_HANDLER for the originating
|
|
request.
|
|
|
|
Buffer - Supplies the space to store the data.
|
|
|
|
SlotNumber - Supplies a variable to receives the number of available slots.
|
|
|
|
Length - Supplies a count in bytes of the stored data. If this function
|
|
returns STATUS_BUFFER_TOO_SMALL, this variable supplies the required
|
|
size.
|
|
|
|
Return Value:
|
|
|
|
STATUS_BUFFER_TOO_SMALL if caller supplied buffer is not big enough.
|
|
|
|
--*/
|
|
|
|
{
|
|
PMB_BUS_EXTENSION busExtension;
|
|
PSINGLE_LIST_ENTRY link;
|
|
PDEVICE_DATA deviceData;
|
|
ULONG count = 0;
|
|
|
|
PAGED_CODE ();
|
|
|
|
busExtension = (PMB_BUS_EXTENSION)BusHandler->BusData;
|
|
|
|
//
|
|
// Synchronize with other pnp bios device handle assignment.
|
|
//
|
|
|
|
ExAcquireFastMutex(&MbpMutex);
|
|
|
|
//
|
|
// Fill in returned buffer length, or what size buffer is needed
|
|
//
|
|
|
|
|
|
*ReturnedLength = busExtension->NoValidSlots * sizeof (ULONG);
|
|
if (BufferSize < *ReturnedLength) {
|
|
|
|
//
|
|
// Callers buffer is not large enough
|
|
//
|
|
|
|
ExReleaseFastMutex (&MbpMutex);
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
//
|
|
// Return caller all the possible slot number
|
|
//
|
|
|
|
for (link = busExtension->ValidSlots.Next; link; link = link->Next) {
|
|
deviceData = CONTAINING_RECORD (link, DEVICE_DATA, Next);
|
|
if (deviceData->Flags & DEVICE_FLAGS_VALID) {
|
|
*SlotNumbers = DeviceDataSlot(deviceData);
|
|
SlotNumbers++;
|
|
count += 1;
|
|
}
|
|
}
|
|
|
|
*ReturnedLength = count * sizeof (ULONG);
|
|
ExReleaseFastMutex (&MbpMutex);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
MbDeviceControl (
|
|
IN PHAL_DEVICE_CONTROL_CONTEXT Context
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The function is the bus handler specific verion of HalDeviceControl.
|
|
|
|
Arguments:
|
|
|
|
Context - The DeviceControl context. The context has all the information
|
|
for the HalDeviceControl operation being performed.
|
|
|
|
Return Value:
|
|
|
|
A NTSTATUS code to indicate the result of the operation.
|
|
|
|
--*/
|
|
{
|
|
ULONG i, junk;
|
|
ULONG controlCode;
|
|
PULONG bufferLength;
|
|
NTSTATUS status = STATUS_INVALID_PARAMETER;
|
|
|
|
for (i = 0; i < NUMBER_DEVICE_CONTROL_FUNCTIONS; i++) {
|
|
|
|
if (MbpDeviceControl[i].ControlCode == Context->DeviceControl.ControlCode) {
|
|
if (MbpDeviceControl[i].ControlHandler == NULL) {
|
|
Context->DeviceControl.Status = STATUS_NOT_IMPLEMENTED;
|
|
status = STATUS_NOT_IMPLEMENTED;
|
|
goto deviceControlDone;
|
|
}
|
|
|
|
//
|
|
// Found DeviceControl handler
|
|
//
|
|
|
|
Context->ContextControlHandler = (ULONG)(MbpDeviceControl + i);
|
|
|
|
//
|
|
// Verify callers buffer is the min required length
|
|
//
|
|
|
|
if (*Context->DeviceControl.BufferLength < MbpDeviceControl[i].MinBuffer) {
|
|
Context->DeviceControl.Status = STATUS_BUFFER_TOO_SMALL;
|
|
*Context->DeviceControl.BufferLength = MbpDeviceControl[i].MinBuffer;
|
|
status = STATUS_BUFFER_TOO_SMALL;
|
|
goto deviceControlDone;
|
|
}
|
|
|
|
if (KeGetCurrentIrql() < DISPATCH_LEVEL) {
|
|
|
|
//
|
|
// All supported slot control functions touch paged code or data.
|
|
// If the current irql is low enough go dispatch now; otherwise,
|
|
// queue the request to a worker thread.
|
|
//
|
|
|
|
MbpDispatchControl (Context);
|
|
|
|
} else {
|
|
|
|
//
|
|
// Enqueue to worker thread
|
|
//
|
|
|
|
ExInterlockedInsertTailList (
|
|
&MbpControlWorkerList,
|
|
(PLIST_ENTRY) &Context->ContextWorkQueue,
|
|
&MbpSpinlock
|
|
);
|
|
|
|
//
|
|
// Make sure worker is requested
|
|
//
|
|
|
|
MbpStartWorker ();
|
|
}
|
|
return STATUS_PENDING;
|
|
}
|
|
}
|
|
|
|
deviceControlDone:
|
|
HalCompleteDeviceControl (Context);
|
|
return status;
|
|
}
|
|
|
|
VOID
|
|
MbpCheckBus (
|
|
IN PBUS_HANDLER BusHandler
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The function reenumerates the bus specified by BusHandler.
|
|
|
|
Arguments:
|
|
|
|
BusHandler - supplies a pointer to the BusHandler of the bus to be enumerated.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
ULONG slotNumber, nextSlotNumber;
|
|
BOOLEAN dockConnector;
|
|
PDEVICE_DATA deviceData;
|
|
PPNP_BIOS_DEVICE_NODE busData;
|
|
PMB_BUS_EXTENSION busExtension;
|
|
ULONG length, noSlots;
|
|
NTSTATUS status;
|
|
PHAL_SYSTEM_DOCK_INFORMATION dockInfo;
|
|
PDEVICE_HANDLER_OBJECT deviceHandler;
|
|
ULONG objectSize;
|
|
OBJECT_ATTRIBUTES objectAttributes;
|
|
HANDLE handle;
|
|
BOOLEAN notifyBusCheck;
|
|
|
|
PAGED_CODE();
|
|
|
|
busExtension = (PMB_BUS_EXTENSION)BusHandler->BusData;
|
|
notifyBusCheck = FALSE;
|
|
|
|
//
|
|
// We may be removing references to this bus handler, so add
|
|
// a reference now
|
|
//
|
|
|
|
HalReferenceBusHandler (BusHandler);
|
|
|
|
//
|
|
// Acquire fast mutex to access device data
|
|
//
|
|
|
|
ExAcquireFastMutex (&MbpMutex);
|
|
MbpInvalidateSlots(busExtension);
|
|
|
|
//
|
|
// Check the bus for new devices
|
|
//
|
|
|
|
nextSlotNumber = 0;
|
|
while (nextSlotNumber != (ULONG) -1) {
|
|
slotNumber = nextSlotNumber;
|
|
status = MbpGetBusData(BusHandler->BusNumber,
|
|
&nextSlotNumber,
|
|
&busData,
|
|
&length,
|
|
&dockConnector);
|
|
if (NT_SUCCESS(status)) {
|
|
deviceData = MbpFindDeviceData (busExtension, slotNumber);
|
|
if (deviceData == NULL ||
|
|
length != deviceData->BusDataLength ||
|
|
RtlCompareMemory(busData, deviceData->BusData, length) != length) {
|
|
|
|
notifyBusCheck = TRUE;
|
|
|
|
//
|
|
// if Not found - this is a newly added device or
|
|
// if devicedata exists already, make sure its busdata is not changed.
|
|
// Otherwise, we assign a new handler to this slot. This invalidate
|
|
// the access to the old bus data.
|
|
//
|
|
|
|
//
|
|
// Initialize the object attributes that will be used to create the
|
|
// Device Handler Object.
|
|
//
|
|
|
|
InitializeObjectAttributes(
|
|
&objectAttributes,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
objectSize = MbpDeviceHandlerObjectSize + sizeof (DEVICE_DATA);
|
|
|
|
//
|
|
// Create the object
|
|
//
|
|
|
|
status = ObCreateObject(
|
|
KernelMode,
|
|
*IoDeviceHandlerObjectType,
|
|
&objectAttributes,
|
|
KernelMode,
|
|
NULL,
|
|
objectSize,
|
|
0,
|
|
0,
|
|
(PVOID *) &deviceHandler
|
|
);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
RtlZeroMemory (deviceHandler, objectSize);
|
|
|
|
deviceHandler->Type = (USHORT) *IoDeviceHandlerObjectType;
|
|
deviceHandler->Size = (USHORT) objectSize;
|
|
if (dockConnector) {
|
|
deviceHandler->SlotNumber = DOCK_VIRTUAL_SLOT_NUMBER;
|
|
} else {
|
|
deviceHandler->SlotNumber = slotNumber;
|
|
}
|
|
|
|
//
|
|
// Get a reference to the object
|
|
//
|
|
|
|
status = ObReferenceObjectByPointer(
|
|
deviceHandler,
|
|
FILE_READ_DATA | FILE_WRITE_DATA,
|
|
*IoDeviceHandlerObjectType,
|
|
KernelMode
|
|
);
|
|
}
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
//
|
|
// Insert it into the object table
|
|
//
|
|
|
|
status = ObInsertObject(
|
|
deviceHandler,
|
|
NULL,
|
|
FILE_READ_DATA | FILE_WRITE_DATA,
|
|
0,
|
|
NULL,
|
|
&handle
|
|
);
|
|
}
|
|
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
//
|
|
// Object not created correctly. Skip this slot.
|
|
//
|
|
|
|
continue;
|
|
}
|
|
|
|
ZwClose (handle);
|
|
|
|
//
|
|
// Intialize device tracking structure
|
|
//
|
|
|
|
deviceHandler->BusHandler = BusHandler;
|
|
HalReferenceBusHandler(BusHandler);
|
|
|
|
deviceData = DeviceHandler2DeviceData(deviceHandler);
|
|
deviceData->BusData = busData;
|
|
deviceData->BusDataLength = length;
|
|
deviceData->Flags |= DEVICE_FLAGS_VALID;
|
|
|
|
DebugPrint ((DEBUG_MESSAGE, "PnpBios: adding slot %x\n", DeviceDataSlot(deviceData)));
|
|
|
|
//
|
|
// Add it to the list of devices for this bus
|
|
//
|
|
|
|
busExtension->NoValidSlots += 1;
|
|
ExInterlockedPushEntryList (
|
|
&busExtension->ValidSlots,
|
|
&deviceData->Next,
|
|
&MbpSpinlock
|
|
);
|
|
} else {
|
|
ExFreePool(busData);
|
|
deviceData->Flags |= DEVICE_FLAGS_VALID;
|
|
}
|
|
|
|
//
|
|
// If this is the docking station slot, remember it.
|
|
//
|
|
|
|
if (dockConnector) {
|
|
busExtension->DockingStationDevice = deviceData;
|
|
deviceData->Flags |= DEVICE_FLAGS_DOCKING_STATION;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Go through the slot data link list to delete all the removed slots.
|
|
//
|
|
|
|
noSlots = busExtension->NoValidSlots;
|
|
MbpDeleteSlots(busExtension);
|
|
if (noSlots != busExtension->NoValidSlots) {
|
|
notifyBusCheck = TRUE;
|
|
}
|
|
ExReleaseFastMutex (&MbpMutex);
|
|
|
|
//
|
|
// If this is top level pnp bios bus we will determine docking station information
|
|
// and all Hal to set dock information.
|
|
//
|
|
|
|
if (BusHandler->BusNumber == MbpBusNumber[0] &&
|
|
NT_SUCCESS(MbpGetDockInformation(&dockInfo, &length)) ) {
|
|
HalSetSystemInformation(HalSystemDockInformation, length, dockInfo);
|
|
ExFreePool(dockInfo);
|
|
}
|
|
|
|
//
|
|
// Undo reference to bus handler from top of function
|
|
//
|
|
|
|
HalDereferenceBusHandler (BusHandler);
|
|
|
|
//
|
|
// Do we need to notify the system buscheck callback?
|
|
//
|
|
|
|
if (notifyBusCheck) {
|
|
HAL_BUS_INFORMATION busInfo;
|
|
|
|
busInfo.BusType = BusHandler->InterfaceType;
|
|
busInfo.ConfigurationType = BusHandler->ConfigurationType;
|
|
busInfo.BusNumber = BusHandler->BusNumber;
|
|
busInfo.Reserved = 0;
|
|
ExNotifyCallback (
|
|
MbpHalCallbacks.BusCheck,
|
|
&busInfo,
|
|
(PVOID)BusHandler->BusNumber
|
|
);
|
|
}
|
|
}
|
|
|
|
PDEVICE_HANDLER_OBJECT
|
|
MbpReferenceDeviceHandler (
|
|
IN struct _BUS_HANDLER *BusHandler,
|
|
IN struct _BUS_HANDLER *RootHandler,
|
|
IN ULONG SlotNumber
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The function returns a reference to the devce handler specified by SlotNumber
|
|
and BusHandler.
|
|
|
|
Arguments:
|
|
|
|
BusHandler -
|
|
|
|
RootHanler -
|
|
|
|
SlotNumber -
|
|
|
|
Return Value:
|
|
|
|
a reference to DEVICE_HANDLER_OBJECT.
|
|
|
|
--*/
|
|
{
|
|
PDEVICE_DATA deviceData;
|
|
PDEVICE_HANDLER_OBJECT deviceHandler;
|
|
PMB_BUS_EXTENSION busExtension;
|
|
NTSTATUS status;
|
|
|
|
PAGED_CODE ();
|
|
|
|
ExAcquireFastMutex (&MbpMutex);
|
|
|
|
busExtension = (PMB_BUS_EXTENSION)BusHandler->BusData;
|
|
deviceData = MbpFindDeviceData (busExtension, SlotNumber);
|
|
deviceHandler = NULL;
|
|
if (deviceData) {
|
|
deviceHandler = DeviceData2DeviceHandler (deviceData);
|
|
status = ObReferenceObjectByPointer(
|
|
deviceHandler,
|
|
FILE_READ_DATA | FILE_WRITE_DATA,
|
|
*IoDeviceHandlerObjectType,
|
|
KernelMode
|
|
);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
deviceHandler = NULL;
|
|
}
|
|
}
|
|
|
|
ExReleaseFastMutex (&MbpMutex);
|
|
return deviceHandler;
|
|
}
|
|
|
|
PDEVICE_DATA
|
|
MbpFindDeviceData (
|
|
IN PMB_BUS_EXTENSION BusExtension,
|
|
IN ULONG SlotNumber
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The function goes through device data list to find the desired SlotNumber's
|
|
device data. The caller must hold the MbpMutex to call this routine.
|
|
|
|
Arguments:
|
|
|
|
BusExtension - supplies a pointer to current bus'es extension.
|
|
|
|
SlotNumber - specified the desired device data. -1 means docking station device data.
|
|
|
|
Return Value:
|
|
|
|
A pointer to the DEVICE_DATA if found. Otherwise a value of NULL is returned.
|
|
|
|
--*/
|
|
{
|
|
PDEVICE_DATA deviceData;
|
|
PSINGLE_LIST_ENTRY link;
|
|
PDEVICE_HANDLER_OBJECT deviceHandler;
|
|
|
|
//
|
|
// Go through the slot data link list to find a match.
|
|
//
|
|
|
|
if (SlotNumber == DOCK_VIRTUAL_SLOT_NUMBER) {
|
|
return BusExtension->DockingStationDevice;
|
|
} else {
|
|
for (link = BusExtension->ValidSlots.Next; link; link = link->Next) {
|
|
deviceData = CONTAINING_RECORD (link, DEVICE_DATA, Next);
|
|
if (DeviceDataSlot(deviceData) == SlotNumber) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!link) {
|
|
return NULL;
|
|
} else {
|
|
return deviceData;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
MbpInvalidateSlots (
|
|
IN PMB_BUS_EXTENSION BusExtension
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The function goes through device data list and marks all the devices as invalid.
|
|
The caller must acquire MbpMutex to call this routine.
|
|
|
|
Arguments:
|
|
|
|
BusExtension - supplies a pointer to the extension data of desired bus.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PDEVICE_DATA deviceData;
|
|
PSINGLE_LIST_ENTRY link;
|
|
|
|
//
|
|
// Go through the slot data link list to mark ALL the slots as
|
|
// in transition state.
|
|
//
|
|
|
|
for (link = BusExtension->ValidSlots.Next; link; link = link->Next) {
|
|
deviceData = CONTAINING_RECORD (link, DEVICE_DATA, Next);
|
|
deviceData->Flags &= ~DEVICE_FLAGS_VALID;
|
|
}
|
|
|
|
//
|
|
// Invalidate the docking station slot pointer
|
|
//
|
|
|
|
BusExtension->DockingStationDevice = NULL;
|
|
BusExtension->DockingStationId = UNKNOWN_DOCKING_IDENTIFIER;
|
|
BusExtension->DockingStationSerialNumber = 0;
|
|
}
|
|
|
|
VOID
|
|
MbpDeleteSlots (
|
|
IN PMB_BUS_EXTENSION BusExtension
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The function goes through device data list and deletes all the invalid
|
|
slots/devices.
|
|
Note the MbpMutex must be acquired before calling this routine.
|
|
|
|
Arguments:
|
|
|
|
BusExtension - supplies a pointer to the extension data of desired bus.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PDEVICE_DATA deviceData;
|
|
PDEVICE_HANDLER_OBJECT deviceHandler;
|
|
PSINGLE_LIST_ENTRY *link;
|
|
|
|
//
|
|
// Go through the slot data link list to free all the slot
|
|
// marked as invalid.
|
|
//
|
|
|
|
link = &BusExtension->ValidSlots.Next;
|
|
while (*link) {
|
|
deviceData = CONTAINING_RECORD (*link, DEVICE_DATA, Next);
|
|
if (!(deviceData->Flags & DEVICE_FLAGS_VALID)) {
|
|
DebugPrint((DEBUG_MESSAGE, "Remove slot %x\n", DeviceDataSlot(deviceData)));
|
|
|
|
//
|
|
// In theory I should deallocate the BusData only when the ref count of the
|
|
// deviceData down to zero and deallocated. Here I am safe to do so because
|
|
// the DeviceDispatchContol routine checks the DeviceData flag is valid before
|
|
// reference the BusData.
|
|
//
|
|
|
|
if (deviceData->BusData) {
|
|
ExFreePool(deviceData->BusData);
|
|
}
|
|
*link = (*link)->Next;
|
|
deviceHandler = DeviceData2DeviceHandler(deviceData);
|
|
ObDereferenceObject (deviceHandler);
|
|
HalDereferenceBusHandler (BusExtension->BusHandler);
|
|
BusExtension->NoValidSlots--;
|
|
} else {
|
|
link = &((*link)->Next);
|
|
}
|
|
}
|
|
}
|
|
|
|
|