svi-328.dev

SVI-609 Bootstrap Card — ROM Analysis

Overview

The SVI-609 is a Bootstrap Card for the SVI-328 computer, providing automatic boot capability from either a floppy disk drive or a SASI hard disk (such as the SV-608M). The card contains a 4K EPROM that takes over the boot process.

Property Value
ROM size 4096 bytes (4K EPROM)
Active code 745 bytes (offsets 0x000–0x2E8)
Padding 0xFF from offset 0x2F9 to 0xFEF
Signature NETROM 1.0 CWJ at offset 0xFF0
Disassembly svi-609.asm

ROM Layout

0000h–0012h   Bootstrap stub (19 bytes) — copies code to RAM, jumps there
0013h–02F9h   Main code body (743 bytes) — runs from RAM at 8000h
02FAh–0FEFh   0xFF padding (unused EPROM space)
0FF0h–0FFFh   "NETROM 1.0 CWJ" + 15h E7h (signature / author initials)

Boot Mechanism

Phase 1: Bootstrap Stub (ROM at 0000h)

The SVI-609 ROM is mapped at 0000h on power-up, taking priority over the standard BIOS ROM. The CPU executes the bootstrap stub directly from the EPROM:

DI                          ; Disable interrupts
LD A,00h
OUT (34h),A                 ; Deselect all floppy drives, motor off
LD HL,0013h                 ; Source: ROM at offset 13h
LD DE,8000h                 ; Destination: RAM at 8000h
LD BC,02E7h                 ; Length: 743 bytes
LDIR                        ; Copy main code to RAM
JP 8000h                    ; Jump to RAM copy

This is a standard takeover ROM technique: copy yourself to RAM, then execute from RAM so the ROM can be unmapped and the original BIOS restored.

Phase 2: System Initialization (RAM at 8000h)

After jumping to 8000h the main code:

  1. Resets the FDC — sends Force Interrupt (D0h) to port 30h
  2. Unmaps the SVI-609 ROM — writes to port 6Fh, which restores the standard SVI-328 BIOS/BASIC ROM at 0000h–7FFFh
  3. Initializes PSG — sets AY-3-8910 register 15 (port B) to DFh
  4. Calls BIOS initCALL 34D9h (BIOS hardware initialization)
  5. Stores cartridge signature — writes “MS” to FFFEh (warm-boot marker)
  6. Sets up interrupt mode 1
  7. Clears work area — fills FA00h–FFB3h (1460 bytes) with 00h
  8. Initializes hook vectors — 105 three-byte hook slots at FE79h, each set to RET (C9h), meaning “hook disabled”
  9. Copies function tables from BIOS ROM to RAM work area:
    • 78 bytes from ROM 084Ch → F500h
    • 222 bytes from ROM 7A66h → FA00h
  10. Calls screen/BASIC init routines:
    • CALL 4066h — text mode screen init
    • CALL 40BEh — screen setup
    • CALL 7CDAh — hook/vector init
    • CALL 65B5h — BASIC init (part 2)
    • CALL 6557h — BASIC init (part 1)
    • CALL FAC0h — execute installed hook
  11. Sets up BASIC workspace pointers at various system variable locations

Phase 3: Boot Decision

After initialization, the ROM makes a boot decision with the following priority:

┌─────────────────────────┐
│  Reset FDC              │
│  Detect SASI target     │──── Timeout (HL=0) ──→ JP 0000h (restart)
│  (10240 iterations)     │
└───────────┬─────────────┘
            │ SASI target found
            ▼
┌─────────────────────────┐
│  Check floppy drive     │
│  (FDC Restore to trk 0) │
└───┬──────────────────┬──┘
    │ A=1 (floppy)     │ A=0 (no floppy)
    ▼                  ▼
┌──────────┐    ┌──────────────────┐
│ Read     │    │ SASI Read(6)     │
│ FDC boot │    │ LBA 0, 2 sectors │
│ sector   │    │ → C100h          │
└────┬─────┘    └────────┬─────────┘
     │                   │
     ▼                   ▼
     JP C100h            JP C100h

Key point: The SASI hard disk must be present (the SVI-609 requires it). If no SASI target responds, the system restarts. If the HDD is present and a floppy disk is inserted, the floppy takes priority. This allows the user to override HDD boot by inserting a floppy diskette.

Hard Disk Access (SASI Protocol)

Port Usage

The SVI-609 uses the same SASI host adapter ports as the SV-608M CP/M BIOS:

Port Direction Function
40h W SASI bus reset
41h W SASI data write (auto-ACK)
42h R SASI data read (auto-ACK)
43h W Assert SASI SEL signal
46h R SASI bus status (5-bit phase + bit 5 for detection)

SASI Status Register (port 46h)

Bit Signal Meaning
0 BSY Target busy / bus in use
1 REQ Target requests data transfer
2 C/D 1 = Command/Status, 0 = Data
3 I/O 1 = Input to host, 0 = Output from host
4 MSG 1 = Message phase
5 (ext) Used for target presence detection

Standard phase values (AND 1Fh):

Value Phase
00h Bus Free
0Bh Command
13h Data In
1Bh Status
1Fh Message In

Target Detection Sequence

The SASI_DETECT routine (81CBh) performs a three-step detection:

  1. Bus reset + BSY check: Resets the SASI bus, then checks bit 5 of port 46h. If set, a target is present on the bus. Repeats with timeout.

  2. Target selection: Places device ID 01h on the data bus (port 41h), asserts SEL (port 43h), and checks for bit 1 (REQ) response from the target.

  3. Test Unit Ready: Sends a 6-byte Test Unit Ready command (all zeros). Reads status and message phases to confirm the drive is operational.

HDD Boot Read

The SASI_READ_BOOT routine (824Ch) executes a SASI Read(6) command:

CDB: 08h 00h 00h 00h 02h 47h

  08h — Read(6) opcode
  00h — LUN 0, LBA bits 20-16 = 0
  00h — LBA bits 15-8 = 0
  00h — LBA bits 7-0 = 0    → LBA 0 (first block)
  02h — Transfer length = 2 sectors
  47h — Control byte (vendor-specific: retries + ECC + step option)

This reads 2 × 256 = 512 bytes from LBA 0 to memory at C100h.

Data transfer uses INIR (block input instruction), reading 256 bytes at a time from port 42h during Data In phases. The routine polls port 46h to detect phase transitions between Data In (13h) and Status (1Bh).

Comparison with SV-608M CP/M BIOS

Feature SVI-609 Bootstrap SV-608M CP/M BIOS
SASI ports 40h–43h, 46h (identical) 40h–43h, 46h
Target ID 01h (device 0) 01h (device 0)
Read command 08h (Read 6) 08h (Read 6)
Control byte 47h 47h
Boot load address C100h C100h
Boot sectors 2 (512 bytes from LBA 0) 1 (256 bytes from LBA 0)
Set Parameters Not issued 0Ch cmd at init (306 cyl, 4 heads)
Bus reset delay 60 NOPs (~60 µs) Not timed
Detection ports Not used 60h–63h (Centronics printer / detection)

Notable differences:

Floppy Disk Access (WD1793)

Port Usage

Port Direction Function
30h W FDC Command Register (WD1793)
30h R FDC Status Register
31h R/W FDC Track Register
32h R/W FDC Sector Register
33h R/W FDC Data Register (used by INI/OUTI)
34h W Drive select / side / motor latch
34h R INTRQ (bit 7) and DRQ (bit 6) from WD1793
38h W Density select (bit 0: 0=double, 1=single)

Drive Select Latch (port 34h write)

Bit Function
0 Drive 0 select
1 Drive 1 select
2 Side select (0=side 0, 1=side 1)
3 Motor enable

The ROM uses two drive select values:

Floppy Boot Sector Read

The FDC_READ_BOOT routine (813Ch):

  1. Homes the drive (Restore command, verify track 0)
  2. Selects drive 0, sets density
  3. Sets sector register to 1
  4. Issues Read Sector command (80h)
  5. Polls port 34h for DRQ (bit 6) and INTRQ (bit 7)
  6. Uses INI to transfer bytes from port 33h to C100h
  7. Checks status for errors, retries on failure

The boot sector is read from track 0, side 1, sector 1 to C100h.

Floppy Drive Detection

The FDC_RESTORE routine (80C4h) determines whether a floppy disk is present:

  1. Sends Restore command (07h) to seek track 0
  2. Waits for INTRQ with a long timeout (4 × 255 × 255 NOPs ≈ 1 second)
  3. If INTRQ fires, reads status to confirm Track 0 flag
  4. Retries up to 10 times
  5. Returns A=1 if track 0 reached (floppy present), A=0 otherwise

Dead Code

The subroutine at 811Fh (FDC_SELECT_DRV1) is never called from anywhere in the ROM. It selects floppy drive 1 (value 0Eh → port 34h). This may have been used for dual-drive configurations or may be leftover from development.

ROM Signature

The last 16 bytes of the EPROM (offset 0xFF0):

4E 45 54 52 4F 4D 20 31 2E 30 20 43 57 4A 15 E7
N  E  T  R  O  M     1  .  0     C  W  J  .  .

Subroutine Map

Address Name Description
0000h BOOTSTRAP Stub: copy to RAM + jump
8000h INIT System initialization + boot decision
80C4h FDC_RESTORE Try floppy restore, return A=0/1
811Fh FDC_SELECT_DRV1 Select drive 1 (dead code)
812Ch FDC_FORCE_INT WD1793 Force Interrupt
813Ch FDC_READ_BOOT Read floppy boot sector → C100h
817Bh FDC_SELECT_DRV0 Select drive 0, side 1, motor on
8182h FDC_HOME Restore to track 0 with retry
81ACh FDC_WAIT_INTRQ Wait for FDC INTRQ
81B8h FDC_WAIT_READY Wait for FDC not busy
81C4h SASI_BOOT_LOADER Reset + Read from HDD
81CBh SASI_DETECT Detect SASI target + Test Unit Ready
822Bh SASI_TEST_READY Send Test Unit Ready (00h × 6)
824Ch SASI_READ_BOOT Full SASI Read(6) sequence
825Ch SASI_SEND_READ_CMD Send Read(6) CDB
827Dh SASI_DATA_IN_PHASE Receive data blocks via INIR
829Eh SASI_SEND_CMD_BYTE Send one Command phase byte
82ACh SASI_READ_STATUS Read Status phase byte
82BAh SASI_READ_MSG_IN Read Message In phase byte
82C8h SASI_SELECT_TARGET Bus free wait + target select
82DAh SASI_RESET SASI bus reset with delay

External Addresses Called

Address Likely Function
0000h Warm boot / system restart
34D9h BIOS hardware initialization
4066h Text mode screen initialization
40BEh Screen setup
6557h BASIC interpreter init (part 1)
65B5h BASIC interpreter init (part 2)
7CDAh Hook / interrupt vector initialization
FAC0h Hook entry point (RAM, installed by BIOS)
C100h Boot sector entry point