How to access attribute memory of PC Cards (308038)
The information in this article applies to:
- Microsoft Windows Server 2003 Driver Development Kit (DDK)
- Microsoft Windows 2000 Driver Development Kit (DDK)
- Microsoft Windows XP Driver Development Kit (DDK)
- the operating system: Microsoft Windows 2000
- the operating system: Microsoft Windows XP
This article was previously published under Q308038 SUMMARY
This article demonstrates through code how a PC Card driver can use the BUS_INTERFACE_STANDARD interface approach to access the attribute memory at IRQL less than or equal to DISPTACH_LEVEL.
MORE INFORMATION
A function device driver of a PC Card might need to access the card attribute memory for many reasons such as:
- A need to obtain information about the card itself from the card information structure (CIS), which is typically located at the beginning of the attribute memory but can alternatively be located in common memory address space. Such information includes card identity and device type and characteristics, among other things.
- Some PC Card devices use configuration registers (standard registers and possibly manufacturer-specific registers), which are located in attribute memory. Some of the standard configuration registers are required by I/O cards but optional for memory cards. Drivers must typically directly access these registers within an interrupt service routine (ISR), for example to read the configuration status register (CSR) to verify that an interrupt request is pending and, in the case of single function cards, clear the interrupt request. Another example is a driver accessing a manufacturer-specific register for control purposes.
The driver must initially obtain a BUS_INTERFACE_STANDARD interface from the PCMCIA bus driver by sending a plug-and-play request to the physical device object (PDO) (IRP_MN_QUERY_INTERFACE) at IRQL PASSIVE_LEVEL.
NTSTATUS
GetBusInterfaceStandard(
IN PDEVICE_OBJECT DeviceObject,
OUT PBUS_INTERFACE_STANDARD BusInterfaceStandard
)
/*++
Routine Description:
This routine gets the bus interface standard information from the PDO.
Arguments:
DeviceObject - Device object to query for this information.
BusInterface - Supplies a pointer to the retrieved information.
Return Value:
NT status.
--*/
{
KEVENT event;
NTSTATUS status;
PIRP irp;
IO_STATUS_BLOCK ioStatusBlock;
PIO_STACK_LOCATION irpStack;
PDEVICE_OBJECT targetObject;
Bus_KdPrint(("GetPciBusInterfaceStandard entered.\n"));
KeInitializeEvent( &event, NotificationEvent, FALSE );
targetObject = IoGetAttachedDeviceReference( DeviceObject );
irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP,
targetObject,
NULL,
0,
NULL,
&event,
&ioStatusBlock );
if (irp == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto End;
}
irpStack = IoGetNextIrpStackLocation( irp );
irpStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
irpStack->Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_BUS_INTERFACE_STANDARD ;
irpStack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);
irpStack->Parameters.QueryInterface.Version = 1;
irpStack->Parameters.QueryInterface.Interface = (PINTERFACE)BusInterfaceStandard;
irpStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
//
// Initialize the status to error in case the bus driver does not
// set it correctly.
//
irp->IoStatus.Status = STATUS_NOT_SUPPORTED ;
status = IoCallDriver( targetObject, irp );
if (status == STATUS_PENDING) {
KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL );
status = ioStatusBlock.Status;
}
End:
//
// Done with reference
//
ObDereferenceObject( targetObject );
return status;
}
Once you get the PCMCIA bus interface, you can use its interface routines GetBusData or SetBusData to access the attribute memory. Data is written only to even bytes in the attribute memory. Therefore, when accessing the PC Card tuples in the attribute memory, the offset specified in the calls to GetBusData or SetBusData is a 16-bit offset and not an 8-bit offset. For example, if you need to access byte 60 (from the base of the attribute memory), then an offset value of 30 should be used. The bus driver takes care of the translation (multiplying by 2). It was designed this way to prevent access to the odd bytes.
// Read the Configuration Status Register data
ULONG valueRead;
UCHAR tupleData;
ULONG offset = CSR_OFFSET // If CSR is located at byte X from attribute memory base, then use an offset value of X/2
valueRead = (BusInterfaceStandard->GetBusData)(PDO, PCCARD_ATTRIBUTE_MEMORY, &tupleData, offset, 1);
Similarly, SetBusData can be used for writing.
REFERENCES
For more information, click the following article number to view the article in the Microsoft Knowledge Base:
253232
How to get configuration and location information of PCI device
Modification Type: | Major | Last Reviewed: | 7/14/2005 |
---|
Keywords: | kbfile kbhowto kbKMode kbPlugPlay kbWDM KB308038 kbAudDeveloper |
---|
|