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.
1036 lines
31 KiB
1036 lines
31 KiB
/*++
|
|
|
|
Copyright (c) 1994 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
intrface.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the external interfaces of the
|
|
pcmcia driver
|
|
|
|
Author:
|
|
|
|
Neil Sandlin (neilsa) 3-Mar-1999
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
Revision History :
|
|
|
|
|
|
--*/
|
|
|
|
#include "pch.h"
|
|
|
|
//
|
|
// Internal References
|
|
//
|
|
|
|
ULONG
|
|
PcmciaReadCardMemory(
|
|
IN PDEVICE_OBJECT Pdo,
|
|
IN ULONG WhichSpace,
|
|
OUT PUCHAR Buffer,
|
|
IN ULONG Offset,
|
|
IN ULONG Length
|
|
);
|
|
|
|
ULONG
|
|
PcmciaWriteCardMemory(
|
|
IN PDEVICE_OBJECT Pdo,
|
|
IN ULONG WhichSpace,
|
|
IN PUCHAR Buffer,
|
|
IN ULONG Offset,
|
|
IN ULONG Length
|
|
);
|
|
|
|
NTSTATUS
|
|
PcmciaMfEnumerateChild(
|
|
IN PPDO_EXTENSION PdoExtension,
|
|
IN ULONG Index,
|
|
OUT PMF_DEVICE_INFO ChildInfo
|
|
);
|
|
|
|
BOOLEAN
|
|
PcmciaModifyMemoryWindow(
|
|
IN PDEVICE_OBJECT Pdo,
|
|
IN ULONGLONG HostBase,
|
|
IN ULONGLONG CardBase,
|
|
IN BOOLEAN Enable,
|
|
IN ULONG WindowSize OPTIONAL,
|
|
IN UCHAR AccessSpeed OPTIONAL,
|
|
IN UCHAR BusWidth OPTIONAL,
|
|
IN BOOLEAN IsAttributeMemory OPTIONAL
|
|
);
|
|
|
|
BOOLEAN
|
|
PcmciaSetVpp(
|
|
IN PDEVICE_OBJECT Pdo,
|
|
IN UCHAR VppLevel
|
|
);
|
|
|
|
BOOLEAN
|
|
PcmciaIsWriteProtected(
|
|
IN PDEVICE_OBJECT Pdo
|
|
);
|
|
|
|
BOOLEAN
|
|
PcmciaTranslateBusAddress(
|
|
IN PVOID Context,
|
|
IN PHYSICAL_ADDRESS BusAddress,
|
|
IN ULONG Length,
|
|
IN OUT PULONG AddressSpace,
|
|
OUT PPHYSICAL_ADDRESS TranslatedAddress
|
|
);
|
|
|
|
PDMA_ADAPTER
|
|
PcmciaGetDmaAdapter(
|
|
IN PVOID Context,
|
|
IN struct _DEVICE_DESCRIPTION *DeviceDescriptor,
|
|
OUT PULONG NumberOfMapRegisters
|
|
);
|
|
|
|
VOID
|
|
PcmciaNop(
|
|
IN PVOID Context
|
|
);
|
|
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE, PcmciaPdoQueryInterface)
|
|
#pragma alloc_text(PAGE, PcmciaMfEnumerateChild)
|
|
#pragma alloc_text(PAGE, PcmciaNop)
|
|
#pragma alloc_text(PAGE, PcmciaGetInterface)
|
|
#pragma alloc_text(PAGE, PcmciaUpdateInterruptLine)
|
|
#endif
|
|
|
|
|
|
|
|
NTSTATUS
|
|
PcmciaPdoQueryInterface(
|
|
IN PDEVICE_OBJECT Pdo,
|
|
IN OUT PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Fills in the interface requested
|
|
|
|
|
|
Interfaces supported are:
|
|
|
|
GUID_PCMCIA_INTERFACE_STANDARD:
|
|
|
|
This returns a pointer to a PCMCIA_INTERFACE_STANDARD structure.
|
|
These interfaces are exported solely for flash memory card support as
|
|
a means for flash memory card drivers to slide memory windows,
|
|
set Vpp levels etc.
|
|
|
|
GUID_TRANSLATOR_INTERFACE_STANDARD:
|
|
|
|
This returns an interrupt translator for 16-bit pc-cards which is used
|
|
by PnP for translating raw IRQs. We simply return the Hal implemented
|
|
translator, since PCMCIA does not need any specific translation. We do not
|
|
return a translator if this is for a cardbus card
|
|
|
|
GUID_PCMCIA_BUS_INTERFACE_STANDARD:
|
|
|
|
This returns a pointer to a PCMCIA_BUS_INTERFACE_STANDARD structure.
|
|
This contains entry points to set/get PCMCIA config data for the pc-card
|
|
|
|
|
|
GUID_MF_ENUMERATION_INTERFACE
|
|
|
|
For 16-bit multifunction pc-cards returns a pointer to MF_ENUMERATION_INTERFACE
|
|
structure which contains entry points to enumerate multifunction children of
|
|
the pc-card
|
|
|
|
Completes the Passed in IRP before returning
|
|
|
|
Arguments
|
|
|
|
Pdo - Pointer to the device object
|
|
Irp - Pointer to the io request packet
|
|
|
|
Return Value
|
|
|
|
STATUS_SUCCESS
|
|
STATUS_INSUFFICIENT_RESOURCES - if supplied interface size is
|
|
not big enough to accomodate the interface
|
|
STATUS_INVALID_PARAMETER_1 - if the requested interface is not supported
|
|
by this driver
|
|
--*/
|
|
|
|
{
|
|
|
|
PIO_STACK_LOCATION irpStack;
|
|
PPCMCIA_INTERFACE_STANDARD pcmciaInterfaceStandard;
|
|
GUID *interfaceType;
|
|
PPDO_EXTENSION pdoExtension;
|
|
PFDO_EXTENSION fdoExtension;
|
|
NTSTATUS status = STATUS_NOT_SUPPORTED;
|
|
|
|
PAGED_CODE();
|
|
|
|
irpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
interfaceType = (GUID *) irpStack->Parameters.QueryInterface.InterfaceType;
|
|
pdoExtension = Pdo->DeviceExtension;
|
|
fdoExtension = pdoExtension->Socket->DeviceExtension;
|
|
|
|
try{
|
|
|
|
if (Is16BitCard(pdoExtension) && CompareGuid(interfaceType, (PVOID) &GUID_PCMCIA_INTERFACE_STANDARD)) {
|
|
|
|
if (irpStack->Parameters.QueryInterface.Size < sizeof(PCMCIA_INTERFACE_STANDARD)) {
|
|
status = STATUS_INVALID_PARAMETER;
|
|
leave;
|
|
}
|
|
|
|
//
|
|
// Ignore the version for the present
|
|
//
|
|
pcmciaInterfaceStandard = (PPCMCIA_INTERFACE_STANDARD) irpStack->Parameters.QueryInterface.Interface;
|
|
|
|
RtlZeroMemory(pcmciaInterfaceStandard, sizeof (PCMCIA_INTERFACE_STANDARD));
|
|
pcmciaInterfaceStandard->Size = sizeof(PCMCIA_INTERFACE_STANDARD);
|
|
pcmciaInterfaceStandard->Version = 1;
|
|
pcmciaInterfaceStandard->Context = Pdo;
|
|
//
|
|
// Fill in the exported functions
|
|
//
|
|
|
|
pcmciaInterfaceStandard->InterfaceReference = (PINTERFACE_REFERENCE) PcmciaNop;
|
|
pcmciaInterfaceStandard->InterfaceDereference = (PINTERFACE_DEREFERENCE) PcmciaNop;
|
|
pcmciaInterfaceStandard->ModifyMemoryWindow = PcmciaModifyMemoryWindow;
|
|
pcmciaInterfaceStandard->SetVpp = PcmciaSetVpp;
|
|
pcmciaInterfaceStandard->IsWriteProtected = PcmciaIsWriteProtected;
|
|
DebugPrint((PCMCIA_DEBUG_INTERFACE, "pdo %08x returning PCMCIA_INTERFACE_STANDARD\n", Pdo));
|
|
status = STATUS_SUCCESS;
|
|
|
|
} else if (CompareGuid(interfaceType, (PVOID) &GUID_TRANSLATOR_INTERFACE_STANDARD)
|
|
&& ((ULONG_PTR)irpStack->Parameters.QueryInterface.InterfaceSpecificData ==
|
|
CmResourceTypeInterrupt)) {
|
|
|
|
if ((Is16BitCard(pdoExtension) && !IsSocketFlagSet(pdoExtension->Socket, SOCKET_CB_ROUTE_R2_TO_PCI)) &&
|
|
//
|
|
// Eject a translator only if the controller is PCI enumerated
|
|
// (i.e. we are enumerated by PCI - so we eject a PCI-Isa translator)
|
|
//
|
|
(CardBusExtension(fdoExtension) || PciPcmciaBridgeExtension(fdoExtension))) {
|
|
|
|
PTRANSLATOR_INTERFACE translator;
|
|
ULONG busNumber;
|
|
//
|
|
// We need a translator for this PDO (16-bit pc-card) which uses
|
|
// ISA resources.
|
|
//
|
|
status = HalGetInterruptTranslator(
|
|
PCIBus,
|
|
0,
|
|
Isa,
|
|
irpStack->Parameters.QueryInterface.Size,
|
|
irpStack->Parameters.QueryInterface.Version,
|
|
(PTRANSLATOR_INTERFACE) irpStack->Parameters.QueryInterface.Interface,
|
|
&busNumber
|
|
);
|
|
}
|
|
|
|
} else if (IsDeviceMultifunction(pdoExtension) && CompareGuid(interfaceType, (PVOID)&GUID_MF_ENUMERATION_INTERFACE)) {
|
|
//
|
|
// Multifunction enumeration interface
|
|
//
|
|
PMF_ENUMERATION_INTERFACE mfEnum;
|
|
|
|
if (irpStack->Parameters.QueryInterface.Size < sizeof(MF_ENUMERATION_INTERFACE)) {
|
|
status = STATUS_INVALID_PARAMETER;
|
|
leave;
|
|
}
|
|
|
|
mfEnum = (PMF_ENUMERATION_INTERFACE) irpStack->Parameters.QueryInterface.Interface;
|
|
mfEnum->Context = pdoExtension;
|
|
mfEnum->InterfaceReference = PcmciaNop;
|
|
mfEnum->InterfaceDereference = PcmciaNop;
|
|
mfEnum->EnumerateChild = (PMF_ENUMERATE_CHILD) PcmciaMfEnumerateChild;
|
|
DebugPrint((PCMCIA_DEBUG_INTERFACE, "pdo %08x returning MF_ENUMERATION_INTERFACE\n", Pdo));
|
|
status = STATUS_SUCCESS;
|
|
|
|
} else if (CompareGuid(interfaceType, (PVOID)&GUID_PCMCIA_BUS_INTERFACE_STANDARD)) {
|
|
|
|
PPCMCIA_BUS_INTERFACE_STANDARD busInterface;
|
|
|
|
if (irpStack->Parameters.QueryInterface.Size < sizeof(PCMCIA_BUS_INTERFACE_STANDARD)) {
|
|
status = STATUS_INVALID_PARAMETER;
|
|
leave;
|
|
}
|
|
|
|
busInterface = (PPCMCIA_BUS_INTERFACE_STANDARD) irpStack->Parameters.QueryInterface.Interface;
|
|
busInterface->Context = Pdo;
|
|
busInterface->InterfaceReference = PcmciaNop;
|
|
busInterface->InterfaceDereference = PcmciaNop;
|
|
busInterface->ReadConfig = PcmciaReadCardMemory;
|
|
busInterface->WriteConfig = PcmciaWriteCardMemory;
|
|
DebugPrint((PCMCIA_DEBUG_INTERFACE, "pdo %08x returning PCMCIA_BUS_INTERFACE_STANDARD\n", Pdo));
|
|
status = STATUS_SUCCESS;
|
|
|
|
} else if (Is16BitCard(pdoExtension) && CompareGuid(interfaceType, (PVOID) &GUID_BUS_INTERFACE_STANDARD)) {
|
|
PBUS_INTERFACE_STANDARD busInterface = (PBUS_INTERFACE_STANDARD)irpStack->Parameters.QueryInterface.Interface;
|
|
|
|
if (irpStack->Parameters.QueryInterface.Size < sizeof(BUS_INTERFACE_STANDARD)) {
|
|
status = STATUS_INVALID_PARAMETER;
|
|
leave;
|
|
}
|
|
|
|
busInterface->Size = sizeof( BUS_INTERFACE_STANDARD );
|
|
busInterface->Version = 1;
|
|
busInterface->Context = Pdo;
|
|
busInterface->InterfaceReference = PcmciaNop;
|
|
busInterface->InterfaceDereference = PcmciaNop;
|
|
busInterface->TranslateBusAddress = PcmciaTranslateBusAddress;
|
|
busInterface->GetDmaAdapter = PcmciaGetDmaAdapter;
|
|
busInterface->GetBusData = PcmciaReadCardMemory;
|
|
busInterface->SetBusData = PcmciaWriteCardMemory;
|
|
DebugPrint((PCMCIA_DEBUG_INTERFACE, "pdo %08x returning BUS_INTERFACE_STANDARD\n", Pdo));
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
|
|
} finally {
|
|
|
|
if (status == STATUS_NOT_SUPPORTED) {
|
|
//
|
|
// Query Interface type not supported
|
|
//
|
|
if (pdoExtension->LowerDevice != NULL) {
|
|
PcmciaSkipCallLowerDriver(status, pdoExtension->LowerDevice, Irp);
|
|
} else {
|
|
status = Irp->IoStatus.Status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
} else {
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
ULONG
|
|
PcmciaReadCardMemory(
|
|
IN PDEVICE_OBJECT Pdo,
|
|
IN ULONG WhichSpace,
|
|
OUT PUCHAR Buffer,
|
|
IN ULONG Offset,
|
|
IN ULONG Length
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Stub for reading card memory which is exported via
|
|
PCMCIA_BUS_INTERFACE_STANDARD. This just calls the
|
|
PcmciaReadWriteCardMemory which does the real work
|
|
|
|
Note: this has to be non-paged since it can be called by
|
|
clients at DISPATCH_LEVEL
|
|
|
|
Arguments:
|
|
|
|
Pdo - Device object representing the PC-CARD whose config memory needs to be read
|
|
WhichSpace - Indicates which memory space needs to be mapped: one of
|
|
PCCARD_COMMON_MEMORY_SPACE
|
|
PCCARD_ATTRIBUTE_MEMORY_SPACE
|
|
PCCARD_PCI_CONFIGURATION_MEMORY_SPACE (only for cardbus cards)
|
|
|
|
|
|
Buffer - Caller supplied buffer into which the memory contents are copied
|
|
Offset - Offset of the attribute memory at which we copy
|
|
Length - Number of bytes of attribute memory to be copied
|
|
|
|
Return value:
|
|
|
|
Count of bytes read
|
|
|
|
--*/
|
|
{
|
|
|
|
DebugPrint((PCMCIA_DEBUG_INTERFACE, "pdo %08x read card memory\n", Pdo));
|
|
return NT_SUCCESS(PcmciaReadWriteCardMemory(Pdo, WhichSpace, Buffer, Offset, Length, TRUE)) ?
|
|
Length : 0;
|
|
}
|
|
|
|
|
|
|
|
ULONG
|
|
PcmciaWriteCardMemory(
|
|
IN PDEVICE_OBJECT Pdo,
|
|
IN ULONG WhichSpace,
|
|
IN PUCHAR Buffer,
|
|
IN ULONG Offset,
|
|
IN ULONG Length
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Stub for writing to card memory which is exported via
|
|
PCMCIA_BUS_INTERFACE_STANDARD. This just calls
|
|
PcmciaReadWriteCardMemory which does the real work
|
|
|
|
Note: this has to be non-paged since it can be called by
|
|
clients at DISPATCH_LEVEL
|
|
|
|
Arguments:
|
|
|
|
Pdo - Device object representing the PC-CARD whose config memory needs to be written to
|
|
WhichSpace - Indicates which memory space needs to be mapped: one of
|
|
PCCARD_COMMON_MEMORY_SPACE
|
|
PCCARD_ATTRIBUTE_MEMORY_SPACE
|
|
PCCARD_PCI_CONFIGURATION_MEMORY_SPACE (only for cardbus cards)
|
|
|
|
|
|
Buffer - Caller supplied buffer out of which the memory contents are copied
|
|
Offset - Offset of the attribute memory at which we copy
|
|
Length - Number of bytes of buffer to be copied
|
|
|
|
Return value:
|
|
|
|
Count of bytes written
|
|
|
|
--*/
|
|
{
|
|
|
|
DebugPrint((PCMCIA_DEBUG_INTERFACE, "pdo %08x write card memory\n", Pdo));
|
|
return NT_SUCCESS(PcmciaReadWriteCardMemory(Pdo, WhichSpace, Buffer, Offset, Length, FALSE)) ?
|
|
Length : 0;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
PcmciaModifyMemoryWindow(
|
|
IN PDEVICE_OBJECT Pdo,
|
|
IN ULONGLONG HostBase,
|
|
IN ULONGLONG CardBase,
|
|
IN BOOLEAN Enable,
|
|
IN ULONG WindowSize OPTIONAL,
|
|
IN UCHAR AccessSpeed OPTIONAL,
|
|
IN UCHAR BusWidth OPTIONAL,
|
|
IN BOOLEAN IsAttributeMemory OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Part of the interfaces originally developed to
|
|
support flash memory cards.
|
|
|
|
This routine enables the caller to 'slide' the supplied
|
|
host memory window across the given (16-bit)pc-card's card memory.
|
|
i.e. the host memory window will be modified to map
|
|
the pc-card at a new card memory offset
|
|
|
|
Arguments:
|
|
|
|
Pdo - Pointer to the device object for the PC-Card
|
|
|
|
HostBase - Host memory window base to be mapped
|
|
|
|
CardBase - Mandatory if Enable is TRUE
|
|
New card memory offset to map the host memory window
|
|
to
|
|
|
|
Enable - If this is FALSE - all the remaining arguments
|
|
are ignored and the host window will simply be
|
|
disabled
|
|
|
|
WindowSize - Specifies the size of the host memory window to
|
|
be mapped. Note this must be at the proper alignment
|
|
and must be less than or equal to the originally
|
|
allocated window size for the host base.
|
|
If this is zero, the originally allocated window
|
|
size will be used.
|
|
|
|
AccessSpeed - Mandatory if Enable is TRUE
|
|
Specifies the new access speed for the pc-card.
|
|
(AccessSpeed should be encoded as per the pc-card
|
|
standard, card/socket services spec)
|
|
|
|
BusWidth - Mandatory if Enable is TRUE
|
|
One of PCMCIA_MEMORY_8BIT_ACCESS
|
|
or PCMCIA_MEMORY_16BIT_ACCESS
|
|
|
|
IsAttributeMemory - Mandatory if Enable is TRUE
|
|
Specifies if the window should be mapped
|
|
to the pc-card's attribute or common memory
|
|
|
|
|
|
Return Value:
|
|
|
|
TRUE - Memory window was enabled/disabled as requested
|
|
FALSE - If not
|
|
|
|
--*/
|
|
{
|
|
PPDO_EXTENSION pdoExtension;
|
|
PSOCKET socket;
|
|
|
|
pdoExtension = Pdo->DeviceExtension;
|
|
socket = pdoExtension->Socket;
|
|
|
|
DebugPrint((PCMCIA_DEBUG_INTERFACE, "pdo %08x modify memory window\n", Pdo));
|
|
if (socket->SocketFnPtr->PCBModifyMemoryWindow == NULL) {
|
|
return FALSE;
|
|
} else {
|
|
return (*(socket->SocketFnPtr->PCBModifyMemoryWindow))(Pdo, HostBase, CardBase, Enable,
|
|
WindowSize, AccessSpeed, BusWidth,
|
|
IsAttributeMemory);
|
|
}
|
|
}
|
|
|
|
BOOLEAN
|
|
PcmciaSetVpp(
|
|
IN PDEVICE_OBJECT Pdo,
|
|
IN UCHAR VppLevel
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Part of the interfaces originally developed to
|
|
support flash memory cards.
|
|
Sets VPP1 to the required setting
|
|
|
|
Arguments
|
|
|
|
Pdo - Pointer to device object for the PC-Card
|
|
Vpp - Desired Vpp setting. This is currently one of
|
|
PCMCIA_VPP_12V (12 volts)
|
|
PCMCIA_VPP_0V (disable VPP)
|
|
PCMCIA_VPP_IS_VCC (route VCC to VPP)
|
|
|
|
Return
|
|
|
|
TRUE - if successful
|
|
FALSE - if not. This will be returned if the
|
|
PC-Card is not already powered up
|
|
--*/
|
|
{
|
|
PPDO_EXTENSION pdoExtension;
|
|
PSOCKET socket;
|
|
|
|
pdoExtension = Pdo->DeviceExtension;
|
|
socket = pdoExtension->Socket;
|
|
|
|
DebugPrint((PCMCIA_DEBUG_INTERFACE, "pdo %08x set vpp\n", Pdo));
|
|
if (socket->SocketFnPtr->PCBSetVpp == NULL) {
|
|
return FALSE;
|
|
} else {
|
|
return (*(socket->SocketFnPtr->PCBSetVpp))(Pdo, VppLevel);
|
|
}
|
|
}
|
|
|
|
BOOLEAN
|
|
PcmciaIsWriteProtected(
|
|
IN PDEVICE_OBJECT Pdo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Part of the interfaces originally developed to
|
|
support flash memory cards.
|
|
|
|
Returns the status of the write protected pin
|
|
for the given PC-Card
|
|
|
|
Arguments:
|
|
|
|
Pdo - Pointer to the device object for the PC-Card
|
|
|
|
Return Value:
|
|
|
|
TRUE - if the PC-Card is write-protected
|
|
FALSE - if not
|
|
|
|
--*/
|
|
{
|
|
PPDO_EXTENSION pdoExtension;
|
|
PSOCKET socket;
|
|
|
|
pdoExtension = Pdo->DeviceExtension;
|
|
socket = pdoExtension->Socket;
|
|
|
|
DebugPrint((PCMCIA_DEBUG_INTERFACE, "pdo %08x is write protected \n", Pdo));
|
|
if (socket->SocketFnPtr->PCBIsWriteProtected == NULL) {
|
|
return FALSE;
|
|
} else {
|
|
return (*(socket->SocketFnPtr->PCBIsWriteProtected))(Pdo);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN
|
|
PcmciaTranslateBusAddress(
|
|
IN PVOID Context,
|
|
IN PHYSICAL_ADDRESS BusAddress,
|
|
IN ULONG Length,
|
|
IN OUT PULONG AddressSpace,
|
|
OUT PPHYSICAL_ADDRESS TranslatedAddress
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
This function is used to translate bus addresses from legacy drivers.
|
|
|
|
Arguments
|
|
|
|
Context - Supplies a pointer to the interface context. This is actually
|
|
the PDO for the root bus.
|
|
|
|
BusAddress - Supplies the orginal address to be translated.
|
|
|
|
Length - Supplies the length of the range to be translated.
|
|
|
|
AddressSpace - Points to the location of of the address space type such as
|
|
memory or I/O port. This value is updated by the translation.
|
|
|
|
TranslatedAddress - Returns the translated address.
|
|
|
|
Return Value
|
|
|
|
Returns a boolean indicating if the operations was a success.
|
|
|
|
--*/
|
|
{
|
|
return HalTranslateBusAddress(Isa,
|
|
0,
|
|
BusAddress,
|
|
AddressSpace,
|
|
TranslatedAddress);
|
|
}
|
|
|
|
|
|
|
|
PDMA_ADAPTER
|
|
PcmciaGetDmaAdapter(
|
|
IN PVOID Context,
|
|
IN struct _DEVICE_DESCRIPTION *DeviceDescriptor,
|
|
OUT PULONG NumberOfMapRegisters
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Passes IoGetDmaAdapter calls to the parent.
|
|
|
|
Arguments
|
|
|
|
Context - Supplies a pointer to the interface context. This is actually the PDO.
|
|
|
|
DeviceDescriptor - Supplies the device descriptor used to allocate the dma
|
|
adapter object.
|
|
|
|
NubmerOfMapRegisters - Returns the maximum number of map registers a device
|
|
can allocate at one time.
|
|
|
|
Return Value
|
|
|
|
Returns a DMA adapter or NULL.
|
|
|
|
--*/
|
|
{
|
|
PDEVICE_OBJECT Pdo = Context;
|
|
PPDO_EXTENSION pdoExtension;
|
|
PFDO_EXTENSION fdoExtension;
|
|
|
|
pdoExtension = Pdo->DeviceExtension;
|
|
|
|
if (!pdoExtension || !pdoExtension->Socket || !pdoExtension->Socket->DeviceExtension) {
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Get the parent FDO extension
|
|
//
|
|
fdoExtension = pdoExtension->Socket->DeviceExtension;
|
|
|
|
//
|
|
// Pass the call on to the parent
|
|
//
|
|
return IoGetDmaAdapter(fdoExtension->Pdo,
|
|
DeviceDescriptor,
|
|
NumberOfMapRegisters);
|
|
}
|
|
|
|
|
|
VOID
|
|
PcmciaNop(
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Does nothing
|
|
|
|
Arguments
|
|
|
|
none
|
|
|
|
Return Value
|
|
|
|
none
|
|
|
|
--*/
|
|
{
|
|
PAGED_CODE();
|
|
UNREFERENCED_PARAMETER(Context);
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
PcmciaMfEnumerateChild(
|
|
IN PPDO_EXTENSION PdoExtension,
|
|
IN ULONG Index,
|
|
OUT PMF_DEVICE_INFO ChildInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Returns required enumeration information for the multifunction children
|
|
of the given pc-card. This fills in the required info. for the child
|
|
indicated, returing STATUS_NO_MORE_ENTRIES when there are no more
|
|
children to be enumerated
|
|
|
|
Arguments
|
|
|
|
PdoExtension - Pointer to the device extension for the multifunction parent pc-card
|
|
Index - Zero based index for the child to be enumerated
|
|
ChildInfo - Caller allocated buffer in which the info about the child is returned.
|
|
We may allocate additional buffers for each field in the supplied
|
|
structure. This will be freed by the caller when no longer needed
|
|
|
|
Return value
|
|
|
|
STATUS_SUCCESS - supplied child info filled in & returned
|
|
STATUS_NO_MORE_ENTRIES - No child of the given index exists. Caller is
|
|
assumed to iteratively call this routine with index incremented
|
|
from 0 upwards till this status value is returned
|
|
STATUS_NO_SUCH_DEVICE - if the pc-card no longer exists
|
|
--*/
|
|
{
|
|
PSOCKET socket;
|
|
PSOCKET_DATA socketData;
|
|
PCONFIG_ENTRY configEntry, mfConfigEntry;
|
|
ULONG i, currentIndex, count;
|
|
NTSTATUS status;
|
|
UCHAR iRes;
|
|
PUCHAR idString;
|
|
ANSI_STRING ansiString;
|
|
|
|
PAGED_CODE();
|
|
|
|
DebugPrint((PCMCIA_DEBUG_INTERFACE,
|
|
"PcmciaMfEnumerateChild: parent ext %x child index %x\n",
|
|
PdoExtension,
|
|
Index
|
|
));
|
|
try {
|
|
if (IsDeviceDeleted(PdoExtension) ||
|
|
IsDeviceLogicallyRemoved(PdoExtension)) {
|
|
//
|
|
// This pdo is deleted or marked to be deleted
|
|
//
|
|
status = STATUS_NO_SUCH_DEVICE;
|
|
leave;
|
|
}
|
|
|
|
socket = PdoExtension->Socket;
|
|
ASSERT (socket != NULL);
|
|
|
|
RtlZeroMemory(ChildInfo, sizeof(MF_DEVICE_INFO));
|
|
|
|
if (Index >= socket->NumberOfFunctions) {
|
|
//
|
|
// info requested for a child which doesn't exist
|
|
//
|
|
status = STATUS_NO_MORE_ENTRIES;
|
|
leave;
|
|
}
|
|
|
|
//
|
|
// Fill in the name field
|
|
// This is of the form ChildXX
|
|
// where XX is the number of the function
|
|
// Examples: Child00, Child01 etc.
|
|
//
|
|
idString = (PUCHAR) ExAllocatePool(PagedPool, PCMCIA_MAXIMUM_DEVICE_ID_LENGTH);
|
|
if (!idString) {
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
leave;
|
|
}
|
|
sprintf(idString, "Child%02x", Index);
|
|
RtlInitAnsiString(&ansiString, idString);
|
|
status = RtlAnsiStringToUnicodeString(&ChildInfo->Name,
|
|
&ansiString,
|
|
TRUE);
|
|
ExFreePool(idString);
|
|
if (!NT_SUCCESS(status)) {
|
|
leave;
|
|
}
|
|
|
|
//
|
|
// Get compatible ids
|
|
//
|
|
status = PcmciaGetCompatibleIds(PdoExtension->DeviceObject,
|
|
Index,
|
|
&ChildInfo->CompatibleID);
|
|
if (!NT_SUCCESS(status)) {
|
|
leave;
|
|
}
|
|
|
|
//
|
|
// Get hardware ids
|
|
//
|
|
status = PcmciaGetHardwareIds(PdoExtension->DeviceObject,
|
|
Index,
|
|
&ChildInfo->HardwareID);
|
|
if (!NT_SUCCESS(status)) {
|
|
leave;
|
|
}
|
|
|
|
//
|
|
// Fill in the resource map stuff
|
|
//
|
|
// Locate the socket data structure corresponding to this function
|
|
for (socketData = PdoExtension->SocketData, i=0; (socketData != NULL) && (i != Index); socketData=socketData->Next, i++);
|
|
|
|
if (!socketData) {
|
|
//
|
|
// this condition should never be encountered
|
|
//
|
|
ASSERT (FALSE);
|
|
status = STATUS_NO_MORE_ENTRIES;
|
|
leave;
|
|
}
|
|
|
|
if (!(socketData->NumberOfConfigEntries > 0)) {
|
|
//
|
|
// No resource map required
|
|
//
|
|
status = STATUS_SUCCESS;
|
|
leave;
|
|
}
|
|
|
|
count = (socketData->MfNeedsIrq ? 1 : 0) + socketData->MfIoPortCount + socketData->MfMemoryCount;
|
|
if (count == 0) {
|
|
ASSERT(FALSE);
|
|
//
|
|
// No resource map required
|
|
//
|
|
status = STATUS_SUCCESS;
|
|
leave;
|
|
}
|
|
|
|
//
|
|
// Allocate resource map
|
|
//
|
|
ChildInfo->ResourceMap = ExAllocatePool(PagedPool,
|
|
sizeof(MF_RESOURCE_MAP) + (count-1) * sizeof(UCHAR));
|
|
if (!ChildInfo->ResourceMap) {
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
leave;
|
|
}
|
|
|
|
ChildInfo->ResourceMap->Count = count;
|
|
//
|
|
// Compute the resource map indices
|
|
// The config entry *already* contains fields (MfIrqResourceMapIndex, MfIoPortResourceMapIndex etc.)
|
|
// which indicate the relative index of the resource requested for this function within the resource type.
|
|
// We calculate the absolute index by adding up the number of instances of each resource type requested,
|
|
// preceding the current resource type, to this relative index.
|
|
//
|
|
currentIndex = 0;
|
|
//
|
|
// Fill the irq map if there's one
|
|
//
|
|
if (socketData->MfNeedsIrq) {
|
|
ChildInfo->ResourceMap->Resources[currentIndex++] = socketData->MfIrqResourceMapIndex;
|
|
}
|
|
//
|
|
// Fill the i/o port map if there's one
|
|
//
|
|
if (socketData->MfIoPortCount) {
|
|
for (iRes=0; iRes<socketData->MfIoPortCount; iRes++) {
|
|
|
|
ChildInfo->ResourceMap->Resources[currentIndex++] = socketData->MfIoPortResourceMapIndex + iRes;
|
|
|
|
}
|
|
}
|
|
//
|
|
// Fill the memory request map if there's one
|
|
//
|
|
if (socketData->MfMemoryCount) {
|
|
for (iRes=0; iRes<socketData->MfMemoryCount; iRes++) {
|
|
|
|
ChildInfo->ResourceMap->Resources[currentIndex++] = socketData->MfMemoryResourceMapIndex + iRes;
|
|
|
|
}
|
|
}
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
} finally {
|
|
if (!NT_SUCCESS(status)) {
|
|
//
|
|
// Free up all the allocated buffers
|
|
//
|
|
if (ChildInfo->Name.Buffer) {
|
|
ExFreePool(ChildInfo->Name.Buffer);
|
|
}
|
|
|
|
if (ChildInfo->CompatibleID.Buffer) {
|
|
ExFreePool(ChildInfo->CompatibleID.Buffer);
|
|
}
|
|
|
|
if (ChildInfo->HardwareID.Buffer) {
|
|
ExFreePool(ChildInfo->HardwareID.Buffer);
|
|
}
|
|
|
|
if (ChildInfo->ResourceMap) {
|
|
ExFreePool(ChildInfo->ResourceMap);
|
|
}
|
|
|
|
if (ChildInfo->VaryingResourceMap) {
|
|
ExFreePool(ChildInfo->ResourceMap);
|
|
}
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
PcmciaGetInterface(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN CONST GUID *pGuid,
|
|
IN USHORT sizeofInterface,
|
|
OUT PINTERFACE pInterface
|
|
)
|
|
/*
|
|
|
|
Routine Description
|
|
|
|
Gets the interface exported by PCI for enumerating 32-bit cardbus cards, which
|
|
appear as regular PCI devices. This interface will be used to respond during
|
|
subsequent enumeration requests from PnP to invoke PCI to enumerate the cards.
|
|
|
|
Arguments
|
|
|
|
Pdo - Pointer to physical device object for the cardbus controller
|
|
PciCardBusInterface - Pointer to the PCI-Cardbus interface will be returned
|
|
in this variable
|
|
|
|
Return Value
|
|
|
|
Status
|
|
|
|
*/
|
|
|
|
{
|
|
KEVENT event;
|
|
PIRP irp;
|
|
NTSTATUS status;
|
|
IO_STATUS_BLOCK statusBlock;
|
|
PIO_STACK_LOCATION irpSp;
|
|
|
|
PAGED_CODE();
|
|
|
|
KeInitializeEvent (&event, NotificationEvent, FALSE);
|
|
irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
|
|
DeviceObject,
|
|
NULL,
|
|
0,
|
|
0,
|
|
&event,
|
|
&statusBlock
|
|
);
|
|
|
|
irp->IoStatus.Status = STATUS_NOT_SUPPORTED ;
|
|
irp->IoStatus.Information = 0;
|
|
|
|
irpSp = IoGetNextIrpStackLocation(irp);
|
|
|
|
irpSp->MinorFunction = IRP_MN_QUERY_INTERFACE;
|
|
|
|
irpSp->Parameters.QueryInterface.InterfaceType= pGuid;
|
|
irpSp->Parameters.QueryInterface.Size = sizeofInterface;
|
|
irpSp->Parameters.QueryInterface.Version = 1;
|
|
irpSp->Parameters.QueryInterface.Interface = pInterface;
|
|
|
|
status = IoCallDriver(DeviceObject, irp);
|
|
|
|
if (status == STATUS_PENDING) {
|
|
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
|
|
status = statusBlock.Status;
|
|
}
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((PCMCIA_DEBUG_INFO, "GetInterface failed with status %x\n", status));
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
PcmciaUpdateInterruptLine(
|
|
IN PPDO_EXTENSION PdoExtension,
|
|
IN PFDO_EXTENSION FdoExtension
|
|
)
|
|
/*
|
|
|
|
Routine Description
|
|
|
|
This routine uses the PCI Irq Routing interface to update the raw interrupt
|
|
line of a cardbus card. This is done in order to allow cardbus cards to run
|
|
on non-acpi machines without pci irq routing, as long as the bios supplies
|
|
the interrupt for the cardbus controller.
|
|
|
|
Arguments
|
|
|
|
PdoExtension - Pointer to the extension for the cardbus card
|
|
FdoExtension - Pointer to the extension for the cardbus controller
|
|
|
|
Return Value
|
|
|
|
Status
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
if (!IsDeviceFlagSet(FdoExtension, PCMCIA_INT_ROUTE_INTERFACE)) {
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
if (FdoExtension->Configuration.Interrupt.u.Interrupt.Vector == 0) {
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
(FdoExtension->PciIntRouteInterface.UpdateInterruptLine)(PdoExtension->PciPdo,
|
|
(UCHAR) FdoExtension->Configuration.Interrupt.u.Interrupt.Vector);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|