![]() |
![]() |
![]() |
<iohw.h>
[added with TR18015 and TR18037]
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 <iohw.h>
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);
The header <iohw.h>
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:
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.ioindex_t
describes an integer type that can
be used to index into a
hardware buffer, an array of I/O
addresses.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:
buf
performs the operation with the element
idx
of a buffer.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:
acquire
establishes group
as the
active hardware group.release
disestablished group
as the
active hardware group.map
maps the dynamic group
into
the actual hardware group direct
.In this 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)
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 */ }
All actual driver calls will be to the function
(or macro) kbd_brd
.
See also the Table of Contents and the Index.
Copyright © 1992-2006 by P.J. Plauger. All rights reserved.
![]() |
![]() |
![]() |