Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

553 lines
12 KiB

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
ixbusdat.c
Abstract:
This module contains the IoXxx routines for the NT I/O system that
are hardware dependent. Were these routines not hardware dependent,
they would reside in the iosubs.c module.
Author:
Environment:
Kernel mode
Revision History:
--*/
#include "bootia64.h"
#include "arc.h"
#include "ixfwhal.h"
#if defined(NEC_98)
#include "nec98.h"
#else //NEC_98
#include "eisa.h"
#endif //NEC_98
#include "mca.h"
#include "ntconfig.h"
#if defined(NEC_98)
#else
ULONG
HalpGetCmosData(
IN ULONG BusNumber,
IN ULONG SlotNumber,
IN PVOID Buffer,
IN ULONG Length
);
ULONG
HalpGetPosData(
IN ULONG BusNumber,
IN ULONG SlotNumber,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
);
ULONG
HalpGetEisaData(
IN ULONG BusNumber,
IN ULONG SlotNumber,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
);
#endif //!NEC_98
ULONG
HalpGetPCIData(
IN ULONG BusNumber,
IN ULONG SlotNumber,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
);
ULONG
HalpSetPCIData(
IN ULONG BusNumber,
IN ULONG SlotNumber,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
);
NTSTATUS
HalpAssignPCISlotResources (
IN ULONG BusNumber,
IN ULONG Slot,
IN OUT PCM_RESOURCE_LIST *AllocatedResources
);
/*
*
* Router functions. Routes each call to specific handler
*
*/
ULONG
HalGetBusData(
IN BUS_DATA_TYPE BusDataType,
IN ULONG BusNumber,
IN ULONG SlotNumber,
IN PVOID Buffer,
IN ULONG Length
)
{
return HalGetBusDataByOffset (BusDataType,BusNumber,SlotNumber,Buffer,0,Length);
}
ULONG
HalGetBusDataByOffset (
IN BUS_DATA_TYPE BusDataType,
IN ULONG BusNumber,
IN ULONG Slot,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
)
/*++
Routine Description:
Dispatcher for GetBusData
--*/
{
switch (BusDataType) {
#if defined(NEC_98)
#else
case Cmos:
if (Offset != 0) {
return 0;
}
return HalpGetCmosData(BusNumber, Slot, Buffer, Length);
case Pos:
return HalpGetPosData(BusNumber, Slot, Buffer, Offset, Length);
case EisaConfiguration:
return HalpGetEisaData(BusNumber, Slot, Buffer, Offset, Length);
#endif //NEC_98
case PCIConfiguration:
return HalpGetPCIData(BusNumber, Slot, Buffer, Offset, Length);
}
return 0;
}
ULONG
HalSetBusData(
IN BUS_DATA_TYPE BusDataType,
IN ULONG BusNumber,
IN ULONG SlotNumber,
IN PVOID Buffer,
IN ULONG Length
)
{
return HalSetBusDataByOffset (BusDataType,BusNumber,SlotNumber,Buffer,0,Length);
}
ULONG
HalSetBusDataByOffset(
IN BUS_DATA_TYPE BusDataType,
IN ULONG BusNumber,
IN ULONG Slot,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
)
/*++
Routine Description:
Dispatcher for SetBusData
--*/
{
switch (BusDataType) {
case PCIConfiguration:
return HalpSetPCIData(BusNumber, Slot, Buffer, Offset, Length);
}
return 0;
}
NTSTATUS
HalAssignSlotResources (
IN PUNICODE_STRING RegistryPath,
IN PUNICODE_STRING DriverClassName OPTIONAL,
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT DeviceObject OPTIONAL,
IN INTERFACE_TYPE BusType,
IN ULONG BusNumber,
IN ULONG SlotNumber,
IN OUT PCM_RESOURCE_LIST *AllocatedResources
)
/*++
Routine Description:
Dispatcher for AssignSlotResources
--*/
{
switch (BusType) {
case PCIBus:
return HalpAssignPCISlotResources (
BusNumber,
SlotNumber,
AllocatedResources
);
default:
break;
}
return STATUS_NOT_FOUND;
}
/**
**
** Standard PC bus functions
**
**/
BOOLEAN
HalTranslateBusAddress(
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN PHYSICAL_ADDRESS BusAddress,
IN OUT PULONG AddressSpace,
OUT PPHYSICAL_ADDRESS TranslatedAddress
)
/*++
Routine Description:
This function translates a bus-relative address space and address into
a system physical address.
Arguments:
BusNumber - Supplies the bus number. This is ignored on
standard x86 systems
BusAddress - Supplies the bus-relative address
AddressSpace - Supplies the address space number.
Returns the host address space number.
AddressSpace == 0 => I/O space
AddressSpace == 1 => memory space
TranslatedAddress - Pointer to a physical_address.
Return Value:
System physical address corresponding to the supplied bus relative
address and bus address number.
--*/
{
TranslatedAddress->HighPart = 0;
TranslatedAddress->LowPart = BusAddress.LowPart;
return(TRUE);
}
#if defined(NEC_98)
#else
ULONG
HalpGetPosData (
IN ULONG BusNumber,
IN ULONG SlotNumber,
IN PVOID Buffer,
IN ULONG DOffset,
IN ULONG Length
)
/*--
Arguments:
BusDataType - Supplies the type of bus.
BusNumber - Indicates which bus.
Buffer - Supplies the space to store the data.
Length - Supplies a count in bytes of the maximum amount to return.
Return Value:
Returns the amount of data stored into the buffer.
--*/
{
PVOID McaRegisterBase = 0;
ULONG Index = 0;
PUCHAR DataBuffer = Buffer;
ULONG DataLength = 0;
PUCHAR PosBase;
ULONG Offset;
if (DOffset != 0 || MachineType != MACHINE_TYPE_MCA) {
return 0;
}
PosBase = (PUCHAR) &((PMCA_CONTROL) McaRegisterBase)->Pos;
//
// Place the specified adapter into setup mode.
//
WRITE_PORT_UCHAR((PVOID) &((PMCA_CONTROL) McaRegisterBase)->AdapterSetup,
(UCHAR) ( MCA_ADAPTER_SETUP_ON | SlotNumber ));
while (DataLength < Length && DataLength < 6) {
DataBuffer[DataLength] = READ_PORT_UCHAR( PosBase + DataLength );
DataLength++;
}
while (DataLength < Length) {
WRITE_PORT_UCHAR((PVOID) &((PPROGRAMMABLE_OPTION_SELECT)
PosBase)->SubaddressExtensionLsb, (UCHAR) Index);
WRITE_PORT_UCHAR((PVOID) &((PPROGRAMMABLE_OPTION_SELECT)
PosBase)->SubaddressExtensionMsb, (UCHAR) (Index >> 8));
DataBuffer[Index + 6] = READ_PORT_UCHAR(
(PVOID) &((PPROGRAMMABLE_OPTION_SELECT)PosBase)->OptionSelectData2);
DataLength++;
if (DataLength < Length) {
Offset = DataLength + ((Length - DataLength) / 2);
DataBuffer[Offset] = READ_PORT_UCHAR(
(PVOID) &((PPROGRAMMABLE_OPTION_SELECT)PosBase)->OptionSelectData3);
DataLength++;
Index++;
}
}
//
// Disable adapter setup.
//
WRITE_PORT_UCHAR((PVOID) &((PMCA_CONTROL) McaRegisterBase)->AdapterSetup,
(UCHAR) ( MCA_ADAPTER_SETUP_OFF ));
return 1;
}
ULONG
HalpGetEisaData (
IN ULONG BusNumber,
IN ULONG SlotNumber,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
)
/*--
Arguments:
BusDataType - Supplies the type of bus.
BusNumber - Indicates which bus.
Buffer - Supplies the space to store the data.
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 = 0;
ULONG i;
ULONG TotalDataSize;
ULONG SlotDataSize;
ULONG PartialCount;
ULONG Index = 0;
PUCHAR DataBuffer = Buffer;
PCONFIGURATION_COMPONENT_DATA ConfigData;
PCM_EISA_SLOT_INFORMATION SlotInformation;
PCM_PARTIAL_RESOURCE_LIST Descriptor;
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource;
BOOLEAN Found = FALSE;
if (MachineType != MACHINE_TYPE_EISA) {
return 0;
}
ConfigData = KeFindConfigurationEntry(
FwConfigurationTree,
AdapterClass,
EisaAdapter,
NULL
);
if (ConfigData == NULL) {
#if defined(ENABLE_LOADER_EBUG)
DbgPrint("HalGetBusData: KeFindConfigurationEntry failed\n");
#endif
return(0);
}
Descriptor = ConfigData->ConfigurationData;
PartialResource = Descriptor->PartialDescriptors;
PartialCount = Descriptor->Count;
for (i = 0; i < PartialCount; i++) {
//
// Do each partial Resource
//
switch (PartialResource->Type) {
case CmResourceTypeNull:
case CmResourceTypePort:
case CmResourceTypeInterrupt:
case CmResourceTypeMemory:
case CmResourceTypeDma:
//
// We dont care about these.
//
PartialResource++;
break;
case CmResourceTypeDeviceSpecific:
//
// Bingo!
//
TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize;
SlotInformation = (PCM_EISA_SLOT_INFORMATION)
((PUCHAR)PartialResource +
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
while (((LONG)TotalDataSize) > 0) {
if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) {
SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
} else {
SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
SlotInformation->NumberFunctions *
sizeof(CM_EISA_FUNCTION_INFORMATION);
}
if (SlotDataSize > TotalDataSize) {
//
// Something is wrong again
//
#if defined(ENABLE_LOADER_EBUG)
DbgPrint("HalGetBusData: SlotDataSize > TotalDataSize\n");
#endif
return(0);
}
if (SlotNumber != 0) {
SlotNumber--;
SlotInformation = (PCM_EISA_SLOT_INFORMATION)
((PUCHAR)SlotInformation + SlotDataSize);
TotalDataSize -= SlotDataSize;
continue;
}
//
// This is our slot
//
Found = TRUE;
break;
}
//
// End loop
//
i = PartialCount;
break;
default:
#if defined(ENABLE_LOADER_EBUG)
DbgPrint("Bad Data in registry!\n");
#endif
return(0);
}
}
if (Found) {
//
// As a hack if the length is zero then the buffer points to a
// PVOID where the pointer to the data should be stored. This is
// done in the loader because we quickly run out of heap scaning
// all of the EISA configuration data.
//
if (Length == 0) {
//
// Return the pointer to the mini-port driver.
//
*((PVOID *)Buffer) = SlotInformation;
return(SlotDataSize);
}
i = Length + Offset;
if (i > SlotDataSize) {
i = SlotDataSize;
}
DataLength = i - Offset;
RtlMoveMemory(Buffer, ((PUCHAR) SlotInformation + Offset), DataLength);
}
return(DataLength);
}
#endif //NEC_98