xtalk_pio(D3)xtalk_pio(D3)NAME
xtalk_pio_addr - construct PIO address
xtalk_piotrans_addr - construct PIO address
xtalk_piomap_alloc - allocate an XIO PIO channel
xtalk_piomap_addr - set PIO channel target
xtalk_piomap_done - mark PIO channel unused
xtalk_piomap_free - release XIO PIO channel resources
SYNOPSIS
#include <sys/XIO/xtalk.h>
caddr_t
xtalk_pio_addr(vertex_hdl_t vhdl,
device_desc_t desc,
iopaddr_t addr,
size_t size,
xtalk_piomap_t *mapp,
unsigned flags)
caddr_t
xtalk_piotrans_addr(vertex_hdl_t vhdl,
device_desc_t desc,
iopaddr_t addr,
size_t size,
unsigned flags)
xtalk_piomap_t
xtalk_piomap_alloc(vertex_hdl_t vhdl,
device_desc_t desc,
iopaddr_t addr,
size_t size,
size_t max,
unsigned flags)
caddr_t
xtalk_piomap_addr(xtalk_piomap_t map,
iopaddr_t addr,
size_t size);
void
xtalk_piomap_done(xtalk_piomap_t xtalk_piomap)
void
xtalk_piomap_free(xtalk_piomap_t xtalk_piomap)
Arguments
vhdl is the appropriate XIO connection point.
desc is a device descriptor, usually zero.
Page 1
xtalk_pio(D3)xtalk_pio(D3)
addr is the XIO address on the target device.
size is the size of the mapped region.
align is a desired alignment.
max is the maximum size mapped at any one time.
flags is reserved and should be zero.
map is the result of a previous xtalk_piomap_alloc call.
mapp is a place to record a map that may be allocated.
DESCRIPTION
When a device driver wishes to use Programmed I/O (PIO) to communicate
with a device, the system needs to have a chance to set up any
appropriate mapping registers.
There are two different models for how to do this. The simple model
provides permanent mappings through fixed mapping resources.
o xtalk_piotrans_addr() is generally called at device attach time to
construct a permanent address that can be used for PIO access to a
device's control registers; it attempts to use shared resources to
construct a physical address that, when used, will route transactions
to the proper target on the XIO bus. This is not always possible,
and when it is not, the function will return NULL.
o xtalk_pio_addr() is a wrapper function that calls
xtalk_piotrans_addr() to establish a mapping, and if that fails, it
then allocates a piomap using xtalk_piomap_alloc() and fills it in
using xtalk_piomap_addr(), returning the resulting piomap via the map
pointer mapp.
It is not always possible to establish such mappings using common shared
system resources, so the concept of a PIO channel that preallocates
scarce mapping resources is provided.
Such channels are allocated using xtalk_piomap_alloc(), which is given
the limits of the region that will be mapped, and the maximum size to be
mapped from within that region.
o xtalk_piomap_addr() is then used to actually establish the proper
mappings for a PIO target; given the address and the size of the
region for PIO, it will hand back the base address to be used for
accessing that region.
o If the same PIO channel is to be used at different times to map
different target areas, xtalk_piomap_done() should be called to idle
any mapping hardware (and possibly flush out any pipes or buffers
Page 2
xtalk_pio(D3)xtalk_pio(D3)
along the path that might do unexpected things when mapping registers
are modified). Then xtalk_piomap_addr() can again be called,
specifying the new target area.
When a driver is completely finished with a PIO channel -- either because
the channel is used only for initialization of the device, or because the
device or the driver is being shut down -- the PIO channel resources
should be released back to the system using xtalk_piomap_free().
EXAMPLES
Here is a contrived example of how one might initialize a very strange
XIO card. It is not clear that this would be the best way to do it, but
it does give an example of the relationship between the various
functions.
xiofoo_attach(vertex_hdl_t vhdl)
{
unsigned *cfgspace;
struct xiofoo_devregs *devregs;
xtalk_piomap_t pmap;
xtalk_piomap_t cmap;
struct xiofoo_chan_config *tune;
...
/* Get a pointer we can use for PIO to our
* device's control registers. This call
* is blindly assuming that a "piotrans"
* to the base of a widget will always work,
* which we would like to be true but may
* not be able to always guarantee.
*/
devregs = xtalk_piotrans_addr(
vhdl, 0,
0, sizeof (struct xiofoo_devregs),
0);
if (cfgspace == NULL) {
cmn_err(CE_ALERT,
"xiofoo_attach: xtalk_piotrans_addr failed");
return -1;
}
...
/* pretend our "channel" space is too big
* to successfully map with piotrans, so
* we have to use piomap, and that it is
* too big for us to get it in one call
* to piomap_addr.
*
Page 3
xtalk_pio(D3)xtalk_pio(D3)
* This would be the case, for instance,
* if the board took its 48 bits of address
* space, divided it into 16 equal pieces,
* and assigned each one to a logical portion
* of its task: on some large systems, we
* just can't keep fixed shared mapping
* resources set up for all 48 bits of all
* the widgets in the system.
*/
cmap = xtalk_piomap_alloc(vhdl, 0,
CHAN_OFFSET, CHAN_SEP * CHANS,
sizeof (struct xiofoo_chan_config), 0);
for (chan = 0; chan < chans; ++chan) {
tune = (struct xiofoo_chan_config *)
xtalk_piomap_addr(cmap, CHAN_SEP * chan,
sizeof (struct xiofoo_chan_config));
/* now fiddle with this particular channel */
tune->chan = chan + 2;
tune->volume = 5;
tune->balance = 0;
xtalk_piomap_done(cmap);
}
xtalk_piomap_free(cmap);
...
}
NOTES
It is not necessary to separately establish mappings for each individual
PIO target register; it is more efficient to use a single mapping to
cover an entire device register set.
SEE ALSOxtalk(D3), xtalk_dma(D3), xtalk_error(D3), xtalk_get(D3), xtalk_intr(D3).
DIAGNOSTICSxtalk_piotrans_addr() will return a null pointer if shared (fixed)
resources can not be used to construct a valid physical address that maps
to the desired range of XIO addresses.
xtalk_piomap_alloc() will return a null pointer if resources can not be
allocated to establish PIO mappings to the described region, or if the
parameters are inconsistent.
Page 4
xtalk_pio(D3)xtalk_pio(D3)xtalk_piomap_addr() will return a null pointer if the specified target
address can not be mapped using the specified PIO channel; this would
usually be due to specifying a target block that is outside the
previously specified target area or is larger than the previously
specified maximum mapping size. It may also return a null pointer if the
PIO channel is currently in use and has not been marked idle by a
xtalk_piomap_done() call.
Page 5