NAME
ISA,
isa_intr_alloc,
isa_intr_establish,
isa_intr_disestablish,
isa_intr_evcnt,
isa_dmamap_create,
isa_dmamap_destroy,
isa_dmamem_alloc,
isa_dmamem_free,
isa_dmamem_map,
isa_dmamem_unmap,
isa_malloc,
isa_free,
isa_dmastart,
isa_dmaabort,
isa_dmacount,
isa_dmadone,
isa_dmamaxsize,
isa_drq_alloc,
isa_drq_free,
isa_drq_isfree,
isa_dmacascade,
isa_mappage —
Industry-standard
Architecture
SYNOPSIS
#include <sys/bus.h>
#include <dev/isa/isareg.h>
#include <dev/isa/isavar.h>
int
isa_intr_alloc(
isa_chipset_tag_t
ic,
int mask,
int type,
int *irq);
const struct evcnt *
isa_intr_evcnt(
isa_chipset_tag_t
ic,
int irq);
void *
isa_intr_establish(
isa_chipset_tag_t
ic,
int irq,
int type,
int level,
int (*handler)(void *),
void *arg);
void
isa_intr_disestablish(
isa_chipset_tag_t
ic,
void *ih);
#include <dev/isa/isadmareg.h>
#include <dev/isa/isadmavar.h>
int
isa_dmamap_create(
isa_chipset_tag_t
ic,
int chan,
bus_size_t size,
int flags);
void
isa_dmamap_destroy(
isa_chipset_tag_t
ic,
int chan);
int
isa_dmamem_alloc(
isa_chipset_tag_t
ic,
int chan,
bus_size_t size,
bus_addr_t *addrp,
int flags);
void
isa_dmamem_free(
isa_chipset_tag_t
ic,
int chan,
bus_addr_t addr,
bus_size_t size);
int
isa_dmamem_map(
isa_chipset_tag_t
ic,
int chan,
bus_addr_t addr,
bus_size_t size,
void **kvap,
int flags);
void
isa_dmamem_unmap(
isa_chipset_tag_t
ic,
int chan,
void *kva,
size_t size);
void *
isa_malloc(
isa_chipset_tag_t
ic,
int chan,
size_t size,
int pool,
int flags);
void
isa_free(
void
*addrp,
int pool);
int
isa_dmastart(
isa_chipset_tag_t
ic,
int chan,
bus_addr_t addr,
bus_size_t size,
struct lwp *lwp,
int flags,
int bf);
void
isa_dmaabort(
isa_chipset_tag_t
ic,
int chan);
bus_size_t
isa_dmacount(
isa_chipset_tag_t
ic,
int chan);
void
isa_dmadone(
isa_chipset_tag_t
ic,
int chan);
bus_size_t
isa_dmamaxsize(
isa_chipset_tag_t
ic,
int chan);
int
isa_drq_alloc(
isa_chipset_tag_t
ic,
int chan);
int
isa_drq_free(
isa_chipset_tag_t
ic,
int chan);
int
isa_drq_isfree(
isa_chipset_tag_t
ic,
int chan);
int
isa_dmacascade(
isa_chipset_tag_t
ic,
int chan);
paddr_t
isa_mappage(
void
*mem,
off_t offset,
int prot);
DESCRIPTION
The machine-independent
ISA subsystem provides support for the
ISA bus.
The ISA bus was introduced on the IBM PC/AT. It is an extension to the original
bus found on the original IBM PC. The ISA bus is essentially the host bus of
the Intel 80286 processor, however the widespread acceptance of the bus as a
de facto standard has seen it appear on systems without Intel processors.
The ISA bus has a 16-bit data bus, a 24-bit memory address bus, a 16-bit I/O
address bus, and operates at 8MHz. It provides 15 interrupt lines and 8 DMA
channels supporting DMA transfers of 64KB or 128KB transfers depending on the
width of the channel being used. Historically, some devices only decoded the
10 lowest bits of the I/O address bus, preventing use of the full 16-bit
address space.
On newer machines, the ISA bus is no longer connected directly to the host bus,
and is usually connected via a PCI-ISA bridge. Either way, the bus looks the
same to the device driver.
DATA TYPES
Drivers for devices attached to the
ISA bus will make use of
the following data types:
-
-
- isa_chipset_tag_t
- Chipset tag for the ISA bus.
-
-
- struct
isa_attach_args
- Location hints for devices are recorded in this structure.
It contains the following members:
bus_space_tag_t ia_iot; /* isa i/o space tag */
bus_space_tag_t ia_memt; /* isa mem space tag */
bus_dma_tag_t ia_dmat; /* DMA tag */
isa_chipset_tag_t ia_ic;
int ia_iobase; /* base i/o address */
int ia_iosize; /* span of ports used */
int ia_maddr; /* physical mem addr */
u_int ia_msize; /* size of memory */
int ia_irq; /* interrupt request */
int ia_drq; /* DMA request */
int ia_drq2; /* second DMA request */
void *ia_aux; /* driver specific */
FUNCTIONS
-
-
- isa_intr_alloc(ic,
mask, type,
irq)
- This function is generally not required by device drivers.
It is used by bridges attaching other busses to the ISA bus.
-
-
- isa_intr_evcnt(ic,
irq)
- Returns the event counter associated with interrupt line
irq.
-
-
- isa_intr_establish(ic,
irq, type,
level, handler,
arg)
- To establish an ISA interrupt handler, a driver calls
isa_intr_establish() with the interrupt number
irq, type type, and level
level. When the interrupt occurs the function
handler is called with argument
arg. Valid values for type
are:
-
-
- IST_NONE
- Reserve interrupt, but don't actually establish.
-
-
- IST_EDGE
- Edge-triggered interrupt.
-
-
- IST_LEVEL
- Level-triggered interrupt.
-
-
- IST_PULSE
- Pulse-triggered interrupt.
isa_intr_establish() returns an opaque handle to an event
descriptor if it succeeds, and returns NULL on failure.
-
-
- isa_intr_disestablish(ic,
ih)
- Dis-establish the interrupt handler with handle
ih. The handle was returned from
isa_intr_establish().
-
-
- isa_drq_alloc(ic,
chan)
- Reserves the DMA channel chan for
future use. Normally, this call precedes an
isa_dmamap_create() call. It is an error to start DMA on
a channel that has not been reserved with
isa_drq_alloc().
-
-
- isa_drq_free(ic,
chan)
- Marks the DMA channel chan as
available again.
-
-
- isa_dmamap_create(ic,
chan, size,
flags)
- Creates a DMA map for channel chan.
It is initialised to accept maximum DMA transfers of size
size. Valid values for the
flags argument are the same as for
bus_dmamap_create() (see
bus_dma(9)). This function
returns zero on success or an error value on failure.
-
-
- isa_dmamap_destroy(ic,
chan)
- Destroy the DMA map for DMA channel
chan.
-
-
- isa_dmamem_alloc(ic,
chan, size,
addrp, flags)
- Allocate DMA-safe memory of size size
for channel chan. Valid values for the
flags argument are the same as for
bus_dmamem_alloc() (see
bus_dma(9)). The
bus-address of the memory is returned in addrp. This
function returns zero on success or an error value on failure.
-
-
- isa_dmamem_free(ic,
chan, addr,
size)
- Frees memory previously allocated by
isa_dmamem_alloc() for channel
chan. The bus-address and size of the memory are
specified by addr and size
respectively.
-
-
- isa_dmamem_map(ic,
chan, addr,
size, kvap,
flags)
- Maps DMA-safe memory (allocated with
isa_dmamem_alloc()) specified by bus-address
addr and of size size into
kernel virtual address space for DMA channel chan.
Valid values for the flags argument are the same as
for bus_dmamem_map() (see
bus_dma(9)). The kernel
virtual address is returned in kvap. This function
returns zero on success or an error value on failure.
-
-
- isa_dmamem_unmap(ic,
chan, kva,
size)
- Unmaps memory (previously mapped with
isa_dmamem_map()) of size size for
channel chan. The kernel virtual address space used
by the mapping is freed.
-
-
- isa_malloc(ic,
chan, size,
pool, flags)
- This function is a shortcut for allocating and mapping
DMA-safe memory in a single step. The arguments correspond with the
arguments to isa_dmamem_alloc() and
isa_dmamem_map(). The argument
pool is a pool to record the memory allocation. This
function returns a pointer to the DMA-safe memory.
-
-
- isa_free(addrp,
pool)
- This function is a shortcut for unmapping and deallocating
DMA-safe memory in a single step. It replaces
isa_dmamem_unmap() and
isa_dmamem_free(). The argument
addrp is the pointer to the DMA-safe memory returned
by isa_malloc(). The argument pool
is the same as the value passed to isa_malloc().
-
-
- isa_dmastart(ic,
chan, addr,
size, lwp,
flags, bf)
- Load DMA memory specified by address
addr of size size into the DMA
controller at channel chan and set it in motion. The
argument lwp is used to indicate the address space
in which the buffer is located. If NULL, the buffer is assumed to be in
kernel space. Otherwise, the buffer is assumed to be in lwp
lwp 's address space. The argument
flags describes the type of ISA DMA. Valid values
are:
-
-
- DMAMODE_WRITE
- DMA transfer from host to device.
-
-
- DMAMODE_READ
- DMA transfer to host from device.
-
-
- DMAMODE_SINGLE
- Transfer buffer once and stop.
-
-
- DMAMODE_DEMAND
- Demand mode.
-
-
- DMAMODE_LOOP
- Transfer buffer continuously in loop until notified to
stop.
-
-
- DMAMODE_LOOPDEMAND
- Transfer buffer continuously in loop and demand
mode.
The argument bf is the bus-space flags. Valid values
are the same as for bus_dmamap_load() (see
bus_dma(9)).
-
-
- isa_dmaabort(ic,
chan)
- Abort a DMA transfer on channel
chan.
-
-
- isa_dmacount(ic,
chan)
- Returns the offset in the DMA memory of the current DMA
transfer on channel chan.
-
-
- isa_dmadone(ic,
chan)
- Unloads the DMA memory on channel
chan after a DMA transfer has completed.
-
-
- isa_dmamaxsize(ic,
chan)
- Returns the maximum allowable DMA transfer size for channel
chan.
-
-
- isa_drq_isfree(ic,
chan)
- If the ia_drq or
ia_drq2 members of struct
isa_attach_args are wildcarded, then the driver is expected to probe
the hardware for valid DMA channels. In this case, the driver can check to
see if the hardware-supported DMA channel chan is
available for use.
-
-
- isa_dmacascade(ic,
chan)
- Programs the 8237 DMA controller channel
chan to accept external DMA control by the device
hardware.
-
-
- isa_mappage(mem,
offset, prot)
- Provides support for user
mmap(2)'ing of DMA-safe
memory.
AUTOCONFIGURATION
The ISA bus is an indirect-connection bus. During autoconfiguration each driver
is required to probe the bus for the presence of a device. An ISA driver will
receive a pointer to
struct isa_attach_args hinting at
"locations" on the ISA bus where the device may be located. They
should use the
ia_iobase,
ia_iosize,
ia_maddr, and
ia_msize members. Not all of
these hints will be necessary; locators may be wildcarded with IOBASEUNK and
MADDRUNK for
ia_iobase and
ia_maddr
respectively. If a driver can probe the device for configuration information
at default locations, it may update the members of
struct
isa_attach_args. The IRQ and DMA locators can also be wildcarded with
IRQUNK and DRQUNK respectively.
During the driver attach step, the I/O and memory address spaces should be
mapped (see
bus_space(9)).
DMA SUPPORT
Extensive DMA facilities are provided for the ISA bus. A driver can use up to
two DMA channels simultaneously. The DMA channels allocated during
autoconfiguration are passed to the driver during the driver attach using the
ia_drq and
ia_drq2 members of
struct isa_attach_args.
Before allocating resources for DMA transfers on the ISA bus, a driver should
check the maximum allowable DMA transfer size for the DMA channel using
isa_dmamaxsize().
A DMA map should be created first using
isa_dmamap_create(). A
DMA map describes how DMA memory is loaded into the DMA controllers. Only
DMA-safe memory can be used for DMA transfers. DMA-safe memory is allocated
using
isa_dmamem_alloc(). The memory allocated by
isa_dmamem_alloc() must now be mapped into kernel virtual
address space by
isa_dmamem_map() so that it can be accessed
by the driver.
For a DMA transfer from the host to the device, the driver will fill the DMA
memory with the data to be transferred. The DMA-transfer of the memory is
started using
isa_dmastart() with
flags containing DMAMODE_WRITE. When the DMA transfer is
completed, a call to
isa_dmadone() cleans up the DMA
transfer by unloading the memory from the controller.
For a DMA transfer from the device to the host, the DMA-transfer is started
using
isa_dmastart() with
flags
containing DMAMODE_READ. When the DMA transfer is completed, a call to
isa_dmadone() cleans up the DMA transfer by unloading the
memory from the controller. The memory can now be access by the driver.
When the DMA resources are no longer required they should be released using
isa_dmamem_unmap(),
isa_dmamem_free() and
isa_dmamap_destroy().
CODE REFERENCES
The ISA subsystem itself is implemented within the files
sys/dev/isa/isa.c and
sys/dev/isa/isadma.c.
SEE ALSO
isa(4),
autoconf(9),
bus_dma(9),
bus_space(9),
driver(9),
isapnp(9)
HISTORY
The machine-independent
ISA subsystem appeared in
NetBSD 1.2.
BUGS
The previous behaviour of
isa_intr_establish() was to invoke
panic() on failure.
isa_intr_establish()
now returns NULL on failure. Some old drivers written for the former behaviour
discard the return value.