<hardware>[added with TR18015]
dynamic_address
· hw_base
· platform_traits
· register_access
· register_buffer
· register_traits
· static_address
Include the added header <hardware>
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 any additions to the C++ language, as none are mandated by TR18015.
#include <iohw.h>
namespace std {
    namespace hardware {
class hw_base
    {   // define hardware address type
public:
    enum access_mode
        {   // access modes
        random,
        read,
        read_write,
        write
        };
    enum device_bus
        {   // device register widths
        device8,
        device16,
        device32,
        device64
        };
    enum byte_order
        {   // endianness
        msb_low,
        msb_high
        };
    enum processor_bus
        {   // processor bus widths
        bus8,
        bus16,
        bus32,
        bus64
        };
    enum data_bus
        {   // type name for data bus
        };
    enum io_bus
        {   // type name for I/O bus
        };
    enum address_kind
        {   // addressing model
        is_static,
        is_dynamic
        };
    typedef ::ioreg address_type;  // HARDWARE DEPENDENT
    };
        // TEMPLATE CLASS static_address
template<hw_base::address_type Val>
    class static_address
    {   // specialization for value of type hw_base::address_type
public:
    enum
        {   // define value from template parameter
        value_ = Val
        };
    hw_base::address_type value() const
        {   // get value of this static address
        return (Val);
        }
    };
        // CLASS dynamic_address
class dynamic_address
    {   // store dynamic address
public:
    dynamic_address(hw_base::address_type address);
        :    value_(address)
        {   // construct from address
        }
    hw_base::address_type value() const
        {   // get value of stored address
        return (value_);
        }
    hw_base::address_type value_;
    };
        // CLASS platform_traits
class platform_traits
    {   // default platform traits (ALL CONTENTS OPTIONAL)
public:
    typedef hw_base::address_type address_holder;
    typedef hw_base::address_type processor_bus;
    enum
        {   // platform traits
        address_mode,
        processor_endianness,
        processor_bus_width
        };
    };
        // CLASS register_traits
class register_traits
    {   // default register traits (ALL CONTENTS OPTIONAL)
public:
    typedef unsigned int value_type;
    typedef hw_base::address_type address_holder;
    enum
        {   // platform traits
        address_mode,
        access_mode,
        endianness,
        device_bus_width
        };
    };
        // TEMPLATE CLASS register_access
template<class Reg_traits = register_traits,
    class Platform_traits = platform_traits>
    class register_access
    {   // access wrapper for a hardware I/O register
    typedef typename Platform_traits::address_holder Plat_t;
    typedef typename Reg_traits::address_holder Reg_t;
public:
    typedef typename Reg_traits::value_type value_type;
    register_access();
    register_access(const Plat_t& plat_addr);
    register_access(const Reg_t& reg_addr,
        const Plat_t& plat_addr);
    // access operators
    operator value_type() const;
    void operator=(value_type val);
    void operator|=(value_type val);
    void operator&=(value_type val);
    void operator^=(value_type val);
    // access functions
    value_type read() const;
    void write(value_type val);
    void or_with(value_type val);
    void and_with(value_type val);
    void xor_with(value_type val);
    };
        // TEMPLATE CLASS register_buffer
template<class Reg_traits = register_traits,
    class Platform_traits = platform_traits>
    class register_buffer
    {   // access wrapper for a hardware I/O register
    typedef typename Platform_traits::address_holder Plat_t;
    typedef typename Reg_traits::address_holder Reg_t;
public:
    typedef register_access<Reg_traits, Platform_traits> ref_type;
    typedef typename Reg_traits::value_type value_type;
    register_buffer();
    register_buffer(const Plat_t& plat_addr);
    register_buffer(const Reg_t& reg_addr,
        const Plat_t& plat_addr);
    // access operators
    ref_type operator[](ioindex_t idx) const;
    // access functions
    ref_type get_buffer_element(ioindex_t idx) const;
    };
    }    // namespace hardware
}    // namespace std
The header <hardware> defines a number of classes
and templates. You should view
this header as a prototype for defining the C++ interface
to the atomic operations needed to
express a low-level I/O hardware driver.
It supplements the C header <iohw.h>.
The facilities in this header are structured around a few basic concepts:
access_mode supplies the enumeration
constants needed to describes the properties of I/O addresses.
The member type address_type is used in other classes as the type
of I/O addresses.platform_traits supplies the enumeration
constants needed to describes the properties of an I/O bus in general.
The member type address_holder is used in other classes as the type
of I/O addresses. Class register_traits performs
a similar role for specific ports on an I/O bus.static_address wraps an I/O
address whose value is known at translation time,
while class dynamic_address
waps one that might nit be known until program execution.register_access supplies the member
functions that call actual drivers to perform I/O operations. Similarly,
class register_buffer supplies register_access
objects for different elements of a hardware buffer.In this
implementation, all operations
are performed by calling one of the five low-level functions
(defined in <iohw.h>):
    iordbuf(_IOHW_NAME, idx)
    iowrbuf(_IOHW_NAME, idx, val)
    ioorbuf(_IOHW_NAME, idx, val)
    ioandbuf(_IOHW_NAME, idx, val)
    ioxorbuf(_IOHW_NAME, idx, val)
If the macro _IOHW_NAME is not defined when the header
<hardware> is first included, the macro is defined
as hardware. Further, the code assumes that all I/O
occurs within a flat address space, where the effective port address
is simply the sum of the platform address, the register address, and
the index into a specific buffer.
So you can write code such as:
#define KBD         0xffe0  // base address of keyboard ports
#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 hardware_brd(ioindex_t idx);  // actual driver
typedef std::hardware::register_buffer<> buffer_t;
buffer_t::value_type getkbd()
    {   // read keyboard when ready
    buffer_t status(KBD, KBD_STATUS);
    buffer_t data(KBD, KBD_DATA);
    while ((status.read() & KBD_DONE) == 0)
        ;   // wait until character is present
    return (data);  // read character and clear DONE
    }
All actual driver calls will be to the function
(or macro) hardware_brd.
See also the Table of Contents and the Index.
Copyright © 1992-2013 by P.J. Plauger. All rights reserved.