Driver Services provides a link between Card Services client drivers
and user mode utilities like the cardmgr
daemon. It is a sort of
Card Services ``super-client''. Driver Services uses the
BindDevice
function to link other client drivers with their
corresponding PCMCIA cards. Unlike other clients, Driver Services
remains permanently bound to all sockets as cards are inserted and
removed.
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 PCMCIA card.
Each client driver is identified by a unique 16-character tag that has
the special type dev_info_t
, defined in cs_types.h
. Each
device instance is described by a dev_link_t
structure.
dev_link_t
structure The dev_link_t
data structure is given by:
#include "ds.h"
typedef struct dev_link_t {
char dev_name[8];
u_char major, minor;
u_long state;
u_long 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;
The dev_name
field should be filled in by the driver with a
device file name for accessing this device, if appropriate. For
example, the serial_cs
driver uses names like ``cua1
''. The
major
and minor
fields give major and minor device numbers
for accessing this device. Driver Services relays these fields to
user mode programs via the DS_GET_DEVICE_INFO
ioctl.
The state
field should be used to keep track of the current
device state. The following flags are defined:
DEV_PRESENT
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.
DEV_CONFIG
Indicates that the card is configured for use.
DEV_CONFIG_PENDING
Indicates that configuration is in progress.
DEV_SUSPEND
Indicates that the card is suspended.
DEV_BUSY
Indicates that an IO operation is in progress. This bit may be used as an interlock to prevent access conflicts.
DEV_STALE_CONFIG
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.
DEV_STALE_LINK
A driver instance should not be deleted until all its PCMCIA resources are released. This flag indicates that this driver instance should be freed as soon as the socket is unconfigured.
The open
field is a usage count for this device. The device
should only be freed when the open count is zero. The pending
field can be used to manage a queue of processes waiting to use the
device.
The 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 DEV_PRESENT
bit in the device state, then
scheduling the shutdown processing to run at a later time.
The handle
, io
, irq
, conf
, and win
fields
comprise all the normal PCMCIA data structures needed to configure an
ordinary PCMCIA IO card.
The priv
field can be used for any sort of private data structure
needed to manage the device. The next
field can be used to build
linked lists of dev_link_t
structures, for drivers that can
handle multiple instances.
int register_pcmcia_driver(dev_info_t *dev_info,
dev_link_t *(*attach)(void),
void (*detach)(dev_link_t *));
register_pcmcia_driver
informs Driver Services that a client
driver is present and ready to be bound to sockets. When Driver
Services receives a DS_BIND_REQUEST
ioctl that matches this
driver's dev_info
string, it will call the driver's attach()
entry point. When it gets a DS_UNBIND_REQUEST
ioctl, it will
call detach()
.
int unregister_pcmcia_driver(dev_info_t *dev_info);
This informs Driver Services that it should no longer bind sockets to the specified client driver.
Driver Services creates a pseudo-device for communicating with user
mode PCMCIA utilities. The major number of the device is chosen
dynamically, and PCMCIA utilities should read /proc/devices
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 ioctl
calls. A read/write connection can issue all ioctl
calls, and
can also receive Card Services event notifications.
Driver Services implements read()
and select()
functions for
event notification. Reading from a pcmcia device returns an unsigned
long value containing all the events received by Driver Services since
the previous read()
. If no events have been received, the call
will block until the next event. A select()
call can be used to
monitor several sockets for new events.
The following events are monitored by Driver Services:
CS_EVENT_CARD_INSERTION
, CS_EVENT_CARD_REMOVAL
,
CS_EVENT_RESET_PHYSICAL
, CS_EVENT_CARD_RESET
, and
CS_EVENT_RESET_COMPLETE
.
ioctl
descriptions Most Driver Services ioctl
operations directly map to Card
Services functions. An ioctl call has the form:
int ioctl(int fd, int cmd, ds_ioctl_arg_t *arg);
The ds_ioctl_arg_t structure is given by:
typedef union ds_ioctl_arg_t {
servinfo_t servinfo;
adjust_t adjust;
config_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;
} ds_ioctl_arg_t;
The following ioctl
commands execute the corresponding Card
Services function:
DS_GET_CARD_SERVICES_INFO
Calls CardServices(GetCardServicesInfo, ..., &arg->servinfo)
.
DS_ADJUST_RESOURCE_INFO
Calls CardServices(AdjustResourceInfo, ..., &arg->adjust)
.
DS_GET_CONFIGURATION_INFO
Calls CardServices(GetConfigurationInfo, ..., &arg->config)
.
DS_GET_FIRST_TUPLE
Calls CardServices(GetFirstTuple, ..., &arg->tuple)
.
DS_GET_NEXT_TUPLE
Calls CardServices(GetNextTuple, ..., &arg->tuple)
.
DS_GET_TUPLE_DATA
Calls CardServices(GetTupleData, ..., &arg->tuple_parse.tuple)
.
The tuple data is returned in arg->tuple_parse.data
.
DS_PARSE_TUPLE
Calls CardServices(ParseTuple, ..., &arg->tuple_parse.tuple, &arg->tuple_parse.parse)
.
DS_RESET_CARD
Calls CardServices(ResetCard, ...)
.
DS_GET_STATUS
Calls CardServices(GetStatus, ..., &arg->status)
.
DS_ACCESS_CONFIGURATION_REGISTER
Calls CardServices(AccessConfigurationRegister, ..., &arg->conf_reg)
.
DS_VALIDATE_CIS
Calls CardServices(ValidateCIS, ..., &arg->cisinfo)
.
DS_SUSPEND_CARD
Calls CardServices(SuspendCard, ...)
.
DS_RESUME_CARD
Calls CardServices(ResumeCard, ...)
.
DS_EJECT_CARD
Calls CardServices(EjectCard, ...)
.
DS_INSERT_CARD
Calls CardServices(InsertCard, ...)
.
DS_GET_FIRST_REGION
Calls CardServices(GetFirstRegion, ..., &arg->region)
.
DS_GET_NEXT_REGION
Calls CardServices(GetNextRegion, ..., &arg->region)
.
The following ioctl
commands invoke special Driver Services
functions. They act on bind_info_t
structures:
typedef struct bind_info_t {
dev_info_t dev_info;
struct dev_info_t *instance;
char name[8];
u_char major, minor;
void *next;
} bind_info_t;
DS_BIND_REQUEST
This call connects a socket to a client driver. The specified device
ID dev_info
is looked up in the list of registered drivers. If
found, the driver is bound to this socket using the BindDevice
call. Then, Driver Services calls the client driver's attach()
entry point to create a device instance. The new dev_link_t
pointer is returned in instance
.
DS_GET_DEVICE_INFO
This call retrieves the dev_name
, major
, and minor
entries from the dev_link_t
structure pointed to by
instance
.
DS_UNBIND_REQUEST
This call calls the detach()
function for the specified driver
and instance, shutting down this device.
Finally, the DS_BIND_MTD
request takes an argument of type
mtd_info_t
:
typedef struct mtd_info_t {
dev_info_t dev_info;
u_long Attributes;
u_long CardOffset;
} mtd_info_t;
This call associates an MTD identified by dev_info
with a memory
region described by Attributes
and CardOffset
, which have
the same meanings as in the Card Services BindMTD
call.
Next Chapter, Previous Chapter
Table of contents of this chapter, General table of contents
Top of the document, Beginning of this Chapter