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.
This commit is contained in:
Ilia Sharin 2026-04-23 12:16:52 -04:00
parent f07a368bf1
commit 21751c0025
172 changed files with 19701 additions and 0 deletions

View file

@ -0,0 +1,109 @@
[← Home](../../README.md) · [Hardware](../README.md)
# Amiga Address Space
## Overview
The Amiga uses a **24-bit physical address bus** on OCS/ECS machines (68000/68020 effective), giving 16 MB of addressable space. AGA machines with 68030/040 and 32-bit-clean software can address the full 4 GB, but Chip RAM and custom registers remain in the lower 16 MB.
## Memory Map — 24-bit (OCS/ECS, A500/A600/A3000)
```
$000000$1FFFFF Chip RAM (max 2 MB on ECS, 512 KB on OCS A500)
$200000$9FFFFF Fast RAM (expansion via Zorro II autoconfig)
$A00000$BEFFFF Zorro II I/O space
$BFD000$BFDFFF CIA-B (8520, keyboard, floppy motor, disk side)
$BFE001$BFE1FF CIA-A (8520, parallel port, serial flags, timer)
$C00000$C7FFFF Slow RAM ("Ranger", DMA-visible but not fast)
$C80000$CFFFFF Zorro II expansion I/O (boards)
$D00000$D7FFFF Zorro II expansion I/O
$D80000$DBFFFF Reserved / board-specific
$DC0000$DCFFFF Real-Time Clock (MSM6242B / RF5C01A)
$DD0000$DEFFFF Reserved
$DF0000$DFFFFF Custom chip registers ($DFF000$DFF1FE)
$E00000$E7FFFF Kick memory (WCS / Ranger slow RAM mirror)
$E80000$EFFFFF Autoconfig space (Zorro II probe)
$F00000$F7FFFF Extended Kickstart ROM (OS 3.1: second 256 KB)
$F80000$FFFFFF Kickstart ROM (512 KB mirror at top of 16 MB)
```
## Memory Map — 32-bit (AGA, A1200/A4000)
```
$000000$1FFFFF 2 MB Chip RAM
$200000$07FFFFFF Fast RAM (on-board: 416 MB via Ramsey on A4000)
Trapdoor/PCMCIA on A1200
$A00000$BEFFFF Zorro II I/O
$BFD000 CIA-B
$BFE001 CIA-A
$C00000$CFFFFF Slow RAM / board I/O
$D80000$D8FFFF IDE / Gayle (A1200/A4000)
$DA0000$DA3FFF PCMCIA attribute memory (A1200)
$DC0000 RTC
$DFF000$DFFFFF Custom registers
$E00000$E7FFFF Kick mirror / WCS
$F00000$F7FFFF Extended ROM
$F80000$FFFFFF Kickstart ROM (512 KB)
$01000000+ Zorro III expansion (32-bit, A3000/A4000 only)
```
## Memory Type Classification
AmigaOS classifies memory by access flags used in `AllocMem()`:
| MEMF Flag | Value | Description |
|---|---|---|
| `MEMF_ANY` | 0 | No constraint |
| `MEMF_PUBLIC` | 1<<0 | Accessible to all tasks and DMA |
| `MEMF_CHIP` | 1<<1 | Chip RAM accessible to custom chips (DMA) |
| `MEMF_FAST` | 1<<2 | Fast RAM CPU-only, no DMA, faster |
| `MEMF_LOCAL` | 1<<8 | Not mapped out (always present) |
| `MEMF_24BITDMA` | 1<<9 | Addressable within 24-bit space |
| `MEMF_CLEAR` | 1<<16 | Zero-fill before returning |
| `MEMF_REVERSE` | 1<<17 | Allocate from top of memory |
| `MEMF_LARGEST` | 1<<18 | Return size of largest free block |
| `MEMF_TOTAL` | 1<<19 | Return total memory of type |
### Chip RAM Requirement
Custom chip DMA can only access **Chip RAM** (`MEMF_CHIP`). This means:
- Graphics bitmaps rendered by Blitter/Copper must be in Chip RAM
- Audio sample data must be in Chip RAM
- Copper lists must be in Chip RAM
- Sprite data must be in Chip RAM
Fast RAM is **CPU-only** — generally used for code, non-DMA data structures, and stacks.
## Diagram
```mermaid
block-beta
columns 1
block:chip["Chip RAM\n$000000$1FFFFF\n(DMA accessible)"]
block:fast["Fast RAM\n$200000$9FFFFF\n(CPU only, faster)"]
block:zio["Zorro II I/O\n$A00000$BEFFFF"]
block:cia["CIA-A/B\n$BFD000/$BFE001"]
block:slow["Slow/Ranger RAM\n$C00000$C7FFFF"]
block:rtc["RTC $DC0000"]
block:custom["Custom Registers\n$DFF000$DFFFFF"]
block:rom["Kickstart ROM\n$F80000$FFFFFF"]
```
## Key Chip RAM Addresses
| Address | Content |
|---|---|
| $000000$000400 | Exception vector table (copied from ROM) |
| $000004 | `SysBase` pointer (exec library base) |
| $000100 | Copper list scratch area (boot) |
| $000400$001000 | Reserved by OS |
| $001000+ | Free Chip RAM (AvailMem result) |
> [!WARNING]
> Writing to $000000$000400 corrupts the exception table. Writing to $000004 corrupts `SysBase`. These addresses must never be allocated by user code; exec reserves them.
## References
- NDK39: `exec/memory.h` — MEMF_ flag definitions
- ADCD 2.1 Hardware Manual: memory map chapter
- Commodore A1200/A4000 Technical Reference Manuals (local archive)

View file

@ -0,0 +1,152 @@
[← Home](../../README.md) · [Hardware](../README.md)
# CIA Chips — 8520 MOS Technology
## Overview
The Amiga uses **two MOS 8520 CIA** (Complex Interface Adapter) chips, providing timers, parallel/serial I/O ports, a time-of-day clock, and interrupt generation. They are the primary source of hardware timing outside the vertical blank and audio DMA.
- **CIA-A** at `$BFE001` (even byte addresses)
- **CIA-B** at `$BFD000` (odd byte addresses)
Both CIAs are accessed via byte reads/writes; the 68000 byte-lane placement means CIA-A uses even offsets and CIA-B uses odd offsets on the 16-bit bus.
## Register Map
Each CIA has 16 registers, spaced 256 bytes apart in the Amiga address space:
| Offset | Register | CIA-A Function | CIA-B Function |
|---|---|---|---|
| $000 | PRA | Parallel port data (input) | Disk control outputs |
| $100 | PRB | Parallel port data (output) | Disk status inputs |
| $200 | DDRA | Port A direction (1=output) | Port A direction |
| $300 | DDRB | Port B direction | Port B direction |
| $400 | TALO | Timer A low byte | Timer A low byte |
| $500 | TAHI | Timer A high byte | Timer A high byte |
| $600 | TBLO | Timer B low byte | Timer B low byte |
| $700 | TBHI | Timer B high byte | Timer B high byte |
| $800 | TODLO | TOD clock low (1/60 s) | Disk position (latched) |
| $900 | TODMID | TOD clock mid | |
| $A00 | TODHI | TOD clock high | |
| $B00 | (unused) | — | — |
| $C00 | SDR | Serial data register | Serial data register |
| $D00 | ICR | Interrupt control | Interrupt control |
| $E00 | CRA | Control register A | Control register A |
| $F00 | CRB | Control register B | Control register B |
## CIA-A: $BFE001
CIA-A handles:
| Bit | Port A (PRA, read $BFE001) |
|---|---|
| 7 | `/FIR1` — joystick port 1 button |
| 6 | `/FIR0` — joystick port 0 button |
| 5 | `/RDY` — floppy ready |
| 4 | `/TK0` — track 0 sensor |
| 3 | `/WPRO` — write-protect |
| 2 | `/CHNG` — disk change |
| 1 | `/LED` — power LED (write: 0=bright) |
| 0 | `/OVL` — Chip RAM overlay (write during boot) |
Port B (PRB, $BFE101): Parallel port data lines D0D7.
**CIA-A interrupts** appear on **CPU IPL level 2** via INTENA bit `INTB_EXTER` — actually CIA is on IPL 6.
## CIA-B: $BFD000
CIA-B handles floppy drive motor/selection and disk DMA sync:
| Bit | Port A (PRA, $BFD000) |
|---|---|
| 7 | `/MTR` — motor on/off |
| 6 | `/SEL3` — drive 3 select |
| 5 | `/SEL2` — drive 2 select |
| 4 | `/SEL1` — drive 1 select |
| 3 | `/SEL0` — drive 0 select |
| 2 | `/SIDE` — head side (0=upper) |
| 1 | `/DIR` — step direction |
| 0 | `/STEP` — step pulse |
Port B (PRB, $BFD100): Parallel port shadow (less commonly used on B).
**CIA-B interrupts** appear on **CPU IPL level 6**.
## Timers
Each CIA has two 16-bit countdown timers (Timer A and Timer B):
- Count from a loaded latch value down to zero
- Can be one-shot or continuous
- Clock sources: system clock (709 kHz PAL / 715 kHz NTSC), or Timer A output (for Timer B)
- Timer A can generate `SDR` baud rate for serial output
**Control Register A (CRA) bits:**
```
bit 0: START — 1 = timer running
bit 1: PBON — 1 = timer output on Port B bit 6
bit 2: OUTMODE — 0=pulse, 1=toggle
bit 3: RUNMODE — 0=continuous, 1=one-shot
bit 4: LOAD — 1 = force load latch into counter
bit 5: INMODE — 0=clock, 1=count rising edges on CNT pin
bit 6: SPMODE — 0=SDR input, 1=SDR output
bit 7: TODIN — 0=60 Hz TOD, 1=50 Hz TOD (PAL)
```
## Time-of-Day (TOD) Clock
24-bit counter, clocked at 60 Hz (NTSC) or 50 Hz (PAL):
- CIA-A TOD: used by OS as software clock
- TOD registers latch on read of TODHI — must read TODHI first, then TODMID, then TODLO
- `ciaa.ciatodhi``ciaa.ciatodmid``ciaa.ciatodlo`
- Set by writing TODHI → TODMID → TODLO (halts during write)
## Interrupt Control Register (ICR)
Write to enable interrupts, read to see which fired:
```c
/* Enable Timer A interrupt */
ciaa.ciaicr = CIAICRF_SETCLR | CIAICRF_TA;
/* On read: bits indicate which sources fired */
UBYTE icr = ciaa.ciaicr;
if (icr & CIAICRF_TA) { /* Timer A fired */ }
if (icr & CIAICRF_TB) { /* Timer B fired */ }
if (icr & CIAICRF_ALRM) { /* TOD alarm fired */ }
if (icr & CIAICRF_SP) { /* Serial register full/empty */ }
if (icr & CIAICRF_FLG) { /* /FLAG pin (index pulse on CIA-B) */ }
```
Write bit 7 (`CIAICRF_SETCLR`): 1 = set enable bits, 0 = clear enable bits.
## AmigaOS Timer Device Integration
AmigaOS's `timer.device` uses CIA timers internally:
- `UNIT_MICROHZ` — uses CIA-A Timer A for microsecond delays
- `UNIT_VBLANK` — uses vertical blank interrupt (not CIA)
- `UNIT_ECLOCK` — uses the E clock (709/715 kHz, same as CIA clock)
Direct CIA programming should be done with `ciaa`/`ciab` resource claims via `OpenResource("ciaa.resource")` — not by poking CIA registers directly.
## C Access via NDK Headers
```c
#include <hardware/cia.h>
#include <resources/cia.h>
/* CIA-A is at fixed address */
#define ciaa (*((volatile struct CIA *)0xBFE001))
#define ciab (*((volatile struct CIA *)0xBFD000))
/* struct CIA fields (hardware/cia.h): */
/* ciaa.ciapra, ciaa.ciaprb, ciaa.ciaicr, ciaa.ciacra, ... */
```
## References
- MOS Technology 6526/8520 datasheet
- ADCD 2.1 Hardware Manual — CIA chapter: http://amigadev.elowar.com/read/ADCD_2.1/Hardware_Manual_guide/
- NDK39: `hardware/cia.h`, `resources/cia.h`
- Autodocs: `cia` resource — http://amigadev.elowar.com/read/ADCD_2.1/Includes_and_Autodocs_3._guide/node00C7.html

View file

@ -0,0 +1,141 @@
[← Home](../../README.md) · [Hardware](../README.md)
# M68k CPU on the Amiga
## Overview
AmigaOS runs on the Motorola 68000 family exclusively. The CPU operates in two privilege modes and interacts with the custom chips via the shared 16/32-bit bus arbitrated by Agnus/Alice.
## Privilege Modes
| Mode | SR[13] (S-bit) | Stack Pointer | Access |
|---|---|---|---|
| **Supervisor** | 1 | SSP (A7') | Full hardware access |
| **User** | 0 | USP (A7) | Restricted — no privileged instructions |
AmigaOS runs entirely in **supervisor mode**. User-mode tasks switch to supervisor via `Supervisor()` or trap instructions. The OS does not enforce user-mode isolation — all tasks share one address space.
## Register Set
```
D0D7 Data registers (32-bit)
A0A6 Address registers (32-bit)
A7 Stack pointer (USP in user mode, SSP in supervisor mode)
PC Program counter
SR Status register (CCR + supervisor bits)
```
**CCR (Condition Code Register) — lower byte of SR:**
```
bit 4: X (extend)
bit 3: N (negative)
bit 2: Z (zero)
bit 1: V (overflow)
bit 0: C (carry)
```
**SR upper byte (supervisor only):**
```
bit 15: T1 (trace mode — single-step)
bit 14: T0
bit 13: S (supervisor state)
bit 10-8: I2-I0 (interrupt mask level, 07)
```
## Exception Vector Table
Located at **$000000** (physical), shadowed from Kick ROM into Chip RAM on boot.
| Offset | Vector | Description |
|---|---|---|
| $000 | Reset SSP | Initial supervisor stack pointer |
| $004 | Reset PC | Initial program counter (ROM entry) |
| $008 | Bus Error | Access fault |
| $00C | Address Error | Odd-address word/long access |
| $010 | Illegal Instruction | Undefined opcode |
| $014 | Divide by Zero | DIVS/DIVU by zero |
| $018 | CHK | CHK instruction bound check fail |
| $01C | TRAPV / cpTRAPcc | Overflow trap |
| $020 | Privilege Violation | User-mode privileged instruction |
| $024 | Trace | Single-step trap |
| $028 | Line 1010 (A-line) | Opcode $Axxx — OS trap dispatch |
| $02C | Line 1111 (F-line) | Opcode $Fxxx — FPU / emulation |
| $060 | Spurious Interrupt | No response to interrupt acknowledge |
| $064 | Level 1 Autovector | CIA-B timer / serial / disk |
| $068 | Level 2 Autovector | CIA-A, software |
| $06C | Level 3 Autovector | VBL, copper, blitter |
| $070 | Level 4 Autovector | Audio, disk DMA |
| $074 | Level 5 Autovector | Serial port |
| $078 | Level 6 Autovector | CIA / ext interrupt |
| $07C | Level 7 Autovector | NMI (not maskable) |
| $080$0BC | TRAP #0#15 | Software traps |
## AmigaOS Use of Exception Vectors
- **A-Line ($028):** AmigaOS uses this for its internal library call dispatch on some early titles; modern code uses direct JSR via library base.
- **Level 3 ($06C):** Vertical Blank interrupt — exec's `AddIntServer(INTB_VERTB, ...)` chains here.
- **Level 6 ($078):** CIA interrupts chain here; exec dispatches to `INTB_EXTER` servers.
- **TRAP #0 ($080):** Used by `Supervisor()` to enter supervisor mode from user code.
## Interrupt Priority Levels
AmigaOS maps hardware interrupt levels to internal interrupt bits (`INTENA`/`INTREQ`):
| IPL | Source | INTENA bits |
|---|---|---|
| 1 | Serial TX, disk block | `INTB_TBE`, `INTB_DSKBLK` |
| 2 | Software (PostIntServer) | `INTB_SOFTINT` |
| 3 | VBlank, copper, blitter | `INTB_VERTB`, `INTB_COPPER`, `INTB_BLIT` |
| 4 | Audio ch 03, disk DMA | `INTB_AUD0``INTB_AUD3`, `INTB_DSKSYNC` |
| 5 | Serial RX | `INTB_RBF` |
| 6 | External / CIA | `INTB_EXTER` |
| 7 | NMI (rarely used) | — |
## CPU Detection at Runtime
AmigaOS stores CPU capability flags in `ExecBase->AttnFlags` (offset $128):
```c
#include <exec/execbase.h>
struct ExecBase *SysBase = *((struct ExecBase **)4);
UWORD attn = SysBase->AttnFlags;
if (attn & AFF_68020) { /* 68020+ present */ }
if (attn & AFF_68030) { /* 68030+ present */ }
if (attn & AFF_68040) { /* 68040+ present */ }
if (attn & AFF_68060) { /* 68060 present */ }
if (attn & AFF_FPU) { /* FPU present */ }
if (attn & AFF_68881) { /* 68881/68882 */ }
```
**AttnFlags bit definitions** (`exec/execbase.h`):
```c
#define AFF_68010 (1<<0)
#define AFF_68020 (1<<1)
#define AFF_68030 (1<<2)
#define AFF_68040 (1<<3)
#define AFF_68881 (1<<4) /* on-chip FPU or external 68881 */
#define AFF_FPU (1<<4)
#define AFF_68882 (1<<5)
#define AFF_FPU40 (1<<6) /* 040/060 on-chip FPU */
#define AFF_68060 (1<<7)
```
## Key Instruction Subsets by CPU
| Instruction | 68000 | 68020 | 68030 | 68040 |
|---|---|---|---|---|
| MULS/MULU 16×16 | ✓ | ✓ | ✓ | ✓ |
| MULS/MULU 32×32 | ✗ | ✓ | ✓ | ✓ |
| Bit-field (BFEXTU etc.) | ✗ | ✓ | ✓ | ✓ |
| CALLM/RTM | ✗ | ✓ | ✗ | ✗ |
| CAS/CAS2 | ✗ | ✓ | ✓ | ✓ |
| LPSTOP | ✗ | ✗ | ✓ | ✓ |
| CINV/CPUSH | ✗ | ✗ | ✓ | ✓ |
## References
- Motorola *M68000 Family Programmer's Reference Manual* (M68000PM/AD)
- ADCD 2.1 Hardware Manual: http://amigadev.elowar.com/read/ADCD_2.1/Hardware_Manual_guide/node0000.html
- NDK39: `exec/execbase.h``AttnFlags` definitions

View file

@ -0,0 +1,139 @@
[← Home](../../README.md) · [Hardware](../README.md)
# Zorro Bus — Expansion Architecture
## Overview
The Amiga uses the **Zorro** expansion bus for add-on cards. There are two generations:
- **Zorro II** — 16-bit, 24-bit addressing, 7 MHz, compatible with A2000/A3000/A4000
- **Zorro III** — 32-bit, 32-bit addressing, up to 33 MHz burst, A3000/A4000 only
Zorro uses **AutoConfig** — a standardised plug-and-play configuration protocol that predates PCI by several years.
## Zorro II
| Parameter | Value |
|---|---|
| Data bus | 16-bit |
| Address bus | 24-bit |
| Clock | 7.14 MHz (bus cycle ≈ 280 ns) |
| Max transfer | ~5 MB/s (DMA) |
| Address space | $A00000$EFFFFF (I/O), $200000$9FFFFF (RAM) |
| Slots | 5 (A2000), 3 (A3000) |
Zorro II cards appear in the 16 MB address space. RAM cards are configured into $200000$9FFFFF. I/O cards use $A00000$DEFFFF.
## Zorro III
| Parameter | Value |
|---|---|
| Data bus | 32-bit |
| Address bus | 32-bit |
| Clock | Up to 33 MHz burst |
| Max transfer | ~40 MB/s (DMA) |
| Address space | $01000000 and above |
| Slots | 4 (A3000), 5 (A4000) |
Zorro III extends into the 32-bit address space, allowing large RAM cards (32128 MB) and fast peripherals. Requires a 32-bit CPU (68030+) and OS support.
## AutoConfig Protocol
AutoConfig allows the OS to discover and configure cards without jumpers:
```mermaid
sequenceDiagram
participant OS as AmigaOS (expansion.library)
participant Card as Zorro Card
OS->>Card: Read $E80000 (config space)
Card-->>OS: Manufacturer ID (16-bit)
OS->>Card: Read $E80002
Card-->>OS: Product ID, flags
OS->>Card: Read board size, type
OS->>OS: AllocAbs() / ConfigBoard()
OS->>Card: Write base address
Card-->>OS: Card configured, moves off $E80000
```
**Key AutoConfig registers** (read from $E80000$E8007F before configuration):
| Offset | Content |
|---|---|
| $00 | er_Type (board type: RAM/IO, Zorro II/III) |
| $02 | er_Product (product ID) |
| $04 | er_Flags |
| $06 | er_Reserved03 |
| $08$0A | er_Manufacturer (16-bit) |
| $0C$0F | er_SerialNumber |
| $10$11 | er_InitDiagVec (diagnostic ROM vector) |
**Board types** (`er_Type` bits):
```c
#define ERT_TYPEMASK 0xC0
#define ERT_ZORROII 0xC0 /* Zorro II card */
#define ERT_ZORROIII 0x80 /* Zorro III card */
#define ERTB_MEMLIST 5 /* board is RAM, add to free list */
#define ERTB_DIAGVALID 4 /* DiagArea ROM is valid */
#define ERTB_CHAINEDCONFIG 3 /* more boards to configure */
```
## expansion.library
AmigaOS provides `expansion.library` to manage Zorro configuration:
```c
#include <libraries/expansion.h>
#include <clib/expansion_protos.h>
/* Find a configured board by manufacturer/product */
struct ConfigDev *cd = NULL;
while ((cd = FindConfigDev(cd, MANUF_ID, PROD_ID)) != NULL) {
APTR base = cd->cd_BoardAddr;
ULONG size = cd->cd_BoardSize;
/* use board at base */
}
```
**Key structures:**
```c
struct ConfigDev {
struct Node cd_Node;
UBYTE cd_Flags;
UBYTE cd_Pad;
struct ExpansionRom cd_Rom; /* copy of autoconfig ROM area */
APTR cd_BoardAddr; /* configured base address */
ULONG cd_BoardSize;
UWORD cd_SlotAddr;
UWORD cd_SlotSize;
APTR cd_Driver;
struct ConfigDev *cd_NextCD;
ULONG cd_Unused[4];
};
```
## DiagArea — Card ROM
Cards with `ERTB_DIAGVALID` have a small ROM (DiagArea) that the OS calls during boot:
```c
struct DiagArea {
UBYTE da_Config; /* flags */
UBYTE da_Flags;
UWORD da_Size;
UWORD da_DiagPoint; /* offset to diagnostic code */
UWORD da_BootPoint; /* offset to boot code */
UWORD da_Name; /* offset to name string */
UWORD da_Reserved01;
UWORD da_Reserved02;
};
```
The boot vector is called by `ConfigChain()` during the early boot sequence — this is how SCSI controllers install their filesystem handlers.
## References
- NDK39: `libraries/expansion.h`, `libraries/configregs.h`, `libraries/configvars.h`
- ADCD 2.1 Autodocs: `expansion` — http://amigadev.elowar.com/read/ADCD_2.1/Includes_and_Autodocs_3._guide/node025B.html
- *Amiga Hardware Reference Manual* 3rd ed. — AutoConfig chapter
- Dave Haynie's Zorro III specification documents