From 4f0c1a73700f1d17ddcf9c784f38ace0067cfd60 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sun, 20 Mar 2022 17:06:25 -0300 Subject: [PATCH] Document I/O traps --- dev/api/device.rst | 2 +- dev/api/io.rst | 108 +++++++++++++++++++++++++++++++++++++++++++++ dev/api/thread.rst | 6 +-- 3 files changed, 112 insertions(+), 4 deletions(-) diff --git a/dev/api/device.rst b/dev/api/device.rst index 1c512d0..ff3e9e4 100644 --- a/dev/api/device.rst +++ b/dev/api/device.rst @@ -139,7 +139,7 @@ Most devices need a place to store their internal state. We discourage the use o static void foo_close(void *priv) { - /* Get the state structure. */ + /* Get the device state structure. */ foo_t *dev = (foo_t *) priv; /* Do whatever you want, then deallocate the state structure. */ diff --git a/dev/api/io.rst b/dev/api/io.rst index cfdb182..1d6d656 100644 --- a/dev/api/io.rst +++ b/dev/api/io.rst @@ -139,3 +139,111 @@ Any given I/O port can have an **unlimited** amount of I/O handlers, such that: Read callbacks can effectively return "don't care" (without interfering with other handlers) by returning a value with all bits set: ``0xff`` with ``inb``, ``0xffff`` with ``inw`` or ``0xffffffff`` with ``inl``. .. note:: The same callback fallback rules specified above also apply with multiple handlers. Handlers without valid callbacks for the operation's type and width are automatically skipped. + +I/O traps +--------- + +A second type of I/O handler, **I/O traps** allow a device (usually System Management Mode on chipsets and legacy compatibility on PCI sound cards) to act upon a read/write operation to an I/O port operation without affecting its result. + +.. container:: toggle + + .. container:: toggle-header + + Code example: I/O trap on ports ``0x220``-``0x22f`` + + .. code-block:: + + typedef struct { + void *trap_220; + } foo_t; + + static void + foo_trap_220(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv) + { + /* Get the device state structure. */ + foo_t *dev = (foo_t *) priv; + + /* Do whatever you want. */ + pclog("Foo: Trapped I/O %s to port %04X, size %d\n", + write ? "write" : "read", addr, size); + if (write) + pclog("Foo: Written value: %02X\n", val); + } + + static void * + foo_init(const device_t *info) + { + /* Allocate the device state structure. */ + foo_t *dev = /* ... */ + + /* Add I/O trap. */ + dev->trap_220 = io_trap_add(foo_trap_220, dev); + + /* Map I/O trap to 16 ports starting at 0x220. */ + io_trap_remap(dev->trap_220, 1, 0x220, 16); + + return dev; + } + + static void + foo_close(void *priv) + { + /* Get the device state structure. */ + foo_t *dev = (foo_t *) priv; + + /* Remove I/O trap before deallocating the device state structure. */ + io_trap_remove(dev->trap_220); + free(dev); + } + + const device_t foo4321_device = { + /* ... */ + .init = foo_init, + .close = foo_close, + /* ... */ + }; + +.. flat-table:: io_trap_add + :header-rows: 1 + :widths: 1 999 + + * - Parameter + - Description + + * - func + - Function called whenever an I/O operation of any type or size is performed to the trap's I/O address range. Takes the form of: + + ``void func(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv)`` + + * ``size``: I/O operation width: ``1``, ``2`` or ``4``; + * ``addr``: I/O address the operation is being performed on; + * ``write``: ``0`` if this operation is a *read*, or ``1`` if it's a *write*; + * ``val``: value being written if this operation is a write; + * ``priv``: opaque pointer (see ``priv`` below). + + * - priv + - Opaque pointer passed to the ``func`` callback above. + Usually a pointer to a device's :ref:`state structure `. + + * - **Return value** + - Opaque (``void``) pointer representing the newly-created I/O trap. + +.. flat-table:: io_trap_remap + :header-rows: 1 + :widths: 1 999 + + * - Parameter + - Description + + * - trap + - Opaque pointer representing the I/O trap to remap. + + * - enable + - * ``1`` to enable this trap; + * ``0`` to disable it. + + * - addr + - First I/O port (0x0000-0xffff) covered by this trap. + + * - size + - Amount of I/O ports (1-65536) covered by this trap. diff --git a/dev/api/thread.rst b/dev/api/thread.rst index 07bc2b1..2e0bf53 100644 --- a/dev/api/thread.rst +++ b/dev/api/thread.rst @@ -84,7 +84,7 @@ Events - ``event_t`` pointer representing the event to wait for. * - timeout - - Maximum amount of time in **milliseconds** (not microseconds, unlike :doc:`timers `) to spend waiting for the event to be *set*. If set to ``-1``, this function will not return until the event is *set*. + - Maximum amount of time in **milliseconds** (not microseconds, unlike :doc:`timers `) to spend waiting for this event to be *set*. If set to ``-1``, this function will not return until the event is *set*. * - **Return value** - * ``0`` on success; @@ -116,7 +116,7 @@ Mutexes * - arg - ``mutex_t`` pointer representing the mutex to *lock* (``thread_wait_mutex``), *release* (``thread_release_mutex``) or deallocate (``thread_close_mutex``). - If the mutex is locked, ``thread_wait_mutex`` will not return until the mutex is *released* by another thread. + If this mutex is locked, ``thread_wait_mutex`` will not return until the mutex is *released* by another thread. .. flat-table:: thread_test_mutex :header-rows: 1 @@ -129,5 +129,5 @@ Mutexes - ``mutex_t`` pointer representing the mutex to check. * - **Return value** - - * ``0`` if the mutex is *locked*; + - * ``0`` if this mutex is *locked*; * Any other value if the mutex is *released*.