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_REGSIndicates that this socket supports full 32-bit addressing for 16-bit PC Card memory windows.
SS_CAP_VIRTUAL_BUSIndicates 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_ALIGNIndicates that memory windows must be aligned by the window size.
SS_CAP_STATIC_MAPIndicates that memory windows are statically mapped at fixed locations in the host address space, and cannot be repositioned.
SS_CAP_PCCARDIndicates that this socket supports 16-bit PC cards.
SS_CAP_CARDBUSIndicates 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_DETECTA card detect change (insertion or removal) has been detected.
SS_READYA memory card's ready signal has changed state.
SS_BATDEADA memory card has raised the battery-dead signal.
SS_BATWARNA memory card has raised the battery-low signal.
SS_STSCHGAn 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_WRPROTThe card is write-protected.
SS_BATDEADA memory card has raised the battery-dead signal.
SS_BATWARNA memory card has raised the battery-low signal.
SS_READYA memory card has raised its ready signal.
SS_DETECTA card is present.
SS_POWERONPower has been applied to the socket.
SS_STSCHGAn IO card has raised the status change signal.
SS_CARDBUSThe socket contains a CardBus card (as opposed to a 16-bit PC Card).
SS_3VCARDThe card must be operated at no more than 3.3V.
SS_XVCARDThe 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_DETECTCard detect changes (insertion or removal).
SS_READYMemory card ready/busy changes.
SS_BATDEADMemory card battery-dead changes.
SS_BATWARNMemory card battery-low changes.
SS_STSCHGIO 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_AUTOIndicates that the socket should automatically power up sockets at card insertion time, if supported.
SS_IOCARDIndicates that the socket should be configured for ``memory and IO'' interface mode, as opposed to simple memory card mode.
SS_RESETIndicates that the card's hardware reset signal should be raised.
SS_SPKR_ENAIndicates that speaker output should be enabled for this socket.
SS_OUTPUT_ENAIndicates 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_ACTIVESpecifies that the address map should be enabled.
MAP_16BITSpecifies that the map should be configured for 16-bit accesses (as opposed to 8-bit).
MAP_AUTOSZSpecifies that the map should be configured to auto-size bus accesses
in response to the card's IOCS16 signal.
MAP_0WSRequests zero wait states, as opposed to standard ISA bus timing.
MAP_WRPROTSpecifies that the map should be write protected.
MAP_USE_WAITSpecifies that access timing should respect the card's WAIT
signal.
MAP_PREFETCHSpecifies 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_ACTIVESpecifies that the address map should be enabled.
MAP_16BITSpecifies that the map should be configured for 16-bit accesses (as opposed to 8-bit).
MAP_AUTOSZSpecifies that the map should be configured to auto-size bus accesses
in response to the card's IOCS16 signal.
MAP_0WSRequests zero wait states, as opposed to standard ISA bus timing.
MAP_WRPROTSpecifies that the map should be write protected.
MAP_ATTRIBSpecifies that the map should be for attribute (as opposed to common) memory.
MAP_USE_WAITSpecifies 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_ACTIVESpecifies that the address map should be enabled.
MAP_PREFETCHSpecifies that this map can be configured for prefetching.
MAP_IOSPACESpecifies 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_nsinsb, insw, insl, insw_ns, insl_nsoutb, outw, outl, outw_ns, outl_nsoutsb, outsw, outsl, outsw_ns, outsl_nsreadb, readw, readl, readw_ns, readl_nswriteb, writew, writel, writew_ns, writel_nsioremap, iounmapmemcpy_fromio, memcpy_toiorequest_irq, free_irqThe 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.