.\" $NetBSD: isa.9,v 1.20 2011/05/30 01:48:40 dyoung Exp $
.\"
.\" Copyright (c) 2001, 2005, 2006 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to The NetBSD Foundation
.\" by Gregory McGarry.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd January 29, 2006
.Dt ISA 9
.Os
.Sh NAME
.Nm ISA ,
.Nm isa_intr_alloc ,
.Nm isa_intr_establish ,
.Nm isa_intr_disestablish ,
.Nm isa_intr_evcnt ,
.Nm isa_dmamap_create ,
.Nm isa_dmamap_destroy ,
.Nm isa_dmamem_alloc ,
.Nm isa_dmamem_free ,
.Nm isa_dmamem_map ,
.Nm isa_dmamem_unmap ,
.Nm isa_malloc ,
.Nm isa_free ,
.Nm isa_dmastart ,
.Nm isa_dmaabort ,
.Nm isa_dmacount ,
.Nm isa_dmadone ,
.Nm isa_dmamaxsize ,
.Nm isa_drq_alloc ,
.Nm isa_drq_free ,
.Nm isa_drq_isfree ,
.Nm isa_dmacascade ,
.Nm isa_mappage
.Nd Industry-standard Architecture
.Sh SYNOPSIS
.In sys/bus.h
.In dev/isa/isareg.h
.In dev/isa/isavar.h
.Ft int
.Fn isa_intr_alloc "isa_chipset_tag_t ic" "int mask" "int type" \
"int *irq"
.Ft const struct evcnt *
.Fn isa_intr_evcnt "isa_chipset_tag_t ic" "int irq"
.Ft void *
.Fn isa_intr_establish "isa_chipset_tag_t ic" "int irq" "int type" \
"int level" "int (*handler)(void *)" "void *arg"
.Ft void
.Fn isa_intr_disestablish "isa_chipset_tag_t ic" "void *ih"
.In dev/isa/isadmareg.h
.In dev/isa/isadmavar.h
.Ft int
.Fn isa_dmamap_create "isa_chipset_tag_t ic" "int chan" "bus_size_t size" \
"int flags"
.Ft void
.Fn isa_dmamap_destroy "isa_chipset_tag_t ic" "int chan"
.Ft int
.Fn isa_dmamem_alloc "isa_chipset_tag_t ic" "int chan" "bus_size_t size" \
"bus_addr_t *addrp" "int flags"
.Ft void
.Fn isa_dmamem_free "isa_chipset_tag_t ic" "int chan" "bus_addr_t addr" \
"bus_size_t size"
.Ft int
.Fn isa_dmamem_map "isa_chipset_tag_t ic" "int chan" "bus_addr_t addr" \
"bus_size_t size" "void **kvap" "int flags"
.Ft void
.Fn isa_dmamem_unmap "isa_chipset_tag_t ic" "int chan" "void *kva" \
"size_t size"
.Ft void *
.Fn isa_malloc "isa_chipset_tag_t ic" "int chan" "size_t size" \
"int pool" "int flags"
.Ft void
.Fn isa_free "void *addrp" "int pool"
.Ft int
.Fn isa_dmastart "isa_chipset_tag_t ic" "int chan" "bus_addr_t addr" \
"bus_size_t size" "struct lwp *lwp" "int flags" "int bf"
.Ft void
.Fn isa_dmaabort "isa_chipset_tag_t ic" "int chan"
.Ft bus_size_t
.Fn isa_dmacount "isa_chipset_tag_t ic" "int chan"
.Ft void
.Fn isa_dmadone "isa_chipset_tag_t ic" "int chan"
.Ft bus_size_t
.Fn isa_dmamaxsize "isa_chipset_tag_t ic" "int chan"
.Ft int
.Fn isa_drq_alloc "isa_chipset_tag_t ic" "int chan"
.Ft int
.Fn isa_drq_free "isa_chipset_tag_t ic" "int chan"
.Ft int
.Fn isa_drq_isfree "isa_chipset_tag_t ic" "int chan"
.Ft int
.Fn isa_dmacascade "isa_chipset_tag_t ic" "int chan"
.Ft paddr_t
.Fn isa_mappage "void *mem" "off_t offset" "int prot"
.Sh DESCRIPTION
The machine-independent
.Nm
subsystem provides support for the ISA bus.
.Pp
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.
.Pp
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.
.Pp
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.
.Sh DATA TYPES
Drivers for devices attached to the
.Nm
bus will make use of the following data types:
.Bl -tag -width compact
.It Fa isa_chipset_tag_t
Chipset tag for the ISA bus.
.It Fa struct isa_attach_args
Location hints for devices are recorded in this structure.
It contains the following members:
.Bd -literal
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 */
.Ed
.El
.Sh FUNCTIONS
.Bl -tag -width compact
.It Fn 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.
.It Fn isa_intr_evcnt "ic" "irq"
Returns the event counter associated with interrupt line
.Fa irq .
.It Fn isa_intr_establish "ic" "irq" "type" "level" "handler" "arg"
To establish an ISA interrupt handler, a driver calls
.Fn isa_intr_establish
with the interrupt number
.Fa irq ,
type
.Fa type ,
and level
.Fa level .
When the interrupt occurs the function
.Fa handler
is called with argument
.Fa arg .
Valid values for
.Fa type
are:
.Bl -tag -width compact
.It IST_NONE
Reserve interrupt, but don't actually establish.
.It IST_EDGE
Edge-triggered interrupt.
.It IST_LEVEL
Level-triggered interrupt.
.It IST_PULSE
Pulse-triggered interrupt.
.El
.Pp
.Fn isa_intr_establish
returns an opaque handle to an event descriptor if it succeeds, and
returns NULL on failure.
.Pp
.It Fn isa_intr_disestablish "ic" "ih"
Dis-establish the interrupt handler with handle
.Fa ih .
The handle was returned from
.Fn isa_intr_establish .
.It Fn isa_drq_alloc "ic" "chan"
Reserves the DMA channel
.Fa chan
for future use.
Normally, this call precedes an
.Fn isa_dmamap_create
call.
It is an error to start DMA on a channel that has not been reserved with
.Fn isa_drq_alloc .
.It Fn isa_drq_free "ic" "chan"
Marks the DMA channel
.Fa chan
as available again.
.It Fn isa_dmamap_create "ic" "chan" "size" "flags"
Creates a DMA map for channel
.Fa chan .
It is initialised to accept maximum DMA transfers of size
.Fa size .
Valid values for the
.Fa flags
argument are the same as for
.Fn bus_dmamap_create
(see
.Xr bus_dma 9 ) .
This function returns zero on success or an error value on failure.
.It Fn isa_dmamap_destroy "ic" "chan"
Destroy the DMA map for DMA channel
.Fa chan .
.It Fn isa_dmamem_alloc "ic" "chan" "size" "addrp" "flags"
Allocate DMA-safe memory of size
.Fa size
for channel
.Fa chan .
Valid values for the
.Fa flags
argument are the same as for
.Fn bus_dmamem_alloc
(see
.Xr bus_dma 9 ) .
The bus-address of the memory is returned in
.Fa addrp .
This function returns zero on success or an error value on failure.
.It Fn isa_dmamem_free "ic" "chan" "addr" "size"
Frees memory previously allocated by
.Fn isa_dmamem_alloc
for channel
.Fa chan .
The bus-address and size of the memory are specified by
.Fa addr
and
.Fa size
respectively.
.It Fn isa_dmamem_map "ic" "chan" "addr" "size" "kvap" "flags"
Maps DMA-safe memory (allocated with
.Fn isa_dmamem_alloc )
specified by bus-address
.Fa addr
and of size
.Fa size
into kernel virtual address space for DMA channel
.Fa chan .
Valid values for the
.Fa flags
argument are the same as for
.Fn bus_dmamem_map
(see
.Xr bus_dma 9 ) .
The kernel virtual address is returned in
.Fa kvap .
This function returns zero on success or an error value on failure.
.It Fn isa_dmamem_unmap "ic" "chan" "kva" "size"
Unmaps memory (previously mapped with
.Fn isa_dmamem_map )
of size
.Fa size
for channel
.Fa chan .
The kernel virtual address space used by the mapping is freed.
.It Fn 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
.Fn isa_dmamem_alloc
and
.Fn isa_dmamem_map .
The argument
.Fa pool
is a pool to record the memory allocation.
This function returns a pointer to the DMA-safe memory.
.It Fn isa_free "addrp" "pool"
This function is a shortcut for unmapping and deallocating DMA-safe
memory in a single step.
It replaces
.Fn isa_dmamem_unmap
and
.Fn isa_dmamem_free .
The argument
.Fa addrp
is the pointer to the DMA-safe memory returned by
.Fn isa_malloc .
The argument
.Fa pool
is the same as the value passed to
.Fn isa_malloc .
.It Fn isa_dmastart "ic" "chan" "addr" "size" "lwp" "flags" "bf"
Load DMA memory specified by address
.Fa addr
of size
.Fa size
into the DMA controller at channel
.Fa chan
and set it in motion.
The argument
.Fa 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
.Fa lwp 's
address space.
The argument
.Fa flags
describes the type of ISA DMA.
Valid values are:
.Bl -tag -width compact
.It DMAMODE_WRITE
DMA transfer from host to device.
.It DMAMODE_READ
DMA transfer to host from device.
.It DMAMODE_SINGLE
Transfer buffer once and stop.
.It DMAMODE_DEMAND
Demand mode.
.It DMAMODE_LOOP
Transfer buffer continuously in loop until notified to stop.
.It DMAMODE_LOOPDEMAND
Transfer buffer continuously in loop and demand mode.
.El
.Pp
The argument
.Fa bf
is the bus-space flags.
Valid values are the same as for
.Fn bus_dmamap_load
(see
.Xr bus_dma 9 ) .
.It Fn isa_dmaabort "ic" "chan"
Abort a DMA transfer on channel
.Fa chan .
.It Fn isa_dmacount "ic" "chan"
Returns the offset in the DMA memory of the current DMA transfer on
channel
.Fa chan .
.It Fn isa_dmadone "ic" "chan"
Unloads the DMA memory
on channel
.Fa chan
after a DMA transfer has completed.
.It Fn isa_dmamaxsize "ic" "chan"
Returns the maximum allowable DMA transfer size for channel
.Fa chan .
.It Fn isa_drq_isfree "ic" "chan"
If the
.Fa ia_drq
or
.Fa ia_drq2
members of
.Fa 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
.Fa chan
is available for use.
.It Fn isa_dmacascade "ic" "chan"
Programs the 8237 DMA controller channel
.Fa chan
to accept external DMA control by the device hardware.
.It Fn isa_mappage "mem" "offset" "prot"
Provides support for user
.Xr mmap 2 Ns 'ing
of DMA-safe memory.
.El
.Sh 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
.Fa struct isa_attach_args
hinting at "locations" on the ISA bus where the device may be located.
They should use the
.Em ia_iobase ,
.Em ia_iosize ,
.Em ia_maddr ,
and
.Em ia_msize
members.
Not all of these hints will be necessary; locators may be wildcarded
with IOBASEUNK and MADDRUNK for
.Em ia_iobase
and
.Em ia_maddr
respectively.
If a driver can probe the device for configuration information at default
locations, it may update the members of
.Fa struct isa_attach_args .
The IRQ and DMA locators can also be wildcarded with IRQUNK and DRQUNK
respectively.
.Pp
During the driver attach step, the I/O and memory address spaces
should be mapped (see
.Xr bus_space 9 ) .
.Sh 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
.Fa ia_drq
and
.Fa ia_drq2
members of
.Fa struct isa_attach_args .
.Pp
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
.Fn isa_dmamaxsize .
.Pp
A DMA map should be created first using
.Fn 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
.Fn isa_dmamem_alloc .
The memory allocated by
.Fn isa_dmamem_alloc
must now be mapped into kernel virtual address space by
.Fn isa_dmamem_map
so that it can be accessed by the driver.
.Pp
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
.Fn isa_dmastart
with
.Fa flags
containing DMAMODE_WRITE.
When the DMA transfer is completed, a call to
.Fn isa_dmadone
cleans up the DMA transfer by unloading the memory from the
controller.
.Pp
For a DMA transfer from the device to the host, the DMA-transfer is
started using
.Fn isa_dmastart
with
.Fa flags
containing DMAMODE_READ.
When the DMA transfer is completed, a call to
.Fn isa_dmadone
cleans up the DMA transfer by unloading the memory from the
controller.
The memory can now be access by the driver.
.Pp
When the DMA resources are no longer required they should be released
using
.Fn isa_dmamem_unmap ,
.Fn isa_dmamem_free
and
.Fn isa_dmamap_destroy .
.Sh CODE REFERENCES
The ISA subsystem itself is implemented within the files
.Pa sys/dev/isa/isa.c
and
.Pa sys/dev/isa/isadma.c .
.Sh SEE ALSO
.Xr isa 4 ,
.Xr autoconf 9 ,
.Xr bus_dma 9 ,
.Xr bus_space 9 ,
.Xr driver 9 ,
.Xr isapnp 9
.Sh HISTORY
The machine-independent
.Nm
subsystem appeared in
.Nx 1.2 .
.Sh BUGS
The previous behaviour of
.Fn isa_intr_establish
was to invoke
.Fn panic
on failure.
.Fn isa_intr_establish
now returns NULL on failure.
Some old drivers written for the former behaviour discard the return value.