mirror of
https://github.com/alfishe/amiga-bootcamp.git
synced 2026-06-13 00:26:28 +00:00
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.
153 lines
4.5 KiB
Markdown
153 lines
4.5 KiB
Markdown
[← Home](../README.md) · [Exec Kernel](README.md)
|
|
|
|
# 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
|
|
|
|
```c
|
|
/* 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
|
|
|
|
```c
|
|
/* 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`)
|
|
|
|
```c
|
|
/* 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
|
|
|
|
```c
|
|
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:
|
|
```c
|
|
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:
|
|
|
|
```c
|
|
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`
|
|
|
|
```c
|
|
/* 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`
|
|
|
|
```c
|
|
/* 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`
|
|
|
|
```c
|
|
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
|
|
|
|
```c
|
|
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
|