Flameman/pcmcia
from http://pcmcia-cs.sourceforge.net/ftp/doc/PCMCIA-PROG.html
Contents
Basic Concepts
The socket interface
The PC Card bus has two basic operating modes: ``memory-only and ``memory and IO. The first mode was defined by the original Version 1.0 specification and only supports simple memory cards. The second mode, defined in Version 2.0, redefines a few of the memory card control signals to support IO port addressing and IO interrupt signaling.
PC Card devices have two memory spaces: ``attribute memory and ``common memory. The interface can address up to 16MB of each type of memory. Attribute memory is typically used for holding descriptive information and configuration registers. Common memory may include the bulk storage of a memory card, or device buffers in the case of IO cards. All cards that are compliant with the version 2.0 PC Card specification should have a Card Information Structure (or ``CIS) in attribute memory, which describes the card and how it should be configured.
Separate control signals allow cards to signal their operating status to the host. These signals include card detect, ready/busy, write protect, battery low, and battery dead.
The ``memory and IO interface mode allows cards to address up to 64K of IO ports. It also allows cards to signal IO interrupts, and routes one card output to the host system's speaker. In this mode, several of the memory card control signals are unavailable because those pins are used to carry the extra IO card signals. On some cards, these signals can instead be read from a special configuration register in attribute memory, the ``Pin Replacement Register.
The socket controller
The socket controller serves as a bridge between PC Card devices and the system bus. There are several varieties of controllers, but all share the same basic functionality. The Socket Services software layer takes care of all the details of how to program the host controller.
The socket controller has the job of mapping windows of addresses in the host memory and IO spaces to windows of addresses in card space. All supported controllers support at least four independent memory windows and two IO windows per socket.
Each memory window is defined by a base address in the host address space, a base address in the card address space, and a window size. Some controllers differ in their alignment rules for memory windows, but all controllers will support windows whose size is at least 4K and also a power of two, and where the base address is a multiple of the window size. Each window can be programmed to point to either attribute or common memory.
IO windows differ from memory windows in that host addresses that fall within an IO window are not modified before they are passed on to an IO card. Effectively, the base addresses of the window in the host and card address spaces are always equal. IO windows also have no alignment or size restrictions; an IO window can start and end on any byte boundary in the 64K IO address space.
The PC Card bus defines a single interrupt signal from the card to the controller. The controller then has the responsibility of steering this interrupt to an appropriate interrupt request (``irq) line. All controllers support steering card IO interrupts to essentially any free interrupt line. Because steering happens in the controller, the card itself is unaware of which interrupt it uses.
All PC Card controllers can generate interrupts in response to card status changes. These interrupts are distinct from the IO interrupts generated by an IO card, and use a separate interrupt line. Signals that can generate interrupts include card detect, ready/busy, write protect, battery low, and battery dead.
Card Services Subfunction Descriptions
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.
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_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.
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_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.
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, 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.XV 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.
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.
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.
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_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.
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.
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.
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_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.
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_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.
ModifyConfiguration
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.
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_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.
3.4 Card Information Structure (CIS) calls
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.
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_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.
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; 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.
ValidateCIS
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.
ReplaceCIS
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.
Memory window control
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.
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_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.
ModifyWindow
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.
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.
GetFirstWindow, GetNextWindow
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.
MapMemPage, GetMemPage
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
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_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.
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_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.
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_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.
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_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.
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_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.
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_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.
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_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.
AdjustResourceInfo
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.
ReportError
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.
Card Information Structure Definitions
CIS Tuple Definitions
The Card Services ParseTuple function interprets raw CIS tuple data from a call to GetTupleData and returns the tuple contents in a form dependant on the tuple type. This section describes the parsed tuple contents.
#include "cistpl.h"
CISTPL_CHECKSUM
The cistpl_checksum_t structure is given by:
typedef struct cistpl_checksum_t { u_short addr; u_short len; u_char sum; } cistpl_checksum_t;
CISTPL_LONGLINK_A, CISTPL_LONGLINK_C, CISTPL_LINKTARGET,CISTPL_NOLINK
The cistpl_longlink_t structure is given by:
typedef struct cistpl_longlink_t { u_int addr; } cistpl_longlink_t;
These tuples are pointers to additional chains of CIS tuples, either in attribute or common memory. Each CIS tuple chain can have at most one long link. CISTPL_LONGLINK_A tuples point to attribute memory, and CISTPL_LONGLINK_C tuples point to common memory. The standard CIS chain starting at address 0 in attribute memory has an implied long link to address 0 in common memory. A CISTPL_NOLINK tuple can be used to cancel this default link.
The first tuple of a chain pointed to by a long link must be a CISTPL_LINKTARGET. The CS tuple handling code will automatically follow long links and verify link targets; these tuples are normally invisible unless the TUPLE_RETURN_LINK attribute is specified in GetNextTuple.
CISTPL_LONGLINK_MFC
The cistpl_longlink_mfc_t structure is given by:
typedef struct cistpl_longlink_mfc_t { int nfn; struct { u_char space; u_int addr; } fn[CISTPL_MAX_FUNCTIONS; } cistpl_longlink_mfc_t;
This tuple identifies a multifunction card, and specifies long link pointers to CIS chains specific for each function. The space field is either CISTPL_MFC_ATTR or CISTPL_MFC_COMMON for attribute or common memory space.
CISTPL_DEVICE, CISTPL_DEVICE_A
The cistpl_device_t structure is given by:
typedef struct cistpl_device_t { int ndev; struct { u_char type; u_char wp; u_int speed; u_int size; } dev[CISTPL_MAX_DEVICES]; } cistpl_device_t;
The CISTPL_DEVICE tuple describes address regions in a card's common memory. The CISTPL_DEVICE_A tuple describes regions in attribute memory. The type flag indicates the type of memory device for this region. The wp flag indicates if this region is write protected. The speed field is in nanoseconds, and size is in bytes. Address regions are assumed to be ordered consecutively starting with address 0. The following device types are defined:
CISTPL_DTYPE_NULL
Specifies that there is no device, or a ``hole in the card address space.
CISTPL_DTYPE_ROM
Masked ROM
CISTPL_DTYPE_OTPROM
One-type programmable ROM.
CISTPL_DTYPE_EPROM
UV erasable PROM.
CISTPL_DTYPE_EEPROM
Electrically erasable PROM.
CISTPL_DTYPE_FLASH
Flash EPROM.
CISTPL_DTYPE_SRAM
Static or non-volatile RAM.
CISTPL_DTYPE_DRAM
Dynamic or volatile RAM.
CISTPL_DTYPE_FUNCSPEC
Specifies a function-specific device, such as a memory-mapped IO device or buffer, as opposed to general purpose storage.
CISTPL_DTYPE_EXTEND
Specifies an extended device type. This type is reserved for future use.
CISTPL_VERS_1
The cistpl_vers_1_t structure is given by:
typedef struct cistpl_vers_1_t { u_char major; u_char minor; int ns; int ofs[CISTPL_VERS_1_MAX_PROD_STRINGS]; char str[254]; } cistpl_vers_1_t;
The ns field specifies the number of product information strings in the tuple. The string data is contained in the str array. Each string is null terminated, and ofs gives the offset to the start of each string.
CISTPL_ALTSTR
The cistpl_altstr_t structure is given by:
typedef struct cistpl_altstr_t { int ns; int ofs[CISTPL_ALTSTR_MAX_STRINGS]; char str[254]; } cistpl_altstr_t;
The ns field specifies the number of alternate language strings in the tuple. The string data is contained in the str array. Each string is null terminated, and ofs gives the offset to the start of each string.
CISTPL_JEDEC_C, CISTPL_JEDEC_A
The cistpl_jedec_t structure is given by:
typedef struct cistpl_jedec_t { int nid; struct { u_char mfr; u_char info; } id[CISTPL_MAX_DEVICES]; } cistpl_jedec_t;
JEDEC identifiers describe the specific device type used to implement a region of card memory. The nid field specifies the number of JEDEC identifiers in the tuple. There should be a one-to-one correspondence between JEDEC identifiers and device descriptions in the corresponding CISTPL_DEVICE tuple.
CISTPL_CONFIG, CISTPL_CONFIG_CB
The cistpl_config_t structure is given by:
typedef struct cistpl_config_t { u_char last_idx; u_int base; u_int rmask[4]; u_char subtuples; } cistpl_config_t;
The last_idx field gives the index of the highest numbered configuration table entry. The base field gives the offset of a card's configuration registers in attribute memory. The rmask array is a series of bit masks indicating which configuration registers are present. Bit 0 of rmask[0] is for the COR, bit 1 is for the CCSR, and so on. The subtuples field gives the number of bytes of subtuples following the normal tuple contents.
For CISTPL_CONFIG_CB, rmask is undefined, and base points to the CardBus status registers.
CISTPL_BAR
The cistpl_bar_t structure is given by:
typedef struct cistpl_bar_t { u_char attr; u_int size; } cistpl_long_t;
A CISTPL_BAR tuple describes the characteristics of an address space region pointed to by a PCI base address register, for CardBus cards.
The following bit fields are defined in attr:
CISTPL_BAR_SPACE
Identifies the base address register, from 1 to 6. A value of 7 describes the card's Extension ROM space.
CISTPL_BAR_SPACE_IO
If set, this address register maps IO space (as opposed to memory space).
CISTPL_BAR_PREFETCH
If set, this region can be prefetched. controller.
CISTPL_BAR_CACHEABLE
If set, this region is cacheable as well as prefetchable.
CISTPL_BAR_1MEG_MAP
If set, this region should only be mapped into the first 1MB of the host's physical address space.
CISTPL_CFTABLE_ENTRY
The cistpl_cftable_entry_t structure is given by:
typedef struct cistpl_cftable_entry_t { u_char index; u_char flags; u_char interface; cistpl_power_t vcc, vpp1, vpp2; cistpl_timing_t timing; cistpl_io_t io; cistpl_irq_t irq; cistpl_mem_t mem; u_char subtuples; } cistpl_cftable_entry_t;
A CISTPL_CFTABLE_ENTRY structure describes a complete operating mode for a card. Many sections are optional. The index field gives the configuration index for this operating mode; writing this value to the card's Configuration Option Register selects this mode. The following fields are defined in flags:
CISTPL_CFTABLE_DEFAULT
Specifies that this is the default configuration table entry.
CISTPL_CFTABLE_BVDS
Specifies that this configuration implements the BVD1 and BVD2 signals in the Pin Replacement Register.
CISTPL_CFTABLE_WP
Specifies that this configuration implements the write protect signal in the Pin Replacement Register.
CISTPL_CFTABLE_RDYBSY
Specifies that this configuration implements the Ready/Busy signal in the Pin Replacement Register.
CISTPL_CFTABLE_MWAIT
Specifies that the WAIT signal should be observed during memory access cycles.
CISTPL_CFTABLE_AUDIO
Specifies that this configuration generates an audio signal that can be routed to the host system speaker.
CISTPL_CFTABLE_READONLY
Specifies that the card has a memory region that is read-only in this configuration.
CISTPL_CFTABLE_PWRDOWN
Specifies that this configuration supports a power down mode, via the Card Configuration and Status Register.
The cistpl_power_t structure is given by:
typedef struct cistpl_power_t { u_char present; u_char flags; u_int param[7]; } cistpl_power_t;
The present field is bit mapped and indicates which parameters are present for this power signal. The following indices are defined:
CISTPL_POWER_VNOM
The nominal supply voltage.
CISTPL_POWER_VMIN
The minimum supply voltage.
CISTPL_POWER_VMAX
The maximum supply voltage.
CISTPL_POWER_ISTATIC
The continuous supply current required.
CISTPL_POWER_IAVG
The maximum current averaged over one second.
CISTPL_POWER_IPEAK
The maximum current averaged over 10 ms.
CISTPL_POWER_IDOWN
The current required in power down mode.
Voltages are given in units of 10 microvolts. Currents are given in units of 100 nanoamperes.
The cistpl_timing_t structure is given by:
typedef cistpl_timing_t { u_int wait, waitscale; u_int ready, rdyscale; u_int reserved, rsvscale; } cistpl_timing_t;
Each time consists of a base time in nanoseconds, and a scale multiplier. Unspecified times have values of 0.
The cistpl_io_t structure is given by:
typedef struct cistpl_io_t { u_char flags; int nwin; struct { u_int base; u_int len; } win[CISTPL_IO_MAX_WIN; } cistpl_io_t;
The number of IO windows is given by nwin. Each window is described by a base address, base, and a length in bytes, len. The following bit fields are defined in flags:
CISTPL_IO_LINES_MASK
The number of IO lines decoded by this card.
CISTPL_IO_8BIT
Indicates that the card supports split 8-bit accesses to 16-bit IO registers.
CISTPL_IO_16BIT
Indicates that the card supports full 16-bit accesses to IO registers.
The cistpl_irq_t structure is given by:
typedef struct cistpl_irq_t { u_int IRQInfo1; u_int IRQInfo2; } cistpl_irq_t;
The following bit fields are defined in IRQInfo1:
IRQ_MASK
A specific interrupt number that this card should use.
IRQ_NMI_ID, IRQ_IOCK_ID, IRQ_BERR_ID, IRQ_VEND_ID
When IRQ_INFO2_VALID is set, these indicate if a corresponding special interrupt signal may be assigned to this card. The four flags are for the non-maskable, IO check, bus error, and vendor specific interrupts.
IRQ_INFO2_VALID
Indicates that IRQInfo2 contains a valid bit mask of allowed interrupt request numbers.
IRQ_LEVEL_ID
Indicates that the card supports level mode interrupts.
IRQ_PULSE_ID
Indicates that the card supports pulse mode interrupts.
IRQ_SHARE_ID
Indicates that the card supports sharing interrupts.
If IRQInfo1 is 0, then no interrupt information is available.
The cistpl_mem_t structure is given by:
typedef struct cistpl_mem_t { u_char nwin; struct { u_int len; u_int card_addr; u_int host_addr; } win[CISTPL_MEM_MAX_WIN; } cistpl_mem_t;
The number of memory windows is given by nwin. Each window is described by an address in the card memory space, card_addr, an address in the host memory space, host_addr, and a length in bytes, len. If the host address is 0, the position of the window is arbitrary.
CISTPL_CFTABLE_ENTRY_CB
The cistpl_cftable_entry_cb_t structure is given by:
typedef struct cistpl_cftable_entry_cb_t { u_char index; u_char flags; cistpl_power_t vcc, vpp1, vpp2; u_char io; cistpl_irq_t irq; u_char mem; u_char subtuples; } cistpl_cftable_entry_cb_t;
A CISTPL_CFTABLE_ENTRY_CB structure describes a complete operating mode for a CardBus card. Many fields are identical to corresponding fields in CISTPL_CFTABLE_ENTRY.
The io and mem fields specify which base address registers need to be initialized for this configuration. Bits 1 through 6 correspond to the six base address registers, and bit 7 indicates the expansion ROM base register.
CISTPL_MANFID
The cistpl_manfid_t structure is given by:
typedef struct cistpl_manfid_t { u_short manf; u_short card; } cistpl_manfid_t;
The manf field identifies the card manufacturer. The card field is chosen by the vendor and should identify the card type and model.
CISTPL_FUNCID
The cistpl_funcid_t structure is given by:
typedef struct cistpl_funcid_t { u_char func; u_char sysinit; } cistpl_funcid_t;
The func field identifies the card function. The sysinit field contains several bit-mapped flags describing how the card should be configured at boot time.
The following functions are defined:
CISTPL_FUNCID_MULTI
A multi-function card.
CISTPL_FUNCID_MEMORY
A simple memory device.
CISTPL_FUNCID_SERIAL
A serial port or modem device.
CISTPL_FUNCID_PARALLEL
A parallel port device.
CISTPL_FUNCID_FIXED
A fixed disk device.
CISTPL_FUNCID_VIDEO
A video interface.
CISTPL_FUNCID_NETWORK
A network adapter.
CISTPL_FUNCID_AIMS
An auto-incrementing mass storage device.
The following flags are defined in sysinit:
CISTPL_SYSINIT_POST
Indicates that the system should attempt to configure this card during its power-on initialization.
CISTPL_SYSINIT_ROM
Indicates that the card contains a system expansion ROM that should be configured at boot time.
CISTPL_DEVICE_GEO
The cistpl_device_geo_t structure is given by:
typedef struct cistpl_device_geo_t { int ngeo; struct { u_char buswidth; u_int erase_block; u_int read_block; u_int write_block; u_int partition; u_int interleave; } geo[CISTPL_MAX_DEVICES]; } cistpl_device_geo_t;
The erase_block, read_block, and write_block sizes are in units of buswidth bytes times interleave. The partition size is in units of erase_block.
CISTPL_VERS_2
The cistpl_vers_2_t structure is given by:
typedef struct cistpl_vers_2_t { u_char vers; u_char comply; u_short dindex; u_char vspec8, vspec9; u_char nhdr; int vendor, info; char str[244]; } cistpl_vers_2_t;
The vers field should always be 0. The comply field indicates the degree of standard compliance and should also be 0. The dindex field reserves the specified number of bytes at the start of common memory. The vspec8 and vspec9 fields may contain vendor-specific information. The nhdr field gives the number of copies of the CIS that are present on this card. The str array contains two strings: a vendor name, and an informational message describing the card. The offset of the vendor string is given by vendor, and the offset of the product info string is in info.
CISTPL_ORG
The cistpl_org_t structure is given by:
typedef struct cistpl_org_t { u_char data_org; char desc[30];
This tuple describes the data organization of a memory partition. The following values are defined for data_org:
CISTPL_ORG_FS
The partition contains a filesystem.
CISTPL_ORG_APPSPEC
The partition is in an application specific format.
CISTPL_ORG_XIP
The partition follows the Execute-In-Place specification.
The desc field gives a text description of the data organization.
CISTPL_FORMAT
The cistpl_format_t structure is given by:
typedef struct cistpl_org_t { u_char type; u_char edc; u_int offset; u_int length;
This tuple describes the data recording format for a memory region. The following values are defined for type:
CISTPL_FORMAT_DISK
The partition uses a disk-like format.
CISTPL_FORMAT_MEM
The partition uses a memory-like format.
The following values are defined for edc:
CISTPL_EDC_NONE
No error detection code is used.
CISTPL_EDC_CKSUM
Each block has a one-byte arithmetic checksum.
CISTPL_EDC_CRC
Each block has a two-byte cyclic redundancy check.
CISTPL_EDC_PCC
The entire partition has a one-byte checksum.
The offset field specifies the address of the first data byte, and length specifies the total number of data bytes in this partition.
CIS configuration register definitions
The PC Card standard defines a few standard configuration registers located in a card's attribute memory space. A card's CONFIG tuple specifies which of these registers are implemented. Programs using these definitions should include:
#include "cisreg.h"
Configuration Option Register
This register should be present for virtually all IO cards. Writing to this register selects a configuration table entry and enables a card's IO functions.
The following bit fields are defined:
COR_CONFIG_MASK
Specifies the configuration table index describing the card's current operating mode.
COR_LEVEL_REQ
Specifies that the card should generate level mode (edge-triggered) interrupts, the default.
COR_SOFT_RESET
Setting this bit performs a ``soft reset operation. Drivers should use the ResetCard call to reset a card, rather than writing directly to this register.
Card Configuration and Status Register
The following bit fields are defined:
CCSR_INTR_ACK
If this bit is set, then the CCSR_INTR_PENDING bit will remain set until it is explicitly cleared.
CCSR_INTR_PENDING
Signals that the card is currently asserting an interrupt request. This signal may be helpful for supporting interrupt sharing.
CCSR_POWER_DOWN
Setting this bit signals that the card should enter a power down state.
CCSR_AUDIO_ENA
Specifies that the card's audio output should be enabled.
CCSR_IOIS8
This is used by the host to indicate that it can only perform 8-bit IO operations and that 16-bit accesses will be carried out as two 8-bit accesses.
CCSR_SIGCHG_ENA
This indicates to the card that it should use the SIGCHG signal to indicate changes in the WP, READY, BVD1, and BVD2 signals.
CCSR_CHANGED
This bit signals to the host that one of the signals in the Pin Replacement Register has changed state.
Pin Replacement Register
Signals in this register replace signals that are not available when a socket is operating in memory and IO mode. An IO card will normally assert the SIGCHG signal to indicate that one of these signals has changed state, then a driver can poll this register to find out specifically what happened.
The following bit fields are defined:
PRR_WP_STATUS
The current state of the write protect signal.
PRR_READY_STATUS
The current state of the ready signal.
PRR_BVD2_STATUS
The current state of the battery warn signal.
PRR_BVD1_STATUS
The current state of the battery dead signal.
PRR_WP_EVENT
Indicates that the write protect signal has changed state since the PRR register was last read.
PRR_READY_EVENT
Indicates that the ready signal has changed state since the PRR register was last read.
PRR_BVD2_EVENT
Indicates that the battery warn signal has changed state since the PRR register was last read.
PRR_BVD1_EVENT
Indicates that the battery dead signal has changed state since the PRR register was last read.
This register can also be written. In this case, the STATUS bits act as a mask; if a STATUS bit is set, the corresponding EVENT bit is updated by the write.
Socket and Copy Register
This register is used when several identical cards may be set up to share the same range of IO ports, to emulate an ISA bus card that would control several devices. For example, an ISA hard drive controller might control several drives, selectable by writing a drive number to an IO port. For several card drives to emulate this controller interface, each needs to ``know which drive it is, so that it can identify which IO operations are intended for it.
The following bit fields are defined:
SCR_SOCKET_NUM
This should indicate the socket number in which the card is located.
SCR_COPY_NUM
If several identical cards are installed in a system, this field should be set to a unique number identifying which of the identical cards this is.
Extended Status Register
The following bit fields are defined:
ESR_REQ_ATTN_ENA
When set, the CCSR_CHANGED bit will be set when the ESR_REQ_ATTN bit is set, possibly generating a status change interrupt.
ESR_REQ_ATTN
Signals a card event, such as an incoming call for a modem.
IO Base and Size Registers
For multifunction cards, these registers are used to tell the card how the host IO windows have been configured for each card function. There are four IO Base registers, from CISREG_IOBASE_0 to CISREG_IOBASE_3, for the low-order through high-order bytes of an IO address up to 32 bits long. The CISREG_IOSIZE register is supposed to be written as the number of IO ports allocated, minus one. For MFC-compliant cards, Card Services will automatically set all of these registers when RequestConfiguration is called.