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.
Card Services provides special entry points for registering and unregistering socket drivers:
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);
The socket driver invokes register_ss_entry
with nsock
indicating how many sockets are owned by this driver, and entry
pointing to the function that will provide socket services for these
sockets. The unregister_ss_entry
routine can be safely invoked
whenever Card Services does not have any callback functions registered
for sockets owned by this driver.
Socket Services calls have the following form:
#include "pcmcia/ss.h"
int (*ss_entry)(u_int sock, int service, void *arg);
Non-zero return codes indicate that a request failed.
int (*ss_entry)(u_int sock, SS_InquireSocket, socket_cap_t *cap);
The socket_cap_t
data structure is given by:
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;
The SS_InquireSocket
service is used to retrieve socket
capabilities. The irq_mask
field is a bit mask indicating which
ISA interrupts can be configured for IO cards. The map_size
field gives the address granularity of memory windows. The
pci_irq
field, if not zero, is the PCI interrupt number assigned
to this socket. It is independent of irq_mask
, and can actually
be used in any situation where exactly one interrupt is associated
with a specific socket. For CardBus bridges, the cardbus
field
should be non-zero, and gives the PCI bus number of the CardBus side
of the bridge.
For sockets that do not directly map cards into the host IO and memory
space, the bus
field is a pointer to a table of entry points for
IO primitives for this socket.
The following flags may be specified in features
:
SS_CAP_PAGE_REGS
Indicates that this socket supports full 32-bit addressing for 16-bit PC Card memory windows.
SS_CAP_VIRTUAL_BUS
Indicates that 16-bit card memory and IO accesses must be performed using the bus operations table, rather than using native bus operations.
SS_CAP_MEM_ALIGN
Indicates that memory windows must be aligned by the window size.
SS_CAP_STATIC_MAP
Indicates that memory windows are statically mapped at fixed locations in the host address space, and cannot be repositioned.
SS_CAP_PCCARD
Indicates that this socket supports 16-bit PC cards.
SS_CAP_CARDBUS
Indicates that this socket supports 32-bit CardBus cards.
int (*ss_entry)(u_int sock, SS_RegisterCallback, ss_callback_t *call);
The ss_callback_t
data structure is given by:
typedef struct ss_callback_t {
void (*handler)(void *info, u_int events);
void *info;
} ss_callback_t;
The SS_RegisterCallback
service sets up a callback function to be
invoked when the socket driver receives card status change events. To
unregister a callback, this function is called with a handler value of
NULL
. Only one callback function can be registered per socket.
The handler will be called with the value of info
that was passed
to SS_RegisterCallback
for this socket, and with a bit map of
events in the events
parameter. The following events are
defined:
SS_DETECT
A card detect change (insertion or removal) has been detected.
SS_READY
A memory card's ready signal has changed state.
SS_BATDEAD
A memory card has raised the battery-dead signal.
SS_BATWARN
A memory card has raised the battery-low signal.
SS_STSCHG
An IO card has raised the status change signal.
int (*ss_entry)(u_int sock, SS_GetStatus, u_int *status);
The SS_GetStatus
service returns the current status of this
socket. The status
parameter will be constructed out of the
following flags:
SS_WRPROT
The card is write-protected.
SS_BATDEAD
A memory card has raised the battery-dead signal.
SS_BATWARN
A memory card has raised the battery-low signal.
SS_READY
A memory card has raised its ready signal.
SS_DETECT
A card is present.
SS_POWERON
Power has been applied to the socket.
SS_STSCHG
An IO card has raised the status change signal.
SS_CARDBUS
The socket contains a CardBus card (as opposed to a 16-bit PC Card).
SS_3VCARD
The card must be operated at no more than 3.3V.
SS_XVCARD
The card must be operated at no more than X.XV (not yet defined).
int (*ss_entry)(u_int sock, SS_GetSocket, socket_state_t *);
int (*ss_entry)(u_int sock, SS_SetSocket, socket_state_t *);
The socket_state_t
data structure is given by:
typedef struct socket_state_t {
u_int flags;
u_int csc_mask;
u_char Vcc, Vpp;
u_char io_irq;
} socket_state_t;
The csc_mask
field indicates which event types should generate
card status change interrupts. The following event types can be
monitored:
SS_DETECT
Card detect changes (insertion or removal).
SS_READY
Memory card ready/busy changes.
SS_BATDEAD
Memory card battery-dead changes.
SS_BATWARN
Memory card battery-low changes.
SS_STSCHG
IO card status changes.
The Vcc
and Vpp
parameters are in units of 0.1 volts. If
non-zero, io_irq
specifies an interrupt number to be assigned to
the card, in IO mode. The following fields are defined in flags
:
SS_PWR_AUTO
Indicates that the socket should automatically power up sockets at card insertion time, if supported.
SS_IOCARD
Indicates that the socket should be configured for ``memory and IO'' interface mode, as opposed to simple memory card mode.
SS_RESET
Indicates that the card's hardware reset signal should be raised.
SS_SPKR_ENA
Indicates that speaker output should be enabled for this socket.
SS_OUTPUT_ENA
Indicates that data signals to the card should be activated.
int (*ss_entry)(u_int sock, SS_GetIOMap, pccard_io_map *);
int (*ss_entry)(u_int sock, SS_SetIOMap, pccard_io_map *);
The pccard_io_map
data structure is given by:
typedef struct pccard_io_map {
u_char map;
u_char flags;
u_short speed;
u_short start, stop;
} pccard_io_map;
The SS_GetIOMap
and SS_SetIOMap
entries are used to
configure IO space windows. IO windows are assumed to not support
address translation. The Linux Card Services layer assumes that each
socket has at least two independently configurable IO port windows.
The map
field specifies which IO map should be accessed. The
speed
field is the map access speed in nanoseconds. The
start
and stop
fields give the lower and upper addresses for
the IO map. The flags
field is composed of the following:
MAP_ACTIVE
Specifies that the address map should be enabled.
MAP_16BIT
Specifies that the map should be configured for 16-bit accesses (as opposed to 8-bit).
MAP_AUTOSZ
Specifies that the map should be configured to auto-size bus accesses
in response to the card's IOCS16
signal.
MAP_0WS
Requests zero wait states, as opposed to standard ISA bus timing.
MAP_WRPROT
Specifies that the map should be write protected.
MAP_USE_WAIT
Specifies that access timing should respect the card's WAIT
signal.
MAP_PREFETCH
Specifies that this map may be configured for prefetching.
int (*ss_entry)(u_int sock, SS_GetMemMap, pccard_mem_map *);
int (*ss_entry)(u_int sock, SS_SetMemMap, pccard_mem_map *);
The pccard_mem_map
data structure is given by:
typedef struct pccard_mem_map {
u_char map;
u_char flags;
u_short speed;
u_long sys_start, sys_stop;
u_int card_start;
} pccard_mem_map;
The map
field specifies the map number. The speed
field
specifies an access speed in nanoseconds. The sys_start
and
sys_stop
fields give the starting and ending addresses for the
window in the host's physical address space. The card_start
value specifies the card address to be mapped to sys_start
.
The Linux Card Services layer assumes that each socket has at least
four independently configurable memory windows.
MAP_ACTIVE
Specifies that the address map should be enabled.
MAP_16BIT
Specifies that the map should be configured for 16-bit accesses (as opposed to 8-bit).
MAP_AUTOSZ
Specifies that the map should be configured to auto-size bus accesses
in response to the card's IOCS16
signal.
MAP_0WS
Requests zero wait states, as opposed to standard ISA bus timing.
MAP_WRPROT
Specifies that the map should be write protected.
MAP_ATTRIB
Specifies that the map should be for attribute (as opposed to common) memory.
MAP_USE_WAIT
Specifies that access timing should respect the card's WAIT
signal.
int (*ss_entry)(u_int sock, SS_GetBridge, cb_bridge_map *);
int (*ss_entry)(u_int sock, SS_SetBridge, cb_bridge_map *);
The cb_bridge_map
data structure is given by:
typedef struct cb_bridge_map {
u_char map;
u_char flags;
u_int start, stop;
} cb_bridge_map;
The SS_GetBridge
and SS_SetBridge
entry points are used for
configuring bridge address windows for CardBus devices. They are
similar to the 16-bit IO and memory map services. It is assumed that
each CardBus socket has at least two IO and two memory bridge windows.
The flags
field is composed of:
MAP_ACTIVE
Specifies that the address map should be enabled.
MAP_PREFETCH
Specifies that this map can be configured for prefetching.
MAP_IOSPACE
Specifies that this map should be for IO space (as opposed to memory space).
int (*ss_entry)(u_int sock, SS_ProcSetup, struct proc_dir_entry *base);
Card Services uses this entry point to give the socket driver a procfs directory handle under which it may create status files for a specific socket. It is the socket driver's responsbility to delete any proc entries before it is unloaded.
The Socket Services interface is oriented towards socket controllers that allow PCMCIA cards to be configured to mimic native system devices with the same functionality. The ExCA standard specifies that socket controllers should provide two IO and five memory windows per socket, which can be independently configured and positioned in the host address space and mapped to arbitrary segments of card address space. Some controllers and architectures do not provide this level of functionality. In these situations, Socket Services can effectively virtualize the socket interface for client drivers.
On the client side (including internal Card Services uses), to use the virtualized socket interface, code must first specify:
#include "pcmcia/bus_ops.h"
All IO operations then need to be replaced with new bus-neutral forms. The following functions need to be virtualized:
inb
, inw
, inl
, inw_ns
, inl_ns
insb
, insw
, insl
, insw_ns
, insl_ns
outb
, outw
, outl
, outw_ns
, outl_ns
outsb
, outsw
, outsl
, outsw_ns
, outsl_ns
readb
, readw
, readl
, readw_ns
, readl_ns
writeb
, writew
, writel
, writew_ns
, writel_ns
ioremap
, iounmap
memcpy_fromio
, memcpy_toio
request_irq
, free_irq
The bus-neutral functions have a prefix of ``bus_
'', with a new
first argument, the bus operations table pointer returned by
SS_InquireSocket
. For example, inb(port)
should be replaced
with bus_inb(bus, port)
.
All the IO primitives are defined as macros that call entry points in the bus operations table. There is not a one-to-one mapping from IO primitives to bus operation entry points.
The bus operations table is defined as:
typedef struct bus_operations {
void *priv;
u32 (*b_in)(void *bus, u32 port, s32 sz);
void (*b_ins)(void *bus, u32 port, void *buf,
u32 count, s32 sz);
void (*b_out)(void *bus, u32 val, u32 port, s32 sz);
void (*b_outs)(void *bus, u32 port, void *buf,
u32 count, s32 sz);
void *(*b_ioremap)(void *bus, u_long ofs, u_long sz);
void (*b_iounmap)(void *bus, void *addr);
u32 (*b_read)(void *bus, void *addr, s32 sz);
void (*b_write)(void *bus, u32 val, void *addr, s32 sz);
void (*b_copy_from)(void *bus, void *d, void *s, u32 count);
void (*b_copy_to)(void *bus, void *d, void *s, u32 count);
int (*b_request_irq)(void *bus, u_int irq,
void (*handler)(int, void *,
struct pt_regs *),
u_long flags, const char *device,
void *dev_id);
void (*b_free_irq)(void *bus, u_int irq, void *dev_id);
} bus_operations;
The priv
field can be used for any purpose by the socket driver,
for instance, to indicate which of several sockets is being addressed.
The b_in
, b_out
, b_read
, and b_write
entry points
each support byte, word, and dword operations, either byte-swapped or
unswapped. The sz
parameter is 0, 1, or 2 for byte, word, or
dword accesses; -1 and -2 select word and dword unswapped accesses.