text: /*++
  
  Copyright (c) 1994  Microsoft Corporation
  
  Module Name:
  
      pcmcia.h
  
  Abstract:
  
  Revision History
      27-Apr-95
           Databook support added.
      1-Nov-96
           Complete overhaul to make this a bus enumerator +
           CardBus support
                         - Ravisankar Pudipeddi (ravisp)
  --*/
  
  #ifndef _PCMCIAPRT_
  #define _PCMCIAPRT_
  
  #define MAX_NUMBER_OF_IO_RANGES     2
  #define MAX_NUMBER_OF_MEMORY_RANGES 4
  
  #define MAX_MANFID_LENGTH    64
  #define MAX_IDENT_LENGTH     64
  
  
  //
  // Function number for a multi-function pc-card
  //
  #define PCMCIA_MULTIFUNCTION_PARENT     0xFFFFFFFF
  
  typedef enum _DEVICE_OBJECT_TYPE {
      FDO = 0,
      PDO
  } DEVICE_OBJECT_TYPE;
  
  //
  // Type of the controller
  //
  typedef ULONG PCMCIA_CONTROLLER_TYPE, *PPCMCIA_CONTROLLER_TYPE;
  
  struct _SOCKET;                              //forward references
  struct _FDO_EXTENSION;
  struct _PDO_EXTENSION;
  
  //
  // Define SynchronizeExecution routine.
  //
  
  typedef
  BOOLEAN
  (*PSYNCHRONIZATION_ROUTINE) (
      IN PKINTERRUPT           Interrupt,
      IN PKSYNCHRONIZE_ROUTINE Routine,
      IN PVOID                     SynchronizeContext
      );
  
  //
  // Define the Pcmcia controller detection routine
  //
  
  typedef
  NTSTATUS
  (*PPCMCIA_DETECT_ROUTINE) (
      struct _FDO_EXTENSION  *DeviceExtension
      );
  
  //
  // Completion routine called by various timed routines
  //
  
  typedef
  VOID
  (*PPCMCIA_COMPLETION_ROUTINE) (
      IN PVOID Context,
      IN NTSTATUS status
      );
  
  //
  // Register context structure used to save register contents
  // when cardbus controllers are powered down..
  //
  typedef struct _PCMCIA_CONTEXT_RANGE {
      USHORT wOffset;
      USHORT wLen;
  } PCMCIA_CONTEXT_RANGE, *PPCMCIA_CONTEXT_RANGE;
  
  typedef struct _PCMCIA_CONTEXT {
      PPCMCIA_CONTEXT_RANGE Range;
      ULONG                    RangeCount;
      ULONG                    BufferLength;
      ULONG                    MaxLen;
  } PCMCIA_CONTEXT, *PPCMCIA_CONTEXT;
  
  //
  // Configuration entry parsed from CISTPL_CFTABLE_ENTRY
  // on a pc-card. Indicates what kind of resource configurations
  // the pc-card supports
  //
  typedef struct _CONFIG_ENTRY {
      struct _CONFIG_ENTRY *NextEntry;
      USHORT                   NumberOfIoPortRanges;
      USHORT                   NumberOfMemoryRanges;
      USHORT                   IoPortBase[MAX_NUMBER_OF_IO_RANGES];
      USHORT                   IoPortLength[MAX_NUMBER_OF_IO_RANGES];
      USHORT                   IoPortAlignment[MAX_NUMBER_OF_IO_RANGES];
      ULONG                    MemoryHostBase[MAX_NUMBER_OF_MEMORY_RANGES];
      ULONG                    MemoryCardBase[MAX_NUMBER_OF_MEMORY_RANGES];
      ULONG                    MemoryLength[MAX_NUMBER_OF_MEMORY_RANGES];
      USHORT                   IrqMask;
  
      //
      // Only one flag used now. Expect to have more in future..
      //
  #define PCMCIA_INVALID_CONFIGURATION     0x00000001
      USHORT                   Flags;
  
      //
      // Level or Edge triggered IRQ
      //
      UCHAR                    LevelIrq;
      //
      // Share disp.for the IRQ
      //
      UCHAR                    ShareDisposition;
      UCHAR                    IndexForThisConfiguration;
      //
      // Indicates if the i/o requirement supports 16-bit access
      //
      BOOLEAN                  Io16BitAccess;
      //
      // Indicates if the i/o requirement supports 8-bit access
      // At least one of Io8BitAccess and Io16BitAccess must always
      // be true for a valid configuration
      //
      BOOLEAN                  Io8BitAccess;
  } CONFIG_ENTRY, *PCONFIG_ENTRY;
  
  //
  // Function configuration holds the data that goes in each functions's
  // configuration registers
  //
  
  typedef struct _FUNCTION_CONFIGURATION {
      struct _FUNCTION_CONFIGURATION *Next;
      ULONG   ConfigRegisterBase;
      UCHAR   ConfigOptions;
      UCHAR   ConfigFlags;
      UCHAR   IoLimit;
      UCHAR   Reserved;
      ULONG   IoBase;
  } FUNCTION_CONFIGURATION, *PFUNCTION_CONFIGURATION;
  
  //
  // Socket configuration is the holder of the actual controller setup
  //
  
  typedef struct _SOCKET_CONFIGURATION {
      //
      // Device irq assigned
      //
      ULONG   Irq;
      //
      // Optional Irq to indicate when card is ready
      //
      ULONG   ReadyIrq;
      ULONG   ConfigRegisterBase;
  
      ULONG   NumberOfIoPortRanges;
  
      struct _SOCKET_CONFIG_IO_ENTRY {
          ULONG Base;
          USHORT Length;
          BOOLEAN Width16;
          BOOLEAN WaitState16;
          BOOLEAN Source16;
          BOOLEAN ZeroWait8;
      } Io[MAX_NUMBER_OF_IO_RANGES];
  
      ULONG   NumberOfMemoryRanges;
  
      struct _SOCKET_CONFIG_MEM_ENTRY {
          ULONG HostBase;
          ULONG CardBase;
          ULONG Length;
          UCHAR IsAttribute;
          UCHAR WaitState;
          BOOLEAN Width16;
      } Memory[MAX_NUMBER_OF_MEMORY_RANGES];
  
      PFUNCTION_CONFIGURATION FunctionConfiguration;
      UCHAR   IndexForCurrentConfiguration;
  } SOCKET_CONFIGURATION, *PSOCKET_CONFIGURATION;
  
  
  //
  // Each function on a PCCARD present gets socket data.  Socket data
  // contains information concerning the function and its configuration.
  //
  
  typedef struct _SOCKET_DATA {
      //
      // Multi function pcards: links to
      // other socket-datas' off the same PC-Card
      //
      struct _SOCKET_DATA  *Next;
      struct _SOCKET_DATA  *Prev;
  
      struct _SOCKET       *Socket;
      //
      // Pointer to the pdo's extension corresponding
      // to this socket
      //
      struct _PDO_EXTENSION *PdoExtension;
  
  
      UCHAR           Mfg[MAX_MANFID_LENGTH];
      UCHAR           Ident[MAX_IDENT_LENGTH];
      USHORT          ManufacturerCode;
      USHORT          ManufacturerInfo;
  
      ULONG           ConfigRegisterBase; // Base address from config tuple.
  
      //
      // Number of configurations possible
      //
      ULONG           NumberOfConfigEntries;
      //
      // Pointer to head of list of configurations
      //
      PCONFIG_ENTRY   ConfigEntryChain;               // Offset 0x114
      //
      // CRC calculated from the relevant tuples, used in
      // constructing hardware ids
      //
      USHORT          CisCrc;
      //
      // Device Type: PCCARD_TYPE_xxxx
      //
      UCHAR           DeviceType;
      UCHAR           LastEntryInCardConfig;
      //
      // Voltage values requested
      //
      UCHAR           Vcc;
      UCHAR           Vpp1;
      UCHAR           Vpp2;
      UCHAR           Audio;
  
      UCHAR           RegistersPresentMask[16];
      //
      // Configuration entry number used when actually
      // starting the pc-card
      //
      UCHAR           ConfigIndexUsed;
      //
      // Number of function in a multifunction card - zero-based
      //
      UCHAR           Function;
      UCHAR           Flags;
      //
      // Pointer to the default configuration among the list of config entries
      // which will be used when the default bit is zero in a tuple (and
      // set when the default bit is one)
      //
      PCONFIG_ENTRY   DefaultConfiguration;
  
      ULONG           Instance;
      USHORT          JedecId;
      //
      // Resource map indices for the requested resources in the
      // merged multifunction resource requirements list
      //
      UCHAR           MfIrqResourceMapIndex;
      UCHAR           MfIoPortResourceMapIndex;
      UCHAR           MfMemoryResourceMapIndex;
      BOOLEAN         MfNeedsIrq;
      USHORT          MfIoPortCount;
      USHORT          MfMemoryCount;
  } SOCKET_DATA, *PSOCKET_DATA;
  
  //
  // Bits defined in Flags field
  //
  #define SDF_ZV      1                                   // Zoom video custom interface
  #define SDF_JEDEC_ID 2
  
  #define IsConfigRegisterPresent(xSocketData, reg) ((((xSocketData)->RegistersPresentMask[reg / 8] &          \
                                                                                                               (1 << (reg % 8)) )) ?       \
                                                                                                                                  TRUE:FALSE)
  
  //
  // Config list is an array used in translating CONFIG_ENTRY data to
  // IO_RESOURCE_LISTs
  //
  
  typedef struct _CONFIG_LIST {
  
      PSOCKET_DATA SocketData;
      PCONFIG_ENTRY ConfigEntry;
  
  } CONFIG_LIST, * PCONFIG_LIST;
  
  //
  // PCMCIA configuration information structure contains information
  // about the PCMCIA controller attached and its configuration.
  //
  
  typedef struct _PCMCIA_CONFIGURATION_INFORMATION {
      INTERFACE_TYPE                       InterfaceType;
      ULONG                                BusNumber;
      ULONG                                SlotNumber;
      PHYSICAL_ADDRESS                     PortAddress;
      USHORT                               PortSize;
      USHORT                               UntranslatedPortAddress;
      //
      // Card status change interrupt: these fields are used only
      // for cardbus controllers.
      //
      CM_PARTIAL_RESOURCE_DESCRIPTOR Interrupt;
      CM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedInterrupt;
      //
      // For PCI-based controllers, indicates the pin number which we need
      // for programming the controller interrupt.
      // NOTE: This is no longer needed (this was to handle CSC interrupts
      // for PCI-PCMCIA bridges (like CL PD6729). We no longer support interrupt
      // based card status change for these cntrollers. Get rid of it
      // whenever possible.
      //
      UCHAR                                InterruptPin;
      //
      // Another dead field. Legacy.
      //
      BOOLEAN                              FloatingSave;
      USHORT                               Reserved;    // Alignment
  } PCMCIA_CONFIGURATION_INFORMATION, *PPCMCIA_CONFIGURATION_INFORMATION;
  
  //
  // PCMCIA_CTRL_BLOCK allows for a level of indirection, thereby allowing
  // the top-level PCMCIA code to do it's work without worrying about who's
  // particular brand of PCMCIA controller it's addressing.
  //
  // Note that this only implements TWO architectures, pcic and tcic. For
  // more indirection, see DEVICE_DISPATCH_TABLE
  
  
  typedef struct _PCMCIA_CTRL_BLOCK {
  
      //
      // Function to initialize the socket
      //
  
      BOOLEAN (*PCBInitializePcmciaSocket)(
          IN struct _SOCKET *Socket
          );
  
      //
      // Function to initialize the card in the socket.
      //
  
      NTSTATUS
      (*PCBResetCard)(
          IN struct _SOCKET *Socket,
          OUT PULONG pDelayTime
          );
  
      //
      // Function to determine if a card is in the socket
      //
  
      BOOLEAN (*PCBDetectCardInSocket)(
          IN struct _SOCKET *Socket
          );
  
      //
      // Function to determine if insertion status has changed.
      //
  
      BOOLEAN (*PCBDetectCardChanged)(
          IN struct _SOCKET *Socket
          );
  
      //
      // Function to determine if card status has been asserted.
      //
  
      BOOLEAN (*PCBDetectCardStatus)(
          IN struct _SOCKET *Socket
          );
  
      //
      // Function to determine if "card ready" status has changed
      //
  
      BOOLEAN (*PCBDetectReadyChanged)(
          IN struct _SOCKET *Socket
          );
  
      //
      // Function which requests that the controller be examined to
      // determine what power settings the current device in the socket
      // requires.
      //
  
      NTSTATUS
      (*PCBGetPowerRequirements)(
          IN struct _SOCKET *Socket
          );
  
      //
      // Function to configure cards.
      //
  
      BOOLEAN (*PCBProcessConfigureRequest)(
          IN struct _SOCKET *Socket,
          IN struct _CARD_REQUEST *ConfigRequest,
          IN PUCHAR            Base
          );
  
      //
      // Function to enable/disable status change interrupts
      //
  
      BOOLEAN (*PCBEnableDisableCardDetectEvent)(
          IN struct _SOCKET *Socket,
          IN BOOLEAN           Enable
          );
  
      //
      // Function to set/reset the ring enable bit  for the given
      // socket. Setting Ring Enable would cause the CSC to be used
      // as a wakeup event for pc-card modems/netcards etc.
      //
  
      VOID (*PCBEnableDisableWakeupEvent) (
          IN  struct _SOCKET *SocketPtr,
          IN struct _PDO_EXTENSION *PdoExtension,
          IN  BOOLEAN Enable
          );
  
      //
      // Function to return the set of IRQs supported
      // by the controller
      //
      ULONG (*PCBGetIrqMask) (
          IN struct _FDO_EXTENSION *DeviceExtension
          );
  
      //
      // Function to read the memory contents (attribute/common)
      // on the given PC-Card
      //
      ULONG (*PCBReadCardMemory) (
          IN struct _PDO_EXTENSION *PdoExtension,
          IN MEMORY_SPACE MemorySpace,
          IN ULONG  Offset,
          IN PUCHAR Buffer,
          IN ULONG  Length
          );
  
      //
      // Function to write to the attribute/common memory of
      // the given PC-Card
      //
      ULONG (*PCBWriteCardMemory) (
          IN struct _PDO_EXTENSION *PdoExtension,
          IN  MEMORY_SPACE MemorySpace,
          IN  ULONG  Offset,
          IN  PUCHAR Buffer,
          IN  ULONG  Length
          );
  
      //
      // Flash memory card interfaces:
      //
      //
      // Function to slide the host memory window on a pc-card
      //
      PPCMCIA_MODIFY_MEMORY_WINDOW PCBModifyMemoryWindow;
      //
      // Function to set the Vpp to the supplied value
      //
      PPCMCIA_SET_VPP               PCBSetVpp;
      //
      // Function to test if the given card is write protected
      //
      PPCMCIA_IS_WRITE_PROTECTED   PCBIsWriteProtected;
  
  }PCMCIA_CTRL_BLOCK, *PPCMCIA_CTRL_BLOCK;
  
  //
  // Each socket on the PCMCIA controller has a socket structure
  // to contain current information on the state of the socket and
  // and PCCARD inserted.
  //
  
  #define IsSocketFlagSet(Socket, Flag)           (((Socket)->Flags & (Flag))?TRUE:FALSE)
  #define SetSocketFlag(Socket, Flag)             ((Socket)->Flags |= (Flag))
  #define ResetSocketFlag(Socket,Flag)            ((Socket)->Flags &= ~(Flag))
  
  //
  // Socket flags
  //
  #define SOCKET_CARD_INITIALIZED         0x00000002
  #define SOCKET_CARD_POWERED_UP          0x00000004
  #define SOCKET_CARD_CONFIGURED          0x00000008
  #define SOCKET_CARD_MULTIFUNCTION       0x00000010
  #define SOCKET_CARD_MEMORY              0x00000040
  #define SOCKET_CHANGE_INTERRUPT         0x00000080
  #define SOCKET_CUSTOM_INTERFACE         0x00000100
  #define SOCKET_SUPPORT_MESSAGE_SENT     0x00000800
  #define SOCKET_MEMORY_WINDOW_ENABLED    0x00001000
  #define SOCKET_CARD_STATUS_CHANGE       0x00002000
  #define SOCKET_ENUMERATE_PENDING        0x00008000
  #define SOCKET_CLEANUP_PENDING          0x00010000
  #define SOCKET_CB_ROUTE_R2_TO_PCI       0x00020000
  #define SOCKET_POWER_PREFER_3V          0x00040000
  #define SOCKET_ENABLED_FOR_CARD_DETECT 0x00080000
  #define SOCKET_DEVICE_HIDDEN                0x00100000
  
  #define SOCKET_CLEANUP_MASK (SOCKET_CARD_CONFIGURED | SOCKET_CLEANUP_PENDING)
  
  //
  // Socket insertion states
  //
  #define SKT_Empty                       0
  #define SKT_CardBusCard                 1
  #define SKT_R2Card                      2
  
  //
  // Worker states for socket power operations
  //
  typedef enum _SPW_STATE {
      SPW_Stopped = 0,
      SPW_Exit,
      SPW_RequestPower,
      SPW_ReleasePower,
      SPW_SetPowerOn,
      SPW_SetPowerOff,
      SPW_ResetCard,
      SPW_Deconfigure
  } SPW_STATE;
  
  
  #define PCMCIA_SOCKET_SIGNATURE                 'SmcP'
  
  //
  // Socket structure
  //
  
  typedef struct _SOCKET {
      ULONG                       Signature;
  
      struct _SOCKET              *NextSocket;
      //
      // Pointer to the pdo for the pc-card in this socket. This is a linked
      // list running through "NextPdoInSocket" in the pdo extension. This list
      // represents the functions that are physically contained within a socket.
      //
      PDEVICE_OBJECT              PdoList;
      //
      // Parent pcmcia controller's fdo extension of this socket
      //
      struct _FDO_EXTENSION       *DeviceExtension;
      //
      // Pointer to the miniport-like
      //
      PPCMCIA_CTRL_BLOCK          SocketFnPtr;
      //
      // Flags prefixed SOCKET_ defined above
      //
      ULONG                       Flags;
      //
      // For 16-bit cards we use the i/o address port to read/write
      // to the socket registers
      // For cardbus cards, we use the CardBus socket register base
      //
      PUCHAR                      AddressPort;
  
      KEVENT                      PCCardReadyEvent;
      BOOLEAN                     ReadyChanged;
      //
      // Voltage values requested
      //
      UCHAR                       Vcc;
      UCHAR                       Vpp1;
      UCHAR                       Vpp2;
      //
      // Socket states
      //
      UCHAR                       DeviceState;
      UCHAR                       Reserved0;
      //
      // For PCIC controllers: register offset of the socket
      //
      USHORT                      RegisterOffset;
      //
      // PCIC revision
      //
      UCHAR                       Revision;
      //
      // PCIC controllers: zero-based number of the socket
      //
      UCHAR                       SocketNumber;
      //
      // Indicates the number of functions this pc-card has
      // (this will be > 1 only for multifunction cards like modem/net combos)
      //
      UCHAR                       NumberOfFunctions;
      //
      // Current memory window used internally for reading attributes
      //
      UCHAR                       CurrentMemWindow;
  
      //
      // Timer and DPC objects to handle socket power and initialization
      //
      KTIMER                      PowerTimer;
      KDPC                        PowerDpc;
      //
      // Function and parameter to call at the end of power operation
      //
      PPCMCIA_COMPLETION_ROUTINE  PowerCompletionRoutine;
      PVOID                       PowerCompletionContext;
      NTSTATUS                    CallerStatus;
      NTSTATUS                    DeferredStatus;
      LONG                        DeferredStatusLock;
      //
      // Phase variables control state machine for socket power
      //
      LONG                        WorkerBusy;
      SPW_STATE                   WorkerState;
      UCHAR                       PowerPhase;
      UCHAR                       CardResetPhase;
  
      UCHAR                       Reserved;
      //
      // PowerData is temporary storage for power "miniports"
      //
      ULONG                       PowerData;
      //
      // semaphore to count # of functions requesting power on this socket
      //
      LONG                        PowerRequests;
      //
      // Context buffers
      //
      PUCHAR                      CardbusContextBuffer;
      PUCHAR                      ExcaContextBuffer;
      //
      // Current IRQ routing settings on socket
      //
      ULONG                       IrqMask;
      ULONG                       FdoIrq;
  } SOCKET, *PSOCKET;
  
  
  
  //
  // Lock used for synhing access to device(pcmcia controller registers etc.)
  // If the definition for this changes, the following 3 defs for
  // acquiring/releasing the locks also may need to change
  //
  typedef struct _PCMCIA_DEVICE_LOCK {
  
      KSPIN_LOCK  Lock;
      KIRQL       Irql;
  
  } PCMCIA_DEVICE_LOCK, * PPCMCIA_DEVICE_LOCK;
  
  #define PCMCIA_INITIALIZE_DEVICE_LOCK(X)                KeInitializeSpinLock(&(X)->DeviceLock.Lock)
  #define PCMCIA_ACQUIRE_DEVICE_LOCK(X)                   KeAcquireSpinLock(&(X)->DeviceLock.Lock, &(X)->DeviceLock.Irql)
  #define PCMCIA_ACQUIRE_DEVICE_LOCK_AT_DPC_LEVEL(X)      KeAcquireSpinLockAtDpcLevel(&(X)->DeviceLock.Lock)
  #define PCMCIA_RELEASE_DEVICE_LOCK(X)                   KeReleaseSpinLock(&(X)->DeviceLock.Lock, (X)->DeviceLock.Irql)
  #define PCMCIA_RELEASE_DEVICE_LOCK_FROM_DPC_LEVEL(X)    KeReleaseSpinLockFromDpcLevel(&(X)->DeviceLock.Lock)
  
  #define PCMCIA_TEST_AND_SET(X)  (InterlockedCompareExchange(X, 1, 0) == 0)
  #define PCMCIA_TEST_AND_RESET(X) (InterlockedCompareExchange(X, 0, 1) == 1)
  
  //
  // Wait-Wake states
  //
  typedef enum {
      WAKESTATE_DISARMED,
      WAKESTATE_WAITING,
      WAKESTATE_WAITING_CANCELLED,
      WAKESTATE_ARMED,
      WAKESTATE_ARMING_CANCELLED,
      WAKESTATE_COMPLETING
  } WAKESTATE;
  
  //
  // Power Policy Flags
  //
  
  #define PCMCIA_PP_WAKE_FROM_D0                  0x00000001
  #define PCMCIA_PP_D3_ON_IDLE                    0x00000002
  
  //
  // Functional Device Object's device extension information
  //
  // There is one device object for each PCMCIA 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 PCMCIA_DEVICE_STARTED                   0x00000001
  #define PCMCIA_DEVICE_LOGICALLY_REMOVED         0x00000002
  #define PCMCIA_DEVICE_PHYSICALLY_REMOVED        0x00000004
  #define PCMCIA_DEVICE_DELETED                   0x00000040
  #define PCMCIA_DEVICE_CARDBUS                   0x00000080
  
  //
  // Flags indicating controller state (fdoExtension)
  //
  
  #define PCMCIA_DEVICE_LEGACY_DETECTED           0x00000020
  #define PCMCIA_FILTER_ADDED_MEMORY              0x00000100
  #define PCMCIA_MEMORY_24BIT                     0x00000200
  #define PCMCIA_CARDBUS_NOT_SUPPORTED            0x00000400
  #define PCMCIA_USE_POLLED_CSC                   0x00000800
  #define PCMCIA_ATTRIBUTE_MEMORY_MAPPED          0x00001000
  #define PCMCIA_SOCKET_REGISTER_BASE_MAPPED      0x00002000
  #define PCMCIA_INTMODE_COMPAQ                   0x00004000
  #define PCMCIA_INT_ROUTE_INTERFACE              0x00080000
  #define PCMCIA_FDO_CONTEXT_SAVED                0x00100000
  #define PCMCIA_FDO_OFFLINE                      0x00800000
  #define PCMCIA_FDO_ON_DEBUG_PATH                0x01000000
  #define PCMCIA_FDO_DISABLE_AUTO_POWEROFF        0x02000000
  #define PCMCIA_FDO_PREFER_3V                    0x04000000
  #define PCMCIA_FDO_IOCTL_INTERFACE_ENABLED      0x08000000
  
  //
  // FDO Flags
  //
  
  #define PCMCIA_FDO_IRQ_DETECT_DEVICE_FOUND      0x00000001
  #define PCMCIA_FDO_IRQ_DETECT_COMPLETED         0x00000002
  #define PCMCIA_FDO_IN_ACPI_NAMESPACE            0x00000004
  
  #define PCMCIA_FDO_FORCE_PCI_ROUTING            0x00000010
  #define PCMCIA_FDO_PREFER_PCI_ROUTING           0x00000020
  #define PCMCIA_FDO_FORCE_ISA_ROUTING            0x00000040
  #define PCMCIA_FDO_PREFER_ISA_ROUTING           0x00000080
  
  #define PCMCIA_FDO_WAKE_BY_CD                   0x00000100
  
  //
  // states for FdoPowerWorker
  //
  
  typedef enum _FDO_POWER_WORKER_STATE {
      FPW_Stopped = 0,
      FPW_BeginPowerDown,
      FPW_PowerDown,
      FPW_PowerDownSocket,
      FPW_PowerDownComplete,
      FPW_BeginPowerUp,
      FPW_PowerUp,
      FPW_PowerUpSocket,
      FPW_PowerUpSocket2,
      FPW_PowerUpSocketVerify,
      FPW_PowerUpSocketComplete,
      FPW_PowerUpComplete,
      FPW_SendIrpDown,
      FPW_CompleteIrp
  } FDO_POWER_WORKER_STATE;
  
  #define FPW_END_SEQUENCE 128
  
  #define PCMCIA_FDO_EXTENSION_SIGNATURE      'FmcP'
  
  //
  // Device extension for the functional device object for pcmcia controllers
  //
  typedef struct _FDO_EXTENSION {
      ULONG                                   Signature;
      //
      // Pointer to the next pcmcia controller's FDO in the central list
      // of all pcmcia 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 pcmcia controller
      //
      //
      PDEVICE_OBJECT                          Pdo;
      //
      // The immediately lower device attached beneath the pcmcia controller's FDO.
      // This would be the same as the Pdo above, excepting in cases when there are
      // lower filter drivers for the pcmcia controller - like the ACPI driver
      //
      PDEVICE_OBJECT                          LowerDevice;
      //
      // Pointer to the list of sockets which hang off this pcmcia controller
      //
      PSOCKET                                 SocketList;
      //
      // Various flags used to track the state of this
      // (flags prefixed by PCMCIA_ above)
      //
      ULONG                                   Flags;
      //
      // FDO specific flags
      //
      ULONG                                   FdoFlags;
      //
      // Bus numbering for PCI devices
      //
      UCHAR                                   PciBusNumber;
      UCHAR                                   PciDeviceNumber;
      UCHAR                                   PciFunctionNumber;
      UCHAR                                   reserved;
      //
      // 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.
      //
      PCMCIA_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;
      //
      // Symbolic link name exported for this pcmcia controller
      //
      UNICODE_STRING                          LinkName;
      //
      // 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 pcmcia controller upon an IRP_MN_QUERY_DEVICE_RELATIONS
      //
      ULONG                                   LivePdoCount;
      //
      // Lock for synching device access
      //
      PCMCIA_DEVICE_LOCK                      DeviceLock;
  
      //
      // Card status change poll related structures
      //
      //
      // Dpc which periodically polls to see if card has been inserted or removed
      //
      KDPC                                    TimerDpc;
      //
      // The PollTimer object which is initialized and triggered if a Card Status change
      // interrupt is not used & we resort to polling..
      //
      KTIMER                                  PollTimer;
      //
      // Kernel objects to defer power up initialization of controller
      //
      KTIMER                                  PowerTimer;
      KDPC                                    PowerDpc;
      //
      // Kernel objects to handle controller events
      //
      KTIMER                                  EventTimer;
      KDPC                                    EventDpc;
  
      //
      // IRQ Mask used in determining which IRQs are allowed for this
      // controller & it's child pc-cards.
      // 1's in the mask correspond to valid IRQs.
      // IRQs are numbered 0 - 15, lsb to msb
      // LegacyIrqMask is a fixed masked used if detection fails and PCI routing is disabled
      //
      USHORT                                  DetectedIrqMask;
      USHORT                                  LegacyIrqMask;
  
      //
      // Physical address of the attribute memory window used
      // read tuples off a pc-card.
      //
      PHYSICAL_ADDRESS                        PhysicalBase;
      //
      // Attribute memory resource requirement limits
      //
      ULONG                                   AttributeMemoryLow;
      ULONG                                   AttributeMemoryHigh;
  
      //
      // Size of the attribute memory window requested
      //
      ULONG                                   AttributeMemorySize;
      //
      // Alignment of the attribute memory window
      //
      ULONG                                   AttributeMemoryAlignment;
      //
      // Virtual address mapped to the attribute memory window (PhysicalBase)
      //
      PUCHAR                                  AttributeMemoryBase;
      //
      // Sequence number for  event logging
      //
      ULONG                                   SequenceNumber;
  
      //
      // Pointer to the interrupt object - if we use interrupt based
      // card status change detection
      //
      PKINTERRUPT                             PcmciaInterruptObject;
  
      //
      // Power management related stuff.
      //
      //
      // Current system power state..
      //
      SYSTEM_POWER_STATE                      SystemPowerState;
      //
      // Device power state the pcmcia controller is currently in
      //
      DEVICE_POWER_STATE                      DevicePowerState;
      //
      // 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 config register state
      //
      PCMCIA_CONTEXT                          PciContext;
      //
      // Interface obtained from PCI driver, for cardbus controllers.
      // This contains interfaces to enumerate CardBus cards
      // (not this interface is private to PCI & PCMCIA.
      // No other driver is expected to use these interfaces
      //
      PCI_CARDBUS_INTERFACE_PRIVATE           PciCardBusInterface;
      PVOID                                   PciCardBusDeviceContext;
      //
      // 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;
      //
      // PCI Int Route interface standard
      // This contains the interface to update the raw interrupt line
      // of the cardbus card
      //
      INT_ROUTE_INTERFACE_STANDARD            PciIntRouteInterface;
      //
      // Configuration resources for the PCMCIA controller
      //
      PCMCIA_CONFIGURATION_INFORMATION Configuration;
      //
      // Pending power irp
      //
      PIRP                                    PendingPowerIrp;
      PSOCKET                                 PendingPowerSocket;
      //
      // Power worker state machine context
      //
      FDO_POWER_WORKER_STATE                  *PowerWorkerSequence;
      FDO_POWER_WORKER_STATE                  PowerWorkerState;
      UCHAR                                   PowerWorkerPhase;
      UCHAR                                   PowerWorkerMaxPhase;
      //
      // Type of bus we are on
      //
      INTERFACE_TYPE                          InterfaceType;
      //
      // CardBus socket base
      //
      PUCHAR                                  CardBusSocketRegisterBase;
      //
      // Size of the socket register base that has been mapped
      //
      ULONG                                   CardBusSocketRegisterSize;
      //
      // configuration context
      //
      PCMCIA_CONTEXT                          CardbusContext;
      PCMCIA_CONTEXT                          ExcaContext;
      PUCHAR                                  PciContextBuffer;
      //
      // Deferred pdo power irp handling
      //
      LIST_ENTRY                              PdoPowerRetryList;
      KDPC                                    PdoPowerRetryDpc;
      //
      // Count to track cardbus PCI interface calls
      //
      ULONG                                   PciAddCardBusCount;
      //
      // Deletion Mutex
      //
      ULONG                                   DeletionLock;
  } FDO_EXTENSION, *PFDO_EXTENSION;
  
  
  
  //
  // Physical Device Object's device extension information
  //
  // There is one device object for each function of each
  // PC-card in a socket per PCMCIA controller
  // in the system.  This is referred to as the 'PDO' (physical device
  // object)- handled by this bus driver.
  //
  
  //
  // Flags indicating card state
  //
  #define PCMCIA_DEVICE_MULTIFUNCTION         0x00000008
  #define PCMCIA_DEVICE_WAKE_PENDING          0x00000010
  #define PCMCIA_POWER_WORKER_POWERUP         0x00008000
  #define PCMCIA_CONFIG_STATUS_DEFERRED       0x00020000
  #define PCMCIA_POWER_STATUS_DEFERRED        0x00040000
  #define PCMCIA_PDO_ENABLE_AUDIO             0x00200000
  #define PCMCIA_PDO_EXCLUSIVE_IRQ            0x00400000
  
  #define PCMCIA_PDO_INDIRECT_CIS             0x00000001
  #define PCMCIA_PDO_SUPPORTS_WAKE            0x00000002
  
  //
  // states for PdoPowerWorker
  //
  typedef enum _PDO_POWER_WORKER_STATE {
      PPW_Stopped = 0,
      PPW_Exit,
      PPW_InitialState,
      PPW_PowerUp,
      PPW_PowerDown,
      PPW_SendIrpDown,
      PPW_16BitConfigure,
      PPW_CardBusRefresh,
      PPW_CardBusDelay
  } PDO_POWER_WORKER_STATE;
  
  //
  // phases for ConfigurationWorker
  //
  typedef enum _CW_STATE {
      CW_Stopped = 0,
      CW_InitialState,
      CW_ResetCard,
      CW_Phase1,
      CW_Phase2,
      CW_Phase3,
      CW_Exit
  } CW_STATE;
  
  //
  // Flags for ConfigurationWorker
  //
  
  #define CONFIG_WORKER_APPLY_MODEM_HACK  0x01
  
  
  #define PCMCIA_PDO_EXTENSION_SIGNATURE      'PmcP'
  
  //
  // Device extension for the physical device object for pcmcia cards
  //
  typedef struct _PDO_EXTENSION {
      ULONG                                   Signature;
  
      PDEVICE_OBJECT                          DeviceObject;
  
      //
      // Link to next pdo in the Fdo's pdo chain
      //
      PDEVICE_OBJECT                          NextPdoInFdoChain;
  
      //
      // Link to next pdo in the Socket's pdo chain
      //
      PDEVICE_OBJECT                          NextPdoInSocket;
  
      //
      // Following two declarations valid only for cardbus cards
      //
      // Device attached just below us
      //
      PDEVICE_OBJECT                          LowerDevice;
      //
      // Actual PDO (owned by PCI) that was enumerated for this
      // cardbus card
      //
      PDEVICE_OBJECT                          PciPdo;
  
      //
      // Cached copy of device id
      //
      PUCHAR                                  DeviceId;
  
      //
      // Pointer to the appropriate socket struc in the parent FDO
      //
      PSOCKET                                 Socket;
      //
      // Pointer to the structure assembled by gleaning off tuple data
      // from a 16-bit pc-card
      //
      PSOCKET_DATA                            SocketData;
  
      //
      // Resource configuration assigned to this socket
      //
      PSOCKET_CONFIGURATION                   SocketConfiguration;
  
      //
      // Flags prefixed PCMCIA_ above
      //
      ULONG                                   Flags;
  
      //
      // PDO Flags
      //
      ULONG                                   PdoFlags;
  
      //
      // Power declarations
      //
      DEVICE_POWER_STATE                      DevicePowerState;
      SYSTEM_POWER_STATE                      SystemPowerState;
      //
      // Device Capabilities
      //
      DEVICE_CAPABILITIES                     DeviceCapabilities;
      //
      // Pending wait wake irp
      //
      PIRP                                    WaitWakeIrp;
      //
      // Other pending power irps
      //
      PIRP                                    PendingPowerIrp;
      //
      // power worker state machine variables
      //
      KTIMER                                  PowerWorkerTimer;
      KDPC                                    PowerWorkerDpc;
      NTSTATUS                                PowerWorkerDpcStatus;
      PUCHAR                                  PowerWorkerSequence;
      UCHAR                                   PowerWorkerPhase;
      PDO_POWER_WORKER_STATE                  PowerWorkerState;
      //
      // Type of card based on an INF override
      //
      UCHAR                                   SpecifiedDeviceType;
  
      //
      // Timer and DPC objects to handle card enables
      //
      CW_STATE                                ConfigurationPhase;
      UCHAR                                   ConfigurationFlags;
      KTIMER                                  ConfigurationTimer;
      KDPC                                    ConfigurationDpc;
      NTSTATUS                                ConfigurationStatus;
      NTSTATUS                                DeferredConfigurationStatus;
      USHORT                                  ConfigureDelay1;
      USHORT                                  ConfigureDelay2;
      USHORT                                  ConfigureDelay3;
      USHORT                                  Reserved2;
      PPCMCIA_COMPLETION_ROUTINE              ConfigCompletionRoutine;
      //
      // PCI Bus interface standard
      // This contains interfaces to read/write from PCI config space
      // of the cardbus card, among other stuff..
      //
      BUS_INTERFACE_STANDARD                  PciBusInterface;          // size 0x20  (32)
      //
      // ID used to check for card changes while powered off
      //
      ULONG                                   CardBusId;
      //
      // CIS cache for reading tuple data
      //
      PUCHAR                                  CisCache;
      MEMORY_SPACE                            CisCacheSpace;
      ULONG                                   CisCacheBase;
      //
      // Lock for power requests
      //
      LONG                                    SocketPowerRequested;
      //
      // Deletion Mutex
      //
      ULONG                                   DeletionLock;
  } 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;
      PCMCIA_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;
      PCMCIA_CONTROLLER_CLASS ControllerClass;
  } PCI_VENDOR_INFORMATION, *PPCI_VENDOR_INFORMATION;
  
  
  //
  // Tuple packet used to access tuples
  //
  typedef struct _TUPLE_PACKET {
      PSOCKET      Socket;
      PSOCKET_DATA SocketData;
      UCHAR        TupleCode;
      UCHAR        TupleLink;
      UCHAR        TupleOffset;
      UCHAR        DesiredTuple;
      USHORT       Attributes;
      USHORT       TupleDataMaxLength;
      USHORT       TupleDataIndex;
      PUCHAR       TupleData;
      ULONG        LinkOffset;
      ULONG        CISOffset;
      USHORT       TupleDataLength;
      USHORT       Flags;
      UCHAR        Function;
  } TUPLE_PACKET, * PTUPLE_PACKET;
  
  //
  // Memory space definitions for accessing CardBus CIS data
  //
  
  #define   PCCARD_CARDBUS_BAR0               0x6e627301
  #define   PCCARD_CARDBUS_BAR1               0x6e627302
  #define   PCCARD_CARDBUS_BAR2               0x6e627303
  #define   PCCARD_CARDBUS_BAR3               0x6e627304
  #define   PCCARD_CARDBUS_BAR4               0x6e627305
  #define   PCCARD_CARDBUS_BAR5               0x6e627306
  #define   PCCARD_CARDBUS_ROM                0x6e627307
  
  //
  // Chain of resource lists built by PcmciaConfigEntriesToResourceList
  //
  typedef struct _PCMCIA_RESOURCE_CHAIN {
      struct _PCMCIA_RESOURCE_CHAIN *NextList;
      PIO_RESOURCE_LIST IoResList;
  } PCMCIA_RESOURCE_CHAIN, *PPCMCIA_RESOURCE_CHAIN;
  
  //
  // Linked list of CM_PCCARD_DEVICE_DATA's pulled from the registry
  //
  
  typedef struct _PCMCIA_NTDETECT_DATA {
      struct _PCMCIA_NTDETECT_DATA *Next;
      CM_PCCARD_DEVICE_DATA PcCardData;
  } PCMCIA_NTDETECT_DATA, *PPCMCIA_NTDETECT_DATA;
  
  
  //
  // Poll interval for card status change (in case interrupt not available)
  // Expressed in milliseconds
  //
  #define PCMCIA_CSC_POLL_INTERVAL 1000    // 1 Second
  
  // The pccard device id prefix
  #define PCMCIA_ID_STRING            "PCMCIA"
  
  // String to be substituted if manufacturer name is not known
  #define PCMCIA_UNKNOWN_MANUFACTURER_STRING "UNKNOWN_MANUFACTURER"
  
  // Max length of device id
  #define PCMCIA_MAXIMUM_DEVICE_ID_LENGTH 128
  
  // Pcmcia controller device name
  #define PCMCIA_DEVICE_NAME      "\\Device\\Pcmcia"
  
  // Pcmcia controller device symbolic link name
  #define PCMCIA_LINK_NAME            "\\DosDevices\\Pcmcia"
  
  // PcCard's device name (PDO name)
  #define PCMCIA_PCCARD_NAME      "\\Device\\PcCard"
  
  // Jedec prefix for memory cards
  #define PCMCIA_MEMORY_ID_STRING "MTD"
  
  //
  // Max no. of pccard instances of a particular device id allowed
  // at a time
  #define PCMCIA_MAX_INSTANCE     100             //arbitrary
  
  #define PCMCIA_ENABLE_DELAY                       10000
  
  //
  // Number of times we attempt to configure the card before
  // we give up   (could be the card has been removed)
  //
  #define PCMCIA_MAX_CONFIG_TRIES         2
  
  //
  // problems observed on tecra 750 and satellite 300, with dec-chipset cb nic
  //
  #define PCMCIA_CONTROLLER_POWERUP_DELAY  250000   // 250 msec
  
  //
  // Amount of time to wait after an event interrupt was asserted on the controller
  //
  #define PCMCIA_DEFAULT_EVENT_DPC_DELAY  400000   // 400 msec
  #define PCMCIA_MAX_EVENT_DPC_DELAY       2000000
  
  //
  // Timeout for deletion locks (secs)
  //
  #define PCMCIA_DELETION_TIMEOUT         20
  
  //
  // Global Flags
  //
  #define   PCMCIA_GLOBAL_FORCE_POLL_MODE     0x00000002      // use polled mode for detecting card insert/remove
  #define PCMCIA_DISABLE_ACPI_NAMESPACE_CHECK 0x00000004      // irq routing test
  #define PCMCIA_DEFAULT_ROUTE_R2_TO_ISA      0x00000008
  //
  // Flags for PcmciaSetSocketPower
  //
  
  #define PCMCIA_POWERON TRUE
  #define PCMCIA_POWEROFF FALSE
  
  //
  // This accepts device extension as  paramter: need to keep adding to this macro
  // as more PciPcmciaBridges are supported
  //
    #define PciPcmciaBridgeExtension(DeviceExtension)  (((DeviceExtension)->ControllerType==PcmciaPciPcmciaBridge)    ||   \
                                                                        ((DeviceExtension)->ControllerType==PcmciaCLPD6729))
  
  
  // These accept the socket as parameter
  
  //
  // Cirrus Logic PD6729 PCI-PCMCIA Bridge
  //
  #define CLPD6729(s)   (((s)->DeviceExtension) && ((s)->DeviceExtension->ControllerType==PcmciaCLPD6729))
  
  //
  // Databook TCIC 16-bit pcmcia controller
  //
  #define Databook(s)   (((s)->DeviceExtension) && ((s)->DeviceExtension->ControllerType==PcmciaDatabook))
  
  //
  // Compaq Elite controller
  //
  #define Elc(s)        (((s)->DeviceExtension) && ((s)->DeviceExtension->ControllerType==PcmciaElcController))
  
  //
  // Generic cardbus controller
  //
  #define CardBus(s)    (((s)->DeviceExtension) && CardBusExtension((s)->DeviceExtension))
  
  //
  // Generic PCI-PCMCIA Bridge
  //
  #define PciPcmciaBridge(s) (((s)->DeviceExtension) && PciPcmciaBridgeExtension((s)->DeviceExtension))
  
  //
  // 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 IsFdoFlagSet(fdoExtension, Flag)                (((fdoExtension)->FdoFlags & (Flag))?TRUE:FALSE)
  #define SetFdoFlag(fdoExtension, Flag)                  ((fdoExtension)->FdoFlags |= (Flag))
  #define ResetFdoFlag(fdoExtension,Flag)                 ((fdoExtension)->FdoFlags &= ~(Flag))
  
  #define IsPdoFlagSet(pdoExtension, Flag)                (((pdoExtension)->PdoFlags & (Flag))?TRUE:FALSE)
  #define SetPdoFlag(pdoExtension, Flag)                  ((pdoExtension)->PdoFlags |= (Flag))
  #define ResetPdoFlag(pdoExtension,Flag)                 ((pdoExtension)->PdoFlags &= ~(Flag))
  
  #define IsFdoExtension(fdoExtension)                    (fdoExtension->Signature == PCMCIA_FDO_EXTENSION_SIGNATURE)
  #define IsPdoExtension(pdoExtension)                    (pdoExtension->Signature == PCMCIA_PDO_EXTENSION_SIGNATURE)
  #define IsSocket(socket)                                (socket->Signature == PCMCIA_SOCKET_SIGNATURE)
  
  
  #define MarkDeviceStarted(deviceExtension)              ((deviceExtension)->Flags |=  PCMCIA_DEVICE_STARTED)
  #define MarkDeviceNotStarted(deviceExtension)           ((deviceExtension)->Flags &= ~PCMCIA_DEVICE_STARTED)
  #define MarkDeviceDeleted(deviceExtension)              ((deviceExtension)->Flags |= PCMCIA_DEVICE_DELETED);
  #define MarkDevicePhysicallyRemoved(deviceExtension) \
                                                          ((deviceExtension)->Flags |=  PCMCIA_DEVICE_PHYSICALLY_REMOVED)
  #define MarkDevicePhysicallyInserted(deviceExtension) \
                                                          ((deviceExtension)->Flags &= ~PCMCIA_DEVICE_PHYSICALLY_REMOVED)
  #define MarkDeviceLogicallyRemoved(deviceExtension) \
                                                          ((deviceExtension)->Flags |=  PCMCIA_DEVICE_LOGICALLY_REMOVED)
  #define MarkDeviceLogicallyInserted(deviceExtension) \
                                                          ((deviceExtension)->Flags &= ~PCMCIA_DEVICE_LOGICALLY_REMOVED)
  #define MarkDeviceCardBus(deviceExtension)              ((deviceExtension)->Flags |= PCMCIA_DEVICE_CARDBUS)
  #define MarkDevice16Bit(deviceExtension)                ((deviceExtension)->Flags &= ~PCMCIA_DEVICE_CARDBUS)
  #define MarkDeviceMultifunction(deviceExtension) \
                                                          ((deviceExtension)->Flags |= PCMCIA_DEVICE_MULTIFUNCTION)
  
  
  #define IsDeviceStarted(deviceExtension)                (((deviceExtension)->Flags & PCMCIA_DEVICE_STARTED)?TRUE:FALSE)
  #define IsDevicePhysicallyRemoved(deviceExtension) \
                                                          (((deviceExtension)->Flags & PCMCIA_DEVICE_PHYSICALLY_REMOVED)?TRUE:FALSE)
  #define IsDeviceLogicallyRemoved(deviceExtension) \
                                                          (((deviceExtension)->Flags & PCMCIA_DEVICE_LOGICALLY_REMOVED)?TRUE:FALSE)
  #define IsDeviceDeleted(deviceExtension)                (((deviceExtension)->Flags & PCMCIA_DEVICE_DELETED)?TRUE:FALSE)
  #define IsDeviceMultifunction(deviceExtension)          (((deviceExtension)->Flags & PCMCIA_DEVICE_MULTIFUNCTION)?TRUE:FALSE)
  
  #define IsCardBusCard(deviceExtension)                  (((deviceExtension)->Flags & PCMCIA_DEVICE_CARDBUS)?TRUE:FALSE)
  #define Is16BitCard(deviceExtension)                    (((deviceExtension)->Flags & PCMCIA_DEVICE_CARDBUS)?FALSE:TRUE)
  
  #define CardBusExtension(deviceExtension)               (((deviceExtension)->Flags & PCMCIA_DEVICE_CARDBUS)?TRUE:FALSE)
  
  //
  // Macros for checking & setting type of PC-CARD in a socket
  //
  #define IsCardBusCardInSocket(SocketPtr)                (((SocketPtr)->DeviceState == SKT_CardBusCard)?TRUE:FALSE)
  #define Is16BitCardInSocket(SocketPtr)                  (((SocketPtr)->DeviceState == SKT_R2Card)?TRUE:FALSE)
  #define IsCardInSocket(SocketPtr)                       (((SocketPtr)->DeviceState == SKT_Empty)?FALSE:TRUE)
  
  #define SetCardBusCardInSocket(SocketPtr)               ((SocketPtr)->DeviceState = SKT_CardBusCard)
  #define Set16BitCardInSocket(SocketPtr)                 ((SocketPtr)->DeviceState = SKT_R2Card)
  #define SetSocketEmpty(SocketPtr)                       ((SocketPtr)->DeviceState = SKT_Empty)
  
  //
  // NT definitions
  //
  #ifdef POOL_TAGGING
  #undef ExAllocatePool
  #define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'cmcP')
  #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)
  
  //
  // VOID
  // MARK_AS_PDO (IN PDEVICE_OBJECT DeviceObject);
  //
  #define MARK_AS_PDO(DeviceObject) ((DeviceObject)->Flags |= DO_BUS_ENUMERATED_DEVICE)
  
  //
  // BOOLEAN
  // PcmciaSetWindowPage(IN FDO_EXTENSION fdoExtension,
  //                        IN PSOCKET Socket,
  //                        IN USHORT Index,
  //                        IN UCHAR Page);
  //
  #define PcmciaSetWindowPage(fdoExtension, Socket, Index, Page)                                          \
      ((DeviceDispatchTable[fdoExtension->DeviceDispatchIndex].SetWindowPage) ?                           \
          (*DeviceDispatchTable[fdoExtension->DeviceDispatchIndex].SetWindowPage)(Socket, Index, Page) :  \
          FALSE)
  
  #define HasWindowPageRegister(fdoExtension) \
      ((BOOLEAN)(DeviceDispatchTable[fdoExtension->DeviceDispatchIndex].SetWindowPage))
  
  //
  // VOID
  // PcmciaSetAudio(
  //  IN PSOCKET Socket,
  //  IN BOOLEAN enable
  //  );
  //
  #define PcmciaSetAudio(fdoExtension, socket, enable)                                                    \
      if ((DeviceDispatchTable[fdoExtension->DeviceDispatchIndex].SetAudio)) {                            \
          (*DeviceDispatchTable[fdoExtension->DeviceDispatchIndex].SetAudio)(socket, enable);             \
          }
  
  //
  // BOOLEAN
  // PcmciaSetZV(
  //  IN PSOCKET Socket,
  //  IN BOOLEAN enable
  //  );
  //
  #define PcmciaSetZV(fdoExtension, socket, enable)                                                       \
      ((DeviceDispatchTable[fdoExtension->DeviceDispatchIndex].SetZV) ?                                   \
          (*DeviceDispatchTable[fdoExtension->DeviceDispatchIndex].SetZV)(socket, enable) :               \
          FALSE)
  
  //
  // Io extension macro to just pass on the Irp to a lower driver
  //
  
  //
  // VOID
  // PcmciaSkipCallLowerDriver(OUT NTSTATUS Status,
  //                                IN    PDEVICE_OBJECT DeviceObject,
  //                                IN    PIRP Irp);
  //
  #define PcmciaSkipCallLowerDriver(Status, DeviceObject, Irp) {          \
                      IoSkipCurrentIrpStackLocation(Irp);                 \
                      Status = IoCallDriver(DeviceObject,Irp);}
  
  //
  // VOID
  // PcmciaCopyCallLowerDriver(OUT NTSTATUS Status,
  //                                IN    PDEVICE_OBJECT DeviceObject,
  //                                IN    PIRP Irp);
  //
  #define PcmciaCopyCallLowerDriver(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) \
          (CardBusExtension(fdoExtension) ?  \
              ((CBReadSocketRegister(fdoExtension->SocketList, CBREG_SKTMASK) & 0xfffffff0) == 0)  \
              : TRUE)
  
  //
  // Registers for accessing indirect access space
  //
  
  #define IAR_CONTROL_LOW     2
  #define IAR_ADDRESS         4
  #define IAR_DATA            8
  
  // Flags defined in "Control"
  #define IARF_COMMON         1
  #define IARF_AUTO_INC       2
  #define IARF_BYTE_GRAN      4
  
  //
  // Vendor specific dispatches for various controllers
  //
  typedef struct _DEVICE_DISPATCH_TABLE {
  
      //
      // Type of controller for which the dispatches apply
      //
      PCMCIA_CONTROLLER_CLASS   ControllerClass;
  
      //
      // Function to vendor-specific initialize controller
      //
      VOID     (*InitController) (IN PFDO_EXTENSION FdoExtension);
  
      //
      // Vendor specific function to set power for a pc-card
      //
      NTSTATUS
      (*SetPower) (
          IN PSOCKET SocketPtr,
          IN BOOLEAN Enable,
          OUT PULONG pDelayTime
          );
  
      //
      // Vendor specific function to set/reset Audio
      //
      VOID
      (*SetAudio) (
          IN PSOCKET Socket,
          IN BOOLEAN Enable
          );
  
      //
      // Vendor specific function to set/reset Zoom Video mode
      //
      BOOLEAN
      (*SetZV) (
          IN PSOCKET Socket,
          IN BOOLEAN Enable
          );
  
      //
      // Vendor specific function to set page register for memory windows
      //
      BOOLEAN (*SetWindowPage) (IN PSOCKET SocketPtr,
                                IN USHORT Index,
                                IN UCHAR Page);
  
  } DEVICE_DISPATCH_TABLE, *PDEVICE_DISPATCH_TABLE;
  
  //
  // Controller types to hardware/device/compatible id mapping
  //
  typedef struct _PCMCIA_ID_ENTRY {
      PCMCIA_CONTROLLER_TYPE ControllerType;
      PUCHAR                Id;
  } PCMCIA_ID_ENTRY, *PPCMCIA_ID_ENTRY;
  
  //
  // Exca & cardbus register init structure used to
  // initialize the registers on start up
  //
  typedef struct _PCMCIA_REGISTER_INIT {
      //
      // Register offset
      //
      ULONG Register;
      //
      // value: EXCA regs need only a byte,
      // so only the LSB of this field is used for
      // initializing them. Cardbus regs need the
      // entire DWORD
      //
      ULONG Value;
  } PCMCIA_REGISTER_INIT, *PPCMCIA_REGISTER_INIT;
  
  //
  // Structure which defines special per-device configuration parameters
  //
  
  typedef struct _PCMCIA_DEVICE_CONFIG_PARAMS {
      UCHAR ValidEntry;
      UCHAR DeviceType;
      USHORT ManufacturerCode;
      USHORT ManufacturerInfo;
      USHORT CisCrc;
      USHORT ConfigDelay1;
      USHORT ConfigDelay2;
      USHORT ConfigDelay3;
      UCHAR ConfigFlags;
  } PCMCIA_DEVICE_CONFIG_PARAMS, *PPCMCIA_DEVICE_CONFIG_PARAMS;
  
  //
  // 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;
  
  //
  // Defines used both by data.c and registry.c
  //
  
  #define PCMCIA_REGISTRY_ISA_IRQ_RESCAN_COMPLETE      L"IsaIrqRescanComplete"
  
  #endif  //_PCMCIAPRT_
  