3 Card Services subfunction descriptions

Contents of this section

Card Services calls have the general form:

#include "cs_types.h"
#include "cs.h"

int CardServices(int subfunc, void *arg1, void *arg2, ...);

Some Card Services functions require additional #include statements. The particular subfunction determines the number of expected arguments. A return code of CS_SUCCESS indicates that a call succeeded. Other return codes indicate errors.

3.1 Client management functions

Device drivers that use Card Services functions are called ``clients''. A device driver should use the RegisterClient call to get a client handle before using other services. Most Card Services functions will take this client handle as an argument. Before unloading, drivers should also unregister with DeregisterClient.

RegisterClient

int CardServices(RegisterClient, client_handle_t *client, client_reg_t *reg);
The client_reg_t data structure is given by:
typedef struct client_reg_t {
        dev_info_t              *dev_info;
        u_long                  Attributes;
        u_long                  EventMask;
        int                     (*event_handler)(event_t event, int priority,
                                                 event_callback_args_t *args);
        event_callback_args_t   event_callback_args;
        u_long                  Version;
} client_reg_t;

RegisterClient establishes a link between a client driver and Card Services, and connects the client with an appropriate socket. The dev_info parameter is used by Card Services to match the client with a socket and function; this correspondence is normally established by Driver Services via a call to BindDevice. If successful, a client handle will be returned in client.

The following flags can be specified in Attributes:

INFO_MASTER_CLIENT

For use only by the Driver Services client. Among other things, specifies that this client should not be automatically unbound when a card is ejected from this socket.

INFO_IO_CLIENT

Specifies that this client is an IO card driver.

INFO_MTD_CLIENT

Specifies that this client is a Memory Technology Driver.

INFO_MEM_CLIENT

Specifies that this client is a memory card driver.

INFO_CARD_SHARE

Included for compatibility, has no effect.

INFO_CARD_EXCL

Included for compatibility, has no effect.

EventMask specifies what events this client should be notified of. The event_handler entry point will be called by Card Services when an event in EventMask is processed. The event_handler_args structure is a template for the structure that will be passed to the event handler. The Version parameter identifies the Card Services version level that this driver expects; it is currently ignored.

A driver should be prepared to handle Card Services events before calling RegisterClient. This call will always generate a CS_REGISTRATION_COMPLETE event, and may also generate an artificial CS_CARD_INSERTION event if the socket is currently occupied.

Return codes:

CS_OUT_OF_RESOURCE

An appropriate socket could not be found for this driver.

DeregisterClient

int CardServices(DeregisterClient, client_handle_t client);

DeregisterClient severs the connection between a client and Card Services. It should be called after the client has freed any resources it has allocated. Once a connection is broken, it cannot be reestablished until after another call to BindDevice.

Return codes:

CS_BAD_HANDLE

The client handle is invalid.

CS_IN_USE

The client still has allocated resources, such as IO port windows or an interrupt, or the socket configuration is locked.

SetEventMask

int CardServices(SetEventMask, client_handle_t client, eventmask_t *mask);
The eventmask_t structure is given by:
typedef struct eventmask_t {
        u_long          Attributes;
        u_long          EventMask;
} eventmask_t;

SetEventMask updates the mask that determines which events this client will be notified of.

Return codes:

CS_BAD_HANDLE

The client handle is invalid.

BindDevice

int CardServices(BindDevice, bind_req_t *req);
The bind_req structure is given by:
typedef struct bind_req_t {
        socket_t        Socket;
        u_char          Function;
        dev_info_t      *dev_info;
} bind_req_t;

BindDevice associates a device driver with a particular socket. It is normally called by Driver Services after a newly inserted card has been identified. Once a driver has been bound to a socket, it will be eligible to register as a client of that socket. Note that this call does not take a client handle as an argument. This is the only Card Services call that takes a socket number as an argument.

The Function field specifies which function(s) of a multifunction card are to be bound to this driver. Function numbers correspond to entries in the card's CISTPL_LONGLINK_MFC tuple. If Function is set to BIND_FN_ALL, the driver will be bound to all card functions. A driver will only be able to access CIS tuples corresponding to functions for which it is bound.

Return codes:

CS_BAD_SOCKET

The specified socket number is invalid.

3.2 Socket state control

These functions are more or less concerned with getting and setting the current operating state of a socket. GetStatus returns the current socket state. ResetCard is used to send a hard reset signal to a socket. SuspendCard and ResumeCard can be used to power down and power up a socket without releasing the drivers currently bound to that socket. EjectCard and InsertCard essentially mimic real card ejection and insertion events.

GetStatus

int CardServices(GetStatus, client_handle_t client, status_t *status);
The status_t data structure is given by:
typedef struct status_t {
        u_long          CardState;
        u_long          SocketState;
} status_t;

GetStatus returns the current status of a client's socket. For cards that are configured in IO mode, GetStatus uses the Pin Replacement Register and Extended Status Register to determine the card status. The following flags are defined in CardState:

CS_EVENT_CARD_DETECT

Specifies that the socket is occupied.

CS_EVENT_WRITE_PROTECT

Specifies that the card is currently write protected.

CS_EVENT_BATTERY_LOW

Specifies that the card battery is low.

CS_EVENT_BATTERY_DEAD

Specifies that the card battery is dead.

CS_EVENT_READY_CHANGE

Specifies that the card is ready.

CS_EVENT_PM_SUSPEND

Specifies that the socket is suspended.

CS_EVENT_REQUEST_ATTENTION

Specifies that the request attention bit in the extended status register is set.

SocketState is currently unused, but in theory, it should latch changes in the state of the fields in CardState.

Return codes:

CS_BAD_HANDLE

The client handle is invalid.

ResetCard

int CardServices(ResetCard, client_handle_t client);

ResetCard requests that a client's socket be reset. When this call is made, Card Services sends all clients a CS_EVENT_RESET_REQUEST event. If any client rejects the request, Card Services sends the initiating client a CS_EVENT_RESET_COMPLETE event with event_callback_args.info set to the return code of the client that rejected the request.

If all clients agree to the request, Card Services sends a CS_EVENT_RESET_PHYSICAL event, then resets the socket. When the socket signals that it is ready, a CS_EVENT_CARD_RESET event is generated. Finally, a CS_EVENT_RESET_COMPLETE event is sent to the initiating client, with event_callback_args.info set to zero.

Return codes:

CS_BAD_HANDLE

The client handle is invalid.

CS_NO_CARD

The socket assigned to this client is currently vacant.

CS_IN_USE

This socket is currently being reset.

SuspendCard

int CardServices(SuspendCard, client_handle_t client);

Card Services sends all clients CS_EVENT_PM_SUSPEND events, then shuts down and turns off power to the socket.

Return codes:

CS_BAD_HANDLE

The client handle is invalid.

CS_NO_CARD

The socket assigned to this client is currently vacant.

CS_IN_USE

This socket is already suspended.

ResumeCard

int CardServices(ResumeCard, client_handle_t client);

After restoring power to the socket, Card Services will notify all clients with CS_EVENT_PM_RESUME events.

Return codes:

CS_BAD_HANDLE

The client handle is invalid.

CS_NO_CARD

The socket assigned to this client is currently vacant.

CS_IN_USE

This socket is not currently suspended.

EjectCard

int CardServices(EjectCard, client_handle_t client);

Card Services sends eject events to all clients, then shuts down and turns off power to the socket. All clients except for Driver Services will be unlinked from the socket.

Return codes:

CS_BAD_HANDLE

The client handle is invalid.

CS_NO_CARD

The socket assigned to this client is currently vacant.

InsertCard

int CardServices(InsertCard, client_handle_t client);

Card Services sends insertion events to all clients of this socket (normally, only Driver Services).

Return codes:

CS_BAD_HANDLE

The client handle is invalid.

CS_NO_CARD

The socket assigned to this client is currently vacant.

CS_IN_USE

The socket has already been configured.

3.3 IO card configuration calls

The normal order of events is for a driver to reserve IO ports and an interrupt line with calls to RequestIO and RequestIRQ, then to call RequestConfiguration to actually configure the socket. If any of these calls fails, a driver should be sure to release any resources it successfully reserved.

Multifunction cards can have separate configurations for each card function. However, the configurations do need to be consistent with one another. While each card function has its own set of configuration registers, each socket has only a single interrupt line and can only map two contiguous ranges of IO ports.

RequestIO

int CardServices(RequestIO, client_handle_t client, io_req_t *req);
The io_req_t data structure is given by:
typedef struct io_req_t {
        ioaddr_t        BasePort1;
        ioaddr_t        NumPorts1;
        u_long          Attributes1;
        ioaddr_t        BasePort2;
        ioaddr_t        NumPorts2;
        u_long          Attributes2;
        u_long          IOAddrLines;
} io_req_t;

RequestIO reserves IO port windows for a card. If BasePort1 is non-zero, it specifies the IO port address of the window to be reserved; if it is zero, Card Services will find an available window and set BasePort1 to this address. If NumPorts2 is non-zero, a second IO port window will also be reserved. IOAddrLines specifies the number of address lines that are actually decoded by the PCMCIA card; this is not currently used.

With multifunction cards, this call will allocate IO ports for each card function in such a way that all a card's ports can be mapped by the two low-level IO port windows associated with each physical socket. For example, if the drivers for a hypothetical four-function card each attempt to allocate one IO window of 8 ports, Card Services will consolidate these into a single contiguous 32-port block.

This call does not actually configure a socket's IO windows: this is done by a subsequent call to RequestConfiguration.

The following flags can be specified in Attributes1 and Attributes2:

IO_DATA_PATH_WIDTH

This field may either be IO_DATA_PATH_WIDTH_16 for 16-bit access, or IO_DATA_PATH_WIDTH_8 for 8-bit access, or IO_DATA_PATH_WIDTH_AUTO to dynamically size the bus based on the access size.

Return codes:

CS_BAD_HANDLE

The client handle is invalid.

CS_NO_CARD

The socket assigned to this client is currently vacant.

CS_IN_USE

This socket's IO windows have already been reserved.

CS_CONFIGURATION_LOCKED

This socket's configuration has been locked by a call to RequestConfiguration.

CS_BAD_ATTRIBUTE

An unsupported attribute flag was specified.

ReleaseIO

int CardServices(ReleaseIO, client_handle_t client, io_req_t *req);

ReleaseIO un-reserves IO port windows allocated by a previous call to RequestIO. The req parameter should be the same one passed to RequestIO. If several card functions are sharing a larger IO port window, ports released by one function may not become available for other uses until all card functions have released their IO ports.

Return codes:

CS_BAD_HANDLE

The client handle is invalid.

CS_CONFIGURATION_LOCKED

This socket's configuration has been locked by a call to RequestConfiguration. The configuration should be released before calling ReleaseIO.

CS_BAD_ARGS

The parameters in req do not match the parameters passed to RequestIO.

RequestIRQ

int CardServices(RequestIRQ, client_handle_t client, irq_req_t *req);
The irq_req_t structure is given by:
typedef struct irq_req_t {
        u_long          Attributes;
        u_long          AssignedIRQ;
        u_long          IRQInfo1, IRQInfo2;
        void            *(Handler)(int, struct pt_regs *);
} irq_req_t;

RequestIRQ reserves an interrupt line for use by a PCMCIA card. The IRQInfo1 and IRQInfo2 fields correspond to the interrupt description bytes in a CFTABLE_ENTRY tuple. If IRQ_INFO2_VALID is set in IRQInfo1, then IRQInfo2 is a bit-mapped mask of allowed interrupt values. Each bit corresponds to one interrupt line: bit 0 = irq 0, bit 1 = irq 1, etc. So, a mask of 0x1100 would mean that interrupts 12 and 8 could be used. If IRQ_INFO2_VALID is not set, IRQInfo1 is just the desired interrupt number. If the call is successful, the reserved interrupt is returned in AssignedIRQ.

If the IRQ_HANDLER_PRESENT flag is set, then this call will also install the interrupt handler specified by Handler. With multifunction cards, the interrupt will be allocated in shared mode, and the handler(s) have responsibility for determining which card function(s) require attention when an interrupt is received. If a client instead bypasses Card Services to install its own interrupt service routine, it should allocate the interrupt in shared mode if this client could be bound to a multifunction card. The socket interrupt will not be actually enabled until a call to RequestConfiguration.

The following flags can be specified in Attributes:

IRQ_FORCED_PULSE

Specifies that the interrupt should be configured for pulsed mode, rather than the default level mode.

IRQ_TYPE_TIME

Specifies that this interrupt can be time-shared with other Card Services drivers. Only one driver should enable the interrupt at any time.

IRQ_FIRST_SHARED

In conjunction with IRQ_TYPE_TIME, this should be set by the first driver requesting a shared interrupt.

IRQ_HANDLER_PRESENT

Indicates that the Handler field points to an interrupt service routine that should be installed.

Return codes:

CS_BAD_HANDLE

The client handle is invalid.

CS_NO_CARD

The socket assigned to this client is currently vacant.

CS_IN_USE

An interrupt has already been reserved for this socket, or the requested interrupt is unavailable.

CS_CONFIGURATION_LOCKED

This card function's configuration has been locked by a call to RequestConfiguration.

CS_BAD_ATTRIBUTE

An unsupported attribute flag was specified.

ReleaseIRQ

int CardServices(ReleaseIRQ, client_handle_t client, irq_req_t *req);

ReleaseIRQ un-reserves an interrupt assigned by an earlier call to RequestIRQ. The req structure should be the same structure that was passed to RequestIRQ. If a handler was specified in the RequestIRQ call, it will be unregistered at this time.

Return codes:

CS_BAD_HANDLE

The client handle is invalid.

CS_CONFIGURATION_LOCKED

This socket's configuration has been locked by a call to RequestConfiguration. The configuration should be released before calling ReleaseIRQ.

CS_BAD_IRQ

The parameters in req do not match the parameters passed to RequestIRQ.

RequestConfiguration

int CardServices(RequestConfiguration, client_handle_t client, config_req_t *req);
The config_req_t structure is given by:
typedef struct config_req_t {
        u_long          Attributes;
        u_long          Vcc, Vpp1, Vpp2;
        u_long          IntType;
        caddr_t         ConfigBase;
        u_char          Status, Pin, Copy, ExtStatus;
        u_char          ConfigIndex;
        u_long          Present;
} config_req_t;

RequestConfiguration is responsible for actually configuring a socket. This includes setting voltages, setting CIS configuration registers, setting up IO port windows, and setting up interrupts.

IntType specifies the type of interface to use for this card. It may either be INT_MEMORY or INT_MEMORY_AND_IO. Voltages are specified in units of 1/10 volt. Currently, Vpp1 must equal Vpp2.

With multifunction cards, each card function is configured separately. Each function has its own set of CIS configuration registers. However, all functions must be configured with the same power and interface settings.

The following flags can be specified in Attributes. DMA and speaker control are not supported on all systems.

CONF_ENABLE_IRQ

Enable the IO interrupt reserved by a previous call to RequestIRQ.

CONF_ENABLE_DMA

Enable DMA accesses for this socket.

CONF_ENABLE_SPKR

Enable speaker output from this socket.

The Present parameter is a bit map specifying which CIS configuration registers are implemented by this card. ConfigBase gives the offset of the configuration registers in attribute memory. The following registers can be specified:

PRESENT_OPTION

Specifies that the Configuration Option Register is present. The COR register will be set using the ConfigIndex parameter.

PRESENT_STATUS

Specifies that the Card Configuration and Status Register is present. The CCSR will be initialized with the Status parameter.

PRESENT_PIN_REPLACE

Specifies that the Pin Replacement Register is present. The PRR will be initialized with the Pin parameter.

PRESENT_COPY

Specifies that the Socket and Copy Register is present. The SCR will be initialized with the Copy parameter.

PRESENT_EXT_STATUS

Specifies that the Extended Status Register is present. The ESR will be initialized with the ExtStatus parameter.

Return codes:

CS_BAD_HANDLE

The client handle is invalid.

CS_NO_CARD

The socket assigned to this client is currently vacant.

CS_OUT_OF_RESOURCE

Card Services was unable to allocate a memory window to access the card's configuration registers.

CS_CONFIGURATION_LOCKED

This card's configuration has already been locked by another call to RequestConfiguration.

CS_BAD_VCC

The requested Vcc voltage is not supported.

CS_BAD_VPP

The requested Vpp1/Vpp2 voltage is not supported.

ModifyConfiguration

int CardServices(ModifyConfiguration, client_handle_t client, modconf_t *mod);
The modconf_t structure is given by:
typedef struct modconf_t {
        u_long          Attributes;
        u_long          Vcc, Vpp1, Vpp2;
} modconf_t;

ModifyConfiguration modifies some attributes of a socket that has been configured by a call to RequestConfiguration.

The following flags can be specified in Attributes:

CONF_IRQ_CHANGE_VALID

Indicates that the CONF_ENABLE_IRQ setting should be updated.

CONF_ENABLE_IRQ

Specifies that IO interrupts should be enabled for this socket.

CONF_VCC_CHANGE_VALID

Indicates that Vcc should be updated.

CONF_VPP1_CHANGE_VALID

Indicates that Vpp1 should be updated.

CONF_VPP2_CHANGE_VALID

Indicates that Vpp2 should be updated.

Currently, Vpp1 and Vpp2 must always have the same value. So, the two values must always be changed at the same time.

Return codes:

CS_BAD_HANDLE

The client handle is invalid.

CS_NO_CARD

The socket assigned to this client is currently vacant.

CS_CONFIGURATION_LOCKED

This actually means that this socket has not been locked.

CS_BAD_VCC

The requested Vcc voltage is not supported.

CS_BAD_VPP

The requested Vpp1/Vpp2 voltage is not supported.

ReleaseConfiguration

int CardServices(ReleaseConfiguration, client_handle_t client, config_req_t *req);

ReleaseConfiguration un-configures a socket previously set up by a call to RequestConfiguration. The req parameter should be the same one used to configure the socket.

Return codes:

CS_BAD_HANDLE

The window handle is invalid, or the socket is not configured.

GetConfigurationInfo

int CardServices(GetConfigurationInfo, client_handle_t client, config_info_t *config);
The config_info_t structure is given by:
typedef struct config_info_t {
        u_char          Function;
        u_long          Attributes;
        u_long          Vcc, Vpp1, Vpp2;
        u_long          IntType;
        caddr_t         ConfigBase;
        u_char          Status, Pin, Copy, Option, ExtStatus;
        u_long          Present;
        u_long          AssignedIRQ;
        u_long          IRQAttributes;
        ioaddr_t        BasePort1;
        ioaddr_t        NumPorts1;
        u_long          Attributes1;
        ioaddr_t        BasePort2;
        ioaddr_t        NumPorts2;
        u_long          Attributes2;
        u_long          IOAddrLines;
} config_info_t;

GetConfigurationInfo returns the current socket configuration as it was set up by RequestIO, RequestIRQ, and RequestConfiguration. It can only be applied to a fully configured socket. For normal clients bound to a single card function, the Function field is ignored, and data for that client's assigned function is returned. For clients bound to BIND_FN_ALL, this field specifies which function's configuration data should be returned.

Return codes:

CS_BAD_HANDLE

The window handle is invalid, or the socket is not configured.

CS_NO_CARD

The socket assigned to this client is currently vacant.

CS_CONFIGURATION_LOCKED

This actually means that the configuration has not been locked.

3.4 Card Information Structure (CIS) calls

The definition of the Card Information Structure (CIS) is the darkest chapter of the PCMCIA standard. All version 2 PCMCIA cards should have a CIS, which describes the card and how it should be configured. The CIS is a linked list of ``tuples'' in the card's attribute memory space. Each tuple consists of an identification code, a length byte, and a series of data bytes. The layout of the data bytes for some tuple types is absurdly complicated, in an apparent effort to use every last bit.

The ValidateCIS call checks to see if a card has a reasonable CIS. The GetFirstTuple and GetNextTuple calls are used to step through CIS tuple lists. GetTupleData extracts data bytes from a tuple. And ParseTuple interprets a limited number of particularly important tuple types.

GetFirstTuple, GetNextTuple

#include "cistpl.h"

int CardServices(GetFirstTuple, client_handle_t client, tuple_t *tuple);
int CardServices(GetNextTuple, client_handle_t client, tuple_t *tuple);
The tuple_t data structure is given by:
typedef struct tuple_t {
        u_long          Attributes;
        cis_data_t      DesiredTuple;
        u_long          Flags;
        cisdata_t       TupleCode;
        u_long          TupleLink;
        cisdata_t       TupleOffset;
        cisdata_t       TupleDataMax;
        cisdata_t       TupleDataLen;
        cisdata_t       *TupleData;
} tuple_t;

GetFirstTuple searches a card's CIS for the first tuple code matching DesiredTuple. The special code RETURN_FIRST_TUPLE will match the first tuple of any kind. If successful, TupleCode is set to the code of the first matching tuple found, and TupleLink is the address of this tuple in attribute memory.

GetNextTuple is like GetFirstTuple, except that given a tuple_t structure returned by a previous call to GetFirstTuple or GetNextTuple, it will return the next tuple matching DesiredTuple.

These functions will automatically traverse any link tuples found in the CIS. For multifunction cards having a CISTPL_LONGLINK_MFC tuple, these functions will automatically follow just the CIS chain specific to a client driver's assigned function. If a client was bound to BIND_FN_ALL, then all tuples will be returned.

The following flags can be specified in Attributes:

TUPLE_RETURN_LINK

Indicates that link tuples (CISTPL_LONGLINK_A, CISTPL_LONGLINK_C, CISTPL_LONGLINK_MFC, CISTPL_NOLINK, CISTPL_LINKTARGET) should be returned. Normally these tuples are processed silently.

Return codes:

CS_BAD_HANDLE

The client handle is invalid.

CS_OUT_OF_RESOURCE

Card Services was unable to set up a memory window to map the card's CIS.

CS_NO_MORE_ITEMS

There were no tuples matching DesiredTuple.

GetTupleData

#include "cistpl.h"

int CardServices(GetTupleData, client_handle_t client, tuple_t *tuple);

GetTupleData extracts a series of data bytes from the specified tuple, which must have been returned by a previous call to GetFirstTuple or GetNextTuple. A maximum of TupleDataMax bytes will be copied into the TupleData buffer, starting at an offset of TupleOffset bytes. The number of bytes copied is returned in TupleDataLen.

Return codes:

CS_BAD_HANDLE

The client handle is invalid.

CS_OUT_OF_RESOURCE

Card Services was unable to set up a memory window to map the card's CIS.

CS_NO_MORE_ITEMS

The tuple does not contain any more data. TuppleOffset is greater than or equal to the length of the tuple.

ParseTuple

#include "cistpl.h"

int CardServices(ParseTuple, client_handle_t client, tuple_t *tuple, cisparse_t *parse);
The cisparse_t data structure is given by:
typedef union cisparse_t {
        cistpl_device_t         device;
        cistpl_checksum_t       checksum;
        cistpl_longlink_t       longlink;
        cistpl_longlink_mfc_t   longlink_mfc;
        cistpl_vers_1_t         version_1;
        cistpl_altstr_t         altstr;
        cistpl_jedec_t          jedec;
        cistpl_manfid_t         manfid;
        cistpl_funcid_t         funcid;
        cistpl_config_t         config;
        cistpl_cftable_entry_t  cftable_entry;
        cistpl_device_geo_t     device_geo;
        cistpl_vers_2_t         version_2;
        cistpl_org_t            org;
} cisparse_t;

ParseTuple interprets tuple data returned by a previous call to GetTupleData. The structure returned depends on the type of the parsed tuple. See the cistpl.h file for these structure definitions; some of them are quite complex.

Return codes:

CS_BAD_TUPLE

An error was encounted during parsing of this tuple. The tuple may be incomplete, or may be formatted incorrectly.

CS_UNSUPPORTED_FUNCTION

ParseTuple cannot parse the specified tuple type.

ValidateCIS

int CardServices(ValidateCIS, client_handle_t client, cisinfo_t *cisinfo);
The cisinfo_t structure is given by:
typedef struct cisinfo_t {
        u_long          Chains;
} cisinfo_t;

ValidateCIS attempts to verify that a card has a reasonable Card Information Structure. It returns the number of tuples found in Chains. If the CIS appears to be uninterpretable, Chains will be set to 0.

Return codes:

CS_BAD_HANDLE

The client handle is invalid.

CS_OUT_OF_RESOURCE

Card Services was unable to set up a memory window to map the card's CIS.

3.5 Memory window control

Each socket can have up to four active memory windows, mapping portions of PCMCIA memory into the host system address space. A PCMCIA device can address at most 16MB of both common and attribute memory. Windows should typically be sized to a power of two, and be aligned on a boundary that is a multiple of the window size in both the host and card address spaces.

A memory window is initialized by a call to RequestWindow. Some window attributes can be modified using ModifyWindow. The segment of card memory mapped to the window can be modified using MapMemPage. And windows are released with ReleaseWindow. Unlike almost all other Card Services subfunctions, the memory window functions normally act on window_handle_t handles, rather than client_handle_t handles.

RequestWindow

int CardServices(RequestWindow, client_handle_t *handle, win_req_t *req);
The win_req_t structure is given by:
typedef struct win_req_t {
        u_long          Attributes;
        caddr_t         Base;
        u_long          Size;
        u_long          AccessSpeed;
} win_req_t;

RequestWindow maps a window of card memory into system memory. On entry, the handle parameter should point to a valid client handle. On return, this will be replaced by a window_handle_t handle that should be used in subsequent calls to ModifyWindow, MapMemPage, and ReleaseWindow.

The following flags can be specified in Attributes:

WIN_MEMORY_TYPE

This field can be either WIN_MEMORY_TYPE_CM for common memory, or WIN_MEMORY_TYPE_AM for attribute memory.

WIN_DATA_WIDTH

Either WIN_DATA_WIDTH_16 for 16-bit accesses, or WIN_DATA_WIDTH_8 for 8-bit access.

WIN_ENABLE

If this is set, the window is turned on.

WIN_USE_WAIT

Specifies that the controller should observe the card's MWAIT signal.

Base specifies the base address of the window in system memory. If NULL, Card Services will set Base to the first available window address. Size specifies the window size in bytes. AccessSpeed specifies the memory access speed, in nanoseconds.

Return codes:

CS_BAD_HANDLE

The client handle is invalid.

CS_NO_CARD

The socket assigned to this client is currently vacant.

CS_BAD_ATTRIBUTE

An unsupported window attribute was requested.

CS_OUT_OF_RESOURCE

The maximum number of memory windows for this socket are already being used.

CS_IN_USE

RequestWindow was unable to find a free window of system memory.

ModifyWindow

int CardServices(ModifyWindow, window_handle_t, modwin_t *);
The modwin_t structure is given by:
typedef struct modwin_t {
        u_long          Attributes;
        u_long          AccessSpeed;
} modwin_t;

ModifyWindow modifies the attributes of a window handle returned by a previous call to RequestWindow. The following attributes can be changed:

WIN_MEMORY_TYPE

This field can be either WIN_MEMORY_TYPE_CM for common memory, or WIN_MEMORY_TYPE_AM for attribute memory.

WIN_DATA_WIDTH

Either WIN_DATA_WIDTH_16 for 16-bit accesses, or WIN_DATA_WIDTH_8 for 8-bit access.

WIN_ENABLE

If this is set, the window is turned on.

AccessSpeed gives the new memory access speed, in nanoseconds.

Return codes:

CS_BAD_HANDLE

The window handle is invalid.

MapMemPage

int CardServices(MapMemPage, window_handle_t, memreq_t *);
The memreq_t structure is given by:
typedef struct memreq_t {
        u_long          CardOffset;
        page_t          Page;
} memreq_t;

MapMemPage sets the address of card memory that is mapped to the base of a memory window to CardOffset. The window should have been created by a call to RequestWindow. The Page parameter is not implemented in this version and should be set to 0.

Return codes:

CS_BAD_HANDLE

The window handle is invalid.

CS_BAD_PAGE

The Page value was non-zero.

ReleaseWindow

int CardServices(ReleaseWindow, window_handle_t handle);

ReleaseWindow releases a memory window previously allocated with RequestWindow.

Return codes:

CS_BAD_HANDLE

The window handle is invalid.

3.6 Bulk Memory Services

Bulk memory services provide a higher level interface for accessing memory regions than that provided by the memory window services. A client using bulk memory calls does not need to know anything about the underlying memory organization or access methods. The device-specific code is packaged into a special Card Services client called a Memory Technology Driver.

RegisterMTD

int CardServices(RegisterMTD, client_handle_t handle, mtd_reg_t *reg);

The mtd_reg_t data structure is given by:

typedef union mtd_reg_t {
        u_long          Attributes;
        u_long          Offset;
        u_long          MediaID;
} mtd_reg_t;

RegisterMTD informs Card Services that this client MTD will handle requests for a specified memory region. The Offset field specifies the starting address of the memory region. The following fields are defined in Attributes:

REGION_TYPE

Either REGION_TYPE_CM for common memory, or REGION_TYPE_AM for attribute memory.

The MediaID field is recorded by Card Services, and will be passed to the MTD as part of any request that references this memory region.

Once an MTD is bound to a memory region by a call to RegisterMTD, it will remain bound until the MTD calls DeregisterClient.

Return codes:

CS_BAD_HANDLE

The client handle is invalid.

CS_BAD_OFFSET

Either the offset does not match a valid memory region for this card, or another MTD has already registered for this region.

GetFirstRegion, GetNextRegion

int CardServices(GetFirstRegion, client_handle_t handle, region_info_t *region);
int CardServices(GetNextRegion, client_handle_t handle, region_info_t *region);

The region_info_t data structure is given by:

typedef union region_info_t {
        u_long          Attributes;
        u_long          CardOffset;
        u_long          RegionSize;
        u_long          AccessSpeed;
        u_long          BlockSize;
        u_long          PartMultiple;
        u_char          JedecMfr, JedecInfo;
        memory_handle_t next;
} region_info_t;

GetFirstRegion and GetNextRegion summarize the information in a card's CISTPL_DEVICE, CISTPL_JEDEC, and CISTPL_DEVICE_GEO tuples. CardOffset gives the starting address of a region. RegionSize gives the length of the region in bytes. AccessSpeed gives the device's cycle time in nanoseconds. BlockSize gives the erase block size in bytes, and PartMultiple gives the minimum granularity of partitions on this device, in units of BlockSize. JedecMfr and JedecInfo give the JEDEC identification bytes for this region.

The following fields are defined in Attributes:

REGION_TYPE

Either REGION_TYPE_CM for common memory, or REGION_TYPE_AM for attribute memory.

When these calls are made by an MTD client, only regions that have been bound to this client through calls to BindMTD will be returned.

Return codes:

CS_BAD_HANDLE

The client handle is invalid.

CS_NO_MORE_ITEMS

No more memory regions are defined.

OpenMemory

int CardServices(OpenMemory, client_handle_t *handle, open_mem_t *req);
The open_mem_t structure is given by:
typedef struct open_mem_t {
        u_long          Attributes;
        u_long          Offset;
} open_mem_t;

OpenMemory is used to obtain a handle for accessing a memory region via the other bulk memory services. The Offset field specifies the base address of the region to be accessed. If successful, the client handle argument is replaced by the new memory handle.

The following fields are defined in Attributes:

MEMORY_TYPE

Either MEMORY_TYPE_CM for common memory, or MEMORY_TYPE_AM for attribute memory.

MEMORY_EXCLUSIVE

Specifies that this client should have exclusive access to this memory region.

Return codes:

CS_BAD_HANDLE

The window handle is invalid.

CS_BAD_OFFSET

Either the offset does not specify a valid region, or the region does not have an associated MTD to service bulk memory requests.

CloseMemory

int CardServices(CloseMemory, memory_handle_t handle);

CloseMemory releases a memory handle returned by a previous call to OpenMemory. A client should release all memory handles before calling DeregisterClient.

Return codes:

CS_BAD_HANDLE

The memory handle is invalid.

ReadMemory, WriteMemory

int CardServices(ReadMemory, memory_handle_t handle mem_op_t *req, caddr_t buf);
int CardServices(WriteMemory, memory_handle_t handle, mem_op_t *req, caddr_t buf);
The mem_io_t structure is given by:
typedef struct mem_op_t {
        u_long          Attributes;
        u_long          Offset;
        u_long          Count;
} mem_op_t;

ReadMemory and WriteMemory read from and write to a card memory area defined by the specified memory handle, returned by a previous call to OpenMemory. The Offset field gives the offset of the operation from the start of the card memory region. The Count field gives the number of bytes to be transferred. The buf field points to a host memory buffer to be the destination for a ReadMemory operation, or the source for a WriteMemory operation.

The following fields are defined in Attributes:

MEM_OP_BUFFER

Either MEM_OP_BUFFER_USER if the host buffer is in a user memory segment, or MEM_OP_BUFFER_KERNEL if the host buffer is in kernel memory.

MEM_OP_DISABLE_ERASE

Specifies that a card area should not be erased before it is written.

MEM_OP_VERIFY

Specifies verification of write operations.

Return codes:

CS_BAD_HANDLE

The window handle is invalid.

CS_BAD_OFFSET

The specified card offset is beyond the end of the memory region.

CS_BAD_SIZE

The specified transfer size extends past the end of the memory region.

RegisterEraseQueue

int CardServices(RegisterEraseQueue, client_handle_t *handle, eraseq_hdr_t *header);
The eraseq_hdr_t structure is given by:
typedef struct erase_queue_header_t {
        int             QueueEntryCount;
        eraseq_entry_t  *QueueEntryArray;
} eraseq_hdr_t;

This call registers a queue of erase requests with Card Services. An eraseq_handle_t handle will be returned in *handle. When this client calls CheckEraseQueue, Card Services will scan the queue and begin asynchronous processing of any new requests.

The eraseq_entry_t structure is given by:

typedef struct eraseq_entry_t {
        memory_handle_t Handle;
        u_char          State;
        u_long          Size;
        u_long          Offset;
        u_long          *Optional;
} eraseq_entry_t;

In an erase queue entry, the Header field should be a memory handle returned by a previous call to OpenMemory. The State field indicates the state of the erase request. The following values are defined:

ERASE_QUEUED

Set by the client to indicate that this is a new request.

ERASE_IDLE

Set by the client to indicate that this entry is not active.

ERASE_PASSED

Set by the MTD to indicate successful completion.

ERASE_FAILED

Set by the MTD to indicate that the erase failed.

ERASE_MEDIA_WRPROT

Indicates that the region is write protected.

ERASE_NOT_ERASABLE

Indicates that this region does not support erase operations.

ERASE_BAD_OFFSET

Indicates that the erase does not start on an erase block boundary.

ERASE_BAD_SIZE

Indicates that the requested erase size is not a multiple of the erase block size.

ERASE_BAD_SOCKET

Set by the MTD to indicate that there is no card present.

Additionally, the macro ERASE_IN_PROGRESS() will return a true condition for values of State that indicate an erase is being processed.

The Size field gives the size of the erase request in bytes. The Offset field gives the offset from the start of the region. The size and offset should be aligned to erase block boundaries. The Optional field is not used by Card Services and may be used by the client driver.

Return codes:

CS_BAD_HANDLE

The client handle is invalid.

DeregisterEraseQueue

int CardServices(DeregisterEraseQueue, eraseq_handle_t handle);

DeregisterEraseQueue frees a queue previously registered by a call to RegisterEraseQueue. If there are any pending requests in the specified queue, the call will fail.

Return codes:

CS_BAD_HANDLE

The erase queue handle is invalid.

CS_BUSY

The erase queue has erase requests pending.

CheckEraseQueue

int CardServices(CheckEraseQueue, eraseq_handle_t handle);

This call notifies Card Services that there are new erase requests in a queue previously registered with RegisterEraseQueue.

Typically, a client will initially assign each erase queue entry the state value ERASE_IDLE. When new requests are added to the queue, the client will set their states to ERASE_QUEUED, and call CheckEraseQueue. When the client is notified of an erase completion event, it will check the state field to determine whether the request was successful.

Return codes:

CS_BAD_HANDLE

The erase queue handle is invalid.

3.7 Miscellaneous calls

GetCardServicesInfo

int CardServices(GetCardServicesInfo, servinfo_t *info);
The servinfo_t structure is given by:
typedef struct servinfo_t {
        char            Signature[2];
        u_long          Count;
        u_long          Revision;
        u_long          CSLevel;
        char            *VendorString;
} servinfo_t;

GetCardServicesInfo returns revision information about this version of Card Services. Signature is set to ``CS''. Count is set to the number of sockets currently configured. Revision is set to the revision level of the Card Services package, and CSLevel is set to the level of compliance with the PCMCIA standard. These are encoded as BCD numbers. VendorString is set to point to an RCS identification string.

This call always succeeds.

AccessConfigurationRegister

#include "cisreg.h"

int CardServices(AccessConfigurationRegister, client_handle_t handle, conf_reg_t *reg);
The conf_reg_t structure is given by:
typedef struct conf_reg_t {
        u_char          Function;
        u_long          Action;
        off_t           Offset;
        u_long          Value;
} conf_reg_t;

For normal clients bound to a specific card function, the Function field is ignored. For clients bound to BIND_FN_ALL, this field specifies which function's configuration registers should be accessed.

The Action parameter can be one of the following:

CS_READ

Read the specified configuration register and return Value.

CS_WRITE

Write Value to the specified configuration register.

AccessConfigurationRegister either reads or writes the one-byte CIS configuration register at offset Offset from the start of the config register area. It can only be used for a socket that has been configured with RequestConfiguration.

The following values for Offset are defined in cistpl.h:

CISREG_COR

The Configuration Option Register.

CISREG_CCSR

The Card Configuration and Status Register.

CISREG_PRR

The Pin Replacement Register.

CISREG_SCR

The Socket and Copy Register.

CISREG_ESR

The Extended Status Register.

CISREG_IOBASE0..CISREG_IOBASE3

The I/O Base Registers.

CISREG_IOSIZE

The I/O Size Register.

Return codes:

CS_BAD_HANDLE

The client handle is invalid.

CS_BAD_ARGS

The specified Action is not supported.

CS_CONFIGURATION_LOCKED

This actually means that the configuration has not been locked.

CS_OUT_OF_RESOURCE

Card Services was unable to allocate a memory window to access the card's configuration registers.

AdjustResourceInfo

int CardServices(AdjustResourceInfo, client_handle_t handle, adjust_t *adj);
The adjust_t structure is given by:
typedef struct adjust_t {
        u_long          Action;
        u_long          Resource;
        u_long          Attributes;
        union {
                struct memory {
                        caddr_t         Base;
                        u_long          Size;
                } memory;
                struct io {
                        ioaddr_t        BasePort;
                        ioaddr_t        NumPorts;
                        u_long          IOAddrLines;
                } io;
                struct irq {
                        u_long          IRQ;
                } irq;
        } resource;
} adjust_t;

AdjustResourceInfo is used to tell Card Services what resources may or may not be allocated by PCMCIA devices. The normal Linux resource management systems (the *_region calls for IO ports, interrupt allocation) are respected by Card Services, but this call gives the user another level of control.

The Action parameter can have the following values:

ADD_MANAGED_RESOURCE

Place the specified resource under Card Services control, so that it may be allocated by PCMCIA devices.

REMOVE_MANAGED_RESOURCE

Remove the specified resource from Card Services control.

At initialization time, Card Services assumes that it can use all available interrupts, but IO ports and memory regions must be explicitly enabled with ADD_MANAGED_RESOURCE.

The Resource parameter can have the following values:

RES_MEMORY_RANGE

Specifies a memory range resource, described by adj->resource.memory.

RES_IO_RANGE

Specifies an IO port resource, described by adj->resource.io.

RES_IRQ

Specifies an interrupt resource, described by adj->resource.irq.

The following flags may be specified in Attributes:

RES_RESERVED

Indicates that the resource should be reserved for PCMCIA devices that specifically request it. The resource will not be allocated for a device that asks Card Services for any available location. This is not implemented yet.

Return codes:

CS_UNSUPPORTED_FUNCTION

The specified Action or Resource is not supported.

CS_BAD_BASE

The specified IO address is out of range.

CS_BAD_SIZE

The specified memory or IO window size is out of range.

CS_IN_USE

The specified interrupt is currently allocated by a Card Services client.

ReportError

int CardServices(ReportError, char *prefix, int func, int ret);

ReportError generates a kernel error message given a Card Services function code and its return code, with an optional prefix string. For example:

CardServices(ReportError, "serial_cs", RequestIO, CS_BAD_HANDLE);
would generate the following message:
serial_cs: RequestIO: Bad handle

This call always succeeds.

Next Chapter, Previous Chapter

Table of contents of this chapter, General table of contents

Top of the document, Beginning of this Chapter