|
|
/*++
Copyright (c) 2002 Microsoft Corporation
Module Name:
sdbus.h
Abstract:
Author:
Neil Sandlin (neilsa) 1-Jan-2002
Revision History
--*/
#ifndef _SDBUS_H_
#define _SDBUS_H_
typedef enum _DEVICE_OBJECT_TYPE { FDO = 0, PDO } DEVICE_OBJECT_TYPE;
//
// Type of the controller
//
typedef ULONG SDBUS_CONTROLLER_TYPE, *PSDBUS_CONTROLLER_TYPE;
struct _FDO_EXTENSION; struct _PDO_EXTENSION; struct _SD_WORK_PACKET;
//
// Io Worker States
//
typedef enum { WORKER_IDLE = 0, PACKET_PENDING, IN_PROCESS, WAITING_FOR_TIMER } WORKER_STATE;
//
// socket enumeration states
//
typedef enum { SOCKET_EMPTY = 0, CARD_DETECTED, CARD_NEEDS_ENUMERATION, CARD_ACTIVE, CARD_LOGICALLY_REMOVED } SOCKET_STATE;
//
// Define SynchronizeExecution routine.
//
typedef BOOLEAN (*PSYNCHRONIZATION_ROUTINE) ( IN PKINTERRUPT Interrupt, IN PKSYNCHRONIZE_ROUTINE Routine, IN PVOID SynchronizeContext );
//
// Completion routine called by various timed routines
//
typedef VOID (*PSDBUS_COMPLETION_ROUTINE) ( IN PDEVICE_OBJECT DeviceObject, IN PVOID Context );
typedef VOID (*PSDBUS_ACTIVATE_COMPLETION_ROUTINE) ( IN PDEVICE_OBJECT DeviceObject, IN PVOID Context, IN NTSTATUS Status );
//
// SD_FUNCTION_BLOCK allows for a level of indirection, thereby allowing
// the top-level SDBUS code to do it's work without worrying about who's
// particular brand of SD controller it's addressing.
//
typedef struct _SD_FUNCTION_BLOCK {
//
// Function to initialize controller. This is done once after
// the host controller is started, or powered on.
//
VOID (*InitController)( IN struct _FDO_EXTENSION *FdoExtension );
//
// Function to initialize SD function. This is done once after
// the function is started.
//
VOID (*InitFunction)( IN struct _FDO_EXTENSION *FdoExtension, IN struct _PDO_EXTENSION *PdoExtension );
//
// function to set power for a socket
//
NTSTATUS (*SetPower)( IN struct _FDO_EXTENSION *FdoExtension, IN BOOLEAN Enable, OUT PULONG pDelayTime );
//
// function to set reset an SD card
//
NTSTATUS (*ResetHost)( IN struct _FDO_EXTENSION *FdoExtension, IN UCHAR Phase, OUT PULONG pDelayTime ); //
// function to control the external LED
//
VOID (*SetLED)( IN struct _FDO_EXTENSION *FdoExtension, IN BOOLEAN Enable ); //
// Switch focus between IO function or memory function
//
VOID (*SetFunctionType)( IN struct _FDO_EXTENSION *FdoExtension, UCHAR FunctionType );
//
// Function to determine if a card is in the socket
//
BOOLEAN (*DetectCardInSocket)( IN struct _FDO_EXTENSION *FdoExtension );
BOOLEAN (*IsWriteProtected)( IN struct _FDO_EXTENSION *FdoExtension );
NTSTATUS (*CheckStatus)( IN struct _FDO_EXTENSION *FdoExtension );
NTSTATUS (*SendSDCommand)( IN struct _FDO_EXTENSION *FdoExtension, IN struct _SD_WORK_PACKET *WorkPacket );
NTSTATUS (*GetSDResponse)( IN struct _FDO_EXTENSION *FdoExtension, IN struct _SD_WORK_PACKET *WorkPacket );
//
// Interfaces for block memory operations
//
VOID (*StartBlockOperation)( IN struct _FDO_EXTENSION *FdoExtension ); VOID (*SetBlockParameters)( IN struct _FDO_EXTENSION *FdoExtension, IN USHORT SectorCount ); VOID (*EndBlockOperation)( IN struct _FDO_EXTENSION *FdoExtension );
//
// Copy a sector from the data port to a buffer
//
VOID (*ReadDataPort)( IN struct _FDO_EXTENSION *FdoExtension, IN PUCHAR Buffer, IN ULONG Length ); //
// Copy a sector from a buffer to the data port
//
VOID (*WriteDataPort)( IN struct _FDO_EXTENSION *FdoExtension, IN PUCHAR Buffer, IN ULONG Length );
//
// Function to enable/disable status change interrupts
//
VOID (*EnableEvent)( IN struct _FDO_EXTENSION *FdoExtension, IN ULONG EventMask );
VOID (*DisableEvent)( IN struct _FDO_EXTENSION *FdoExtension, IN ULONG EventMask ); //
// vendor-specific function to handle interrupts
//
ULONG (*GetPendingEvents)( IN struct _FDO_EXTENSION *FdoExtension );
VOID (*AcknowledgeEvent)( IN struct _FDO_EXTENSION *FdoExtension, IN ULONG EventMask ); } SD_FUNCTION_BLOCK, *PSD_FUNCTION_BLOCK;
//
// Enumeration structures
//
#define MAX_MANFID_LENGTH 64
#define MAX_IDENT_LENGTH 64
typedef struct _SD_FUNCTION_DATA { struct _SD_FUNCTION_DATA *Next; //
// Function Number
//
UCHAR Function;
ULONG CardPsn; ULONG CsaSize; ULONG Ocr; UCHAR IoDeviceInterface; } SD_FUNCTION_DATA, *PSD_FUNCTION_DATA;
typedef struct _SD_CARD_DATA {
UCHAR MfgText[MAX_MANFID_LENGTH]; UCHAR ProductText[MAX_IDENT_LENGTH];
USHORT MfgId; USHORT MfgInfo;
//
// SD Io card parameters
//
UCHAR CardCapabilities;
//
// SD Memory Card parameters
//
SD_CID SdCid; SD_CSD SdCsd; UCHAR ProductName[6];
//
// array of per-function data
//
PSD_FUNCTION_DATA FunctionData; } SD_CARD_DATA, *PSD_CARD_DATA;
//
// Synchronization primitives
//
#define SDBUS_TEST_AND_SET(X) (InterlockedCompareExchange(X, 1, 0) == 0)
#define SDBUS_TEST_AND_RESET(X) (InterlockedCompareExchange(X, 0, 1) == 1)
//
// Power
//
typedef struct _SD_POWER_CONTEXT { PSDBUS_COMPLETION_ROUTINE CompletionRoutine; PVOID Context; } SD_POWER_CONTEXT, *PSD_POWER_CONTEXT;
typedef struct _SD_ACTIVATE_CONTEXT { PSDBUS_ACTIVATE_COMPLETION_ROUTINE CompletionRoutine; PVOID Context; } SD_ACTIVATE_CONTEXT, *PSD_ACTIVATE_CONTEXT;
//
// Functional Device Object's device extension information
//
// There is one device object for each SDBUS socket controller
// located in the system. This contains the root pointers for
// each of the lists of information on this controller.
//
//
// Flags common to both fdoExtension and pdoExtension
//
#define SDBUS_DEVICE_STARTED 0x00000001
#define SDBUS_DEVICE_LOGICALLY_REMOVED 0x00000002
#define SDBUS_DEVICE_PHYSICALLY_REMOVED 0x00000004
#define SDBUS_DEVICE_WAKE_PENDING 0x00000010
#define SDBUS_DEVICE_DELETED 0x00000040
//
// Flags indicating controller state (fdoExtension)
//
#define SDBUS_HOST_REGISTER_BASE_MAPPED 0x00010000
#define SDBUS_FDO_CONTEXT_SAVED 0x00020000
#define SDBUS_FDO_OFFLINE 0x00040000
#define SDBUS_FDO_WAKE_BY_CD 0x00080000
#define SDBUS_FDO_WORK_ITEM_ACTIVE 0x00100000
//
// Flags indicating interrupt status
//
#define SDBUS_EVENT_INSERTION 0x00000001
#define SDBUS_EVENT_REMOVAL 0x00000002
#define SDBUS_EVENT_CARD_RESPONSE 0x00000004
#define SDBUS_EVENT_CARD_RW_END 0x00000008
#define SDBUS_EVENT_BUFFER_EMPTY 0x00000010
#define SDBUS_EVENT_BUFFER_FULL 0x00000020
#define SDBUS_EVENT_CARD_INTERRUPT 0x00000040
#define SDBUS_EVENT_ALL 0xFFFFFFFF
//
// Flags indicating what type of function is currently being addressed
//
#define SDBUS_FUNCTION_TYPE_MEMORY 1
#define SDBUS_FUNCTION_TYPE_IO 2
//
// FDO Flags
//
#define SDBUS_FDO_EXTENSION_SIGNATURE 'FmcP'
//
// Device extension for the functional device object for sd controllers
//
typedef struct _FDO_EXTENSION { ULONG Signature; //
// Pointer to the next sd controller's FDO in the central list
// of all sd controller managed by this driver.
// The head of the list is pointed to by the global variable FdoList
//
PDEVICE_OBJECT NextFdo; //
// The PDO ejected by the parent bus driver for this sd controller
//
//
PDEVICE_OBJECT Pdo; //
// The immediately lower device attached beneath the sd controller's FDO.
// This would be the same as the Pdo above, excepting in cases when there are
// lower filter drivers for the sd controller - like the ACPI driver
//
PDEVICE_OBJECT LowerDevice; //
// Pointer to the miniport-like
//
PSD_FUNCTION_BLOCK FunctionBlock; //
// Various flags used to track the state of this
// (flags prefixed by SDBUS_ above)
//
ULONG Flags; //
// Type of the controller. We need to know this since this is
// a monolithic driver. We can do controller specific stuff
// based on the type if needed.
//
SDBUS_CONTROLLER_TYPE ControllerType; //
// Index into the device dispatch table for vendor-specific
// controller functions
//
ULONG DeviceDispatchIndex;
PDEVICE_OBJECT DeviceObject; PDRIVER_OBJECT DriverObject; PUNICODE_STRING RegistryPath; //
// Kernel objects to handle Io processing
//
KTIMER WorkerTimer; KDPC WorkerTimeoutDpc; //
// This field holds the "current work packet" so that the timeout
// dpc can pass it back to the worker routine
//
struct _SD_WORK_PACKET *TimeoutPacket; KDPC WorkerDpc;
WORKER_STATE WorkerState; KSPIN_LOCK WorkerSpinLock;
LIST_ENTRY SystemWorkPacketQueue; LIST_ENTRY IoWorkPacketQueue;
//
// Io workitem to execute card functions at passive level
//
PIO_WORKITEM IoWorkItem; KEVENT CardInterruptEvent; KEVENT WorkItemExitEvent;
//
// Sequence number for event logging
//
ULONG SequenceNumber;
//
// Pointer to the interrupt object - if we use interrupt based
// card status change detection
//
PKINTERRUPT SdbusInterruptObject;
//
// IsrEventStatus is the hardware state. It is accessed only at DIRQL
//
ULONG IsrEventStatus; //
// LatchedIsrEventStatus is pulled from IsrEventStatus synchronously. It is
// used by the ISR's DPC to reflect new hardware events.
//
ULONG LatchedIsrEventStatus; //
// WorkerEventEventStatus is the set of events pending to be reflected to
// the io worker engine
//
ULONG WorkerEventStatus; //
// Keeps track of currently enabled events
//
ULONG CurrentlyEnabledEvents; //
// These are the card events we would like to see
//
ULONG CardEvents; //
// Power management related stuff.
//
//
// Current power states
//
SYSTEM_POWER_STATE SystemPowerState; DEVICE_POWER_STATE DevicePowerState; //
// Indicates device busy
//
ULONG PowerStateInTransition; //
// Indicates how many children (pc-cards) are pending on an
// IRP_MN_WAIT_WAKE
//
ULONG ChildWaitWakeCount; //
// Device capabilities as reported by our bus driver
//
DEVICE_CAPABILITIES DeviceCapabilities; //
// Pending wait wake Irp
//
PIRP WaitWakeIrp; LONG WaitWakeState;
//
// PCI Bus interface standard
// This contains interfaces to read/write from PCI config space
// of the cardbus controller, among other stuff..
//
BUS_INTERFACE_STANDARD PciBusInterface; //
// Configuration resources for the sd controller
//
CM_PARTIAL_RESOURCE_DESCRIPTOR Interrupt; CM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedInterrupt; //
// Type of bus we are on
//
INTERFACE_TYPE InterfaceType; //
// SD Host register base
//
PVOID HostRegisterBase; //
// Size of the register base that has been mapped
//
ULONG HostRegisterSize; // Memory = 1, IO = 2
UCHAR FunctionType;
USHORT ArgumentReg; USHORT CmdReg; USHORT CardStatusReg; USHORT ResponseReg; USHORT InterruptMaskReg;
//
// These are used for debugging
//
USHORT cardStatus; USHORT errorStatus;
//
// card data which describes current card in the socket
//
PSD_CARD_DATA CardData;
//
// State of the current card in the slot
//
UCHAR numFunctions; BOOLEAN memFunction; ULONG RelativeAddr; SD_CID SdCid; SD_CSD SdCsd;
//
// Status of socket
//
SOCKET_STATE SocketState;
//
// Head of the list of child pc-card PDO's hanging off this controller.
// This is a linked list running through "NextPdoInFdoChain" in the pdo
// extension. This list represents the devices that were enumerated by
// the fdo.
//
PDEVICE_OBJECT PdoList; //
// Keeps track of the number of PDOs which are actually
// valid (not removed). This is primarily used in
// enumeration of the sd controller upon an IRP_MN_QUERY_DEVICE_RELATIONS
//
ULONG LivePdoCount; //
// Remove lock for PnP synchronization
//
IO_REMOVE_LOCK RemoveLock;
} FDO_EXTENSION, *PFDO_EXTENSION;
//
// Physical Device Object's device extension information
//
// There is one device object for each function of an SD device
//
//
// Flags indicating card state
//
#define SDBUS_PDO_GENERATES_IRQ 0x00010000
#define SDBUS_PDO_DPC_CALLBACK 0x00020000
#define SDBUS_PDO_CALLBACK_REQUESTED 0x00040000
#define SDBUS_PDO_CALLBACK_IN_SERVICE 0x00080000
#define SDBUS_PDO_EXTENSION_SIGNATURE 'PmcP'
//
// The PDO extension represents an instance of a single SD function on an SD card
//
typedef struct _PDO_EXTENSION { ULONG Signature;
PDEVICE_OBJECT DeviceObject;
//
// Link to next pdo in the Fdo's pdo chain
//
PDEVICE_OBJECT NextPdoInFdoChain;
//
// Parent extension
//
PFDO_EXTENSION FdoExtension;
//
// Flags
//
ULONG Flags;
//
// Device ISR
//
PSDBUS_CALLBACK_ROUTINE CallbackRoutine; PVOID CallbackRoutineContext;
//
// Power declarations
//
DEVICE_POWER_STATE DevicePowerState; SYSTEM_POWER_STATE SystemPowerState; //
// Device Capabilities
//
DEVICE_CAPABILITIES DeviceCapabilities; //
// Pending wait wake irp
//
PIRP WaitWakeIrp; //
// Deletion Mutex
//
ULONG DeletionLock; //
// SD Function number
//
UCHAR Function; UCHAR FunctionType; } PDO_EXTENSION, *PPDO_EXTENSION;
//
// Struct for Database of card bus controller information
// which maps the vendor id/device id to a CONTROLLER_TYPE
//
typedef struct _PCI_CONTROLLER_INFORMATION { USHORT VendorID; USHORT DeviceID; SDBUS_CONTROLLER_TYPE ControllerType; } PCI_CONTROLLER_INFORMATION, *PPCI_CONTROLLER_INFORMATION;
//
// Struct for database of generic vendor class based on vendor ID
//
typedef struct _PCI_VENDOR_INFORMATION { USHORT VendorID; PSD_FUNCTION_BLOCK FunctionBlock; } PCI_VENDOR_INFORMATION, *PPCI_VENDOR_INFORMATION;
// The pccard device id prefix
#define SDBUS_ID_STRING "SDBUS"
// String to be substituted if manufacturer name is not known
#define SDBUS_UNKNOWN_MANUFACTURER_STRING "UNKNOWN_MANUFACTURER"
// Max length of device id
#define SDBUS_MAXIMUM_DEVICE_ID_LENGTH 128
// Sdbus controller device name
#define SDBUS_DEVICE_NAME "\\Device\\Sdbus"
// Sdbus controller device symbolic link name
#define SDBUS_LINK_NAME "\\DosDevices\\Sdbus"
#define SDBUS_ENABLE_DELAY 10000
//
// problems observed on tecra 750 and satellite 300, with dec-chipset cb nic
//
#define SDBUS_DEFAULT_CONTROLLER_POWERUP_DELAY 250000 // 250 msec
//
// Amount of time to wait after an event interrupt was asserted on the controller
//
#define SDBUS_DEFAULT_EVENT_DPC_DELAY 400000 // 400 msec
//
// Macros for manipulating PDO's flags
//
#define IsDeviceFlagSet(deviceExtension, Flag) (((deviceExtension)->Flags & (Flag))?TRUE:FALSE)
#define SetDeviceFlag(deviceExtension, Flag) ((deviceExtension)->Flags |= (Flag))
#define ResetDeviceFlag(deviceExtension,Flag) ((deviceExtension)->Flags &= ~(Flag))
#define IsFdoExtension(fdoExtension) (fdoExtension->Signature == SDBUS_FDO_EXTENSION_SIGNATURE)
#define IsPdoExtension(pdoExtension) (pdoExtension->Signature == SDBUS_PDO_EXTENSION_SIGNATURE)
#define MarkDeviceStarted(deviceExtension) ((deviceExtension)->Flags |= SDBUS_DEVICE_STARTED)
#define MarkDeviceNotStarted(deviceExtension) ((deviceExtension)->Flags &= ~SDBUS_DEVICE_STARTED)
#define MarkDeviceDeleted(deviceExtension) ((deviceExtension)->Flags |= SDBUS_DEVICE_DELETED);
#define MarkDevicePhysicallyRemoved(deviceExtension) \
((deviceExtension)->Flags |= SDBUS_DEVICE_PHYSICALLY_REMOVED) #define MarkDevicePhysicallyInserted(deviceExtension) \
((deviceExtension)->Flags &= ~SDBUS_DEVICE_PHYSICALLY_REMOVED) #define MarkDeviceLogicallyRemoved(deviceExtension) \
((deviceExtension)->Flags |= SDBUS_DEVICE_LOGICALLY_REMOVED) #define MarkDeviceLogicallyInserted(deviceExtension) \
((deviceExtension)->Flags &= ~SDBUS_DEVICE_LOGICALLY_REMOVED) #define MarkDeviceMultifunction(deviceExtension) \
((deviceExtension)->Flags |= SDBUS_DEVICE_MULTIFUNCTION)
#define IsDeviceStarted(deviceExtension) (((deviceExtension)->Flags & SDBUS_DEVICE_STARTED)?TRUE:FALSE)
#define IsDevicePhysicallyRemoved(deviceExtension) \
(((deviceExtension)->Flags & SDBUS_DEVICE_PHYSICALLY_REMOVED)?TRUE:FALSE) #define IsDeviceLogicallyRemoved(deviceExtension) \
(((deviceExtension)->Flags & SDBUS_DEVICE_LOGICALLY_REMOVED)?TRUE:FALSE) #define IsDeviceDeleted(deviceExtension) (((deviceExtension)->Flags & SDBUS_DEVICE_DELETED)?TRUE:FALSE)
#define IsDeviceMultifunction(deviceExtension) (((deviceExtension)->Flags & SDBUS_DEVICE_MULTIFUNCTION)?TRUE:FALSE)
//
// NT definitions
//
#ifdef POOL_TAGGING
#undef ExAllocatePool
#define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'ubdS')
#endif
#define IO_RESOURCE_LIST_VERSION 0x1
#define IO_RESOURCE_LIST_REVISION 0x1
#define IRP_MN_PNP_MAXIMUM_FUNCTION IRP_MN_QUERY_LEGACY_BUS_INFORMATION
//
// Some useful macros
//
#define MIN(x,y) ((x) > (y) ? (y) : (x)) // return minimum among x & y
#define MAX(x,y) ((x) > (y) ? (x) : (y)) // return maximum among x & y
//
// BOOLEAN
// IS_PDO (IN PDEVICE_OBJECT DeviceObject);
//
#define IS_PDO(DeviceObject) (((DeviceObject)->Flags & DO_BUS_ENUMERATED_DEVICE)?TRUE:FALSE)
//
// Io extension macro to just pass on the Irp to a lower driver
//
//
// VOID
// SdbusSkipCallLowerDriver(OUT NTSTATUS Status,
// IN PDEVICE_OBJECT DeviceObject,
// IN PIRP Irp);
//
#define SdbusSkipCallLowerDriver(Status, DeviceObject, Irp) { \
IoSkipCurrentIrpStackLocation(Irp); \ Status = IoCallDriver(DeviceObject,Irp);}
//
// VOID
// SdbusCopyCallLowerDriver(OUT NTSTATUS Status,
// IN PDEVICE_OBJECT DeviceObject,
// IN PIRP Irp);
//
#define SdbusCopyCallLowerDriver(Status, DeviceObject, Irp) { \
IoCopyCurrentIrpStackLocationToNext(Irp); \ Status = IoCallDriver(DeviceObject,Irp); }
// BOOLEAN
// CompareGuid(
// IN LPGUID guid1,
// IN LPGUID guid2
// );
#define CompareGuid(g1, g2) ((g1) == (g2) ?TRUE: \
RtlCompareMemory((g1), \ (g2), \ sizeof(GUID)) \ == sizeof(GUID) \ )
//
// BOOLEAN
// ValidateController(IN FDO_EXTENSION fdoExtension)
//
// Bit of paranoia code. Make sure that the cardbus controller's registers
// are still visible.
//
#define ValidateController(fdoExtension) TRUE
//
// Structure which defines what global parameters are read from the registry
//
typedef struct _GLOBAL_REGISTRY_INFORMATION { PWSTR Name; PULONG pValue; ULONG Default; } GLOBAL_REGISTRY_INFORMATION, *PGLOBAL_REGISTRY_INFORMATION;
#endif //_SDBUS_H_
|