<!doctype linuxdoc system>

<article>
<title>Linux PCMCIA Programmer's Guide
<author>David Hinds, <tt><htmlurl
url="mailto:dahinds@users.sourceforge.net" 
name="dahinds@users.sourceforge.net"></tt>. 
<date>v2.33, 22 January 2003
<abstract>
This document describes how to write kernel device drivers for the
Linux PCMCIA Card Services interface.  It also describes how to write
user-mode utilities for communicating with Card Services.  The latest
version of this document can always be found at
<url url="http://pcmcia-cs.sourceforge.net">.
</abstract>

<toc>

<!-- ================================================================= -->

<sect>Introduction
<p>
The Linux kernel PCMCIA system has three main components.  At the
lowest level are the socket drivers.  Next is the Card Services
module.  Drivers for specific cards are layered on top of Card
Services.  One special Card Services client, called Driver Services,
provides a link betweek user level utility programs and the
kernel facilities.

The socket driver layer is loosely based on the Socket Services API.
There are two socket driver modules.  The <tt/tcic/ module supports
the Databook TCIC-2 family of host controllers.  The <tt/i82365/
module supports the Intel i82365sl family and various Intel-compatible
controllers, including Cirrus, VLSI, Ricoh, and Vadem chips.  In
addition, the <tt/i82365/ module implements support for CardBus controllers
that follow the ``Yenta'' register-level specification.

Card Services is the largest single component of the package.
It provides an API somewhat similar to DOS Card Services, adapted to a
Unix environment.  The Linux implementation was based in part on the
Solaris interface specification.  It is implemented in the
<tt/pcmcia_core/ module.  Most version 2.1 features are implemented,
with some PC Card 95 features.

The Driver Services layer implements a user mode pseudo-device for
accessing some Card Services functions from utility programs.
It is responsible for keeping track of all client drivers, and
for matching up drivers with physical sockets.  It is implemented in
the <tt/ds/ module.

This document describes the kernel interface to the Card Services and
Driver Services modules, and the user interface to Driver Services.
It is intended for use by client device driver developers.  The Linux
PCMCIA-HOWTO describes how to install and use Linux PCMCIA support.
It is available from <url url="http://pcmcia-cs.sourceforge.net">.

<!-- ================================================================= -->

<sect1>Copyright notice and disclaimer
<p>
Copyright (c) 1996-2002 David A. Hinds

This document may be reproduced or distributed in any form without my
prior permission.  Modified versions of this document, including
translations into other languages, may be freely distributed, provided
that they are clearly identified as such, and this copyright is
included intact.

This document may be included in commercial distributions without my
prior consent.  While it is not required, I would like to be informed
of such usage.  If you intend to incorporate this document in a
published work, please contact me to make sure you have the latest
available version.

This document is provided ``AS IS'', with no express or implied
warranties.  Use the information in this document at your own risk.

<!-- ================================================================= -->

<sect1>Acknowledgements
<p>

I'd like to thank all the Linux users who have helped test and debug
this software, and who have helped with driver development.  I
should also thank Linus Torvalds, Donald Becker, Alan Cox, and Bjorn
Ekwall for Linux kernel development help.  I'm especially grateful to
Michael Bender for many helpful discussions about the Solaris
implementation.

<!-- ================================================================= -->

<sect>Basic Concepts
<p>

<sect1>The socket interface
<p>
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
signalling.

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''.

<sect1>The socket controller
<p>
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.

<!-- ================================================================= -->

<sect>Card Services Subfunction Descriptions

<p>
Card Services calls have the general form:

<tscreen><verb>
#include "cs_types.h"
#include "cs.h"

int CardServices(int subfunc, void *arg1, void *arg2, ...);
</verb></tscreen>

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

<!-- ================================================================= -->

<sect1>Client management functions
<p>
Device drivers that use Card Services functions are called
``clients''.  A device driver should use the <tt/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
<tt/DeregisterClient/.

<!-- ================================================================= -->

<sect2>RegisterClient
<p>
<tscreen><verb>
int CardServices(RegisterClient, client_handle_t *client, client_reg_t *reg);
</verb></tscreen>
The <tt/client_reg_t/ data structure is given by:
<tscreen><verb>
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;
</verb></tscreen>

<tt/RegisterClient/ establishes a link between a client driver and
Card Services, and connects the client with an appropriate socket.
The <tt/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 <tt/BindDevice/.  If
successful, a client handle will be returned in <tt/client/.

The following flags can be specified in <tt/Attributes/:
<descrip>
<tag><tt/INFO_MASTER_CLIENT/</tag>
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.
<tag><tt/INFO_IO_CLIENT/</tag>
Specifies that this client is an IO card driver.
<tag><tt/INFO_MTD_CLIENT/</tag>
Specifies that this client is a Memory Technology Driver.
<tag><tt/INFO_MEM_CLIENT/</tag>
Specifies that this client is a memory card driver.
<tag><tt/INFO_CARD_SHARE/</tag>
Included for compatibility, has no effect.
<tag><tt/INFO_CARD_EXCL/</tag>
Included for compatibility, has no effect.
</descrip>

<tt/EventMask/ specifies what events this client should be notified
of.  The <tt/event_handler/ entry point will be called by Card
Services when an event in <tt/EventMask/ is processed.  The
<tt/event_handler_args/ structure is a template for the structure that
will be passed to the event handler.  The <tt/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 <tt/RegisterClient/.  This call will always generate a
<tt/CS_REGISTRATION_COMPLETE/ event, and may also generate an
artificial <tt/CS_CARD_INSERTION/ event if the socket is currently
occupied.

Return codes:
<descrip>
<tag><tt/CS_OUT_OF_RESOURCE/</tag>
An appropriate socket could not be found for this driver.
</descrip>

<!-- ================================================================= -->

<sect2>DeregisterClient
<p>
<tscreen><verb>
int CardServices(DeregisterClient, client_handle_t client);
</verb></tscreen>

<tt/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 <tt/BindDevice/.

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
<tag><tt/CS_IN_USE/</tag>
The client still has allocated resources, such as IO port windows or
an interrupt, or the socket configuration is locked.
</descrip>

<!-- ================================================================= -->

<sect2>SetEventMask
<p>
<tscreen><verb>
int CardServices(SetEventMask, client_handle_t client, eventmask_t *mask);
</verb></tscreen>
The <tt/eventmask_t/ structure is given by:
<tscreen><verb>
typedef struct eventmask_t {
	u_int		Attributes;
	u_int		EventMask;
} eventmask_t;
</verb></tscreen>

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

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
</descrip>

<!-- ================================================================= -->

<sect2>BindDevice
<p>
<tscreen><verb>
int CardServices(BindDevice, bind_req_t *req);
</verb></tscreen>
The <tt/bind_req/ structure is given by:
<tscreen><verb>
typedef struct bind_req_t {
	socket_t	Socket;
	u_char		Function;
	dev_info_t	*dev_info;
} bind_req_t;
</verb></tscreen>

<tt/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 <tt/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 <tt/CISTPL_LONGLINK_MFC/ tuple.  If
<tt/Function/ is set to <tt/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:
<descrip>
<tag><tt/CS_BAD_SOCKET/</tag>
The specified socket number is invalid.
</descrip>

<!-- ================================================================= -->

<sect1>Socket state control
<p>

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

<!-- ================================================================= -->

<sect2>GetStatus
<p>
<tscreen><verb>
int CardServices(GetStatus, client_handle_t client, cs_status_t *status);
</verb></tscreen>
The <tt/cs_status_t/ data structure is given by:
<tscreen><verb>
typedef struct cs_status_t {
	u_char		Function;
	u_int		CardState;
	u_int		SocketState;
} cs_status_t;
</verb></tscreen>

<tt/GetStatus/ returns the current status of a client's socket.  For
cards that are configured in IO mode, <tt/GetStatus/ uses the Pin
Replacement Register and Extended Status Register to determine the
card status.  For normal clients, the <tt/Function/ field is ignored,
but for clients bound with <tt/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 <tt/CardState/:

<descrip>
<tag><tt/CS_EVENT_CARD_DETECT/</tag>
Specifies that the socket is occupied.
<tag><tt/CS_EVENT_CB_DETECT/</tag>
Specifies that the socket is occupied by a CardBus device.
<tag><tt/CS_EVENT_WRITE_PROTECT/</tag>
Specifies that the card is currently write protected.
<tag><tt/CS_EVENT_BATTERY_LOW/</tag>
Specifies that the card battery is low.
<tag><tt/CS_EVENT_BATTERY_DEAD/</tag>
Specifies that the card battery is dead.
<tag><tt/CS_EVENT_READY_CHANGE/</tag>
Specifies that the card is ready.
<tag><tt/CS_EVENT_PM_SUSPEND/</tag>
Specifies that the socket is suspended.
<tag><tt/CS_EVENT_REQUEST_ATTENTION/</tag>
Specifies that the request attention bit in the extended status
register is set.
<tag><tt/CS_EVENT_CARD_INSERTION/</tag>
Specifies that a card insertion event is in progress.  An insertion
event will be sent to the client when socket setup is complete.
<tag><tt/CS_EVENT_3VCARD/</tag>
Indicates that the card supports 3.3V operation.
<tag><tt/CS_EVENT_XVCARD/</tag>
Indicates that the card supports ``X.X''V operation.  The actual
voltage is currently undefined in the specification.
</descrip>

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

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
</descrip>

<!-- ================================================================= -->

<sect2>ResetCard
<p>
<tscreen><verb>
int CardServices(ResetCard, client_handle_t client);
</verb></tscreen>

<tt/ResetCard/ requests that a client's socket be reset.  When this
call is made, Card Services sends all clients a
<tt/CS_EVENT_RESET_REQUEST/ event.  If any client rejects the request,
Card Services sends the initiating client a
<tt/CS_EVENT_RESET_COMPLETE/ event with <tt/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
<tt/CS_EVENT_RESET_PHYSICAL/ event, then resets the socket.  When the
socket signals that it is ready, a <tt/CS_EVENT_CARD_RESET/ event is
generated.  Finally, a <tt/CS_EVENT_RESET_COMPLETE/ event is sent to the
initiating client, with <tt/event_callback_args.info/ set to zero.

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
<tag><tt/CS_NO_CARD/</tag>
The socket assigned to this client is currently vacant.
<tag><tt/CS_IN_USE/</tag>
This socket is currently being reset.
</descrip>

<!-- ================================================================= -->

<sect2>SuspendCard
<p>
<tscreen><verb>
int CardServices(SuspendCard, client_handle_t client);
</verb></tscreen>

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

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
<tag><tt/CS_NO_CARD/</tag>
The socket assigned to this client is currently vacant.
<tag><tt/CS_IN_USE/</tag>
This socket is already suspended.
</descrip>

<!-- ================================================================= -->

<sect2>ResumeCard
<p>
<tscreen><verb>
int CardServices(ResumeCard, client_handle_t client);
</verb></tscreen>

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

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
<tag><tt/CS_NO_CARD/</tag>
The socket assigned to this client is currently vacant.
<tag><tt/CS_IN_USE/</tag>
This socket is not currently suspended.
</descrip>

<!-- ================================================================= -->

<sect2>EjectCard
<p>
<tscreen><verb>
int CardServices(EjectCard, client_handle_t client);
</verb></tscreen>

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:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
<tag><tt/CS_NO_CARD/</tag>
The socket assigned to this client is currently vacant.
</descrip>

<!-- ================================================================= -->

<sect2>InsertCard
<p>
<tscreen><verb>
int CardServices(InsertCard, client_handle_t client);
</verb></tscreen>

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

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
<tag><tt/CS_NO_CARD/</tag>
The socket assigned to this client is currently vacant.
<tag><tt/CS_IN_USE/</tag>
The socket has already been configured.
</descrip>

<!-- ================================================================= -->

<sect1>IO card configuration calls
<p>

The normal order of events is for a driver to reserve IO ports and an
interrupt line with calls to <tt/RequestIO/ and <tt/RequestIRQ/, then
to call <tt/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 <tt/RequestIO/
and <tt/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.  

<!-- ================================================================= -->

<sect2>RequestIO
<p>
<tscreen><verb>
int CardServices(RequestIO, client_handle_t client, io_req_t *req);
</verb></tscreen>
The <tt/io_req_t/ data structure is given by:
<tscreen><verb>
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;
</verb></tscreen>

<tt/RequestIO/ reserves IO port windows for a card.  <tt/BasePort1/
specifies the base IO port address of the window to be reserved.  If
<tt/NumPorts2/ is non-zero, a second IO port window will also be
reserved.  <tt/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 <tt/IOAddrLines/ bits will be acceptable, and will update
<tt/BasePort1/ and <tt/BasePort2/ to reflect the address range(s)
actually assigned. 

Prior to release 3.1.4, the <tt/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 <tt/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 <tt/RequestConfiguration/.

The following flags can be specified in <tt/Attributes1/ and
<tt/Attributes2/:
<descrip>
<tag><tt/IO_DATA_PATH_WIDTH/</tag>
This field may either be <tt/IO_DATA_PATH_WIDTH_16/ for 16-bit access, or
<tt/IO_DATA_PATH_WIDTH_8/ for 8-bit access, or
<tt/IO_DATA_PATH_WIDTH_AUTO/ to dynamically size the bus based on the
access size.
</descrip>

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
<tag><tt/CS_NO_CARD/</tag>
The socket assigned to this client is currently vacant.
<tag><tt/CS_IN_USE/</tag>
This socket's IO windows have already been reserved.
<tag><tt/CS_CONFIGURATION_LOCKED/</tag>
This socket's configuration has been locked by a call to
<tt/RequestConfiguration/.
<tag><tt/CS_BAD_ATTRIBUTE/</tag>
An unsupported attribute flag was specified.
<tag><tt/CS_UNSUPPORTED_FUNCTION/</tag>
For a CardBus client, this is returned if Card Services was not
configured with CardBus support.
</descrip>

<!-- ================================================================= -->

<sect2>ReleaseIO
<p>
<tscreen><verb>
int CardServices(ReleaseIO, client_handle_t client, io_req_t *req);
</verb></tscreen>

<tt/ReleaseIO/ un-reserves IO port windows allocated by a previous
call to <tt/RequestIO/.  The <tt/req/ parameter should be the same one
passed to <tt/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:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
<tag><tt/CS_CONFIGURATION_LOCKED/</tag>
This socket's configuration has been locked by a call to
<tt/RequestConfiguration/.  The configuration should be released
before calling ReleaseIO.
<tag><tt/CS_BAD_ARGS/</tag>
The parameters in <tt/req/ do not match the parameters passed to
<tt/RequestIO/.
</descrip>

<!-- ================================================================= -->

<sect2>RequestIRQ
<p>
<tscreen><verb>
int CardServices(RequestIRQ, client_handle_t client, irq_req_t *req);
</verb></tscreen>
The <tt/irq_req_t/ structure is given by:
<tscreen><verb>
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;
</verb></tscreen>

<tt/RequestIRQ/ reserves an interrupt line for use by a card.
The <tt/IRQInfo1/ and <tt/IRQInfo2/ fields correspond to the interrupt
description bytes in a <tt/CFTABLE_ENTRY/ tuple.  If <tt/IRQ_INFO2_VALID/
is set in <tt/IRQInfo1/, then <tt/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 <tt/IRQ_INFO2_VALID/ is
not set, <tt/IRQInfo1/ is just the desired interrupt number.  If the
call is successful, the reserved interrupt is returned in
<tt/AssignedIRQ/.

If the <tt/IRQ_HANDLER_PRESENT/ flag is set, then this call also
specifies an interrupt handler to be installed when the interrupt is
enabled.  When <tt/RequestConfiguration/ is called, the handler
given by <tt/Handler/ will be installed.  For 2.0 and later
kernels, the interrupt handler will be installed with the device
``instance'' given in <tt/Instance/.  For pre-2.1.60 kernels, the
kernel <tt/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 <tt/Attributes/:
<descrip>
<tag><tt/IRQ_FORCED_PULSE/</tag>
Specifies that the interrupt should be configured for pulsed mode,
rather than the default level mode.
<tag><tt/IRQ_TYPE_TIME/</tag>
Specifies that this interrupt can be time-shared with other Card
Services drivers.  Only one driver should enable the interrupt at any
time.
<tag><tt/IRQ_FIRST_SHARED/</tag>
In conjunction with <tt/IRQ_TYPE_TIME/, this should be set by the
first driver requesting a shared interrupt.
<tag><tt/IRQ_HANDLER_PRESENT/</tag>
Indicates that the <tt/Handler/ field points to an interrupt service
routine that should be installed.
</descrip>

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
<tag><tt/CS_NO_CARD/</tag>
The socket assigned to this client is currently vacant.
<tag><tt/CS_IN_USE/</tag>
An interrupt has already been reserved for this socket, or the
requested interrupt is unavailable.
<tag><tt/CS_CONFIGURATION_LOCKED/</tag>
This card function's configuration has been locked by a call to
<tt/RequestConfiguration/.
<tag><tt/CS_BAD_ATTRIBUTE/</tag>
An unsupported attribute flag was specified.
</descrip>

<!-- ================================================================= -->

<sect2>ReleaseIRQ
<p>
<tscreen><verb>
int CardServices(ReleaseIRQ, client_handle_t client, irq_req_t *req);
</verb></tscreen>

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

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
<tag><tt/CS_CONFIGURATION_LOCKED/</tag>
This socket's configuration has been locked by a call to
<tt/RequestConfiguration/.  The configuration should be released
before calling ReleaseIRQ.
<tag><tt/CS_BAD_IRQ/</tag>
The parameters in <tt/req/ do not match the parameters passed to
<tt/RequestIRQ/.
</descrip>

<!-- ================================================================= -->

<sect2>RequestConfiguration
<p>
<tscreen><verb>
int CardServices(RequestConfiguration, client_handle_t client, config_req_t *req);
</verb></tscreen>
The <tt/config_req_t/ structure is given by:
<tscreen><verb>
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;
</verb></tscreen>

<tt/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.

<tt/IntType/ specifies the type of interface to use for this card.  It
may be <tt/INT_MEMORY/, <tt/INT_MEMORY_AND_IO/, or <tt/INT_CARDBUS/.
Voltages are specified in units of 1/10 volt.  Currently, <tt/Vpp1/
must equal <tt/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 <tt/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.  <tt/IntType/ must be set to <tt/INT_CARDBUS/ in
this case.

The following flags can be specified in <tt/Attributes/.  DMA and
speaker control are not supported on all systems.
<descrip>
<tag><tt/CONF_ENABLE_IRQ/</tag>
Enable the IO interrupt reserved by a previous call to
<tt/RequestIRQ/.
<tag><tt/CONF_ENABLE_DMA/</tag>
Enable DMA accesses for this socket.
<tag><tt/CONF_ENABLE_SPKR/</tag>
Enable speaker output from this socket.
</descrip>

The <tt/Present/ parameter is a bit map specifying which CIS
configuration registers are implemented by this card.  <tt/ConfigBase/
gives the offset of the configuration registers in attribute memory.
The following registers can be specified:
<descrip>
<tag><tt/PRESENT_OPTION/</tag>
Specifies that the Configuration Option Register is present.  The COR
register will be set using the <tt/ConfigIndex/ parameter.
<tag><tt/PRESENT_STATUS/</tag>
Specifies that the Card Configuration and Status Register is present.
The CCSR will be initialized with the <tt/Status/ parameter.
<tag><tt/PRESENT_PIN_REPLACE/</tag>
Specifies that the Pin Replacement Register is present.  The PRR will
be initialized with the <tt/Pin/ parameter.
<tag><tt/PRESENT_COPY/</tag>
Specifies that the Socket and Copy Register is present.  The SCR will
be initialized with the <tt/Copy/ parameter.
<tag><tt/PRESENT_EXT_STATUS/</tag>
Specifies that the Extended Status Register is present.  The ESR will
be initialized with the <tt/ExtStatus/ parameter.
</descrip>

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
<tag><tt/CS_NO_CARD/</tag>
The socket assigned to this client is currently vacant.
<tag><tt/CS_OUT_OF_RESOURCE/</tag>
Card Services was unable to allocate a memory window to access the
card's configuration registers.
<tag><tt/CS_CONFIGURATION_LOCKED/</tag>
This card's configuration has already been locked by another call to
<tt/RequestConfiguration/.
<tag><tt/CS_BAD_VCC/</tag>
The requested Vcc voltage is not supported.
<tag><tt/CS_BAD_VPP/</tag>
The requested Vpp1/Vpp2 voltage is not supported.
<tag><tt/CS_UNSUPPORTED_MODE/</tag>
A non-CardBus client attempted to configure a CardBus card, or a
CardBus client attempted to configure a non-CardBus card.
</descrip>

<!-- ================================================================= -->

<sect2>ModifyConfiguration
<p>
<tscreen><verb>
int CardServices(ModifyConfiguration, client_handle_t client, modconf_t *mod);
</verb></tscreen>
The <tt/modconf_t/ structure is given by:
<tscreen><verb>
typedef struct modconf_t {
	u_int		Attributes;
	u_int		Vcc, Vpp1, Vpp2;
} modconf_t;
</verb></tscreen>

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

The following flags can be specified in <tt/Attributes/:
<descrip>
<tag><tt/CONF_IRQ_CHANGE_VALID/</tag>
Indicates that the CONF_ENABLE_IRQ setting should be updated.
<tag><tt/CONF_ENABLE_IRQ/</tag>
Specifies that IO interrupts should be enabled for this socket.
<tag><tt/CONF_VCC_CHANGE_VALID/</tag>
Indicates that Vcc should be updated.
<tag><tt/CONF_VPP1_CHANGE_VALID/</tag>
Indicates that Vpp1 should be updated.
<tag><tt/CONF_VPP2_CHANGE_VALID/</tag>
Indicates that Vpp2 should be updated.
</descrip>

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

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
<tag><tt/CS_NO_CARD/</tag>
The socket assigned to this client is currently vacant.
<tag><tt/CS_CONFIGURATION_LOCKED/</tag>
This actually means that this socket has <bf/not/ been locked.
<tag><tt/CS_BAD_VCC/</tag>
The requested Vcc voltage is not supported.
<tag><tt/CS_BAD_VPP/</tag>
The requested Vpp1/Vpp2 voltage is not supported.
</descrip>

<!-- ================================================================= -->

<sect2>ReleaseConfiguration
<p>
<tscreen><verb>
int CardServices(ReleaseConfiguration, client_handle_t client, config_req_t *req);
</verb></tscreen>

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

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The window handle is invalid, or the socket is not configured.
</descrip>

<!-- ================================================================= -->

<sect2>GetConfigurationInfo
<p>
<tscreen><verb>
int CardServices(GetConfigurationInfo, client_handle_t client, config_info_t *config);
</verb></tscreen>
The <tt/config_info_t/ structure is given by:
<tscreen><verb>
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;
</verb></tscreen>

<tt/GetConfigurationInfo/ returns the current socket configuration as
it was set up by <tt/RequestIO/, <tt/RequestIRQ/, and
<tt/RequestConfiguration/.  Most fields will only be filled in if the
socket is fully configured; the <tt/CONF_VALID_CLIENT/ flag in
<tt/Attributes/ indicates this fact.  For normal clients bound to a
single card function, the <tt/Function/ field is ignored, and data for
that client's assigned function is returned.  For clients bound to
<tt/BIND_FN_ALL/, this field specifies which function's configuration
data should be returned.

For CardBus cards, the <tt/ConfigBase/ field is set to the card's PCI
vendor/device ID, and the <tt/Option/ field is set to the CardBus PCI
bus number.

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The window handle is invalid, or the socket is not configured.
<tag><tt/CS_NO_CARD/</tag>
The socket assigned to this client is currently vacant.
<tag><tt/CS_CONFIGURATION_LOCKED/</tag>
This actually means that the configuration has <bf/not/ been locked.
</descrip>

<!-- ================================================================= -->

<sect1>Card Information Structure (CIS) calls
<p>
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 <tt/ValidateCIS/ call checks to see if a card has a reasonable
CIS.  The <tt/GetFirstTuple/ and <tt/GetNextTuple/ calls are used to
step through CIS tuple lists.  <tt/GetTupleData/ extracts data bytes
from a tuple.  And <tt/ParseTuple/ unpacks most tuple types into more
easily used forms.  Finally, the <tt/ReplaceCIS/ call allows a client
to provide Card Services with a substitute for the CIS found on the
card.

<!-- ================================================================= -->

<sect2>GetFirstTuple, GetNextTuple
<p>
<tscreen><verb>
#include "cistpl.h"

int CardServices(GetFirstTuple, client_handle_t client, tuple_t *tuple);
int CardServices(GetNextTuple, client_handle_t client, tuple_t *tuple);
</verb></tscreen>
The <tt/tuple_t/ data structure is given by:
<tscreen><verb>
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;
</verb></tscreen>

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

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

These functions will automatically traverse any link tuples found in
the CIS.  For multifunction cards having a <tt/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 <tt/BIND_FN_ALL/, then all tuples will be returned.

The following flags can be specified in <tt/Attributes/:

<descrip>
<tag><tt/TUPLE_RETURN_LINK/</tag>
Indicates that link tuples (<tt/CISTPL_LONGLINK_A/,
<tt/CISTPL_LONGLINK_C/, <tt/CISTPL_LONGLINK_MFC/, <tt/CISTPL_NOLINK/,
<tt/CISTPL_LINKTARGET/)
should be returned.  Normally these tuples are processed silently.
<tag><tt/TUPLE_RETURN_COMMON/</tag>
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.
</descrip>

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
<tag><tt/CS_OUT_OF_RESOURCE/</tag>
Card Services was unable to set up a memory window to map the card's
CIS.
<tag><tt/CS_NO_MORE_ITEMS/</tag>
There were no tuples matching <tt/DesiredTuple/.
</descrip>

<!-- ================================================================= -->

<sect2>GetTupleData
<p>
<tscreen><verb>
#include "cistpl.h"

int CardServices(GetTupleData, client_handle_t client, tuple_t *tuple);
</verb></tscreen>

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

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
<tag><tt/CS_OUT_OF_RESOURCE/</tag>
Card Services was unable to set up a memory window to map the card's
CIS.
<tag><tt/CS_NO_MORE_ITEMS/</tag>
The tuple does not contain any more data.  <tt/TuppleOffset/ is
greater than or equal to the length of the tuple.
</descrip>

<!-- ================================================================= -->

<sect2>ParseTuple
<p>
<tscreen><verb>
#include "cistpl.h"

int CardServices(ParseTuple, client_handle_t client, tuple_t *tuple, cisparse_t *parse);
</verb></tscreen>
The <tt/cisparse_t/ data structure is given by:
<tscreen><verb>
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;
</verb></tscreen>

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

Return codes:
<descrip>
<tag><tt/CS_BAD_TUPLE/</tag>
An error was encounted during parsing of this tuple.  The tuple may be
incomplete, or may be formatted incorrectly.
<tag><tt/CS_UNSUPPORTED_FUNCTION/</tag>
<tt/ParseTuple/ cannot parse the specified tuple type.
</descrip>

<!-- ================================================================= -->

<sect2>ValidateCIS
<p>
<tscreen><verb>
int CardServices(ValidateCIS, client_handle_t client, cisinfo_t *cisinfo);
</verb></tscreen>
The <tt/cisinfo_t/ structure is given by:
<tscreen><verb>
typedef struct cisinfo_t {
	u_int		Chains;
} cisinfo_t;
</verb></tscreen>

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

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
<tag><tt/CS_OUT_OF_RESOURCE/</tag>
Card Services was unable to set up a memory window to map the card's
CIS.
</descrip>

<!-- ================================================================= -->

<sect2>ReplaceCIS
<p>
<tscreen><verb>
int CardServices(ReplaceCIS, client_handle_t client, cisdump_t *cisinfo);
</verb></tscreen>
The <tt/cisdump_t/ structure is given by:
<tscreen><verb>
typedef struct cisdump_t {
	u_int		Length;
	cisdata_t	Data[CISTPL_MAX_CIS_SIZE];
} cisinfo_t;
</verb></tscreen>

<tt/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 <tt/Length/ field gives the number of bytes of CIS data in the
<tt/Data/ array.  The <tt/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
<tt/CISTPL_DEVICE/ tuple and a final <tt/CISTPL_END/ tuple.  Long
links (including <tt/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 (<tt/CISTPL_MANFID/, <tt/CISTPL_VERS_1/) as the original card.

This service was added in release 3.0.1.

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
<tag><tt/CS_OUT_OF_RESOURCE/</tag>
Card Services was unable to allocate memory to hold the replacement
CIS.
</descrip>

<!-- ================================================================= -->

<sect1>Memory window control

<p>
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 <tt/RequestWindow/.  Some
window attributes can be modified using <tt/ModifyWindow/.  The
segment of card memory mapped to the window can be modified using
<tt/MapMemPage/.  And windows are released with <tt/ReleaseWindow/.
Unlike almost all other Card Services subfunctions, the memory window
functions normally act on <tt/window_handle_t/ handles, rather than
<tt/client_handle_t/ handles.

<!-- ================================================================= -->

<sect2>RequestWindow
<p>
<tscreen><verb>
int CardServices(RequestWindow, client_handle_t *handle, win_req_t *req);
</verb></tscreen>
The <tt/win_req_t/ structure is given by:
<tscreen><verb>
typedef struct win_req_t {
	u_int		Attributes;
	u_long		Base;
	u_int		Size;
	u_int		AccessSpeed;
} win_req_t;
</verb></tscreen>

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

The following flags can be specified in <tt/Attributes/:
<descrip>
<tag><tt/WIN_MEMORY_TYPE/</tag>
This field can be either <tt/WIN_MEMORY_TYPE_CM/ for common memory, or
<tt/WIN_MEMORY_TYPE_AM/ for attribute memory.
<tag><tt/WIN_DATA_WIDTH/</tag>
Either <tt/WIN_DATA_WIDTH_16/ for 16-bit accesses, or
<tt/WIN_DATA_WIDTH_8/ for 8-bit access.
<tag><tt/WIN_ENABLE/</tag>
If this is set, the window is turned on.
<tag><tt/WIN_USE_WAIT/</tag>
Specifies that the controller should observe the card's MWAIT signal.
<tag><tt/WIN_MAP_BELOW_1MB/</tag>
Requests that the window be mapped below the 1MB address boundary.
This may not be possible on some platforms.
<tag><tt/WIN_STRICT_ALIGN/</tag>
Requests that the window base be aligned to a multiple of the window
size.  Added in release 3.1.2.
</descrip>

<tt/Base/ specifies the base physical address of the window in system
memory.  If zero, Card Services will set <tt/Base/ to the first
available window address.  <tt/Size/ specifies the window size in
bytes.  If zero, Card Services will set <tt/Size/ to the smallest window
size supported by the host controller.  <tt/AccessSpeed/ specifies the
memory access speed, in nanoseconds.

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
<tag><tt/CS_NO_CARD/</tag>
The socket assigned to this client is currently vacant.
<tag><tt/CS_BAD_ATTRIBUTE/</tag>
An unsupported window attribute was requested.
<tag><tt/CS_OUT_OF_RESOURCE/</tag>
The maximum number of memory windows for this socket are already being
used.
<tag><tt/CS_IN_USE/</tag>
<tt/RequestWindow/ was unable to find a free window of system memory.
<tag><tt/CS_BAD_SIZE/</tag>, <tag><tt/CS_BAD_BASE/</tag>
Either <tt/Base/ or <tt/Size/ does not satisfy the alignment rules for
this socket.
</descrip>

<!-- ================================================================= -->

<sect2>ModifyWindow
<p>
<tscreen><verb>
int CardServices(ModifyWindow, window_handle_t handle, modwin_t *mod);
</verb></tscreen>
The <tt/modwin_t/ structure is given by:
<tscreen><verb>
typedef struct modwin_t {
	u_int		Attributes;
	u_int		AccessSpeed;
} modwin_t;
</verb></tscreen>

<tt/ModifyWindow/ modifies the attributes of a window handle returned
by a previous call to <tt/RequestWindow/.  The following attributes
can be changed:
<descrip>
<tag><tt/WIN_MEMORY_TYPE/</tag>
This field can be either <tt/WIN_MEMORY_TYPE_CM/ for common memory, or
<tt/WIN_MEMORY_TYPE_AM/ for attribute memory.
<tag><tt/WIN_DATA_WIDTH/</tag>
Either <tt/WIN_DATA_WIDTH_16/ for 16-bit accesses, or
<tt/WIN_DATA_WIDTH_8/ for 8-bit access.
<tag><tt/WIN_ENABLE/</tag>
If this is set, the window is turned on.
</descrip>

<tt/AccessSpeed/ gives the new memory access speed, in nanoseconds.

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The window handle is invalid.
</descrip>

<!-- ================================================================= -->

<sect2>ReleaseWindow
<p>
<tscreen><verb>
int CardServices(ReleaseWindow, window_handle_t handle);
</verb></tscreen>

<tt/ReleaseWindow/ releases a memory window previously allocated with
<tt/RequestWindow/.

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The window handle is invalid.
</descrip>

<!-- ================================================================= -->

<sect2>GetFirstWindow, GetNextWindow
<p>
<tscreen><verb>
int CardServices(GetFirstWindow, client_handle_t *client, win_req_t *req);
int CardServices(GetNextWindow, window_handle_t *handle, win_req_t *req);
</verb></tscreen>

These calls sequentially retrieve window configuration information for
all of a socket's memory windows.  <tt/GetFirstWindow/ replaces the client 
window handle with a memory window handle, which will in turn be
updated by calls to <tt/GetNextWindow/.

These services were added in release 3.1.0.

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
<tag><tt/CS_NO_MORE_ITEMS/</tag>
No more windows ara configured for this socket.
</descrip>

<!-- ================================================================= -->

<sect2>MapMemPage, GetMemPage
<p>
<tscreen><verb>
int CardServices(MapMemPage, window_handle_t handle, memreq_t *req);
int CardServices(GetMemPage, window_handle_t handle, memreq_t *req);
</verb></tscreen>
The <tt/memreq_t/ structure is given by:
<tscreen><verb>
typedef struct memreq_t {
	u_int		CardOffset;
	page_t		Page;
} memreq_t;
</verb></tscreen>

<tt/MapMemPage/ sets the address of card memory that is mapped to the
base of a memory window to <tt/CardOffset/.  The window should have
been created by a call to <tt/RequestWindow/.  The <tt/Page/ parameter
is not implemented in this version and should be set to 0.  In turn
<tt/GetMemPage/ retrieves the current card address mapping for a
memory window.

The <tt/GetMemPage/ service was added in release 3.1.0.

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The window handle is invalid.
<tag><tt/CS_BAD_PAGE/</tag>
The <tt/Page/ value was non-zero.
<tag><tt/CS_BAD_OFFSET/</tag>
The requested <tt/CardOffset/ was out of range or did not have proper
alignment.
</descrip>

<!-- ================================================================= -->

<sect1>Bulk Memory Services
<p>

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.

<!-- ================================================================= -->

<sect2>RegisterMTD
<p>
<tscreen><verb>
int CardServices(RegisterMTD, client_handle_t handle, mtd_reg_t *reg);
</verb></tscreen>

The <tt/mtd_reg_t/ data structure is given by:
<tscreen><verb>
typedef union mtd_reg_t {
	u_int		Attributes;
	u_int		Offset;
	u_long		MediaID;
} mtd_reg_t;
</verb></tscreen>

<tt/RegisterMTD/ informs Card Services that this client MTD will
handle requests for a specified memory region.  The <tt/Offset/ field
specifies the starting address of the memory region.  The following
fields are defined in <tt/Attributes/: 
<descrip>
<tag><tt/REGION_TYPE/</tag>
Either <tt/REGION_TYPE_CM/ for common memory, or <tt/REGION_TYPE_AM/
for attribute memory.
</descrip>

The <tt/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 <tt/RegisterMTD/,
it will remain bound until the MTD calls <tt/DeregisterClient/.

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
<tag><tt/CS_BAD_OFFSET/</tag>
Either the offset does not match a valid memory region for this card,
or another MTD has already registered for this region.
</descrip>

<!-- ================================================================= -->

<sect2>GetFirstRegion, GetNextRegion
<p>
<tscreen><verb>
int CardServices(GetFirstRegion, client_handle_t handle, region_info_t *region);
int CardServices(GetNextRegion, client_handle_t handle, region_info_t *region);
</verb></tscreen>

The <tt/region_info_t/ data structure is given by:
<tscreen><verb>
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;
</verb></tscreen>

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

The following fields are defined in <tt/Attributes/:

<descrip>
<tag><tt/REGION_TYPE/</tag>
Either <tt/REGION_TYPE_CM/ for common memory, or <tt/REGION_TYPE_AM/
for attribute memory.
</descrip>

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

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
<tag><tt/CS_NO_MORE_ITEMS/</tag>
No more memory regions are defined.
</descrip>

<!-- ================================================================= -->

<sect2>OpenMemory
<p>
<tscreen><verb>
int CardServices(OpenMemory, client_handle_t *handle, open_mem_t *req);
</verb></tscreen>
The <tt/open_mem_t/ structure is given by:
<tscreen><verb>
typedef struct open_mem_t {
	u_int		Attributes;
	u_int		Offset;
} open_mem_t;
</verb></tscreen>

<tt/OpenMemory/ is used to obtain a handle for accessing a memory
region via the other bulk memory services.  The <tt/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 <tt/Attributes/:
<descrip>
<tag><tt/MEMORY_TYPE/</tag>
Either <tt/MEMORY_TYPE_CM/ for common memory, or <tt/MEMORY_TYPE_AM/
for attribute memory.
<tag><tt/MEMORY_EXCLUSIVE/</tag>
Specifies that this client should have exclusive access to this memory
region.
</descrip>

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The window handle is invalid.
<tag><tt/CS_BAD_OFFSET/</tag>
Either the offset does not specify a valid region, or the region does
not have an associated MTD to service bulk memory requests.
</descrip>

<!-- ================================================================= -->

<sect2>CloseMemory
<p>
<tscreen><verb>
int CardServices(CloseMemory, memory_handle_t handle);
</verb></tscreen>

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

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The memory handle is invalid.
</descrip>

<!-- ================================================================= -->

<sect2>ReadMemory, WriteMemory
<p>
<tscreen><verb>
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);
</verb></tscreen>
The <tt/mem_io_t/ structure is given by:
<tscreen><verb>
typedef struct mem_op_t {
	u_int		Attributes;
	u_int		Offset;
	u_int		Count;
} mem_op_t;
</verb></tscreen>

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

The following fields are defined in <tt/Attributes/:
<descrip>
<tag><tt/MEM_OP_BUFFER/</tag>
Either <tt/MEM_OP_BUFFER_USER/ if the host buffer is in a user memory
segment, or <tt/MEM_OP_BUFFER_KERNEL/ if the host buffer is in kernel 
memory.
<tag><tt/MEM_OP_DISABLE_ERASE/</tag>
Specifies that a card area should not be erased before it is written.
<tag><tt/MEM_OP_VERIFY/</tag>
Specifies verification of write operations.
</descrip>

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The window handle is invalid.
<tag><tt/CS_BAD_OFFSET/</tag>
The specified card offset is beyond the end of the memory region.
<tag><tt/CS_BAD_SIZE/</tag>
The specified transfer size extends past the end of the memory region.
</descrip>

<!-- ================================================================= -->

<sect2>RegisterEraseQueue
<p>
<tscreen><verb>
int CardServices(RegisterEraseQueue, client_handle_t *handle, eraseq_hdr_t *header);
</verb></tscreen>
The <tt/eraseq_hdr_t/ structure is given by:
<tscreen><verb>
typedef struct erase_queue_header_t {
	int		QueueEntryCount;
	eraseq_entry_t	*QueueEntryArray;
} eraseq_hdr_t;
</verb></tscreen>

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

The <tt/eraseq_entry_t/ structure is given by:
<tscreen><verb>
typedef struct eraseq_entry_t {
	memory_handle_t	Handle;
	u_char		State;
	u_int		Size;
	u_int		Offset;
	void		*Optional;
} eraseq_entry_t;
</verb></tscreen>

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

<descrip>
<tag><tt/ERASE_QUEUED/</tag>
Set by the client to indicate that this is a new request.
<tag><tt/ERASE_IDLE/</tag>
Set by the client to indicate that this entry is not active.
<tag><tt/ERASE_PASSED/</tag>
Set by the MTD to indicate successful completion.
<tag><tt/ERASE_FAILED/</tag>
Set by the MTD to indicate that the erase failed.
<tag><tt/ERASE_MEDIA_WRPROT/</tag>
Indicates that the region is write protected.
<tag><tt/ERASE_NOT_ERASABLE/</tag>
Indicates that this region does not support erase operations.
<tag><tt/ERASE_BAD_OFFSET/</tag>
Indicates that the erase does not start on an erase block boundary.
<tag><tt/ERASE_BAD_SIZE/</tag>
Indicates that the requested erase size is not a multiple of the erase
block size.
<tag><tt/ERASE_BAD_SOCKET/</tag>
Set by the MTD to indicate that there is no card present.
</descrip>

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

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

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
</descrip>

<!-- ================================================================= -->

<sect2>DeregisterEraseQueue
<p>
<tscreen><verb>
int CardServices(DeregisterEraseQueue, eraseq_handle_t handle);
</verb></tscreen>

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

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The erase queue handle is invalid.
<tag><tt/CS_BUSY/</tag>
The erase queue has erase requests pending.
</descrip>

<!-- ================================================================= -->

<sect2>CheckEraseQueue
<p>
<tscreen><verb>
int CardServices(CheckEraseQueue, eraseq_handle_t handle);
</verb></tscreen>

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

Typically, a client will initially assign each erase queue entry the
state value <tt/ERASE_IDLE/.  When new requests are added to the
queue, the client will set their states to <tt/ERASE_QUEUED/, and call
<tt/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:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The erase queue handle is invalid.
</descrip>

<!-- ================================================================= -->

<sect1>Miscellaneous calls

<!-- ================================================================= -->

<sect2>GetCardServicesInfo
<p>
<tscreen><verb>
int CardServices(GetCardServicesInfo, servinfo_t *info);
</verb></tscreen>
The <tt/servinfo_t/ structure is given by:
<tscreen><verb>
typedef struct servinfo_t {
	char		Signature[2];
	u_int		Count;
	u_int		Revision;
	u_int		CSLevel;
	char		*VendorString;
} servinfo_t;
</verb></tscreen>

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

This call always succeeds.

<!-- ================================================================= -->

<sect2>AccessConfigurationRegister
<p>
<tscreen><verb>
#include "cisreg.h"

int CardServices(AccessConfigurationRegister, client_handle_t handle, conf_reg_t *reg);
</verb></tscreen>
The <tt/conf_reg_t/ structure is given by:
<tscreen><verb>
typedef struct conf_reg_t {
	u_char		Function;
	u_int		Action;
	off_t		Offset;
	u_int		Value;
} conf_reg_t;
</verb></tscreen>

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

The <tt/Action/ parameter can be one of the following:
<descrip>
<tag><tt/CS_READ/</tag>
Read the specified configuration register and return <tt/Value/.
<tag><tt/CS_WRITE/</tag>
Write <tt/Value/ to the specified configuration register.
</descrip>

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

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

<descrip>
<tag><tt/CISREG_COR/</tag>
The Configuration Option Register.
<tag><tt/CISREG_CCSR/</tag>
The Card Configuration and Status Register.
<tag><tt/CISREG_PRR/</tag>
The Pin Replacement Register.
<tag><tt/CISREG_SCR/</tag>
The Socket and Copy Register.
<tag><tt/CISREG_ESR/</tag>
The Extended Status Register.
<tag><tt/CISREG_IOBASE_0/..<tt/CISREG_IOBASE_3/</tag>
The I/O Base Registers.
<tag><tt/CISREG_IOSIZE/</tag>
The I/O Size Register.
</descrip>

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
<tag><tt/CS_BAD_ARGS/</tag>
The specified <tt/Action/ is not supported.
<tag><tt/CS_CONFIGURATION_LOCKED/</tag>
This actually means that the configuration has <bf/not/ been locked.
<tag><tt/CS_OUT_OF_RESOURCE/</tag>
Card Services was unable to allocate a memory window to access the
card's configuration registers.
</descrip>

<!-- ================================================================= -->

<sect2>AdjustResourceInfo
<p>
<tscreen><verb>
int CardServices(AdjustResourceInfo, client_handle_t handle, adjust_t *adj);
</verb></tscreen>
The <tt/adjust_t/ structure is given by:
<tscreen><verb>
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;
</verb></tscreen>

<tt/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 <tt/Action/ parameter can have the following values:
<descrip>
<tag><tt/ADD_MANAGED_RESOURCE/</tag>
Place the specified resource under Card Services control, so that it
may be allocated by PC Card devices.
<tag><tt/REMOVE_MANAGED_RESOURCE/</tag>
Remove the specified resource from Card Services control.
</descrip>

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

The <tt/Resource/ parameter can have the following values:
<descrip>
<tag><tt/RES_MEMORY_RANGE/</tag>
Specifies a memory range resource, described by <tt/adj->resource.memory/.
<tag><tt/RES_IO_RANGE/</tag>
Specifies an IO port resource, described by <tt/adj->resource.io/.
<tag><tt/RES_IRQ/</tag>
Specifies an interrupt resource, described by <tt/adj->resource.irq/.
</descrip>

The following flags may be specified in <tt/Attributes/:
<descrip>
<tag><tt/RES_RESERVED/</tag>
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.
</descrip>

Return codes:
<descrip>
<tag><tt/CS_UNSUPPORTED_FUNCTION/</tag>
The specified <tt/Action/ or <tt/Resource/ is not supported.
<tag><tt/CS_BAD_BASE/</tag>
The specified IO address is out of range.
<tag><tt/CS_BAD_SIZE/</tag>
The specified memory or IO window size is out of range.
<tag><tt/CS_IN_USE/</tag>
The specified interrupt is currently allocated by a Card Services
client.
</descrip>

<!-- ================================================================= -->

<sect2>ReportError
<p>
<tscreen><verb>
int CardServices(ReportError, client_handle_t handle, error_info_t *err);
</verb></tscreen>
The <tt/error_info_t/ structure is given by:
<tscreen><verb>
typedef struct error_info_t {
	int		func;
	int		retcode;
} error_info_t;
</verb></tscreen>

<tt/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:

<tscreen><verb>
error_info_t err = { RequestIO, CS_BAD_HANDLE };
CardServices(ReportError, handle, &amp;err);
</verb></tscreen>
could generate the following message:
<tscreen><verb>
serial_cs: RequestIO: Bad handle
</verb></tscreen>

This call always succeeds.

<!-- ================================================================= -->

<sect>Card Information Structure Definitions
<p>

<!-- ================================================================= -->

<sect1>CIS Tuple Definitions
<p>

The Card Services <tt/ParseTuple/ function interprets raw CIS tuple
data from a call to <tt/GetTupleData/ and returns the tuple contents
in a form dependant on the tuple type.  This section describes the
parsed tuple contents.

<tscreen><verb>
#include "cistpl.h"
</verb></tscreen>

<!-- ================================================================= -->

<sect2>CISTPL_CHECKSUM
<p>

The <tt/cistpl_checksum_t/ structure is given by:
<tscreen><verb>
typedef struct cistpl_checksum_t {
	u_short		addr;
	u_short		len;
	u_char		sum;
} cistpl_checksum_t;
</verb></tscreen>

<!-- ================================================================= -->

<sect2>CISTPL_LONGLINK_A, CISTPL_LONGLINK_C, CISTPL_LINKTARGET,
CISTPL_NOLINK
<p>

The <tt/cistpl_longlink_t/ structure is given by:
<tscreen><verb>
typedef struct cistpl_longlink_t {
	u_int		addr;
} cistpl_longlink_t;
</verb></tscreen>

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.  <tt/CISTPL_LONGLINK_A/ tuples point to attribute
memory, and <tt/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 <tt/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
<tt/CISTPL_LINKTARGET/.  The CS tuple handling code will automatically
follow long links and verify link targets; these tuples are
normally invisible unless the <tt/TUPLE_RETURN_LINK/ attribute is
specified in <tt/GetNextTuple/.

<!-- ================================================================= -->

<sect2>CISTPL_LONGLINK_MFC
<p>

The <tt/cistpl_longlink_mfc_t/ structure is given by:
<tscreen><verb>
typedef struct cistpl_longlink_mfc_t {
	int	nfn;
	struct {
		u_char	space;
		u_int	addr;
	} fn[CISTPL_MAX_FUNCTIONS;
} cistpl_longlink_mfc_t;
</verb></tscreen>

This tuple identifies a multifunction card, and specifies long link
pointers to CIS chains specific for each function.  The <tt/space/
field is either <tt/CISTPL_MFC_ATTR/ or <tt/CISTPL_MFC_COMMON/ for
attribute or common memory space.

<!-- ================================================================= -->

<sect2>CISTPL_DEVICE, CISTPL_DEVICE_A
<p>

The <tt/cistpl_device_t/ structure is given by:
<tscreen><verb>
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;
</verb></tscreen>

The <tt/CISTPL_DEVICE/ tuple describes address regions in a card's
common memory.  The <tt/CISTPL_DEVICE_A/ tuple describes regions in
attribute memory.  The <tt/type/ flag indicates the type of memory
device for this region.  The <tt/wp/ flag indicates if this region is
write protected.  The <tt/speed/ field is in nanoseconds, and
<tt/size/ is in bytes.  Address regions are assumed to be ordered
consecutively starting with address 0.  The following device types are
defined:

<descrip>
<tag><tt/CISTPL_DTYPE_NULL/</tag>
Specifies that there is no device, or a ``hole'' in the card address
space.
<tag><tt/CISTPL_DTYPE_ROM/</tag>
Masked ROM
<tag><tt/CISTPL_DTYPE_OTPROM/</tag>
One-type programmable ROM.
<tag><tt/CISTPL_DTYPE_EPROM/</tag>
UV erasable PROM.
<tag><tt/CISTPL_DTYPE_EEPROM/</tag>
Electrically erasable PROM.
<tag><tt/CISTPL_DTYPE_FLASH/</tag>
Flash EPROM.
<tag><tt/CISTPL_DTYPE_SRAM/</tag>
Static or non-volatile RAM.
<tag><tt/CISTPL_DTYPE_DRAM/</tag>
Dynamic or volatile RAM.
<tag><tt/CISTPL_DTYPE_FUNCSPEC/</tag>
Specifies a function-specific device, such as a memory-mapped IO
device or buffer, as opposed to general purpose storage.
<tag><tt/CISTPL_DTYPE_EXTEND/</tag>
Specifies an extended device type.  This type is reserved for future
use.
</descrip>

<!-- ================================================================= -->

<sect2>CISTPL_VERS_1
<p>

The <tt/cistpl_vers_1_t/ structure is given by:
<tscreen><verb>
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;
</verb></tscreen>

The <tt/ns/ field specifies the number of product information strings
in the tuple.  The string data is contained in the <tt/str/ array.  Each
string is null terminated, and <tt/ofs/ gives the offset to the start
of each string.

<!-- ================================================================= -->

<sect2>CISTPL_ALTSTR
<p>

The <tt/cistpl_altstr_t/ structure is given by:
<tscreen><verb>
typedef struct cistpl_altstr_t {
	int		ns;
	int		ofs[CISTPL_ALTSTR_MAX_STRINGS];
	char		str[254];
} cistpl_altstr_t;
</verb></tscreen>

The <tt/ns/ field specifies the number of alternate language strings
in the tuple.  The string data is contained in the <tt/str/ array.  Each
string is null terminated, and <tt/ofs/ gives the offset to the start
of each string.

<!-- ================================================================= -->

<sect2>CISTPL_JEDEC_C, CISTPL_JEDEC_A
<p>

The <tt/cistpl_jedec_t/ structure is given by:
<tscreen><verb>
typedef struct cistpl_jedec_t {
	int		nid;
	struct {
		u_char	mfr;
		u_char	info;
	} id[CISTPL_MAX_DEVICES];
} cistpl_jedec_t;
</verb></tscreen>

JEDEC identifiers describe the specific device type used to implement
a region of card memory.  The <tt/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 <tt/CISTPL_DEVICE/ tuple.

<!-- ================================================================= -->

<sect2>CISTPL_CONFIG, CISTPL_CONFIG_CB
<p>

The <tt/cistpl_config_t/ structure is given by:
<tscreen><verb>
typedef struct cistpl_config_t {
	u_char		last_idx;
	u_int		base;
	u_int		rmask[4];
	u_char		subtuples;
} cistpl_config_t;
</verb></tscreen>

The <tt/last_idx/ field gives the index of the highest numbered
configuration table entry.  The <tt/base/ field gives the offset of a
card's configuration registers in attribute memory.  The <tt/rmask/
array is a series of bit masks indicating which configuration
registers are present.  Bit 0 of <tt/rmask[0]/ is for the COR, bit 1
is for the CCSR, and so on.  The <tt/subtuples/ field gives the number
of bytes of subtuples following the normal tuple contents.

For <tt/CISTPL_CONFIG_CB/, <tt/rmask/ is undefined, and <tt/base/
points to the CardBus status registers.

<!-- ================================================================= -->

<sect2>CISTPL_BAR
<p>

The <tt/cistpl_bar_t/ structure is given by:
<tscreen><verb>
typedef struct cistpl_bar_t {
	u_char		attr;
	u_int		size;
} cistpl_long_t;
</verb></tscreen>

A <tt/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 <tt/attr/:
<descrip>
<tag><tt/CISTPL_BAR_SPACE/</tag>
Identifies the base address register, from 1 to 6.  A value of 7
describes the card's Extension ROM space.
<tag><tt/CISTPL_BAR_SPACE_IO/</tag>
If set, this address register maps IO space (as opposed to memory
space).
<tag><tt/CISTPL_BAR_PREFETCH/</tag>
If set, this region can be prefetched.
controller.
<tag><tt/CISTPL_BAR_CACHEABLE/</tag>
If set, this region is cacheable as well as prefetchable.
<tag><tt/CISTPL_BAR_1MEG_MAP/</tag>
If set, this region should only be mapped into the first 1MB of the
host's physical address space.
</descrip>

<!-- ================================================================= -->

<sect2>CISTPL_CFTABLE_ENTRY
<p>

The <tt/cistpl_cftable_entry_t/ structure is given by:
<tscreen><verb>
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;
</verb></tscreen>

A <tt/CISTPL_CFTABLE_ENTRY/ structure describes a complete operating
mode for a card.  Many sections are optional.  The <tt/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 <tt/flags/:

<descrip>
<tag><tt/CISTPL_CFTABLE_DEFAULT/</tag>
Specifies that this is the default configuration table entry.
<tag><tt/CISTPL_CFTABLE_BVDS/</tag>
Specifies that this configuration implements the BVD1 and BVD2 signals
in the Pin Replacement Register.
<tag><tt/CISTPL_CFTABLE_WP/</tag>
Specifies that this configuration implements the write protect signal
in the Pin Replacement Register.
<tag><tt/CISTPL_CFTABLE_RDYBSY/</tag>
Specifies that this configuration implements the Ready/Busy signal in
the Pin Replacement Register.
<tag><tt/CISTPL_CFTABLE_MWAIT/</tag>
Specifies that the <tt/WAIT/ signal should be observed during memory
access cycles.
<tag><tt/CISTPL_CFTABLE_AUDIO/</tag>
Specifies that this configuration generates an audio signal that can
be routed to the host system speaker.
<tag><tt/CISTPL_CFTABLE_READONLY/</tag>
Specifies that the card has a memory region that is read-only in this
configuration.
<tag><tt/CISTPL_CFTABLE_PWRDOWN/</tag>
Specifies that this configuration supports a power down mode, via the
Card Configuration and Status Register.
</descrip>

The <tt/cistpl_power_t/ structure is given by:
<tscreen><verb>
typedef struct cistpl_power_t {
	u_char		present;
	u_char		flags;
	u_int		param[7];
} cistpl_power_t;
</verb></tscreen>

The <tt/present/ field is bit mapped and indicates which parameters
are present for this power signal.  The following indices are defined:

<descrip>
<tag><tt/CISTPL_POWER_VNOM/</tag>
The nominal supply voltage.
<tag><tt/CISTPL_POWER_VMIN/</tag>
The minimum supply voltage.
<tag><tt/CISTPL_POWER_VMAX/</tag>
The maximum supply voltage.
<tag><tt/CISTPL_POWER_ISTATIC/</tag>
The continuous supply current required.
<tag><tt/CISTPL_POWER_IAVG/</tag>
The maximum current averaged over one second.
<tag><tt/CISTPL_POWER_IPEAK/</tag>
The maximum current averaged over 10 ms.
<tag><tt/CISTPL_POWER_IDOWN/</tag>
The current required in power down mode.
</descrip>

Voltages are given in units of 10 microvolts.  Currents are given in
units of 100 nanoamperes.

The <tt/cistpl_timing_t/ structure is given by:
<tscreen><verb>
typedef cistpl_timing_t {
	u_int		wait, waitscale;
	u_int		ready, rdyscale;
	u_int		reserved, rsvscale;
} cistpl_timing_t;
</verb></tscreen>

Each time consists of a base time in nanoseconds, and a scale
multiplier.  Unspecified times have values of 0.

The <tt/cistpl_io_t/ structure is given by:
<tscreen><verb>
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;
</verb></tscreen>

The number of IO windows is given by <tt/nwin/.  Each window is
described by a base address, <tt/base/, and a length in bytes,
<tt/len/.  The following bit fields are defined in <tt/flags/:

<descrip>
<tag><tt/CISTPL_IO_LINES_MASK/</tag>
The number of IO lines decoded by this card.
<tag><tt/CISTPL_IO_8BIT/</tag>
Indicates that the card supports split 8-bit accesses to 16-bit
IO registers.
<tag><tt/CISTPL_IO_16BIT/</tag>
Indicates that the card supports full 16-bit accesses to IO registers.
</descrip>

The <tt/cistpl_irq_t/ structure is given by:
<tscreen><verb>
typedef struct cistpl_irq_t {
	u_int		IRQInfo1;
	u_int		IRQInfo2;
} cistpl_irq_t;
</verb></tscreen>

The following bit fields are defined in <tt/IRQInfo1/:
<descrip>
<tag><tt/IRQ_MASK/</tag>
A specific interrupt number that this card should use.
<tag><tt/IRQ_NMI_ID/, <tt/IRQ_IOCK_ID/, <tt/IRQ_BERR_ID/,
<tt/IRQ_VEND_ID/</tag>
When <tt/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.
<tag><tt/IRQ_INFO2_VALID/</tag>
Indicates that <tt/IRQInfo2/ contains a valid bit mask of allowed
interrupt request numbers.
<tag><tt/IRQ_LEVEL_ID/</tag>
Indicates that the card supports level mode interrupts.
<tag><tt/IRQ_PULSE_ID/</tag>
Indicates that the card supports pulse mode interrupts.
<tag><tt/IRQ_SHARE_ID/</tag>
Indicates that the card supports sharing interrupts.
</descrip>

If <tt/IRQInfo1/ is 0, then no interrupt information is available.

The <tt/cistpl_mem_t/ structure is given by:
<tscreen><verb>
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;
</verb></tscreen>

The number of memory windows is given by <tt/nwin/.  Each window is
described by an address in the card memory space, <tt/card_addr/, an
address in the host memory space, <tt/host_addr/, and a length in
bytes, <tt/len/.  If the host address is 0, the position of the window
is arbitrary.

<!-- ================================================================= -->

<sect2>CISTPL_CFTABLE_ENTRY_CB
<p>

The <tt/cistpl_cftable_entry_cb_t/ structure is given by:
<tscreen><verb>
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;
</verb></tscreen>

A <tt/CISTPL_CFTABLE_ENTRY_CB/ structure describes a complete
operating mode for a CardBus card.  Many fields are identical to
corresponding fields in <tt/CISTPL_CFTABLE_ENTRY/.

The <tt/io/ and <tt/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.

<!-- ================================================================= -->

<sect2>CISTPL_MANFID
<p>

The <tt/cistpl_manfid_t/ structure is given by:
<tscreen><verb>
typedef struct cistpl_manfid_t {
	u_short		manf;
	u_short		card;
} cistpl_manfid_t;
</verb></tscreen>

The <tt/manf/ field identifies the card manufacturer.  The <tt/card/
field is chosen by the vendor and should identify the card type and
model.

<!-- ================================================================= -->

<sect2>CISTPL_FUNCID
<p>

The <tt/cistpl_funcid_t/ structure is given by:
<tscreen><verb>
typedef struct cistpl_funcid_t {
	u_char		func;
	u_char		sysinit;
} cistpl_funcid_t;
</verb></tscreen>

The <tt/func/ field identifies the card function.  The <tt/sysinit/
field contains several bit-mapped flags describing how the card should
be configured at boot time.

The following functions are defined:

<descrip>
<tag><tt/CISTPL_FUNCID_MULTI/</tag>
A multi-function card.
<tag><tt/CISTPL_FUNCID_MEMORY/</tag>
A simple memory device.
<tag><tt/CISTPL_FUNCID_SERIAL/</tag>
A serial port or modem device.
<tag><tt/CISTPL_FUNCID_PARALLEL/</tag>
A parallel port device.
<tag><tt/CISTPL_FUNCID_FIXED/</tag>
A fixed disk device.
<tag><tt/CISTPL_FUNCID_VIDEO/</tag>
A video interface.
<tag><tt/CISTPL_FUNCID_NETWORK/</tag>
A network adapter.
<tag><tt/CISTPL_FUNCID_AIMS/</tag>
An auto-incrementing mass storage device.
</descrip>

The following flags are defined in <tt/sysinit/:
<descrip>
<tag><tt/CISTPL_SYSINIT_POST/</tag>
Indicates that the system should attempt to configure this card during
its power-on initialization.
<tag><tt/CISTPL_SYSINIT_ROM/</tag>
Indicates that the card contains a system expansion ROM that should be
configured at boot time.
</descrip>

<!-- ================================================================= -->

<sect2>CISTPL_DEVICE_GEO
<p>

The <tt/cistpl_device_geo_t/ structure is given by:
<tscreen><verb>
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;
</verb></tscreen>

The <tt/erase_block/, <tt/read_block/, and <tt/write_block/ sizes are
in units of <tt/buswidth/ bytes times <tt/interleave/.  The
<tt/partition/ size is in units of <tt/erase_block/.

<!-- ================================================================= -->

<sect2>CISTPL_VERS_2
<p>

The <tt/cistpl_vers_2_t/ structure is given by:
<tscreen><verb>
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;
</verb></tscreen>

The <tt/vers/ field should always be 0.  The <tt/comply/ field
indicates the degree of standard compliance and should also be 0.  The
<tt/dindex/ field reserves the specified number of bytes at the start
of common memory.  The <tt/vspec8/ and <tt/vspec9/ fields may contain
vendor-specific information.  The <tt/nhdr/ field gives the number of
copies of the CIS that are present on this card.  The <tt/str/ array
contains two strings: a vendor name, and an informational message
describing the card.  The offset of the vendor string is given by
<tt/vendor/, and the offset of the product info string is in
<tt/info/.

<!-- ================================================================= -->

<sect2>CISTPL_ORG
<p>

The <tt/cistpl_org_t/ structure is given by:
<tscreen><verb>
typedef struct cistpl_org_t {
	u_char		data_org;
	char		desc[30];
</verb></tscreen>

This tuple describes the data organization of a memory partition.  The
following values are defined for <tt/data_org/:

<descrip>
<tag><tt/CISTPL_ORG_FS/</tag>
The partition contains a filesystem.
<tag><tt/CISTPL_ORG_APPSPEC/</tag>
The partition is in an application specific format.
<tag><tt/CISTPL_ORG_XIP/</tag>
The partition follows the Execute-In-Place specification.
</descrip>

The <tt/desc/ field gives a text description of the data organization.

<!-- ================================================================= -->

<sect2>CISTPL_FORMAT
<p>

The <tt/cistpl_format_t/ structure is given by:
<tscreen><verb>
typedef struct cistpl_org_t {
	u_char		type;
	u_char		edc;
	u_int		offset;
	u_int		length;
</verb></tscreen>

This tuple describes the data recording format for a memory region.
The following values are defined for <tt/type/:

<descrip>
<tag><tt/CISTPL_FORMAT_DISK/</tag>
The partition uses a disk-like format.
<tag><tt/CISTPL_FORMAT_MEM/</tag>
The partition uses a memory-like format.
</descrip>

The following values are defined for <tt/edc/:

<descrip>
<tag><tt/CISTPL_EDC_NONE/</tag>
No error detection code is used.
<tag><tt/CISTPL_EDC_CKSUM/</tag>
Each block has a one-byte arithmetic checksum.
<tag><tt/CISTPL_EDC_CRC/</tag>
Each block has a two-byte cyclic redundancy check.
<tag><tt/CISTPL_EDC_PCC/</tag>
The entire partition has a one-byte checksum.
</descrip>

The <tt/offset/ field specifies the address of the first data byte,
and <tt/length/ specifies the total number of data bytes in this
partition.

<!-- ================================================================= -->

<sect1>CIS configuration register definitions
<p>

The PC Card standard defines a few standard configuration registers
located in a card's attribute memory space.  A card's <tt/CONFIG/
tuple specifies which of these registers are implemented.  Programs
using these definitions should include:

<tscreen><verb>
#include "cisreg.h"
</verb></tscreen>

<!-- ================================================================= -->

<sect2>Configuration Option Register
<p>

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:
<descrip>
<tag><tt/COR_CONFIG_MASK/</tag>
Specifies the configuration table index describing the card's current
operating mode.
<tag><tt/COR_LEVEL_REQ/</tag>
Specifies that the card should generate level mode (edge-triggered)
interrupts, the default.
<tag><tt/COR_SOFT_RESET/</tag>
Setting this bit performs a ``soft'' reset operation.  Drivers should
use the <tt/ResetCard/ call to reset a card, rather than writing
directly to this register.
</descrip>

<!-- ================================================================= -->

<sect2>Card Configuration and Status Register
<p>

The following bit fields are defined:
<descrip>
<tag><tt/CCSR_INTR_ACK/</tag>
If this bit is set, then the <tt/CCSR_INTR_PENDING/ bit will remain
set until it is explicitly cleared.
<tag><tt/CCSR_INTR_PENDING/</tag>
Signals that the card is currently asserting an interrupt request.
This signal may be helpful for supporting interrupt sharing.
<tag><tt/CCSR_POWER_DOWN/</tag>
Setting this bit signals that the card should enter a power down
state.
<tag><tt/CCSR_AUDIO_ENA/</tag>
Specifies that the card's audio output should be enabled.
<tag><tt/CCSR_IOIS8/</tag>
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.
<tag><tt/CCSR_SIGCHG_ENA/</tag>
This indicates to the card that it should use the <tt/SIGCHG/ signal
to indicate changes in the <tt/WP/, <tt/READY/, <tt/BVD1/, and
<tt/BVD2/ signals.
<tag><tt/CCSR_CHANGED/</tag>
This bit signals to the host that one of the signals in the Pin
Replacement Register has changed state.
</descrip>

<!-- ================================================================= -->

<sect2>Pin Replacement Register
<p>

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 <tt/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:
<descrip>
<tag><tt/PRR_WP_STATUS/</tag>
The current state of the write protect signal.
<tag><tt/PRR_READY_STATUS/</tag>
The current state of the ready signal.
<tag><tt/PRR_BVD2_STATUS/</tag>
The current state of the battery warn signal.
<tag><tt/PRR_BVD1_STATUS/</tag>
The current state of the battery dead signal.
<tag><tt/PRR_WP_EVENT/</tag>
Indicates that the write protect signal has changed state since the
PRR register was last read.
<tag><tt/PRR_READY_EVENT/</tag>
Indicates that the ready signal has changed state since the PRR
register was last read.
<tag><tt/PRR_BVD2_EVENT/</tag>
Indicates that the battery warn signal has changed state since the PRR
register was last read.
<tag><tt/PRR_BVD1_EVENT/</tag>
Indicates that the battery dead signal has changed state since the PRR
register was last read.
</descrip>

This register can also be written.  In this case, the <tt/STATUS/ bits
act as a mask; if a <tt/STATUS/ bit is set, the corresponding
<tt/EVENT/ bit is updated by the write.

<!-- ================================================================= -->

<sect2>Socket and Copy Register
<p>

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:
<descrip>
<tag><tt/SCR_SOCKET_NUM/</tag>
This should indicate the socket number in which the card is located.
<tag><tt/SCR_COPY_NUM/</tag>
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.
</descrip>

<!-- ================================================================= -->

<sect2>Extended Status Register
<p>

The following bit fields are defined:
<descrip>
<tag><tt/ESR_REQ_ATTN_ENA/</tag>
When set, the <tt/CCSR_CHANGED/ bit will be set when the
<tt/ESR_REQ_ATTN/ bit is set, possibly generating a status change
interrupt.  
<tag><tt/ESR_REQ_ATTN/</tag>
Signals a card event, such as an incoming call for a modem.
</descrip>

<!-- ================================================================= -->

<sect2>IO Base and Size Registers
<p>

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 <tt/CISREG_IOBASE_0/ to
<tt/CISREG_IOBASE_3/, for the low-order through high-order bytes of an
IO address up to 32 bits long.  The <tt/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 <tt/RequestConfiguration/ is called.

<!-- ================================================================= -->

<sect>Card Services Event Handling
<p>
Card Services events have several sources:

<itemize>
<item>Card status changes reported by the low-level socket drivers.
<item>Artificial events generated by Card Services itself.
<item>Advanced Power Management (APM) events.
<item>Events generated by other Card Services clients.
</itemize>

Socket driver events may be either interrupt-driven or polled.

<!-- ================================================================= -->

<sect1>Event handler operations
<p>
When Card Services recognizes that an event has occurred, it checks
the event mask of each client to determine which clients should
receive an event notification.  When a client registers with Card
Services, it specifies  an event handler callback function.  This
handler should have the form:

<tscreen><verb>
int (*event_handler)(event_t event, int priority, event_callback_args_t *args);
</verb></tscreen>

The <tt/priority/ parameter is set to either <tt/CS_EVENT_PRI_LOW/ for
ordinary events, or <tt/CS_EVENT_PRI_HIGH/ for events that require an
immediate response.  The only high priority event is
<tt/CS_EVENT_CARD_REMOVAL/.  A client event handler should process
this event as efficiently as possible so that Card Services can
quickly notify other clients.

The <tt/event_callback_args_t/ structure is given by:
<tscreen><verb>
typedef struct event_callback_args_t {
	client_handle_t		client_handle;
	void			*info;
	void			*mtdrequest;
	void			*buffer;
	void			*misc;
	void			*client_data;
	struct bus_operations	*bus;
} event_callback_args_t;
</verb></tscreen>

The <tt/client_handle/ member is set to the handle of the client whose
socket was responsible for the event.  This is useful if a driver is
bound to several sockets.  The <tt/info/ field is currently only used
to return an exit status from a call to <tt/ResetCard/.  The
<tt/client_data/ field may be used by a driver to point to a local
data structure associated with this device.  The remaining
fields are currently unused.

For sockets that do not directly map cards into the host IO and memory
space, the <tt/bus/ field is a pointer to a table of entry points for
IO primitives for this socket.

<sect1>Event descriptions
<p>

<descrip>
<tag><tt/CS_EVENT_CARD_INSERTION/</tag>
This event signals that a card has been inserted.  If a driver is
bound to an already occupied socket, Card Services will send the
driver an artificial insertion event.
<tag><tt/CS_EVENT_CARD_REMOVAL/</tag>
This event signals that a card has been removed.  This event should be
handled with minimum delay so that Card Services can notify all
clients as quickly as possible.
<tag><tt/CS_EVENT_BATTERY_LOW/</tag>
This event signals a change of state of the ``battery low'' signal.
<tag><tt/CS_EVENT_BATTERY_DEAD/</tag>
This event signals a change of state of the ``battery dead'' signal.
<tag><tt/CS_EVENT_READY_CHANGE/</tag>
This event signals a change of state of the ``ready'' signal.
<tag><tt/CS_EVENT_WRITE_PROTECT/</tag>
This event signals a change of state of the ``write protect'' signal.
<tag><tt/CS_EVENT_REGISTRATION_COMPLETE/</tag>
This event is sent to a driver after a successful call to
<tt/RegisterClient/.
<tag><tt/CS_EVENT_RESET_REQUEST/</tag>
This event is sent when a client calls <tt/ResetCard/.  An event
handler can veto the reset operation by returning failure.
<tag><tt/CS_EVENT_RESET_PHYSICAL/</tag>
This is sent to all clients just before a reset signal is sent to a
card.
<tag><tt/CS_EVENT_CARD_RESET/</tag>
This event signals that a reset operation is finished.  The success or
failure of the reset should be determined using <tt/GetStatus/.
<tag><tt/CS_EVENT_RESET_COMPLETE/</tag>
This event is sent to a client that has called <tt/ResetCard/ to
signal the end of reset processing.
<tag><tt/CS_EVENT_PM_SUSPEND/</tag>
This event signals that Card Services has received either a user
initiated or APM suspend request.  An event handler can veto the
suspend by returning failure.
<tag><tt/CS_EVENT_PM_RESUME/</tag>
This signals that the system is back on line after a suspend/resume
cycle.
<tag><tt/CS_EVENT_MTD_REQUEST/</tag>
This is used to initiate an MTD memory operation.  A description of
the request is passed in the <tt/mtdrequest/ field of the callback
arguments.  A host buffer address may be passed in <tt/buffer/.
<tag><tt/CS_EVENT_ERASE_COMPLETE/</tag>
This is used to signal a client that a queued erase operation has
completed.  A pointer to the erase queue entry is returned in the
<tt/info/ field of the callback arguments.  
</descrip>

<!-- ================================================================= -->

<sect1>Client driver event handling responsibilities
<p>
A client driver should respond to <tt/CS_EVENT_CARD_INSERTION/ and
<tt/CS_EVENT_CARD_REMOVAL/ events by configuring and un-configuring
the socket.  Because card removal is a high priority event, the driver
should immediately block IO to the socket, perhaps by setting a flag
in a device structure, and schedule all other shutdown processing to
happen later using a timer interrupt.

When a <tt/CS_EVENT_PM_RESET_REQUEST/ event is received, a driver
should block IO and release a locked socket configuration.  When a
<tt/CS_EVENT_CARD_RESET/ is received, a driver should restore the
socket configuration and unblock IO.

A <tt/CS_EVENT_PM_SUSPEND/ event should be handled somewhat like a
<tt/CS_EVENT_PM_RESET_REQUEST/ event, in that IO should be blocked and
the socket configuration should be released.  When a
<tt/CS_EVENT_PM_RESUME/ event is received, a driver can expect a card
to be ready to be reconfigured, similar to when a
<tt/CS_EVENT_CARD_RESET/ event is received.

<!-- ================================================================= -->

<sect>Memory Technology Drivers
<p>
A Memory Technology Driver (``MTD'') is used by Card Services to
implement bulk memory services for a particular type of memory device.
An MTD should register as a normal Card Services client with a call to
<tt/RegisterClient/.  When it receives a card insertion event, it
should use <tt/GetFirstRegion/ and <tt/GetNextRegion/ to identify
memory regions that it will administer.  Then, it should use
<tt/RegisterMTD/ to take control of these regions.  MTD read, write,
copy, and erase requests are packaged into <tt/CS_EVENT_MTD_REQUEST/
events by Card Services, and passed to the MTD's event handler for
processing.

<!-- ================================================================= -->

<sect1>MTD request handling
<p>
An MTD receives requests from Card Services in the form of
<tt/CS_EVENT_MTD_REQUEST/ events.  Card Services passes a description
of the request in the <tt/mtdrequest/ field of the event callback
arguments.  For requests that transfer data to or from the host, the
host buffer address is passed in the <tt/buffer/ field.

The <tt/mtd_request_t/ structure is given by:
<tscreen><verb>
typedef struct mtd_request_t {
	u_int		SrcCardOffset;
	u_int		DestCardOffset;
	u_int		TransferLength;
	u_int		Function;
	u_long		MediaID;
	u_int		Status;
	u_int		Timeout;
} mtd_request_t;
</verb></tscreen>

The <tt/Function/ field is bit mapped and describes the action to be
performed by this request:
<descrip>
<tag><tt/MTD_REQ_ACTION/</tag>
Either <tt/MTD_REQ_ERASE/, <tt/MTD_REQ_READ/, <tt/MTD_REQ_WRITE/, or
<tt/MTD_REQ_COPY/.  
<tag><tt/MTD_REQ_NOERASE/</tag>
For a write command that is sized and aligned on erase block
boundaries, this specifies that no erase should be performed.
<tag><tt/MTD_REQ_VERIFY/</tag>
Specifies that writes should be verified.
<tag><tt/MTD_REQ_READY/</tag>
Indicates that this request is a retry of a previously request that
was delayed until the card asserted <tt/READY/.
<tag><tt/MTD_REQ_TIMEOUT/</tag>
Indicates that this request is a retry of a previously request that
was delayed by a timeout.
<tag><tt/MTD_REQ_FIRST/</tag>
Indicates that this request is the first in a series of requests.
<tag><tt/MTD_REQ_LAST/</tag>
Indicates that this request is the last of a series of requests.
<tag><tt/MTD_REQ_KERNEL/</tag>
Indicates that the host buffer for a read or write command is located
in kernel memory, as opposed to user memory.
</descrip>

The <tt/MediaID/ field is the value specified in the <tt/RegisterMTD/
request for this region.  The <tt/Status/ field is used by the MTD
when it is unable to satisfy a request because a device is busy.  MTD
requests normally run without blocking.  If an MTD request would
block, it should return an error code of <tt/CS_BUSY/, and set
<tt/Status/ to one of the have the following values:

<descrip>
<tag><tt/MTD_WAITREQ/</tag>
Specifies that the request should be retried after another MTD request
currently in progress completes.
<tag><tt/MTD_WAITTIMER/</tag>
Specifies that the request should be continued after the time
specified in the <tt/timeout/ field.
<tag><tt/MTD_WAITRDY/</tag>
Specifies that the request should be continued when the card signals
<tt/READY/, or when the time specified in <tt/Timeout/ elapses,
whichever happens first.
<tag><tt/MTD_WAITPOWER/</tag>
Specifies that the request should be retried after something happens
that affects power availability to the socket.
</descrip>

For <tt/MTD_WAITTIMER/ and <tt/MTD_WAITRDY/, the <tt/Timeout/ field
will specify the timeout interval in milliseconds.

<!-- ================================================================= -->

<sect1>MTD helper functions
<p>
Since an MTD processes requests generated by Card Services, there may
be some restrictions on the sorts of Card Services calls that can be
safely made from the MTD event handler.  The MTD helper functions
provide a limited set of special services that may be needed by an MTD
but would be tricky to implement using the normal Card Services calls.
In the Linux implementation, most CS calls can be safely made from an
MTD event handler, but the MTD helper interface is included for
compatibility. 

<tscreen><verb>
#include "cs_types.h"
#include "cs.h"
#include "bulkmem.h"

int MTDHelperEntry(int subfunc, void *arg1, void *arg2);
</verb></tscreen>

<!-- ================================================================= -->

<sect2>MTDRequestWindow, MTDReleaseWindow
<p>
<tscreen><verb>
int MTDHelperEntry(MTDRequestWindow, client_handle_t *handle, win_req_t *mod);
int MTDHelperEntry(MTDReleaseWindow, window_handle_t handle);
</verb></tscreen>

These services are identical to the standard Card Services
<tt/RequestWindow/ and <tt/ReleaseWindow/ calls.

<!-- ================================================================= -->

<sect2>MTDModifyWindow
<p>
<tscreen><verb>
int MTDHelperEntry(MTDModifyWindow, memory_handle_t handle, mtd_mod_req_t *mod);
</verb></tscreen>
The <tt/mtd_mod_req_t/ structure is give by:
<tscreen><verb>
typedef struct mtd_mod_req_t {
	u_int		Attributes;
	u_int		AccessSpeed;
	u_int		CardOffset;
} mtd_mod_req_t;
</verb></tscreen>

<tt/MTDModifyWindow/ is essentially equivalent to using the normal
<tt/ModifyWindow/ and <tt/MapMemPage/ calls.

The following flags can be specified in <tt/Attributes/:

<descrip>
<tag><tt/WIN_MEMORY_TYPE/</tag>
Either <tt/WIN_MEMORY_TYPE_CM/ for common memory, or
<tt/WIN_MEMORY_TYPE_AM/ for attribute memory.
<tag><tt/WIN_USE_WAIT/</tag>
Specifies that the controller should observe the card's MWAIT signal.
</descrip>

A window configured with <tt/MTDModifyWindow/ will always be enabled,
and have a 16 bit data width.

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The memory handle is invalid.
</descrip>

<!-- ================================================================= -->

<sect2>MTDSetVpp
<p>
<tscreen><verb>
int MTDHelperEntry(MTDSetVpp, client_handle_t client, mtd_vpp_req_t *req);
</verb></tscreen>
<tscreen><verb>
typedef struct mtd_vpp_req_t {
	u_char		Vpp1, Vpp2;
} mtd_vpp_req_t;
</verb></tscreen>

<tt/MTDSetVpp/ changes the programming voltage for a socket.
<tt/Vpp1/ and <tt/Vpp2/ should be given in units of 1/10 volt.
Currently, <tt/Vpp1/ should always equal <tt/Vpp2/.

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
<tag><tt/CS_BAD_VPP/</tag>
The specified Vpp is not available, or Vpp1 does not equal Vpp2.
</descrip>

<!-- ================================================================= -->

<sect2>MTDRDYMask
<p>
<tscreen><verb>
int MTDHelperEntry(MTDRDYMask, client_handle_t client, mtd_rdy_req_t *req);
</verb></tscreen>
<tscreen><verb>
typedef struct mtd_rdy_req_t {
	u_int		Mask;
} mtd_rdy_req_t;
</verb></tscreen>

<tt/MTDRDYMask/ selects whether or not <tt/CS_EVENT_READY_CHANGE/
events will be enabled.  The client should already have indicated to
Card Services that it should receive ready change events, via a call
to either <tt/RegisterClient/ or <tt/SetEventMask/.  Ready change
events will be enabled if the <tt/CS_EVENT_READY_CHANGE/ bit is set in
the <tt/Mask/ argument.

Return codes:
<descrip>
<tag><tt/CS_BAD_HANDLE/</tag>
The client handle is invalid.
</descrip>

<!-- ================================================================= -->

<sect> Driver Services Interface
<p>
Driver Services provides a link between Card Services client drivers
and user mode utilities like the <tt/cardmgr/ daemon.  It is a sort of
Card Services ``super-client''.  Driver Services uses the
<tt/BindDevice/ function to link other client drivers with their
corresponding cards.  Unlike other clients, Driver Services
remains permanently bound to all sockets as cards are inserted and
removed.

<!-- ================================================================= -->

<sect1> Interface to other client drivers
<p>
Driver Services keeps track of all client drivers that are installed
and ready to attach to a socket.  Client drivers need to have entry
points for creating and deleting device ``instances'', where one
device instance is everything needed to manage one physical card.

Each client driver is identified by a unique 16-character tag that has
the special type <tt/dev_info_t/, defined in <tt/cs_types.h/.  Each
device instance is described by a <tt/dev_link_t/ structure.

<sect2> The dev_link_t structure
<p>
The <tt/dev_node_t/ and <tt/dev_link_t/ data structures are given by:
<tscreen><verb>
#include "ds.h"

typedef struct dev_node_t {
	char			dev_name[DEV_NAME_LEN];
	u_char			major, minor;
	struct dev_node_t	*next;
}

typedef struct dev_link_t {
	dev_node_t		*dev;
	u_int			state, open;
	struct wait_queue	*pending
	struct timer_list	release
	client_handle_t		handle;
	io_req_t		io;
	irq_req_t		irq;
	config_req_t		conf;
	window_handle_t		win;
	void			*priv;
	struct dev_link_t	*next;
} dev_link_t;
</verb></tscreen>

The <tt/dev/ field of the <tt/dev_link_t/ structure points to a linked
list of <tt/dev_node_t/ structures.  In <tt/dev_node_t/, the
<tt/dev_name/ field should be filled in by the driver with a
device file name for accessing this device, if appropriate.  For
example, the <tt/serial_cs/ driver uses names like ``<tt/ttyS1/''.  The
<tt/major/ and <tt/minor/ fields give major and minor device numbers
for accessing this device.  Driver Services relays these fields to
user mode programs via the <tt/DS_GET_DEVICE_INFO/ ioctl.

In <tt/dev_link_t/, the <tt/state/ field should be used to keep track
of the current device state.  The following flags are defined:

<descrip>
<tag><tt/DEV_PRESENT/</tag>
Indicates that the card is present.  This bit should be set and
cleared by the driver's event handler in response to card insertion
and removal events.
<tag><tt/DEV_CONFIG/</tag>
Indicates that the card is configured for use.
<tag><tt/DEV_CONFIG_PENDING/</tag>
Indicates that configuration is in progress.
<tag><tt/DEV_SUSPEND/</tag>
Indicates that the card is suspended.
<tag><tt/DEV_BUSY/</tag>
Indicates that an IO operation is in progress.  This bit may be used
as an interlock to prevent access conflicts.
<tag><tt/DEV_STALE_CONFIG/</tag>
For some drivers, when a running card is ejected, the socket should
not be unconfigured until any devices corresponding to this card are
closed.  This flag indicates that the socket should be unconfigured
when the device is closed.
<tag><tt/DEV_STALE_LINK/</tag>
A driver instance should not be deleted until all its resources
are released.  This flag indicates that this driver instance should be
freed as soon as the socket is unconfigured.
</descrip>

The <tt/open/ field is a usage count for this device.  The device
should only be freed when the open count is zero.  The <tt/pending/
field can be used to manage a queue of processes waiting to use the
device.

The <tt/release/ field is used to schedule device shutdown processing
when a card is ejected.  A card removal event needs to be handled at
high priority, so a driver's event handler will typically deal with an
eject by resetting the <tt/DEV_PRESENT/ bit in the device state, then
scheduling the shutdown processing to run at a later time.

The <tt/handle/, <tt/io/, <tt/irq/, <tt/conf/, and <tt/win/ fields
comprise all the normal data structures needed to configure an
ordinary PC Card IO device

The <tt/priv/ field can be used for any sort of private data structure
needed to manage the device.  The <tt/next/ field can be used to build
linked lists of <tt/dev_link_t/ structures, for drivers that can
handle multiple instances.

<!-- ================================================================= -->

<sect2> register_pccard_driver
<p>
<tscreen><verb>
int register_pccard_driver(dev_info_t *dev_info,
			   dev_link_t *(*attach)(void),
			   void (*detach)(dev_link_t *));
</verb></tscreen>
<tt/register_pccard_driver/ informs Driver Services that a client
driver is present and ready to be bound to sockets.  When Driver
Services receives a <tt/DS_BIND_REQUEST/ ioctl that matches this
driver's <tt/dev_info/ string, it will call the driver's <tt/attach()/
entry point.  When it gets a <tt/DS_UNBIND_REQUEST/ ioctl, it will
call <tt/detach()/.

<!-- ================================================================= -->

<sect2> unregister_pccard_driver
<p>
<tscreen><verb>
int unregister_pccard_driver(dev_info_t *dev_info);
</verb></tscreen>

This informs Driver Services that it should no longer bind sockets to
the specified client driver.

<!-- ================================================================= -->

<sect1> The CardBus client interface
<p>
The CardBus card interface is designed to be essentially an extension
of the PCI bus.  CardBus cards are typically designed using standard
PCI chip sets.  For simplicity in the client drivers, and maximum code
sharing with regular kernel PCI drivers, we provide a sort of ``super
client'' for configuring CardBus cards.  This is implemented in the
<tt/cb_enabler/ module.

The <tt/cb_enabler/ module is somewhat similar in philosophy to the
Driver Services layer for 16-bit cards.  CardBus client drivers
register with it, and provide a few entry points for handling device
setup and shutdown, as well as power management handling.  The
<tt/cb_enabler/ module takes care of configuring the card and fielding
Card Services events.  So, all CardBus-specific code is in the enabler
rather than the PCI driver.

It is not mandatory for CardBus clients to use the <tt/cb_enabler/
interface.  If a particular client requires more direct control over
its CardBus configuration than is provided through the <tt/cb_enabler/
module, it can register directly with Card Services and perform Card
Services calls directly, just like a 16-bit client.

The <tt/cb_enabler/ module has two entry points: <tt/register_driver/
and <tt/unregister_driver/.  At some point, these functions may
migrate into the kernel: hence the generic names.

<sect2> register_driver
<p>
<tscreen><verb>
int register_driver(struct driver_operations *ops);
</verb></tscreen>
The <tt/driver_operations/ structure is given by:
<tscreen><verb>
typedef struct driver_operations {
	char		*name
	dev_node_t	*(*attach) (dev_locator_t *loc);
	void		(*suspend) (dev_node_t *dev);
	void		(*resume) (dev_node_t *dev);
	void		(*detach) (dev_node_t *dev);
} driver_operations;
</verb></tscreen>

The <tt/name/ field is used by <tt/cb_enabler/ when registering this
client with Card Services.  The rest of the structure describes a set
of event handlers for this client.

The function returns 0 on success, and -1 on failure.

<sect2> unregister_driver
<p>
<tscreen><verb>
void unregister_driver(struct driver_operations *ops);
</verb></tscreen>

The <tt/ops/ parameter should be the same structure pointer passed to
a prior successful call to <tt/register_driver/.  The client should
take care to only call this function when no devices are currently
being managed by this client.

<sect2> The driver_operations entry points
<p>

The <tt/attach()/ entry point is used to configure a single device,
given a ``device locator'' structure describing where to find it.

The <tt/dev_locator_t/ structure is given by:
<tscreen><verb>
typedef struct dev_locator_t {
	enum { LOC_ISA, LOC_PCI } bus;
	union {
		struct {
			u_short		io_base_1, io_base_2;
			u_long		mem_base;
			u_char		irq, dma;
		} isa;
		struct {
			u_char		bus;
	    		u_char		devfn;
		} pci;
	} b;
} dev_locator_t;
</verb></tscreen>

The <tt/attach()/ function should return either <tt/NULL/ or a valid
<tt/dev_node_t/ structure describing the new device.  All the other
entry points will use this pointer to identify the device to be
manipulated.  The <tt/cb_enabler/ module will invoke the <tt/attach()/
and <tt/detach()/ entry points in response to card insertion and
removal events.  The <tt/suspend()/ and <tt/resume()/ entry points
will be called in response to power management events.

There is no way for a driver to refuse a <tt/suspend()/ or
<tt/detach()/ event.  When a <tt/detach()/ event is received, the
driver should block any subsequent IO to the specified device, but may
preserve internal data structures until the kernel device is actually
closed.

<!-- ================================================================= -->

<sect1> Interface to user mode utilities
<p>
Driver Services creates a pseudo-device for communicating with user
mode PC Card utilities.  The major number of the device is chosen
dynamically, and PC Card utilities should read <tt>/proc/devices</tt> 
to determine it.  Minor device numbers correspond to socket numbers,
starting with 0.

Only one process is allowed to open a socket for read/write access.
Other processes can open the socket in read-only mode.  A read-only
connection to Driver Services can perform a subset of <tt/ioctl/
calls.  A read/write connection can issue all <tt/ioctl/ calls, and
can also receive Card Services event notifications.

<!-- ================================================================= -->

<sect2> Card Services event notifications
<p>
Driver Services implements <tt/read()/ and <tt/select()/ functions for
event notification.  Reading from a PC Card device returns an unsigned
long value containing all the events received by Driver Services since
the previous <tt/read()/.  If no events have been received, the call
will block until the next event.  A <tt/select()/ call can be used to
monitor several sockets for new events.

The following events are monitored by Driver Services:
<tt/CS_EVENT_CARD_INSERTION/, <tt/CS_EVENT_CARD_REMOVAL/,
<tt/CS_EVENT_RESET_PHYSICAL/, <tt/CS_EVENT_CARD_RESET/, and
<tt/CS_EVENT_RESET_COMPLETE/.

<!-- ================================================================= -->

<sect2> Ioctl descriptions
<p>
Most Driver Services <tt/ioctl/ operations directly map to Card
Services functions.  An ioctl call has the form:

<tscreen><verb>
int ioctl(int fd, int cmd, ds_ioctl_arg_t *arg);
</verb></tscreen>
The ds_ioctl_arg_t structure is given by:
<tscreen><verb>
typedef union ds_ioctl_arg_t {
	servinfo_t	servinfo;
	adjust_t	adjust;
	config_info_t	config;
	tuple_t		tuple;
	tuple_parse_t	tuple_parse;
	client_req_t	client_req;
	status_t	status;
	conf_reg_t	conf_reg;
	cisinfo_t	cisinfo;
	region_info_t	region;
	bind_info_t	bind_info;
	mtd_info_t	mtd_info;
	cisdump_t	cisdump;
} ds_ioctl_arg_t;
</verb></tscreen>

The following <tt/ioctl/ commands execute the corresponding Card
Services function:
<descrip>
<tag><tt/DS_GET_CARD_SERVICES_INFO/</tag>
Calls <tt/CardServices(GetCardServicesInfo, ..., &amp;arg->servinfo)/.
<tag><tt/DS_ADJUST_RESOURCE_INFO/</tag>
Calls <tt/CardServices(AdjustResourceInfo, ..., &amp;arg->adjust)/.
<tag><tt/DS_GET_CONFIGURATION_INFO/</tag>
Calls <tt/CardServices(GetConfigurationInfo, ..., &amp;arg->config)/.
<tag><tt/DS_GET_FIRST_TUPLE/</tag>
Calls <tt/CardServices(GetFirstTuple, ..., &amp;arg->tuple)/.
<tag><tt/DS_GET_NEXT_TUPLE/</tag>
Calls <tt/CardServices(GetNextTuple, ..., &amp;arg->tuple)/.
<tag><tt/DS_GET_TUPLE_DATA/</tag>
Calls <tt/CardServices(GetTupleData, ..., &amp;arg->tuple_parse.tuple)/.
The tuple data is returned in <tt/arg->tuple_parse.data/.
<tag><tt/DS_PARSE_TUPLE/</tag>
Calls <tt/CardServices(ParseTuple, ..., &amp;arg->tuple_parse.tuple, &amp;arg->tuple_parse.parse)/.
<tag><tt/DS_RESET_CARD/</tag>
Calls <tt/CardServices(ResetCard, ...)/.
<tag><tt/DS_GET_STATUS/</tag>
Calls <tt/CardServices(GetStatus, ..., &amp;arg->status)/.
<tag><tt/DS_ACCESS_CONFIGURATION_REGISTER/</tag>
Calls <tt/CardServices(AccessConfigurationRegister, ..., &amp;arg->conf_reg)/.
<tag><tt/DS_VALIDATE_CIS/</tag>
Calls <tt/CardServices(ValidateCIS, ..., &amp;arg->cisinfo)/.
<tag><tt/DS_SUSPEND_CARD/</tag>
Calls <tt/CardServices(SuspendCard, ...)/.
<tag><tt/DS_RESUME_CARD/</tag>
Calls <tt/CardServices(ResumeCard, ...)/.
<tag><tt/DS_EJECT_CARD/</tag>
Calls <tt/CardServices(EjectCard, ...)/.
<tag><tt/DS_INSERT_CARD/</tag>
Calls <tt/CardServices(InsertCard, ...)/.
<tag><tt/DS_GET_FIRST_REGION/</tag>
Calls <tt/CardServices(GetFirstRegion, ..., &amp;arg->region)/.
<tag><tt/DS_GET_NEXT_REGION/</tag>
Calls <tt/CardServices(GetNextRegion, ..., &amp;arg->region)/.
<tag><tt/DS_REPLACE_CIS/</tag>
Calls <tt/CardServices(ReplaceCIS, ..., &amp;arg->cisdump)/.
</descrip>

The following <tt/ioctl/ commands invoke special Driver Services
functions.  They act on <tt/bind_info_t/ structures:
<tscreen><verb>
typedef struct bind_info_t {
	dev_info_t		dev_info;
	u_char			function;
	struct dev_info_t	*instance;
	char			name[DEV_NAME_LEN];
	u_char			major, minor;
	void			*next;
} bind_info_t;
</verb></tscreen>
<descrip>
<tag><tt/DS_BIND_REQUEST/</tag>
This call connects a socket to a client driver.  The specified device
ID <tt/dev_info/ is looked up in the list of registered drivers.
If this is a multifunction card, the <tt/function/ field
identifies which card function is being bound.  If
found, the driver is bound to this socket and function using the
<tt/BindDevice/ call.
Then, Driver Services calls the client driver's <tt/attach()/
entry point to create a device instance.  The new <tt/dev_link_t/
pointer is returned in <tt/instance/.
<tag><tt/DS_GET_DEVICE_INFO/</tag>
This call retrieves the <tt/dev_name/, <tt/major/, and <tt/minor/
entries from the <tt/dev_link_t/ structure pointed to by
<tt/instance/.
<tag><tt/DS_UNBIND_REQUEST/</tag>
This call calls the <tt/detach()/ function for the specified driver
and instance, shutting down this device.
</descrip>

Finally, the <tt/DS_BIND_MTD/ request takes an argument of type
<tt/mtd_info_t/:

<tscreen><verb>
typedef struct mtd_info_t {
	dev_info_t	dev_info;
	u_int		Attributes;
	u_int		CardOffset;
} mtd_info_t;
</verb></tscreen>

This call associates an MTD identified by <tt/dev_info/ with a memory
region described by <tt/Attributes/ and <tt/CardOffset/, which have
the same meanings as in the Card Services <tt/BindMTD/ call.

<!-- ================================================================= -->

<sect>Anatomy of a Card Services Client Driver
<p>
Each release of the Linux Card Services package comes with a well-commented
``dummy'' client driver that should be used as a starting point for
writing a new driver.  Look for it in <tt>clients/dummy_cs.c</tt>.
This is not just a piece of sample code: it is written to function as
a sort of generic card enabler.  If bound to an IO card, it will read
the card's CIS and configure the card appropriately, assuming that the
card's CIS is complete and accurate. 

<!-- ================================================================= -->

<sect1>Module initialization and cleanup
<p>
All loadable modules must supply <tt/init_module()/ and
<tt/cleanup_module()/ functions, which are invoked by the module
support code when the module is installed and removed.  A client
driver's init function should register the driver with Driver
Services, via the <tt/register_pccard_driver()/ call.  The cleanup
function should use <tt/unregister_pccard_driver()/ to unregister with
Driver Services.  Depending on the driver, the cleanup function may
also need to free any device structures that still exist at shutdown
time.

<sect1>The *_attach() and *_detach() functions
<p>
The <tt/*_attach()/ entry point is responsible for creating an
``instance'' of the driver, setting up any data structures needed to
manage one card.  The <tt/*_attach()/ function should allocate
and initialize a <tt/dev_link_t/ structure, and call
<tt/RegisterClient/ to establish a link with Card Services.  It
returns a pointer to the new <tt/dev_link_t/ structure, or <tt/NULL/
if the new instance could not be created.

The <tt/*_detach()/ entry point deletes a driver instance created by a
previous call to <tt/*_attach/.  It also breaks the link with Card
Services, using <tt/DeregisterClient/.

The <tt/*_attach()/ entry point is called by Driver Services when a
card has been successfully identified and mapped to a matching driver
by a <tt/DS_BIND_REQUEST/ ioctl().  The <tt/*_detach()/ entry point is
called in response to a <tt/DS_UNBIND_REQUEST/ ioctl() call.

<sect1>The *_config() and *_release() functions
<p>
The <tt/*_config()/ function is called to prepare a card for IO.  Most
drivers read some configuration details from the card itsef, but most
have at least some built-in knowledge of how the device should be set
up.  For example, the serial card driver reads a card's
<tt/CFTABLE_ENTRY/ tuples to determine appropriate IO port base
addresses and corresponding configuration indices, but the driver
ignores the interrupt information in the CIS.  The <tt/*_config/
function will parse relevant parts of a card's CIS, then make calls to
<tt/RequestIO/, <tt/RequestIRQ/, and/or <tt/RequestWindow/, then call
<tt/RequestConfiguration/.  

When a card is successfully configured, the <tt/*_config()/ routine
should fill in the <tt/dev_name/, <tt/major/, and <tt/minor/ fields in
the <tt/dev_link_t/ structure.  These fields will be returned to user
programs by Driver Services in response to a <tt/DS_GET_DEVICE_INFO/
ioctl().

The <tt/*_release()/ function should release any resource allocated by
a previous call to <tt/*_config()/, and blank out the device's
<tt/dev_name/ field.

The <tt/*_config()/ and <tt/*_release/ functions are normally called
in response to card status change events or from timer interrupts.
Thus, they cannot sleep, and should not call other kernel functions
that might block.

<sect1>The client event handler
<p>
The <tt/*_event()/ entry point is called from Card Services to notify
a driver of card status change events.

<sect1>Locking and synchronization issues
<p>
A configured socket should only be released when all associated
devices are closed.  Releasing a socket allows its system resources to
be allocated for use by another device.  If the released resources are
reallocated while IO to the original device is still in progress, the
original driver may interfere with use of the new device.

A driver instance should only be freed after its corresponding socket
configuration has been released.  Card Services requires that a client
explicitly release any allocated resources before a call to
<tt/DeregisterClient/ will succeed.

All loadable modules have a ``use count'' that is used by the system
to determine when it is safe to unload a module.  The convention in
client drivers is to increment the use count when a device is opened,
and to decrement the count when a device is closed.  So, a driver can
be unloaded whenever all associated devices are closed.  in
particular, a driver can be unloaded even if it is still bound to a
socket, and the module cleanup code needs to be able to appropriately
free any such resources that are still allocated.  This should always
be safe, because if the driver has a use count of zero, all devices
are closed, which means all active sockets can be released, and all
device instances can be detached.

If a driver's <tt/*_release()/ function is called while a device is
still open, it should set the <tt/DEV_STALE_CONFIG/ flag in the device
state, to signal that the device should be released when the driver's
<tt/close()/ function is called.  If <tt/*_detach()/ is called for a
configured device, the <tt/DEV_STALE_LINK/ flag should be set to
signal that the instance should be detached when the <tt/*_release()/
function is called.

<sect1>Using existing Linux drivers to access PC Card devices
<p>
Many of the current client drivers use existing Linux driver
code to perform device IO operations.  The Card Services client module
handles card configuration and responds to card status change events,
but delegates device IO to a compatible driver for a conventional ISA
bus card.  In some cases, a conventional driver can be used without
modification.  However, to fully support PC Card features like hot
swapping and power management, there needs to be some communication
between the PC Card client code and the device IO code.

Most Linux drivers expect to probe for devices at boot time, and are
not designed to handle adding and removing devices.  One side-effect of
the move towards driver modularization is that it is usually easier to
adapt a modularized driver to handle removable devices.

It is important that a device driver be able to recover from having a
device disappear at an inappropriate time.  At best, the driver should
check for device presence before attempting any IO operation or before
handling an IO interrupt.  Loops that check device status should have
timeouts so they will eventually exit if a device never responds.

The <tt/dummy_cs/ driver may be useful for loading legacy drivers for
compatible PC Card devices.  After binding <tt/dummy_cs/ to a card, the
legacy driver module may be able to detect and communicate with the
device as if it were not a PC Card.  This arrangement will generally not
support clean hot swapping or power management functions, however it
may be useful as a basis for later developing a more full-featured
client driver.

<!-- ================================================================= -->

<sect>The Socket Driver Layer
<p>
In the Linux PCMCIA model, the ``Socket Services'' layer is a private
API intended only for the use of Card Services.  The API is based
loosely on the PCMCIA Socket Services specification, but is oriented
towards support for the common x86 laptop host controller types.

<sect1>Card Services entry points for socket drivers
<p>

Card Services provides special entry points for registering and
unregistering socket drivers:

<tscreen><verb>
typedef int (*ss_entry_t)(u_int sock, u_int cmd, void *arg);
extern int register_ss_entry(int nsock, ss_entry_t entry);
extern void unregister_ss_entry(ss_entry_t entry);
</verb></tscreen>

The socket driver invokes <tt/register_ss_entry/ with <tt/nsock/
indicating how many sockets are owned by this driver, and <tt/entry/
pointing to the function that will provide socket services for these
sockets.  The <tt/unregister_ss_entry/ routine can be safely invoked
whenever Card Services does not have any callback functions registered
for sockets owned by this driver.

<sect1>Services provided by the socket driver
<p>

Socket Services calls have the following form:

<tscreen><verb>
#include "pcmcia/ss.h"

int (*ss_entry)(u_int sock, int service, void *arg);
</verb></tscreen>

Non-zero return codes indicate that a request failed.

<!-- ================================================================= -->

<sect2>SS_InquireSocket
<p>
<tscreen><verb>
int (*ss_entry)(u_int sock, SS_InquireSocket, socket_cap_t *cap);
</verb></tscreen>
The <tt/socket_cap_t/ data structure is given by:
<tscreen><verb>
typedef struct socket_cap_t {
	u_int		features;
	u_int		irq_mask;
	u_int		map_size;
	u_char		pci_irq;
	u_char		cardbus;
	struct bus_operations *bus;
} socket_cap_t;
</verb></tscreen>

The <tt/SS_InquireSocket/ service is used to retrieve socket
capabilities.  The <tt/irq_mask/ field is a bit mask indicating which
ISA interrupts can be configured for IO cards.  The <tt/map_size/
field gives the address granularity of memory windows.  The
<tt/pci_irq/ field, if not zero, is the PCI interrupt number assigned
to this socket.  It is independent of <tt/irq_mask/, and can actually
be used in any situation where exactly one interrupt is associated
with a specific socket.  For CardBus bridges, the <tt/cardbus/ field
should be non-zero, and giv