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.
902 lines
23 KiB
902 lines
23 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
busdata.c
|
|
|
|
Abstract:
|
|
|
|
This module contains code to query/set pnp bios slot data.
|
|
|
|
Author:
|
|
|
|
Shie-Lin Tzong (shielint) Apr-25-1995
|
|
|
|
Environment:
|
|
|
|
Kernel mode only.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "busp.h"
|
|
|
|
PUCHAR
|
|
MbpFindNextPnpEndTag (
|
|
IN PUCHAR BusData,
|
|
IN LONG Limit
|
|
);
|
|
|
|
#pragma alloc_text(PAGE,MbpGetBusData)
|
|
#pragma alloc_text(PAGE,MbpGetCompatibleDeviceId)
|
|
#pragma alloc_text(PAGE,MbpGetSlotResources)
|
|
#pragma alloc_text(PAGE,MbpGetSlotResourceRequirements)
|
|
#pragma alloc_text(PAGE,MbpSetSlotResources)
|
|
#pragma alloc_text(PAGE,MbpFindNextPnpEndTag)
|
|
|
|
NTSTATUS
|
|
MbpGetBusData (
|
|
ULONG BusNumber,
|
|
PULONG SlotNumber,
|
|
PVOID *BusData,
|
|
PULONG Length,
|
|
PBOOLEAN DockingSlot
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function returns the pnp bios bus data to the caller.
|
|
Caller is responsible to release the data buffer. No mater what the returned
|
|
status is, this routine always returns a valid next slot number.
|
|
|
|
Arguments:
|
|
|
|
BusNumber - specifies the desired bus.
|
|
|
|
SlotNumber - specifies a variable to indicate the slot whoes data is desired and
|
|
to receive the next slot number (-1 if no more slot.)
|
|
|
|
BusData - supplies a variable to receive the data buffer pointer.
|
|
|
|
Length - supplies a variable to receive the length of the data buffer
|
|
|
|
DockingSlot - supplies a variable to receive if the slot is a docking station slot.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS code
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
PPNP_BIOS_DEVICE_NODE busData;
|
|
PUCHAR p, source;
|
|
ULONG size, bufferSize, nextSlot = 0;
|
|
USHORT junk;
|
|
PB_PARAMETERS biosParameters;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// If registry data is availble, we will get it from registry data.
|
|
// Note, the registry data is available at init time only.
|
|
//
|
|
|
|
source = NULL;
|
|
*DockingSlot = FALSE;
|
|
if (PbBiosRegistryData) {
|
|
|
|
//
|
|
// First skip Pnp Bios installation check data
|
|
//
|
|
|
|
p = (PUCHAR)(PbBiosRegistryData + 1);
|
|
size = ((PKEY_VALUE_FULL_INFORMATION)PbBiosKeyInformation)->DataLength;
|
|
size -= sizeof(PNP_BIOS_INSTALLATION_CHECK) + sizeof(CM_PARTIAL_RESOURCE_LIST);
|
|
while (size >= sizeof(PNP_BIOS_DEVICE_NODE)) {
|
|
if (*SlotNumber == ((PPNP_BIOS_DEVICE_NODE)p)->Node) {
|
|
|
|
//
|
|
// Find the desired slot data, determine next slot and
|
|
// do some more checks.
|
|
//
|
|
|
|
bufferSize = ((PPNP_BIOS_DEVICE_NODE)p)->Size;
|
|
size -= bufferSize;
|
|
if (size >= sizeof(PNP_BIOS_DEVICE_NODE)) {
|
|
nextSlot = ((PPNP_BIOS_DEVICE_NODE)(p + bufferSize))->Node;
|
|
} else {
|
|
nextSlot = (ULONG) -1;
|
|
}
|
|
|
|
if (((PPNP_BIOS_DEVICE_NODE)p)->DeviceType[0] == BASE_TYPE_DOCKING_STATION) {
|
|
if (BusNumber == MbpBusNumber[0]) {
|
|
|
|
//
|
|
// If this is a docking station slot and the target BusNumber is the first bus,
|
|
// return the data and indicate this is a docking station slot.
|
|
//
|
|
|
|
*DockingSlot = TRUE;
|
|
source = p;
|
|
}
|
|
break;
|
|
}
|
|
|
|
//
|
|
// If this is a device in the deocking station, it can only belong to BusNumber 1
|
|
// If this is a device in the system board, it can only belong to BusNumber 0
|
|
//
|
|
|
|
if (((PPNP_BIOS_DEVICE_NODE)p)->DeviceAttributes & DEVICE_DOCKING) {
|
|
if (BusNumber == MbpBusNumber[1]) {
|
|
source = p;
|
|
}
|
|
} else if (BusNumber == MbpBusNumber[0]) {
|
|
source = p;
|
|
}
|
|
break;
|
|
}
|
|
size -= ((PPNP_BIOS_DEVICE_NODE)p)->Size;
|
|
p = p + ((PPNP_BIOS_DEVICE_NODE)p)->Size;
|
|
}
|
|
|
|
if (!source) {
|
|
if (*SlotNumber == 0) {
|
|
p = (PUCHAR)(PbBiosRegistryData + 1);
|
|
*SlotNumber = ((PPNP_BIOS_DEVICE_NODE)p)->Node;
|
|
} else {
|
|
*SlotNumber = nextSlot;
|
|
}
|
|
return STATUS_NO_SUCH_DEVICE;
|
|
}
|
|
} else {
|
|
|
|
//
|
|
// Registry data is not available. Call pnp bios or hardware to
|
|
// get the max buffer size if necessary.
|
|
//
|
|
|
|
if (MbpMaxDeviceData == 0) {
|
|
biosParameters.Function = PNP_BIOS_GET_NUMBER_DEVICE_NODES;
|
|
biosParameters.u.GetNumberDeviceNodes.NumberNodes = &junk;
|
|
biosParameters.u.GetNumberDeviceNodes.NodeSize = (PUSHORT)&MbpMaxDeviceData;
|
|
status = PbHardwareService(&biosParameters);
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((DEBUG_BREAK, "GetBusData: calling BIOS GET_NUMBER_NODES failed.\n"));
|
|
*SlotNumber = 0;
|
|
return STATUS_NO_SUCH_DEVICE;
|
|
} else {
|
|
bufferSize = MbpMaxDeviceData;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Allocate space to return the slot data
|
|
//
|
|
|
|
busData = (PPNP_BIOS_DEVICE_NODE) ExAllocatePoolWithTag (
|
|
PagedPool, bufferSize, 'bPnP');
|
|
|
|
if (busData == NULL) {
|
|
|
|
//
|
|
// Leave Slot unchanged, so it wil be the next slot number to try. This gives
|
|
// us another chance to retry the operation.
|
|
//
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// If the data is available already copy it to data buffer and return.
|
|
//
|
|
|
|
if (source) {
|
|
RtlMoveMemory(busData, source, bufferSize);
|
|
*SlotNumber = nextSlot;
|
|
*BusData = busData;
|
|
*Length = busData->Size;
|
|
} else {
|
|
|
|
//
|
|
// Else we need to resort to Pnp Bios runtime API or hardware ...
|
|
//
|
|
|
|
nextSlot = *SlotNumber;
|
|
biosParameters.Function = PNP_BIOS_GET_DEVICE_NODE;
|
|
biosParameters.u.GetDeviceNode.NodeBuffer = busData;
|
|
biosParameters.u.GetDeviceNode.Node = (PUSHORT)&nextSlot;
|
|
biosParameters.u.GetDeviceNode.Control = GET_CURRENT_CONFIGURATION;
|
|
status = PbHardwareService(&biosParameters);
|
|
if (!NT_SUCCESS(status)) {
|
|
*SlotNumber = 0;
|
|
ExFreePool(busData);
|
|
return STATUS_NO_SUCH_DEVICE;
|
|
}
|
|
|
|
if (nextSlot == 0xFF) {
|
|
nextSlot = (ULONG) -1;
|
|
}
|
|
|
|
//
|
|
// Make sure the slot matches the bus number.
|
|
//
|
|
|
|
if (*SlotNumber != (ULONG)busData->Node) {
|
|
|
|
//
|
|
// This happens when *SlotNumber == 0. In this case, bios
|
|
// gives us the first valid slot data.
|
|
//
|
|
|
|
*SlotNumber = (ULONG)busData->Node;
|
|
return STATUS_NO_SUCH_DEVICE;
|
|
} else {
|
|
*SlotNumber = nextSlot;
|
|
}
|
|
if ((busData->DeviceType[0] == BASE_TYPE_DOCKING_STATION && BusNumber != MbpBusNumber[0]) ||
|
|
(busData->DeviceAttributes & DEVICE_DOCKING && BusNumber == MbpBusNumber[0]) ||
|
|
(!(busData->DeviceAttributes & DEVICE_DOCKING) && BusNumber == MbpBusNumber[1]) ) {
|
|
ExFreePool(busData);
|
|
return STATUS_NO_SUCH_DEVICE;
|
|
} else {
|
|
*BusData = busData;
|
|
*Length = busData->Size;
|
|
}
|
|
}
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
MbpGetCompatibleDeviceId (
|
|
PVOID BusData,
|
|
ULONG IdIndex,
|
|
PWCHAR Buffer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function returns the desired pnp bios id for the specified Busdata
|
|
and Id index. If Id index = 0, the Hardware ID will be return; if id
|
|
index = n, the Nth compatible id will be returned.
|
|
|
|
Arguments:
|
|
|
|
BusData - supplies a pointer to the pnp bios slot/device data.
|
|
|
|
IdIndex - supplies the index of the compatible id desired.
|
|
|
|
Buffer - supplies a pointer to a buffer to the compatible Id. Caller must
|
|
make sure the buffer is big enough.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS code
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
PPNP_BIOS_DEVICE_NODE slotData;
|
|
PUCHAR p, end;
|
|
UCHAR tag;
|
|
ULONG count = 0;
|
|
LONG size;
|
|
UNICODE_STRING unicodeString;
|
|
ANSI_STRING ansiString;
|
|
UCHAR eisaId[8];
|
|
ULONG id;
|
|
|
|
PAGED_CODE();
|
|
|
|
slotData = (PPNP_BIOS_DEVICE_NODE)BusData;
|
|
if (IdIndex == 0) {
|
|
|
|
//
|
|
// Caller is asking for hardware id
|
|
//
|
|
|
|
id = slotData->ProductId;
|
|
} else {
|
|
|
|
//
|
|
// caller is asking for compatible id
|
|
//
|
|
|
|
IdIndex--;
|
|
p = (PUCHAR)(slotData + 1);
|
|
size = slotData->Size - sizeof(PNP_BIOS_DEVICE_NODE);
|
|
end = p + size;
|
|
|
|
//
|
|
// Skip all the resource descriptors to find compatible Id descriptor
|
|
//
|
|
|
|
p = MbpFindNextPnpEndTag(p, size); // skip allocated resources
|
|
if (!p) {
|
|
return STATUS_NO_MORE_ENTRIES;
|
|
}
|
|
p += 2;
|
|
p = MbpFindNextPnpEndTag(p, (LONG)(end - p)); // skip possible resources
|
|
if (!p) {
|
|
return STATUS_NO_MORE_ENTRIES;
|
|
}
|
|
p += 2;
|
|
status = STATUS_NO_MORE_ENTRIES;
|
|
while ((tag = *p) != TAG_COMPLETE_END) {
|
|
ASSERT (tag == TAG_COMPLETE_COMPATIBLE_ID);
|
|
if (count == IdIndex) {
|
|
id = *(PULONG)(p + 1);
|
|
status = STATUS_SUCCESS;
|
|
break;
|
|
} else {
|
|
count++;
|
|
}
|
|
|
|
//
|
|
// Advance to next compatible id.
|
|
//
|
|
|
|
p += (TAG_COMPLETE_COMPATIBLE_ID & SMALL_TAG_SIZE_MASK) + 1;
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
PbDecompressEisaId(id, eisaId);
|
|
RtlInitAnsiString(&ansiString, eisaId);
|
|
RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
|
|
swprintf(Buffer, L"BIOS\\*%s", unicodeString.Buffer);
|
|
RtlFreeUnicodeString(&unicodeString);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
MbpGetSlotResources (
|
|
IN ULONG BusNumber,
|
|
IN PVOID BusData,
|
|
IN OUT PCM_RESOURCE_LIST *CmResources,
|
|
OUT PULONG Length
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function returns the desired pnp bios slot/device resource in CM
|
|
format. Caller is responsible to free the resource buffer.
|
|
|
|
Arguments:
|
|
|
|
BusData - supplies a pointer to the pnp bios slot/device data.
|
|
|
|
CmResources - supplies a variable to receive the returned resource list.
|
|
|
|
Length - supplies a variable to receive the length of the data buffer
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS code
|
|
|
|
--*/
|
|
{
|
|
PPNP_BIOS_DEVICE_NODE slotData;
|
|
PUCHAR p;
|
|
NTSTATUS status;
|
|
|
|
PAGED_CODE();
|
|
|
|
slotData = (PPNP_BIOS_DEVICE_NODE)BusData;
|
|
p = (PUCHAR)(slotData + 1);
|
|
status = PbBiosResourcesToNtResources (
|
|
BusNumber,
|
|
slotData->Node,
|
|
&p,
|
|
PB_CM_FORMAT,
|
|
(PUCHAR *) CmResources,
|
|
Length
|
|
);
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
MbpGetSlotResourceRequirements (
|
|
ULONG BusNumber,
|
|
PVOID BusData,
|
|
PIO_RESOURCE_REQUIREMENTS_LIST *IoResources,
|
|
PULONG Length
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function returns the desired pnp bios slot/device resource in IO
|
|
format. Caller is responsible to free the resource buffer.
|
|
|
|
Arguments:
|
|
|
|
BusData - supplies a pointer to the pnp bios slot/device data.
|
|
|
|
IoResources - supplies a variable to receive the returned resource requirements list.
|
|
|
|
Length - supplies a variable to receive the length of the data buffer
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS code
|
|
|
|
--*/
|
|
{
|
|
PPNP_BIOS_DEVICE_NODE slotData;
|
|
PUCHAR p;
|
|
LONG size;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
PAGED_CODE();
|
|
|
|
*IoResources = NULL;
|
|
*Length = 0;
|
|
|
|
slotData = (PPNP_BIOS_DEVICE_NODE)BusData;
|
|
p = (PUCHAR)(slotData + 1);
|
|
size = slotData->Size - sizeof(PNP_BIOS_DEVICE_NODE);
|
|
|
|
//
|
|
// Skip allocated resource descriptors
|
|
//
|
|
|
|
p = MbpFindNextPnpEndTag(p, size); // skip allocated resources
|
|
if (p) {
|
|
p += 2;
|
|
status = PbBiosResourcesToNtResources (
|
|
BusNumber,
|
|
slotData->Node,
|
|
&p,
|
|
PB_IO_FORMAT,
|
|
(PUCHAR *)IoResources,
|
|
Length
|
|
);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
MbpSetSlotResources (
|
|
PVOID *BusData,
|
|
PCM_RESOURCE_LIST CmResources,
|
|
ULONG Length
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function sets the caller specified resource to pnp bios slot/device
|
|
data.
|
|
|
|
Arguments:
|
|
|
|
BusData - supplies a pointer to the pnp bios slot/device data.
|
|
|
|
CmResources - supplies a variable to receive the returned resource list.
|
|
|
|
Length - supplies the length of the resource data
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS code
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
PPNP_BIOS_DEVICE_NODE slotData;
|
|
PUCHAR p, pEnd, src, requirements;
|
|
PUCHAR biosResources;
|
|
ULONG biosResourceSize, totalSize;
|
|
LONG size;
|
|
PB_PARAMETERS biosParameters;
|
|
|
|
PAGED_CODE();
|
|
|
|
slotData = (PPNP_BIOS_DEVICE_NODE)(*BusData);
|
|
p = (PUCHAR)(slotData + 1);
|
|
size = slotData->Size - sizeof(PNP_BIOS_DEVICE_NODE);
|
|
pEnd = p + size;
|
|
|
|
//
|
|
// Skip allocated resource descriptors to find requirements list
|
|
//
|
|
|
|
p = MbpFindNextPnpEndTag(p, size); // skip allocated resources
|
|
if (!p) {
|
|
DebugPrint((DEBUG_BREAK, "SetResource:Could not find allocated resource END tag\n"));
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
p += 2;
|
|
requirements = p;
|
|
size = (ULONG)pEnd - (ULONG)p;
|
|
|
|
status = PbCmResourcesToBiosResources (
|
|
CmResources,
|
|
requirements,
|
|
&biosResources,
|
|
&biosResourceSize
|
|
);
|
|
if (NT_SUCCESS(status)) {
|
|
p = ExAllocatePoolWithTag(
|
|
PagedPool,
|
|
size + sizeof(PNP_BIOS_DEVICE_NODE) + biosResourceSize,
|
|
'bPnP');
|
|
if (!p) {
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
} else {
|
|
RtlMoveMemory(p, slotData, sizeof(PNP_BIOS_DEVICE_NODE));
|
|
slotData = (PPNP_BIOS_DEVICE_NODE)p;
|
|
p += sizeof(PNP_BIOS_DEVICE_NODE);
|
|
RtlMoveMemory(p, biosResources, biosResourceSize);
|
|
p += biosResourceSize;
|
|
RtlMoveMemory(p, requirements, size);
|
|
totalSize = size + sizeof(PNP_BIOS_DEVICE_NODE) + biosResourceSize;
|
|
slotData->Size = (USHORT)totalSize;
|
|
|
|
//
|
|
// call Pnp Bios to set the resources
|
|
//
|
|
|
|
biosParameters.Function = PNP_BIOS_SET_DEVICE_NODE;
|
|
biosParameters.u.SetDeviceNode.Node = slotData->Node;
|
|
biosParameters.u.SetDeviceNode.NodeBuffer = slotData;
|
|
biosParameters.u.SetDeviceNode.Control = SET_CONFIGURATION_NOW;
|
|
status = PbHardwareService (&biosParameters);
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
//
|
|
// Update slotdat pointer
|
|
//
|
|
|
|
ExFreePool(*BusData);
|
|
*BusData = slotData;
|
|
} else {
|
|
ExFreePool(slotData);
|
|
}
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
MbpGetDockInformation (
|
|
OUT PHAL_SYSTEM_DOCK_INFORMATION *DockInfo,
|
|
PULONG Length
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function returns the docking station Id and serial number.
|
|
Caller must free the Buffer.
|
|
|
|
Arguments:
|
|
|
|
DockInfo - supplies a pointer to a variable to receive the dock information.
|
|
|
|
Length - supplies a pointer to a variable to receive the length of the information.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS code
|
|
|
|
--*/
|
|
{
|
|
PB_DOCKING_STATION_INFORMATION biosDockInfo;
|
|
PB_PARAMETERS biosParameters;
|
|
NTSTATUS status;
|
|
PUNICODE_STRING unicodeString;
|
|
ANSI_STRING ansiString;
|
|
UCHAR eisaId[8];
|
|
PHAL_SYSTEM_DOCK_INFORMATION dock;
|
|
ULONG dockIdLength = 0, serialLength = 0;
|
|
USHORT dockState;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// Invoke pnp bios to get docking station information
|
|
//
|
|
|
|
biosParameters.Function = PNP_BIOS_GET_DOCK_INFORMATION;
|
|
biosParameters.u.GetDockInfo.DockingStationInfo = &biosDockInfo;
|
|
biosParameters.u.GetDockInfo.DockState = &dockState;
|
|
status = PbHardwareService(&biosParameters);
|
|
if (!NT_SUCCESS(status)) {
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Allocate memory to return dock information
|
|
//
|
|
|
|
dock = (PHAL_SYSTEM_DOCK_INFORMATION)ExAllocatePool (
|
|
PagedPool,
|
|
sizeof(HAL_SYSTEM_DOCK_INFORMATION));
|
|
if (dock == NULL) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
if (dockState == SYSTEM_NOT_DOCKED) {
|
|
|
|
//
|
|
// System is not docked, simply return the dock state.
|
|
//
|
|
|
|
dock->DockState = SystemUndocked;
|
|
} else {
|
|
|
|
//
|
|
// else system is docked, remember its dock id and serial number.
|
|
//
|
|
|
|
dock->DockState = SystemDocked;
|
|
#if 1
|
|
MbpBusExtension[0]->DockingStationId = biosDockInfo.LocationId;
|
|
MbpBusExtension[0]->DockingStationSerialNumber = biosDockInfo.SerialNumber;
|
|
ExAcquireFastMutex (&MbpMutex);
|
|
if (biosDockInfo.Capabilities && DOCKING_CAPABILITIES_MASK != DOCKING_CAPABILITIES_COLD_DOCKING) {
|
|
MbpBusExtension[0]->DockingStationDevice->Flags |= DEVICE_FLAGS_EJECT_SUPPORTED;
|
|
}
|
|
ExReleaseFastMutex (&MbpMutex);
|
|
#else
|
|
if (biosDockInfo.LocationId != UNKNOWN_DOCKING_IDENTIFIER) {
|
|
|
|
//
|
|
// If docking station location Id is present...
|
|
//
|
|
|
|
unicodeString = &MbpBusExtension[0]->DockingStationId;
|
|
PbDecompressEisaId(biosDockInfo.LocationId, eisaId);
|
|
RtlInitAnsiString(&ansiString, eisaId);
|
|
dockIdLength = sizeof(WCHAR) * (ansiString.Length + 1);
|
|
unicodeString->Buffer = (PWCHAR)ExAllocatePool (
|
|
PagedPool,
|
|
dockIdLength);
|
|
if (unicodeString->Buffer == NULL) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
unicodeString->MaximumLength = (USHORT)dockIdLength;
|
|
RtlAnsiStringToUnicodeString(unicodeString, &ansiString, FALSE);
|
|
}
|
|
// if (biosDockInfo.SerialNumber != 0) {
|
|
|
|
//
|
|
// If docking station serial number is present ...
|
|
//
|
|
|
|
serialLength = sizeof(ULONG) * 2 * sizeof(WCHAR) + sizeof(WCHAR);
|
|
unicodeString = &MbpBusExtension[0]->DockingStationSerialNo;
|
|
unicodeString->Buffer = (PWCHAR)ExAllocatePool (
|
|
PagedPool,
|
|
serialLength);
|
|
if (unicodeString->Buffer == NULL) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
unicodeString->MaximumLength = (USHORT)serialLength;
|
|
unicodeString->Length = sizeof(ULONG) * 2 * sizeof(WCHAR);
|
|
swprintf(unicodeString->Buffer, L"%8x", biosDockInfo.SerialNumber);
|
|
// }
|
|
#endif
|
|
}
|
|
dock->DeviceBusType = Internal;
|
|
dock->DeviceBusNumber = MbpBusNumber[0];
|
|
dock->SlotNumber = DOCK_VIRTUAL_SLOT_NUMBER;
|
|
*Length = sizeof(HAL_SYSTEM_DOCK_INFORMATION);
|
|
*DockInfo = dock;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
MbpReplyEjectEvent (
|
|
ULONG SlotNumber,
|
|
BOOLEAN Eject
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function sends message to pnp bios for event processing.
|
|
|
|
Arguments:
|
|
|
|
SlotNumber - specifies the slot whoes data is desired.
|
|
|
|
Eject - indicates if EJECT operation should be performed.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS code
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
PB_PARAMETERS biosParameters;
|
|
USHORT message;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// Else we need to resort to Pnp Bios runtime API or hardware ...
|
|
//
|
|
|
|
biosParameters.Function = PNP_BIOS_SEND_MESSAGE;
|
|
if (Eject) {
|
|
biosParameters.u.SendMessage.Message = OK_TO_CHANGE_CONFIG;
|
|
} else {
|
|
biosParameters.u.SendMessage.Message = ABORT_CONFIG_CHANGE;
|
|
}
|
|
|
|
status = PbHardwareService(&biosParameters);
|
|
return status;
|
|
}
|
|
|
|
PUCHAR
|
|
MbpFindNextPnpEndTag (
|
|
IN PUCHAR BusData,
|
|
IN LONG Limit
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function searches the Pnp BIOS device data for the frist END_TAG encountered.
|
|
|
|
Arguments:
|
|
|
|
BusData - supplies a pointer to the pnp bios resource descriptor.
|
|
|
|
Limit - maximum length of the search.
|
|
|
|
Return Value:
|
|
|
|
The address of the END_TAG location. Null if not found.
|
|
|
|
--*/
|
|
{
|
|
UCHAR tag;
|
|
USHORT size;
|
|
|
|
tag = *BusData;
|
|
while (tag != TAG_COMPLETE_END && Limit > 0) {
|
|
|
|
//
|
|
// Determine the size of the BIOS resource descriptor
|
|
//
|
|
|
|
if (!(tag & LARGE_RESOURCE_TAG)) {
|
|
size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
|
|
size += 1; // length of small tag
|
|
} else {
|
|
size = *(BusData + 1);
|
|
size += 3; // length of large tag
|
|
}
|
|
|
|
BusData += size;
|
|
Limit -= size;
|
|
tag = *BusData;
|
|
}
|
|
if (tag == TAG_COMPLETE_END) {
|
|
return BusData;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
BOOLEAN
|
|
MbpConfigAboutToChange (
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is invoked by low level component to signal a dock\undock event
|
|
is about to happen.
|
|
|
|
This function is called at DPC level.
|
|
|
|
Arguments:
|
|
|
|
SlotNumber - supplies the docking connector slot number.
|
|
|
|
Return Value:
|
|
|
|
TRUE - allow the change to happen; FALSE - ignore it for now.
|
|
|
|
--*/
|
|
{
|
|
PDEVICE_DATA deviceData;
|
|
HAL_BUS_INFORMATION busInfo;
|
|
PBUS_HANDLER busHandler;
|
|
|
|
//
|
|
// Get docking station slot data
|
|
//
|
|
|
|
deviceData = MbpFindDeviceData (MbpBusExtension[0], DOCK_VIRTUAL_SLOT_NUMBER);
|
|
if (deviceData) {
|
|
|
|
//
|
|
// if docking station slot is present
|
|
//
|
|
|
|
ASSERT (deviceData->Flags & DEVICE_FLAGS_DOCKING_STATION);
|
|
|
|
//
|
|
// If it is presently docked, the change is about-to-undock.
|
|
// We need to notify Eject callback.
|
|
//
|
|
|
|
DebugPrint((DEBUG_MESSAGE, "pnpbios: About to UNDOCK...\n"));
|
|
busHandler = MbpBusExtension[0]->BusHandler;
|
|
busInfo.BusType = busHandler->InterfaceType;
|
|
busInfo.ConfigurationType = busHandler->ConfigurationType;
|
|
busInfo.BusNumber = busHandler->BusNumber;
|
|
busInfo.Reserved = 0;
|
|
ExNotifyCallback (
|
|
MbpEjectCallbackObject,
|
|
&busInfo,
|
|
(PVOID)busHandler->BusNumber
|
|
);
|
|
} else {
|
|
|
|
DebugPrint((DEBUG_MESSAGE, "pnpbios: About to DOCK...\n"));
|
|
|
|
//
|
|
// Otherwise, it is about-to-dock. Simply let it happen.
|
|
//
|
|
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
VOID
|
|
MbpConfigChanged (
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is invoked by low level component to signal a dock-changed,
|
|
a system-device-changed, or a config-change_failed event. We simply notify
|
|
bus check callbacks.
|
|
This function is called at DPC level.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PBUS_HANDLER busHandler;
|
|
ULONG i;
|
|
|
|
//
|
|
// Notify buscheck for ALL the supported buses and queue check bus requests.
|
|
//
|
|
|
|
for (i = 0; i <= 1; i++) {
|
|
busHandler = MbpBusExtension[i]->BusHandler;
|
|
if (busHandler) {
|
|
MbpQueueCheckBus(busHandler);
|
|
}
|
|
}
|
|
}
|
|
|