Microsoft KB Archive/308038

= How to access attribute memory of PC Cards =

Article ID: 308038

Article Last Modified on 7/14/2005

-

APPLIES TO


 * Microsoft Windows Server 2003 Driver Development Kit
 * Microsoft Win32 Device Driver Kit for Windows 2000
 * Microsoft Windows XP Driver Development Kit
 * Microsoft Windows 2000 Standard Edition
 * Microsoft Windows XP Professional

-



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((&quot;GetPciBusInterfaceStandard entered.\n&quot;));

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.

