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.
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
.
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_int Attributes;
u_int EventMask;
int (*event_handler)(event_t event, int priority,
event_callback_args_t *args);
event_callback_args_t event_callback_args;
u_int 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.
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.
int CardServices(SetEventMask, client_handle_t client, eventmask_t *mask);
The eventmask_t
structure is given by:
typedef struct eventmask_t {
u_int Attributes;
u_int 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.
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.
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.
int CardServices(GetStatus, client_handle_t client, cs_status_t *status);
The cs_status_t
data structure is given by:
typedef struct cs_status_t {
u_char Function;
u_int CardState;
u_int SocketState;
} cs_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. For normal clients, the Function
field is ignored,
but for clients bound with BIND_FN_ALL
, this field specifies the
function whose configuration registers should be used to determine the
socket state, if the socket is currently configured.
The following flags are defined in CardState
:
CS_EVENT_CARD_DETECT
Specifies that the socket is occupied.
CS_EVENT_CB_DETECT
Specifies that the socket is occupied by a CardBus device.
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.
CS_EVENT_CARD_INSERTION
Specifies that a card insertion event is in progress. An insertion event will be sent to the client when socket setup is complete.
CS_EVENT_3VCARD
Indicates that the card supports 3.3V operation.
CS_EVENT_XVCARD
Indicates that the card supports ``X.X''V operation. The actual voltage is currently undefined in the specification.
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.
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.
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.
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.
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.
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.
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.
CardBus cards are configured somewhat differently. The RequestIO
and RequestConfiguration
calls have similar roles, however, Card
Services takes responsibility for most of the configuration details,
and the contents of the request structures are ignored.
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_int Attributes1;
ioaddr_t BasePort2;
ioaddr_t NumPorts2;
u_int Attributes2;
u_int IOAddrLines;
} io_req_t;
RequestIO
reserves IO port windows for a card. BasePort1
specifies the base IO port address of the window to be reserved. 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 card. The IO port allocation algorithm
assumes that any alias of the requested address(es) that preserves the
lower IOAddrLines
bits will be acceptable, and will update
BasePort1
and BasePort2
to reflect the address range(s)
actually assigned.
Prior to release 3.1.4, the IOAddrLines
field was ignored. The
allocator always tried to assign the exact address range requested,
unless the base address was zero; in that case, it would assign any
available window aligned to the nearest power of two larger than
the window size. The new allocator verifies that the IOAddrLines
parameter agrees with the requested window parameters, and defaults to
the pre-3.1.4 behavior if an inconsistency is found.
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.
When this function is invoked by a CardBus client, the IO request structure is ignored. Instead, Card Services examines the card and allocates any necessary system resources: this includes IO and memory space, as well as an interrupt, if needed. One call will reserve all resources needed for all card functions, not just the function of the client making the call.
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.
CS_UNSUPPORTED_FUNCTION
For a CardBus client, this is returned if Card Services was not configured with CardBus support.
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.
For a CardBus client, this call releases all system resources allocated for this card.
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
.
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_int Attributes;
u_int AssignedIRQ;
u_int IRQInfo1, IRQInfo2;
void *(Handler)(int, struct pt_regs *);
void *Instance
} irq_req_t;
RequestIRQ
reserves an interrupt line for use by a 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 also
specifies an interrupt handler to be installed when the interrupt is
enabled. When RequestConfiguration
is called, the handler
given by Handler
will be installed. For 2.0 and later
kernels, the interrupt handler will be installed with the device
``instance'' given in Instance
. For pre-2.1.60 kernels, the
kernel irq2dev_map
table will also be updated. 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 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.
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
.
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_int Attributes;
u_int Vcc, Vpp1, Vpp2;
u_int IntType;
u_int ConfigBase;
u_char Status, Pin, Copy, ExtStatus;
u_char ConfigIndex;
u_int 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 be INT_MEMORY
, INT_MEMORY_AND_IO
, or INT_CARDBUS
.
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.
When invoked by a CardBus client, most of the request structure is
ignored, and all card functions will be configured based on data
collected in a previous RequestIO
call. This includes
configuring the CardBus bridge, as well as initializing the Command,
Base Address, and Interrupt Line registers in each card function's
configuration space. IntType
must be set to INT_CARDBUS
in
this case.
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.
CS_UNSUPPORTED_MODE
A non-CardBus client attempted to configure a CardBus card, or a CardBus client attempted to configure a non-CardBus card.
int CardServices(ModifyConfiguration, client_handle_t client, modconf_t *mod);
The modconf_t
structure is given by:
typedef struct modconf_t {
u_int Attributes;
u_int 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.
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.
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_int Attributes;
u_int Vcc, Vpp1, Vpp2;
u_int IntType;
u_int ConfigBase;
u_char Status, Pin, Copy, Option, ExtStatus;
u_int Present;
u_int AssignedIRQ;
u_int IRQAttributes;
ioaddr_t BasePort1;
ioaddr_t NumPorts1;
u_int Attributes1;
ioaddr_t BasePort2;
ioaddr_t NumPorts2;
u_int Attributes2;
u_int IOAddrLines;
} config_info_t;
GetConfigurationInfo
returns the current socket configuration as
it was set up by RequestIO
, RequestIRQ
, and
RequestConfiguration
. Most fields will only be filled in if the
socket is fully configured; the CONF_VALID_CLIENT
flag in
Attributes
indicates this fact. 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.
For CardBus cards, the ConfigBase
field is set to the card's PCI
vendor/device ID, and the Option
field is set to the CardBus PCI
bus number.
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.
The definition of the Card Information Structure (CIS) is the darkest chapter of the PC Card standard. All version 2 compliant 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
unpacks most tuple types into more
easily used forms. Finally, the ReplaceCIS
call allows a client
to provide Card Services with a substitute for the CIS found on the
card.
#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_int Attributes;
cis_data_t DesiredTuple;
u_int Flags;
cisdata_t TupleCode;
u_int 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.
TUPLE_RETURN_COMMON
Indicates that tuples in the ``common'' CIS section of a multifunction CIS should be returned. In the absence of this flag, normally, Card Services will only return tuples specific to the function bound to the client.
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
.
#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.
#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;
cistpl_format_t format;
} 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.
int CardServices(ValidateCIS, client_handle_t client, cisinfo_t *cisinfo);
The cisinfo_t
structure is given by:
typedef struct cisinfo_t {
u_int 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.
int CardServices(ReplaceCIS, client_handle_t client, cisdump_t *cisinfo);
The cisdump_t
structure is given by:
typedef struct cisdump_t {
u_int Length;
cisdata_t Data[CISTPL_MAX_CIS_SIZE];
} cisinfo_t;
ReplaceCIS
allows a client to pass Card Services a replacement
for the CIS found on a card. Its intended application is for cards
with incomplete or inaccurate CIS information. If a correct CIS can
be deduced from other information available for the card, this allows
that information to be provided to clients in a clean fashion. The
alternative is to pollute client source code with fixes targeted for
each card with a CIS error. The replacement CIS remains in effect
until the card is ejected, and all tuple-related services will use the
replacement instead of the card's actual CIS.
The Length
field gives the number of bytes of CIS data in the
Data
array. The Data
array can be considered to be just the
even bytes of a card's attribute memory. It should contain all
required features of a normal CIS, including an initial
CISTPL_DEVICE
tuple and a final CISTPL_END
tuple. Long
links (including CISTPL_LONGLINK_MFC
) may be used: all target
addresses are interpreted in the replacement CIS space. In general, a
replacement CIS should also contain the same basic identification
tuples (CISTPL_MANFID
, CISTPL_VERS_1
) as the original card.
This service was added in release 3.0.1.
Return codes:
CS_BAD_HANDLE
The client handle is invalid.
CS_OUT_OF_RESOURCE
Card Services was unable to allocate memory to hold the replacement CIS.
Each socket can have up to four active memory windows, mapping portions of card memory into the host system address space. A PC Card device can address at most 16MB of both common and attribute memory. Windows should typically be sized to a power of two. Depending on socket capabilities, they may need to 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.
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_int Attributes;
u_long Base;
u_int Size;
u_int 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.
WIN_MAP_BELOW_1MB
Requests that the window be mapped below the 1MB address boundary. This may not be possible on some platforms.
WIN_STRICT_ALIGN
Requests that the window base be aligned to a multiple of the window size. Added in release 3.1.2.
Base
specifies the base physical address of the window in system
memory. If zero, Card Services will set Base
to the first
available window address. Size
specifies the window size in
bytes. If zero, Card Services will set Size
to the smallest window
size supported by the host controller. 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.
CS_BAD_SIZE
,
CS_BAD_BASE
Either Base
or Size
does not satisfy the alignment rules for
this socket.
int CardServices(ModifyWindow, window_handle_t handle, modwin_t *mod);
The modwin_t
structure is given by:
typedef struct modwin_t {
u_int Attributes;
u_int 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.
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.
int CardServices(GetFirstWindow, client_handle_t *client, win_req_t *req);
int CardServices(GetNextWindow, window_handle_t *handle, win_req_t *req);
These calls sequentially retrieve window configuration information for
all of a socket's memory windows. GetFirstWindow
replaces the client
window handle with a memory window handle, which will in turn be
updated by calls to GetNextWindow
.
These services were added in release 3.1.0.
Return codes:
CS_BAD_HANDLE
The client handle is invalid.
CS_NO_MORE_ITEMS
No more windows ara configured for this socket.
int CardServices(MapMemPage, window_handle_t handle, memreq_t *req);
int CardServices(GetMemPage, window_handle_t handle, memreq_t *req);
The memreq_t
structure is given by:
typedef struct memreq_t {
u_int 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. In turn
GetMemPage
retrieves the current card address mapping for a
memory window.
The GetMemPage
service was added in release 3.1.0.
Return codes:
CS_BAD_HANDLE
The window handle is invalid.
CS_BAD_PAGE
The Page
value was non-zero.
CS_BAD_OFFSET
The requested CardOffset
was out of range or did not have proper
alignment.
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.
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_int Attributes;
u_int 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.
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_int Attributes;
u_int CardOffset;
u_int RegionSize;
u_int AccessSpeed;
u_int BlockSize;
u_int 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.
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_int Attributes;
u_int 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.
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.
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_int Attributes;
u_int Offset;
u_int 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.
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_int Size;
u_int Offset;
void *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.
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.
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.
int CardServices(GetCardServicesInfo, servinfo_t *info);
The servinfo_t
structure is given by:
typedef struct servinfo_t {
char Signature[2];
u_int Count;
u_int Revision;
u_int 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
PC Card standard. These are encoded as BCD numbers. VendorString
is set to point to an RCS identification string.
This call always succeeds.
#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_int Action;
off_t Offset;
u_int 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_IOBASE_0
..CISREG_IOBASE_3
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.
int CardServices(AdjustResourceInfo, client_handle_t handle, adjust_t *adj);
The adjust_t
structure is given by:
typedef struct adjust_t {
u_int Action;
u_int Resource;
u_int Attributes;
union {
struct memory {
u_long Base;
u_long Size;
} memory;
struct io {
ioaddr_t BasePort;
ioaddr_t NumPorts;
u_int IOAddrLines;
} io;
struct irq {
u_int IRQ;
} irq;
} resource;
} adjust_t;
AdjustResourceInfo
is used to tell Card Services what resources
may or may not be allocated by PC Card 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 PC Card 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 PC Card 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.
int CardServices(ReportError, client_handle_t handle, error_info_t *err);
The error_info_t
structure is given by:
typedef struct error_info_t {
int func;
int retcode;
} error_info_t;
ReportError
generates a kernel error message given a Card
Services function code and its return code. If the client handle is
valid, then the error will be prefixed with the client driver's name.
For example:
error_info_t err = { RequestIO, CS_BAD_HANDLE };
CardServices(ReportError, handle, &err);
could generate the following message:
serial_cs: RequestIO: Bad handle
This call always succeeds.