# <iohw.h>
<iohw.h>
# ``
[added with
TR18015 and
TR18037]
* * *
**`ioindex_t· ioreg`**
**`ioand· ioandbuf· ioandbufl· ioandl· iogroup_acquire· iogroup_map· iogroup_release· ioor· ioorbuf· ioorbufl· ioorl· iord· iordbuf· iordbufl· iordl· iowr· iowrbuf· iowrbufl· iowrl· ioxor· ioxorbuf· ioxorbufl· ioxorl`**
* * *
Include the added header **``**
so that you can write low-level I/O hardware drivers in C that
are easier to port to different architectures.
Note that the use of this header does **not** require
the additions to the C language mandated by TR18037, which
include fixed-point arithmetic and named address spaces.
/* TYPES */
typedef i-type ioindex_t;
typedef i-type ioreg;
/* FUNCTIONS (all masked by macros) */
unsigned int iord(ioreg dev);
unsigned long iordl(ioreg dev);
unsigned int iordbuf(ioreg dev, ioindex_t idx);
unsigned long iordbufl(ioreg dev, ioindex_t idx);
void iowr(ioreg dev, unsigned int val);
void iowrl(ioreg dev, unsigned int val);
void iowrbuf(ioreg dev, ioindex_t idx, unsigned int val);
void iowrbufl(ioreg dev, ioindex_t idx, unsigned int val);
void ioor(ioreg dev, unsigned int val);
void ioorl(ioreg dev, unsigned int val);
void ioorbuf(ioreg dev, ioindex_t idx, unsigned int val);
void ioorbufl(ioreg dev, ioindex_t idx, unsigned int val);
void ioand(ioreg dev, unsigned int val);
void ioandl(ioreg dev, unsigned int val);
void ioandbuf(ioreg dev, ioindex_t idx, unsigned int val);
void ioandbufl(ioreg dev, ioindex_t idx, unsigned int val);
void ioxor(ioreg dev, unsigned int val);
void ioxorl(ioreg dev, unsigned int val);
void ioxorbuf(ioreg dev, ioindex_t idx, unsigned int val);
void ioxorbufl(ioreg dev, ioindex_t idx, unsigned int val);
void iogroup_acquire(int group);
void iogroup_release(int group);
void iogroup_map(int group, int direct);Copy to clipboard
The header `` defines two types and a number
of functions, all of which are typically masked as macros. You should view
this header as a prototype for defining the atomic operations needed to
express a low-level I/O hardware driver (thus the root name **iohw**)
that is intended to be reasonably portable C.
The facilities in this header are structured around a few basic concepts:
- The type **`ioreg`** describes the space of all I/O addresses.
These can be port addresses, for processors with port I/O instructions,
or memory addresses, for processors with memory-mapped I/O hardware.
In a simpler implementation,
the actual argument corresponding to the parameter name
`dev` can also be used to construct the
name of a function to call.
- The type **`ioindex_t`** describes an integer type that can
be used to index into a
**hardware buffer**, an array of I/O
addresses.
- An argument named **`group`** describes the space of all
**hardware groups**, which might be
meaningful on an architecture that supports switching among groups
of similar I/O addresses by changing a base address dynamically.
In a simpler implementation,
the actual argument corresponding to the parameter name `dev`
can also be used to construct the name of a function to call.
The function names are thus suggestive of specific I/O operations,
though they have no required semantics:
- **`iord`** reads a port and returns as the value of the function.
- **`iowr`** writes `val` to a port.
- **`ioor`** ORs `val` into a port (bitwise inclusive OR).
- **`ioand`** ANDs `val` into a port (bitwise AND).
- **`ioxor`** XORs `val` into a port
(bitwise exclusive OR).
Moreover:
- The suffix **`buf`** performs the operation with the element
`idx` of a buffer.
- The suffix **`l`** (lowercase **`L`**)
takes the type of the port as `unsigned long` instead of
`unsigned int`.
Similarly, functions whose name begins with **`iogroup_`**
operate on hardware groups:
- The suffix **`acquire`** establishes `group` as the
active hardware group.
- The suffix **`release`** disestablished `group` as the
active hardware group.
- The suffix **`map`** maps the dynamic `group` into
the actual hardware group `direct`.
In this
[implementation](https://docs.qualcomm.com/doc/80-N3040-23/topic/c_index.html#implementation), all functions
are masked by macros that follow the pattern:
#define _IOHW_CAT(x, y) x##_##y /* expand arguments and paste */
#define iordbuf(dev, idx) _IOHW_CAT(dev, brd)(idx)Copy to clipboard
Thus, the first argument (after macro expansion) is pasted onto a
suitable suffix to produce the name of the actual function to call.
So you can write code such as:
#define KBD kbd /* root name of keyboard functions */
#define KBD_STATUS 0 /* first of two adjacent ports */
#define KBD_DATA 1 /* second of two adjacent ports */
#define KBD_DONE 0x80 /* DONE status bit */
extern unsigned int kbd_brd(ioindex_t idx); /* actual driver */
unsigned int getkbd()
{ /* read keyboard when ready */
while ((iordbuf(KBD, KBD_STATUS) & KBD_DONE) == 0)
; /* wait until character is present */
return (iordbuf(KBD, KBD_DATA)); /* read character and clear DONE */
}Copy to clipboard
All actual driver calls will be to the function
(or macro) `kbd_brd`.
* * *
See also the
**[Table of Contents](https://docs.qualcomm.com/doc/80-N3040-23/topic/c_index.html#Table%20of%20Contents)** and the
**[Index](https://docs.qualcomm.com/doc/80-N3040-23/topic/_c_index.html)**.
*[Copyright](https://docs.qualcomm.com/doc/80-N3040-23/topic/c_crit_pjp.html) © 1992-2006by P.J. Plauger. All rights reserved.*
Last Published: Oct 06, 2026
Previous Topic
Next Topic