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.
1009 lines
22 KiB
1009 lines
22 KiB
/*++
|
|
|
|
Copyright (c) 1990-1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
bus.c
|
|
|
|
Abstract:
|
|
|
|
NDIS wrapper functions to handle specific buses
|
|
|
|
Author:
|
|
|
|
Adam Barr (adamba) 11-Jul-1990
|
|
|
|
Environment:
|
|
|
|
Kernel mode, FSD
|
|
|
|
Revision History:
|
|
|
|
26-Feb-1991 JohnsonA Added Debugging Code
|
|
10-Jul-1991 JohnsonA Implement revised Ndis Specs
|
|
01-Jun-1995 JameelH Re-organization/optimization
|
|
06-Dec-1996 KyleB Placed a sanity check for MCA SlotNumber in
|
|
ndisFixBusInformation.
|
|
|
|
--*/
|
|
|
|
|
|
#include <precomp.h>
|
|
#pragma hdrstop
|
|
|
|
#include <stdarg.h>
|
|
|
|
//
|
|
// Define the module number for debug code.
|
|
//
|
|
#define MODULE_NUMBER MODULE_BUS
|
|
|
|
VOID
|
|
NdisReadEisaSlotInformation(
|
|
OUT PNDIS_STATUS Status,
|
|
IN NDIS_HANDLE WrapperConfigurationContext,
|
|
OUT PUINT SlotNumber,
|
|
OUT PNDIS_EISA_FUNCTION_INFORMATION EisaData
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine reads the EISA data from the slot given.
|
|
|
|
Arguments:
|
|
|
|
Status - Status of request to be returned to the user.
|
|
WrapperConfigurationContext - Context passed to MacAddAdapter.
|
|
SlotNumber - the EISA Slot where the card is at.
|
|
EisaData - pointer to a buffer where the EISA configuration is to be returned.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PNDIS_EISA_FUNCTION_INFORMATION pData;
|
|
UINT NumberOfFunctions;
|
|
|
|
NdisReadEisaSlotInformationEx(Status,
|
|
WrapperConfigurationContext,
|
|
SlotNumber,
|
|
&pData,
|
|
&NumberOfFunctions);
|
|
if (*Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
ASSERT(NumberOfFunctions > 0);
|
|
*EisaData = *pData;
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
NdisReadEisaSlotInformationEx(
|
|
OUT PNDIS_STATUS Status,
|
|
IN NDIS_HANDLE WrapperConfigurationContext,
|
|
OUT PUINT SlotNumber,
|
|
OUT PNDIS_EISA_FUNCTION_INFORMATION *EisaData,
|
|
OUT PUINT NumberOfFunctions
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine reads the EISA data from the slot given.
|
|
|
|
Arguments:
|
|
|
|
Status - Status of request to be returned to the user.
|
|
WrapperConfigurationContext - Context passed to MacAddAdapter.
|
|
SlotNumber - the EISA Slot where the card is at.
|
|
EisaData - pointer to a buffer where the EISA configuration is to be returned.
|
|
NumberOfFunctions - Returns the number of function structures in the EisaData.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PNDIS_EISA_FUNCTION_INFORMATION EisaBlockPointer;
|
|
PNDIS_EISA_SLOT_INFORMATION SlotInformation;
|
|
NTSTATUS NtStatus;
|
|
ULONG BusNumber;
|
|
ULONG DataLength;
|
|
NDIS_INTERFACE_TYPE BusType;
|
|
NDIS_CONFIGURATION_HANDLE NdisConfiguration;
|
|
|
|
//
|
|
// Get the BusNumber and the BusType from the Context here!!
|
|
//
|
|
NdisConfiguration.KeyQueryTable = (PRTL_QUERY_REGISTRY_TABLE)WrapperConfigurationContext;
|
|
BusType = (NDIS_INTERFACE_TYPE)(NdisConfiguration.KeyQueryTable[3].DefaultType);
|
|
BusNumber = NdisConfiguration.KeyQueryTable[3].DefaultLength;
|
|
|
|
*Status = NDIS_STATUS_FAILURE; // Assume failure
|
|
|
|
do
|
|
{
|
|
//
|
|
// First check if any bus access is allowed
|
|
//
|
|
if (BusType != Eisa)
|
|
{
|
|
break;
|
|
}
|
|
|
|
SlotInformation = NdisConfiguration.KeyQueryTable[3].DefaultData;
|
|
*NumberOfFunctions = 2;
|
|
|
|
//
|
|
// Was there already a buffer allocated?
|
|
//
|
|
|
|
if (SlotInformation == NULL)
|
|
{
|
|
//
|
|
// No, allocate a buffer
|
|
//
|
|
|
|
SlotInformation = (PNDIS_EISA_SLOT_INFORMATION)
|
|
ALLOC_FROM_POOL(sizeof(NDIS_EISA_SLOT_INFORMATION) +
|
|
(*NumberOfFunctions * sizeof(NDIS_EISA_FUNCTION_INFORMATION)),
|
|
NDIS_TAG_SLOT_INFO);
|
|
|
|
if (SlotInformation == NULL)
|
|
{
|
|
*Status = NDIS_STATUS_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Free any old buffer
|
|
//
|
|
|
|
if (NdisConfiguration.KeyQueryTable[3].DefaultData != NULL)
|
|
{
|
|
FREE_POOL(NdisConfiguration.KeyQueryTable[3].DefaultData);
|
|
}
|
|
|
|
NdisConfiguration.KeyQueryTable[3].DefaultData = SlotInformation;
|
|
}
|
|
|
|
//
|
|
// Now get the slot number that we read in earlier
|
|
//
|
|
*SlotNumber = NdisConfiguration.KeyQueryTable[4].DefaultLength;
|
|
DataLength = HalGetBusDataByOffset(EisaConfiguration,
|
|
BusNumber,
|
|
*SlotNumber,
|
|
(PVOID)SlotInformation,
|
|
0,
|
|
sizeof(NDIS_EISA_SLOT_INFORMATION) +
|
|
(*NumberOfFunctions * sizeof(NDIS_EISA_FUNCTION_INFORMATION)));
|
|
|
|
//
|
|
// Check for multiple functions in the Eisa data.
|
|
//
|
|
while (DataLength == (*NumberOfFunctions * sizeof(NDIS_EISA_FUNCTION_INFORMATION)))
|
|
{
|
|
*NumberOfFunctions++;
|
|
|
|
//
|
|
// Now allocate a new buffer
|
|
//
|
|
|
|
SlotInformation = (PNDIS_EISA_SLOT_INFORMATION)
|
|
ALLOC_FROM_POOL(sizeof(NDIS_EISA_SLOT_INFORMATION) +
|
|
(*NumberOfFunctions *sizeof(NDIS_EISA_FUNCTION_INFORMATION)),
|
|
NDIS_TAG_SLOT_INFO);
|
|
|
|
if (SlotInformation == NULL)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Free any old buffer
|
|
//
|
|
|
|
if (NdisConfiguration.KeyQueryTable[3].DefaultData != NULL)
|
|
{
|
|
FREE_POOL(NdisConfiguration.KeyQueryTable[3].DefaultData);
|
|
}
|
|
|
|
NdisConfiguration.KeyQueryTable[3].DefaultData = SlotInformation;
|
|
|
|
//
|
|
// Get new information
|
|
//
|
|
|
|
DataLength = HalGetBusDataByOffset(EisaConfiguration,
|
|
BusNumber,
|
|
*SlotNumber,
|
|
(PVOID)SlotInformation,
|
|
sizeof(NDIS_EISA_SLOT_INFORMATION) +
|
|
0,
|
|
(*NumberOfFunctions * sizeof(NDIS_EISA_FUNCTION_INFORMATION)));
|
|
}
|
|
|
|
if (SlotInformation == NULL)
|
|
{
|
|
*Status = NDIS_STATUS_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
|
|
EisaBlockPointer = (PNDIS_EISA_FUNCTION_INFORMATION)
|
|
((PUCHAR)SlotInformation + sizeof(CM_EISA_SLOT_INFORMATION));
|
|
|
|
*EisaData = EisaBlockPointer;
|
|
*NumberOfFunctions--; // We overshoot by 1 to verify last one found.
|
|
*Status = NDIS_STATUS_SUCCESS;
|
|
} while (FALSE);
|
|
}
|
|
|
|
|
|
VOID
|
|
NdisReadMcaPosInformation(
|
|
OUT PNDIS_STATUS Status,
|
|
IN NDIS_HANDLE WrapperConfigurationContext,
|
|
OUT PUINT ChannelNumber,
|
|
OUT PNDIS_MCA_POS_DATA McaData
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine reads the MCA data from the POS corresponding to
|
|
the channel specified.
|
|
|
|
Arguments:
|
|
|
|
WrapperConfigurationContext - Context passed to MacAddAdapter.
|
|
ChannelNumber - the MCA channel number.
|
|
McaData - pointer to a buffer where the channel information is to be
|
|
returned.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
NDIS_INTERFACE_TYPE BusType;
|
|
ULONG BusNumber;
|
|
NDIS_CONFIGURATION_HANDLE NdisConfiguration;
|
|
ULONG DataLength;
|
|
|
|
//
|
|
// Get the BusNumber and the BusType from the Context here!!
|
|
//
|
|
NdisConfiguration.KeyQueryTable = (PRTL_QUERY_REGISTRY_TABLE)WrapperConfigurationContext;
|
|
BusType = (NDIS_INTERFACE_TYPE)(NdisConfiguration.KeyQueryTable[3].DefaultType);
|
|
BusNumber = NdisConfiguration.KeyQueryTable[3].DefaultLength;
|
|
|
|
*Status = NDIS_STATUS_FAILURE;
|
|
*ChannelNumber = 0;
|
|
|
|
do
|
|
{
|
|
//
|
|
// First check if any bus access is allowed
|
|
//
|
|
if (BusType != MicroChannel)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get the channel number that we read in earlier. Note that the HAL
|
|
// apis expect the channel to be zero based.
|
|
//
|
|
*ChannelNumber = NdisConfiguration.KeyQueryTable[4].DefaultLength;
|
|
|
|
DataLength = HalGetBusDataByOffset(Pos,
|
|
BusNumber,
|
|
*ChannelNumber - 1,
|
|
(PVOID)McaData,
|
|
0,
|
|
sizeof(NDIS_MCA_POS_DATA));
|
|
*Status = NDIS_STATUS_SUCCESS;
|
|
} while (FALSE);
|
|
}
|
|
|
|
|
|
ULONG
|
|
NdisImmediateReadPciSlotInformation(
|
|
IN NDIS_HANDLE WrapperConfigurationContext,
|
|
IN ULONG SlotNumber,
|
|
IN ULONG Offset,
|
|
IN PVOID Buffer,
|
|
IN ULONG Length
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine reads from the PCI configuration space a specified
|
|
length of bytes at a certain offset.
|
|
|
|
Arguments:
|
|
|
|
WrapperConfigurationContext - Context passed to MacAddAdapter.
|
|
|
|
SlotNumber - The slot number of the device.
|
|
|
|
Offset - Offset to read from
|
|
|
|
Buffer - Place to store the bytes
|
|
|
|
Length - Number of bytes to read
|
|
|
|
Return Value:
|
|
|
|
Returns the number of bytes read.
|
|
|
|
--*/
|
|
{
|
|
ULONG DataLength = 0;
|
|
ULONG BusNumber;
|
|
PRTL_QUERY_REGISTRY_TABLE KeyQueryTable;
|
|
KeyQueryTable = (PRTL_QUERY_REGISTRY_TABLE)WrapperConfigurationContext;
|
|
|
|
BusNumber = KeyQueryTable[3].DefaultLength;
|
|
|
|
ASSERT((NDIS_INTERFACE_TYPE)(KeyQueryTable[3].DefaultType) == NdisInterfacePci);
|
|
DataLength = HalGetBusDataByOffset(PCIConfiguration,
|
|
BusNumber,
|
|
SlotNumber,
|
|
Buffer,
|
|
Offset,
|
|
Length);
|
|
return DataLength;
|
|
}
|
|
|
|
|
|
ULONG
|
|
NdisImmediateWritePciSlotInformation(
|
|
IN NDIS_HANDLE WrapperConfigurationContext,
|
|
IN ULONG SlotNumber,
|
|
IN ULONG Offset,
|
|
IN PVOID Buffer,
|
|
IN ULONG Length
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine writes to the PCI configuration space a specified
|
|
length of bytes at a certain offset.
|
|
|
|
Arguments:
|
|
|
|
WrapperConfigurationContext - Context passed to MacAddAdapter.
|
|
|
|
SlotNumber - The slot number of the device.
|
|
|
|
Offset - Offset to read from
|
|
|
|
Buffer - Place to store the bytes
|
|
|
|
Length - Number of bytes to read
|
|
|
|
Return Value:
|
|
|
|
Returns the number of bytes written.
|
|
|
|
--*/
|
|
{
|
|
ULONG DataLength = 0;
|
|
ULONG BusNumber;
|
|
PRTL_QUERY_REGISTRY_TABLE KeyQueryTable;
|
|
KeyQueryTable = (PRTL_QUERY_REGISTRY_TABLE)WrapperConfigurationContext;
|
|
BusNumber = KeyQueryTable[3].DefaultLength;
|
|
|
|
ASSERT((NDIS_INTERFACE_TYPE)(KeyQueryTable[3].DefaultType) == NdisInterfacePci);
|
|
DataLength = HalSetBusDataByOffset(PCIConfiguration,
|
|
BusNumber,
|
|
SlotNumber,
|
|
Buffer,
|
|
Offset,
|
|
Length);
|
|
return DataLength;
|
|
}
|
|
|
|
|
|
ULONG
|
|
NdisReadPciSlotInformation(
|
|
IN NDIS_HANDLE NdisAdapterHandle,
|
|
IN ULONG SlotNumber,
|
|
IN ULONG Offset,
|
|
IN PVOID Buffer,
|
|
IN ULONG Length
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine reads from the PCI configuration space a specified
|
|
length of bytes at a certain offset.
|
|
|
|
Arguments:
|
|
|
|
NdisAdapterHandle - Adapter we are talking about.
|
|
|
|
SlotNumber - The slot number of the device.
|
|
|
|
Offset - Offset to read from
|
|
|
|
Buffer - Place to store the bytes
|
|
|
|
Length - Number of bytes to read
|
|
|
|
Return Value:
|
|
|
|
Returns the number of bytes read.
|
|
|
|
--*/
|
|
{
|
|
ULONG DataLength = 0;
|
|
PNDIS_ADAPTER_BLOCK Adapter = (PNDIS_ADAPTER_BLOCK)NdisAdapterHandle;
|
|
PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)NdisAdapterHandle;
|
|
|
|
if (Adapter->DeviceObject == NULL)
|
|
{
|
|
//
|
|
// This is a mini-port
|
|
//
|
|
ASSERT(Miniport->BusType == NdisInterfacePci);
|
|
|
|
DataLength = HalGetBusDataByOffset(PCIConfiguration,
|
|
Miniport->BusNumber,
|
|
SlotNumber,
|
|
Buffer,
|
|
Offset,
|
|
Length);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(Adapter->BusType == NdisInterfacePci);
|
|
DataLength = HalGetBusDataByOffset(PCIConfiguration,
|
|
Adapter->BusNumber,
|
|
SlotNumber,
|
|
Buffer,
|
|
Offset,
|
|
Length);
|
|
}
|
|
return DataLength;
|
|
}
|
|
|
|
|
|
ULONG
|
|
NdisWritePciSlotInformation(
|
|
IN NDIS_HANDLE NdisAdapterHandle,
|
|
IN ULONG SlotNumber,
|
|
IN ULONG Offset,
|
|
IN PVOID Buffer,
|
|
IN ULONG Length
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine writes to the PCI configuration space a specified
|
|
length of bytes at a certain offset.
|
|
|
|
Arguments:
|
|
|
|
NdisAdapterHandle - Adapter we are talking about.
|
|
|
|
SlotNumber - The slot number of the device.
|
|
|
|
Offset - Offset to read from
|
|
|
|
Buffer - Place to store the bytes
|
|
|
|
Length - Number of bytes to read
|
|
|
|
Return Value:
|
|
|
|
Returns the number of bytes written.
|
|
|
|
--*/
|
|
{
|
|
ULONG DataLength = 0;
|
|
PNDIS_ADAPTER_BLOCK Adapter = (PNDIS_ADAPTER_BLOCK)NdisAdapterHandle;
|
|
PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)NdisAdapterHandle;
|
|
|
|
if (Adapter->DeviceObject == NULL)
|
|
{
|
|
//
|
|
// This is a mini-port
|
|
//
|
|
ASSERT(Miniport->BusType == NdisInterfacePci);
|
|
DataLength = HalSetBusDataByOffset(PCIConfiguration,
|
|
Miniport->BusNumber,
|
|
SlotNumber,
|
|
Buffer,
|
|
Offset,
|
|
Length);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(Adapter->BusType == NdisInterfacePci);
|
|
DataLength = HalSetBusDataByOffset(PCIConfiguration,
|
|
Adapter->BusNumber,
|
|
SlotNumber,
|
|
Buffer,
|
|
Offset,
|
|
Length);
|
|
}
|
|
return DataLength;
|
|
}
|
|
|
|
|
|
VOID
|
|
NdisOverrideBusNumber(
|
|
IN NDIS_HANDLE WrapperConfigurationContext,
|
|
IN NDIS_HANDLE MiniportAdapterHandle OPTIONAL,
|
|
IN ULONG BusNumber
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is used to override the BusNumber value retrieved
|
|
from the registry. It is expected to be used by PCI drivers
|
|
that discover that their adapter's bus number has changed.
|
|
|
|
Arguments:
|
|
|
|
WrapperConfigurationContext - a handle pointing to an RTL_QUERY_REGISTRY_TABLE
|
|
that is set up for this driver's parameters.
|
|
|
|
MiniportAdapterHandle - points to the adapter block, if the calling
|
|
driver is a miniport. If the calling driver is a full MAC, this
|
|
parameter must be NULL.
|
|
|
|
BusNumber - the new bus number.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
|
|
|
|
((PRTL_QUERY_REGISTRY_TABLE)WrapperConfigurationContext)[3].DefaultLength = BusNumber;
|
|
|
|
if (Miniport != NULL)
|
|
{
|
|
Miniport->BusNumber = BusNumber;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
ndisFixBusInformation(
|
|
IN PNDIS_CONFIGURATION_HANDLE ConfigHandle,
|
|
IN PBUS_SLOT_DB pDb
|
|
)
|
|
/*++
|
|
|
|
Make sure that the card is in the slot that the registry says it is. If it is not,
|
|
scan the bus to see if we find the card. If we do, then fix up the registry so that
|
|
next time we do not have to do this. Also keep track of the cards so that we handle
|
|
multiple instances.
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status = NDIS_STATUS_FAILURE;
|
|
ULONGLONG Buffer[(sizeof(NDIS_EISA_SLOT_INFORMATION)+sizeof(NDIS_EISA_FUNCTION_INFORMATION))/sizeof(ULONGLONG) + 1];
|
|
PNDIS_EISA_SLOT_INFORMATION SlotInformation;
|
|
PNDIS_MCA_POS_DATA McaData;
|
|
NDIS_CONFIGURATION_PARAMETER ParmValue;
|
|
ULONG BusId, Mask = 0xFFFFFFFF;
|
|
ULONG DataLength;
|
|
ULONG Bus, Slot, MaxSlot = 0xFF;
|
|
|
|
SlotInformation = (PNDIS_EISA_SLOT_INFORMATION)Buffer;
|
|
McaData = (PNDIS_MCA_POS_DATA)Buffer;
|
|
|
|
//
|
|
// Read the slot information for the slot specified in the registry
|
|
//
|
|
switch (pDb->BusType)
|
|
{
|
|
case NdisInterfaceEisa:
|
|
Mask = 0xFFFFFF;
|
|
DataLength = HalGetBusDataByOffset(EisaConfiguration,
|
|
pDb->BusNumber,
|
|
pDb->SlotNumber,
|
|
SlotInformation,
|
|
0,
|
|
sizeof(NDIS_EISA_SLOT_INFORMATION) +
|
|
sizeof(NDIS_EISA_FUNCTION_INFORMATION));
|
|
BusId = SlotInformation->CompressedId;
|
|
break;
|
|
|
|
case NdisInterfaceMca:
|
|
MaxSlot = 7;
|
|
DataLength = 0;
|
|
if ((pDb->SlotNumber <= MaxSlot) && (pDb->SlotNumber > 0))
|
|
{
|
|
DataLength = HalGetBusDataByOffset(Pos,
|
|
pDb->BusNumber,
|
|
pDb->SlotNumber - 1,
|
|
McaData,
|
|
0,
|
|
sizeof(NDIS_MCA_POS_DATA));
|
|
BusId = McaData->AdapterId;
|
|
}
|
|
|
|
break;
|
|
|
|
case NdisInterfacePci:
|
|
DataLength = HalGetBusDataByOffset(PCIConfiguration,
|
|
pDb->BusNumber,
|
|
pDb->SlotNumber,
|
|
&BusId,
|
|
0,
|
|
sizeof(ULONG));
|
|
}
|
|
|
|
if ((DataLength != 0) &&
|
|
((BusId & Mask) == (pDb->BusId & Mask)))
|
|
{
|
|
//
|
|
// The card seems to be where it is supposed to be. Make sure that is the
|
|
// case by searching our db to see if this is already installed. Use BusId
|
|
// and not the masked busid for search and in our database.
|
|
//
|
|
// If we found an EISA card where the registry says it should be but found another
|
|
// loaded instance, allow it - for multifunction EISA cards, we can have two cards
|
|
// with the same bus#/slot#.
|
|
//
|
|
if (!ndisSearchGlobalDb(pDb->BusType,
|
|
BusId,
|
|
pDb->BusNumber,
|
|
pDb->SlotNumber) ||
|
|
(pDb->BusType == NdisInterfaceEisa))
|
|
{
|
|
if (ndisAddGlobalDb(pDb->BusType,
|
|
BusId,
|
|
pDb->BusNumber,
|
|
pDb->SlotNumber))
|
|
{
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// We could not add to global list. Unlikely we can proceed anyway.
|
|
//
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
}
|
|
|
|
//
|
|
// The card is not where it ought to be. Scan the bus and find out where it is.
|
|
//
|
|
for (Bus = 0; NOTHING; Bus ++)
|
|
{
|
|
for (Slot = 0; Slot < MaxSlot; Slot ++)
|
|
{
|
|
switch (pDb->BusType)
|
|
{
|
|
case NdisInterfaceEisa:
|
|
DataLength = HalGetBusDataByOffset(EisaConfiguration,
|
|
Bus,
|
|
Slot,
|
|
SlotInformation,
|
|
0,
|
|
sizeof(NDIS_EISA_SLOT_INFORMATION) +
|
|
sizeof(NDIS_EISA_FUNCTION_INFORMATION));
|
|
BusId = SlotInformation->CompressedId;
|
|
break;
|
|
|
|
case NdisInterfaceMca:
|
|
DataLength = HalGetBusDataByOffset(Pos,
|
|
Bus,
|
|
Slot,
|
|
McaData,
|
|
0,
|
|
sizeof(NDIS_MCA_POS_DATA));
|
|
BusId = McaData->AdapterId;
|
|
break;
|
|
|
|
case NdisInterfacePci:
|
|
DataLength = HalGetBusDataByOffset(PCIConfiguration,
|
|
Bus,
|
|
Slot,
|
|
&BusId,
|
|
0,
|
|
sizeof(ULONG));
|
|
break;
|
|
}
|
|
|
|
if (DataLength == 0)
|
|
{
|
|
//
|
|
// No more buses, we failed
|
|
//
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
if ((BusId & Mask) == (pDb->BusId & Mask))
|
|
{
|
|
if (pDb->BusType == NdisInterfaceMca)
|
|
{
|
|
//
|
|
// MCA Slot #s are 0 based for HAL and 1 based for registry
|
|
//
|
|
Slot ++;
|
|
}
|
|
|
|
//
|
|
// Found one, make sure we do not already know about it
|
|
//
|
|
if (!ndisSearchGlobalDb(pDb->BusType,
|
|
pDb->BusId,
|
|
Bus,
|
|
Slot))
|
|
{
|
|
NDIS_STRING BusNumStr = NDIS_STRING_CONST("BusNumber");
|
|
NDIS_STRING SlotNumStr = NDIS_STRING_CONST("SlotNumber");
|
|
//
|
|
// This is it. First write it back to the registry. Then
|
|
// to the global db.
|
|
//
|
|
ParmValue.ParameterType = NdisParameterInteger;
|
|
ParmValue.ParameterData.IntegerData = Bus;
|
|
NdisWriteConfiguration(&Status,
|
|
ConfigHandle,
|
|
&BusNumStr,
|
|
&ParmValue);
|
|
|
|
ParmValue.ParameterData.IntegerData = Slot;
|
|
NdisWriteConfiguration(&Status,
|
|
ConfigHandle,
|
|
&SlotNumStr,
|
|
&ParmValue);
|
|
|
|
if (ndisAddGlobalDb(pDb->BusType,
|
|
pDb->BusId,
|
|
Bus,
|
|
Slot))
|
|
{
|
|
pDb->BusNumber = Bus;
|
|
pDb->SlotNumber = Slot;
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// We could not add to global list. Unlikely we can proceed anyway.
|
|
//
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
VOID
|
|
ndisAddBusInformation(
|
|
IN PNDIS_CONFIGURATION_HANDLE ConfigHandle,
|
|
IN PBUS_SLOT_DB pDb
|
|
)
|
|
/*++
|
|
|
|
For OEM adapters that do not have their bus-id in the registry, do them a favor and add it.
|
|
|
|
--*/
|
|
{
|
|
ULONGLONG Buffer[(sizeof(NDIS_EISA_SLOT_INFORMATION)+sizeof(NDIS_EISA_FUNCTION_INFORMATION))/sizeof(ULONGLONG) + 1];
|
|
PNDIS_STRING BusIdStr;
|
|
NDIS_STRING PciIdStr = NDIS_STRING_CONST("AdapterCFID");
|
|
NDIS_STRING EisaIdStr = NDIS_STRING_CONST("EisaCompressedId");
|
|
NDIS_STRING McaIdStr = NDIS_STRING_CONST("McaPosId");
|
|
PNDIS_EISA_SLOT_INFORMATION SlotInformation;
|
|
NDIS_CONFIGURATION_PARAMETER ParmValue;
|
|
PNDIS_MCA_POS_DATA McaData;
|
|
NDIS_STATUS Status;
|
|
ULONG BusId, DataLength = 0;
|
|
|
|
//
|
|
// Read the bus-id by politely asking the HAL
|
|
//
|
|
switch (pDb->BusType)
|
|
{
|
|
case NdisInterfaceEisa:
|
|
SlotInformation = (PNDIS_EISA_SLOT_INFORMATION)Buffer;
|
|
DataLength = HalGetBusDataByOffset(EisaConfiguration,
|
|
pDb->BusNumber,
|
|
pDb->SlotNumber,
|
|
SlotInformation,
|
|
0,
|
|
sizeof(NDIS_EISA_SLOT_INFORMATION) +
|
|
sizeof(NDIS_EISA_FUNCTION_INFORMATION));
|
|
BusId = SlotInformation->CompressedId;
|
|
break;
|
|
|
|
case NdisInterfaceMca:
|
|
McaData = (PNDIS_MCA_POS_DATA)Buffer;
|
|
DataLength = HalGetBusDataByOffset(Pos,
|
|
pDb->BusNumber,
|
|
pDb->SlotNumber - 1,
|
|
McaData,
|
|
0,
|
|
sizeof(NDIS_MCA_POS_DATA));
|
|
BusId = McaData->AdapterId;
|
|
break;
|
|
|
|
case NdisInterfacePci:
|
|
DataLength = HalGetBusDataByOffset(PCIConfiguration,
|
|
pDb->BusNumber,
|
|
pDb->SlotNumber,
|
|
&BusId,
|
|
0,
|
|
sizeof(ULONG));
|
|
}
|
|
if (DataLength != 0)
|
|
{
|
|
ParmValue.ParameterType = NdisParameterInteger;
|
|
ParmValue.ParameterData.IntegerData = BusId;
|
|
|
|
switch (pDb->BusType)
|
|
{
|
|
case NdisInterfaceEisa:
|
|
BusIdStr = &EisaIdStr;
|
|
break;
|
|
|
|
case NdisInterfaceMca:
|
|
BusIdStr = &McaIdStr;
|
|
break;
|
|
|
|
case NdisInterfacePci:
|
|
BusIdStr = &PciIdStr;
|
|
break;
|
|
}
|
|
|
|
if (pDb->BusType != NdisInterfacePci)
|
|
{
|
|
//
|
|
// Do not do it for Pci buses just yet. Some OEM cards do bogus things.
|
|
//
|
|
NdisWriteConfiguration(&Status,
|
|
ConfigHandle,
|
|
BusIdStr,
|
|
&ParmValue);
|
|
|
|
//
|
|
// Finally create a data-base entry for this
|
|
//
|
|
ndisAddGlobalDb(pDb->BusType,
|
|
pDb->BusId,
|
|
pDb->BusNumber,
|
|
pDb->SlotNumber);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
ndisSearchGlobalDb(
|
|
IN NDIS_INTERFACE_TYPE BusType,
|
|
IN ULONG BusId,
|
|
IN ULONG BusNumber,
|
|
IN ULONG SlotNumber
|
|
)
|
|
{
|
|
PBUS_SLOT_DB pScan;
|
|
KIRQL OldIrql;
|
|
BOOLEAN rc = FALSE;
|
|
|
|
ACQUIRE_SPIN_LOCK(&ndisGlobalDbLock, &OldIrql);
|
|
|
|
for (pScan = ndisGlobalDb;
|
|
pScan != NULL;
|
|
pScan = pScan->Next)
|
|
{
|
|
if ((pScan->BusType == BusType) &&
|
|
(pScan->BusId == BusId) &&
|
|
(pScan->BusNumber == BusNumber) &&
|
|
(pScan->SlotNumber == SlotNumber))
|
|
{
|
|
rc = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
RELEASE_SPIN_LOCK(&ndisGlobalDbLock, OldIrql);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
ndisAddGlobalDb(
|
|
IN NDIS_INTERFACE_TYPE BusType,
|
|
IN ULONG BusId,
|
|
IN ULONG BusNumber,
|
|
IN ULONG SlotNumber
|
|
)
|
|
{
|
|
PBUS_SLOT_DB pDb;
|
|
KIRQL OldIrql;
|
|
BOOLEAN rc = FALSE;
|
|
|
|
pDb = ALLOC_FROM_POOL(sizeof(BUS_SLOT_DB), NDIS_TAG_DEFAULT);
|
|
if (pDb != NULL)
|
|
{
|
|
pDb->BusType = BusType;
|
|
pDb->BusId = BusId;
|
|
pDb->BusNumber = BusNumber;
|
|
pDb->SlotNumber = SlotNumber;
|
|
ACQUIRE_SPIN_LOCK(&ndisGlobalDbLock, &OldIrql);
|
|
|
|
pDb->Next = ndisGlobalDb;
|
|
ndisGlobalDb = pDb;
|
|
|
|
RELEASE_SPIN_LOCK(&ndisGlobalDbLock, OldIrql);
|
|
|
|
rc = TRUE;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
BOOLEAN
|
|
ndisDeleteGlobalDb(
|
|
IN NDIS_INTERFACE_TYPE BusType,
|
|
IN ULONG BusId,
|
|
IN ULONG BusNumber,
|
|
IN ULONG SlotNumber
|
|
)
|
|
{
|
|
PBUS_SLOT_DB pScan, *ppScan;
|
|
KIRQL OldIrql;
|
|
|
|
ACQUIRE_SPIN_LOCK(&ndisGlobalDbLock, &OldIrql);
|
|
|
|
for (ppScan = &ndisGlobalDb;
|
|
(pScan = *ppScan) != NULL;
|
|
ppScan = &pScan->Next)
|
|
{
|
|
if ((pScan->BusType == BusType) &&
|
|
(pScan->BusId == BusId) &&
|
|
(pScan->BusNumber == BusNumber) &&
|
|
(pScan->SlotNumber == SlotNumber))
|
|
{
|
|
*ppScan = pScan->Next;
|
|
break;
|
|
}
|
|
}
|
|
|
|
RELEASE_SPIN_LOCK(&ndisGlobalDbLock, OldIrql);
|
|
|
|
if (pScan != NULL)
|
|
{
|
|
FREE_POOL(pScan);
|
|
}
|
|
|
|
return (pScan != NULL);
|
|
}
|
|
|
|
|