amiga-bootcamp/06_exec_os/io_requests.md
Ilia Sharin 21751c0025 docs(amiga): complete AmigaOS 3.1/3.2 developer reference — 172 files across 17 sections
Comprehensive technical documentation covering:
- Hardware: OCS/ECS/AGA custom chip registers, Copper & Blitter deep dives
- Boot sequence: cold boot through startup-sequence
- Binary format: HUNK executable spec, relocation, debug info
- Linking & ABI: .fd files, LVO tables, register calling conventions
- Exec kernel: tasks, interrupts, memory, signals, semaphores
- AmigaDOS: file I/O, FFS/OFS layout, CLI/Shell scripting
- Graphics: planar bitmaps, Copper programming, HAM/EHB modes
- Intuition: screens, windows, IDCMP, BOOPSI
- Devices: trackdisk, SCSI, serial, timer, audio, keyboard
- Libraries: utility, expansion, IFFParse, locale, ARexx
- Networking: bsdsocket API, SANA-II, TCP/IP stack comparison
- Toolchain: GCC, vasm/vlink, SAS/C, NDK, debugging
- Reverse engineering: IDA/Ghidra setup, compiler fingerprints, case studies
- CPU & MMU: 68040/060 emulation libs, PMMU, cache management
- Driver development: SANA-II, Picasso96/RTG, AHI audio

All files include breadcrumb navigation. No local paths or proprietary content.
2026-04-23 12:17:35 -04:00

4.5 KiB

← Home · Exec Kernel

IO Requests — IORequest, DoIO, SendIO, CheckIO, AbortIO

Overview

AmigaOS device I/O uses a message-based asynchronous protocol. Every device operation is described by an IORequest structure sent to a device's command port. The device processes it (synchronously or in the background) and replies when done.


Structures

/* exec/io.h — NDK39 */

struct IORequest {
    struct Message io_Message;  /* embedded Message (has MsgPort reply port) */
    struct Device *io_Device;   /* filled by OpenDevice */
    struct Unit   *io_Unit;     /* filled by OpenDevice */
    UWORD          io_Command;  /* CMD_READ, CMD_WRITE, TD_FORMAT, ... */
    UBYTE          io_Flags;    /* IOF_QUICK = attempt synchronous fast path */
    BYTE           io_Error;    /* result: 0 = success, negative = error code */
};

struct IOStdReq {               /* extended version with data fields */
    struct IORequest io_Request;
    ULONG  io_Actual;           /* actual bytes transferred */
    ULONG  io_Length;           /* requested byte count */
    APTR   io_Data;             /* data buffer pointer */
    ULONG  io_Offset;           /* byte offset (for random-access devices) */
};

Standard Command Codes

/* exec/io.h */
#define CMD_INVALID   0   /* not a valid command */
#define CMD_RESET     1   /* reset the device/unit to initial state */
#define CMD_READ      2   /* read io_Length bytes into io_Data from io_Offset */
#define CMD_WRITE     3   /* write io_Length bytes from io_Data at io_Offset */
#define CMD_UPDATE    4   /* flush write cache to media */
#define CMD_CLEAR     5   /* discard device read buffers */
#define CMD_STOP      6   /* suspend device operation */
#define CMD_START     7   /* resume device operation */
#define CMD_FLUSH     8   /* abort all pending requests */
#define CMD_NONSTD    9   /* first device-specific command number */

Device-specific commands start at CMD_NONSTD (9). Example: trackdisk uses TD_FORMAT (10), TD_MOTOR (11), TD_SEEK (12).


Error Codes (io_Error)

/* exec/errors.h — NDK39 */
#define IOERR_OPENFAIL   -1   /* device/unit could not be opened */
#define IOERR_ABORTED    -2   /* request was aborted via AbortIO */
#define IOERR_NOCMD      -3   /* unknown command */
#define IOERR_BADLENGTH  -4   /* io_Length invalid for this command */
#define IOERR_BADADDRESS -5   /* io_Data not aligned or accessible */
#define IOERR_UNITBUSY   -6   /* unit in use, cannot complete */
#define IOERR_SELFTEST   -7   /* hardware self-test failed */

Opening a Device

struct IOStdReq *ior = CreateStdIO(reply_port);   /* alloc + fill reply port */
if (OpenDevice("trackdisk.device", unit, (struct IORequest *)ior, 0) != 0) {
    /* open failed — ior->io_Error set */
}

Or manually:

struct IOStdReq *ior = AllocMem(sizeof(struct IOStdReq), MEMF_PUBLIC|MEMF_CLEAR);
ior->io_Message.mn_ReplyPort = my_reply_port;
ior->io_Message.mn_Length    = sizeof(struct IOStdReq);
OpenDevice("audio.device", 0, (struct IORequest *)ior, 0);

Synchronous I/O: DoIO

Blocks the calling task until the device completes the request:

ior->io_Command = CMD_READ;
ior->io_Data    = buffer;
ior->io_Length  = 512;
ior->io_Offset  = 0;
LONG err = DoIO((struct IORequest *)ior);
/* io_Actual = bytes actually read; io_Error = error code */

Asynchronous I/O: SendIO + WaitIO

/* Queue the request — returns immediately: */
SendIO((struct IORequest *)ior);

/* Do other work while device operates... */

/* Block until this specific request completes: */
WaitIO((struct IORequest *)ior);
err = ior->io_Error;

Poll without blocking: CheckIO

/* Returns non-NULL if request is done (removed from device queue): */
if (CheckIO((struct IORequest *)ior)) {
    WaitIO((struct IORequest *)ior);  /* must still call WaitIO to dequeue reply */
}

Aborting a Request: AbortIO

AbortIO((struct IORequest *)ior);   /* ask device to cancel */
WaitIO((struct IORequest *)ior);    /* wait for confirmation */
/* io_Error will be IOERR_ABORTED (-2) */

Closing a Device

CloseDevice((struct IORequest *)ior);
DeleteStdIO(ior);   /* or FreeMem */

References

  • NDK39: exec/io.h, exec/errors.h
  • ADCD 2.1: OpenDevice, CloseDevice, DoIO, SendIO, WaitIO, CheckIO, AbortIO
  • 10_devices/ — per-device command codes and structures
  • Amiga ROM Kernel Reference Manual: Exec — I/O requests chapter