xtalk(D3)xtalk(D3)NAME
xtalk - IRIX XIO Infrastructure
xwidget_driver_register - claim a class of XIO widgets
xwidget_driver_unregister - remove driver from registry
xtalk_iterate - revisit all claimed widgets
SYNOPSIS
#include <sys/xtalk/xtalk.h>
int
xwidget_driver_register(
xwidget_part_num_t part_num,
xwidget_mfg_num_t mfg_num,
char *driver_prefix,
unsigned flags);
void
xwidget_driver_unregister(char *driver_prefix);
void
xtalk_iterate(
char *driver_prefix,
xtalk_iter_f *func)
Arguments
part_num and mfg_num
are the values that the XIO-based device will present in its XIO
ID register as identification.
driver_prefix
is the prefix string for the driver's standard functions; the
infrastructure will use this prefix to locate the driver's cdevsw
entry, in order to call the driver's attach and detach routines.
flags Normally passed as zero.
DESCRIPTION
xtalk is the package that drivers for XIO-based devices use to set up
services for their devices. These services include:
o locating all instances of the device in the system (documented in
this page).
o constructing CPU addresses that the driver can use to do PIO accesses
to the device (see xtalk_pio(D3)).
o constructing XIO addresses that the device can use to do DMA accesses
to memory (see xtalk_dma(D3)).
o arranging for a function to be called when the device requests
interrupt service (see xtalk_intr(D3)).
Page 1
xtalk(D3)xtalk(D3)
o arranging for a function to be called when an error occurs during PIO
to, or DMA from the device (see xtalk_error(D3)).
o accessing useful fields in some otherwise opaque data structures (see
xtalk_get(D3)).
Driver Registration
xwidget_driver_register() is used by drivers to inform the infrastructure
that they are interested in certain XIO-based devices; a relation is kept
associating the specified part and manufacturer ID numbers with the noted
device driver prefix. The infrastructure will call the attach routine
with that driver prefix, passing the hardware graph connection point
vertex as the only parameter. This connection point is then used in most
calls to the infrastructure to identify which particular XIO device is of
interest.
Loadable device drivers should call this function from their reg() entry
point. Drivers that are prelinked into the kernel should also make the
call from reg() for consistency, but may call from init() if necessary.
Device drivers may make multiple calls with different vendor and device
ID numbers, representing several compatible XIO devices.
Wildcard values XWIDGET_PART_NUM_NONE and XWIDGET_MFG_NUM_NONE may be
used if cards from any vendor or cards with any device code are of
interest; if both vendor and device are wildcarded, the attach routine
will be called for every XIO device connected to the system.
When a loadable device driver calls xwidget_driver_register(), the calls
to the driver's attach() function may occur before the infrastructure
returns control to the caller. On some large systems, the attach() calls
may be executed by other threads and possibly on other processors,
concurrently with continued execution of the reg() function.
xwidget_driver_unregister() should be called by any unloadable device
driver, from within the driver's unreg() function. This will trigger
calls to the driver's detach() entry point, and remove any references to
the driver from the registry table.
Connection Point Iteration
It is sometimes important for driver code to be able to go back and
revisit each connection point that was passed to its attach routine; the
best case for this is the disconnecting of interrupt and error handling
functions before unloading a driver, and the reconnecting of these
handlers after the driver is reloaded. xtalk_iterate() provides a quick
mechanism to have a private function called with each connection point
that the infrastructure has matched with the specified driver.
Page 2
xtalk(D3)xtalk(D3)
On large systems, the calls may take place in many separate threads on
many separate processors, so the function to be called needs to use
appropriate locking when accessing driver-global structures.
EXAMPLES
Here is how a typical driver might make use of these functions:
static char xiofoo_prefix[] = "xiofoo_";
static char xiofoo_edge[] = "foo";
xiofoo_init(void)
{
/* the first time through, we are not
* registered, so this is a no-op.
* after that, it triggers reload_me.
*/
xtalk_iterate(xiofoo_prefix, xiofoo_reload_me);
}
xiofoo_unload(void)
{
...
xtalk_iterate(xiofoo_prefix, xiofoo_unload_me);
...
}
xiofoo_reg(void)
{
xwidget_driver_register(
XIOFOO_VENDOR_ID,
XIOFOO_DEVICE_ID,
xiofoo_prefix, 0);
}
xiofoo_unreg(void)
{
xwidget_driver_unregister(xiofoo_prefix);
}
xiofoo_reload_me(vertex_hdl_t conn)
{
vertex_hdl_t vhdl;
xiofoo_soft_t xiofoo_soft;
if (GRAPH_SUCCESS !=
hwgraph_traverse(conn, xiofoo_edge, &vhdl))
return;
xiofoo_soft = hwgraph_fastinfo_get(vhdl);
if (!xiofoo_soft)
return;
Page 3
xtalk(D3)xtalk(D3)
if (xiofoo_soft->intr)
xtalk_intr_connect(xiofoo_soft->intr,
xiofoo_intr,
xiofoo_soft);
}
xiofoo_reload_me(vertex_hdl_t conn)
{
vertex_hdl_t vhdl;
xiofoo_soft_t xiofoo_soft;
if (GRAPH_SUCCESS !=
hwgraph_traverse(conn, xiofoo_edge, &vhdl))
return;
xiofoo_soft = hwgraph_fastinfo_get(vhdl);
if (!xiofoo_soft)
return;
if (xiofoo_soft->intr)
xtalk_intr_connect(xiofoo_soft->intr,
xiofoo_intr,
xiofoo_soft);
}
xiofoo_unload_me(vertex_hdl_t conn)
{
vertex_hdl_t vhdl;
xiofoo_soft_t xiofoo_soft;
if (GRAPH_SUCCESS !=
hwgraph_traverse(conn, xiofoo_edge, &vhdl))
return;
xiofoo_soft = hwgraph_fastinfo_get(vhdl);
if (xiofoo_soft->intr)
xtalk_intr_disconnect(xiofoo_soft->intr);
}
SEE ALSOxtalk_dma(D3), xtalk_error(D3), xtalk_get(D3), xtalk_intr(D3),
xtalk_pio(D3).
Page 4