DMA & SCSI
===========#==#=======#===============================================#=====
----------------------|DMA, WD1772 Disk Controller |-----
===========#==#=======#===============================================#=====
$FFFF8604.W|RW|WDC_SEC|FDC/HDC Access/Sector Count |
$FFFF8604 WDC_SEC FDC/HDC Access / Sector Count
The FDC is NOT in the 68000 address space. Its four registers
sit behind the DMA chip and are reached through this word.
Select which one with the mode register at $FFFF8606, then
read or write here. Only the low 8 bits are used; the upper
byte is ignored on write and reads back as all ones.
Mode register values to select each FDC register:
DMA read mode DMA write mode
FDC Command (W)/Status(R) $0080 $0180
FDC Track Register $0082 $0182
FDC Sector Register $0084 $0184
FDC Data Register $0086 $0186
DMA sector count (W only) $0090 $0190
WD1772 command encodings written to the Command Register:
Type Command b7 b6 b5 b4 b3 b2 b1 b0 Base
I Restore 0 0 0 0 h v r1 r0 $00
I Seek 0 0 0 1 h v r1 r0 $10
I Step 0 0 1 u h v r1 r0 $20
I Step-in 0 1 0 u h v r1 r0 $40
I Step-out 0 1 1 u h v r1 r0 $60
II Read Sector 1 0 0 m h e 0 0 $80
II Write Sector 1 0 1 m h e p a0 $A0
III Read Address 1 1 0 0 h e 0 0 $C0
III Read Track 1 1 1 0 h e 0 0 $E0
III Write Track 1 1 1 1 h e p 0 $F0
IV Force Interrupt 1 1 0 1 i3 i2 i1 i0 $D0
Base is the opcode with all flags clear, not the only byte the
command can take. Read Track can appear as $E0, $E4, $E8 or
$EC depending on h and e. Match on the top nibble.
Flags:
u bit 4 update Track Register
m bit 4 multiple sector
h bit 3 0 = enable spin-up sequence, 1 = disable
v bit 2 verify destination track
e bit 2 add settling delay
p bit 1 0 = ENABLE write precompensation, 1 = disable
a0 bit 0 0 = normal data mark, 1 = deleted data mark
Step rates (r1,r0), WD1772 values at 8MHz:
00 = 6ms 01 = 12ms 10 = 2ms 11 = 3ms
These are WD1772 specific. The WD1770 uses 6, 12, 20 and 30ms
for the same encodings. On the Atari 3ms is the normal setting
and h must always be 0, since MO is wired straight to the drive.
Sources: Western Digital's own WD1772 data sheet, cross-checked
against EmuTOS bios/fdc.h. Read Track being 1110 confirmed by
both, correcting a misprint in DrCoolZic's edition.
$FFFF8606.W|R-|WDC_DMA|DMA Status %________ _____DSE | | | | Data request condition--------------------+|| | | | | Sector count 0:zero,1:not zero-------------+| | | | | DMA 0:error,1:no error----------------------+ | |-W| |DMA Mode %_______W FD_SHAA_ | | | | 0:read,1:write---------------------+ || |||| | | | | 0:HDC,1:FDC access-------------------+| |||| | | | | DMA 0:on,1:off (ignored STF/STE)----+ |||| | | | | 0:FDC/HDC register 1:sector count-------+||| | | | | 0:FDC,1:HDC access-----------------------+|| | | | | A1/A0 pin 0:low,1:high--------------------++ |
$FFFF8606 WDC_DMA DMA Status (read) / DMA Mode (write)
READ - status, bits 2-0:
Bit 2 state of the FDC DRQ signal
Bit 1 sector count: 0 = reached zero, 1 = not zero
Bit 0 DMA error: 1 = NO error, 0 = error
Bit 0 is inverted from the obvious reading. It was documented
the wrong way round here and in the widely mirrored Dan Hollis
listing for many years. Atari's own TOS tests it as:
move.w #$0090,(a6) examine DMA status register
move.w (a6),d0
btst #0,d0 bit zero indicates DMA ERROR
beq.s floprd6 (when its zero -- retry)
EmuTOS agrees: DMA_OK is 0x0001, commented 1=ok, 0=error.
Confirmed by ijor, July 2026.
WRITE - mode control:
Bit 8 direction, 1 = memory to controller (write)
Toggling this bit RESETS the DMA, flushing both
FIFOs and clearing the sector count register.
Bit 7 1 = acknowledge FDC DRQ, 0 = acknowledge HDC DRQ
Bit 6 nominally DMA enable, but IGNORED on STF and STE
Bit 4 0 = external controller registers, 1 = sector count
Bit 3 0 = assert FDCS*, 1 = assert HDCS*
Bit 2 CA2 output, drives FDC A1
Bit 1 CA1 output, drives FDC A0
Bit 0 unused, set 0
The DMA FIFOs are 16 bytes and are never flushed automatically,
so data only reaches memory in multiples of 16 bytes. A single
Read Address moves 6 bytes and therefore reaches memory not at
all; issue it repeatedly to push data through.
Do not poll this status register during a transfer, it can
disrupt it. Poll MFP GPIP bit 5 at $FFFFFA01 instead: mask with
$20, result zero means the FDC has interrupted.
$FFFF8609.B|RW|WDC_BSH|DMA Base and Counter Hi |
$FFFF860B.B|RW|WDC_BSM|DMA Base and Counter Mi |
$FFFF860D.B|RW|WDC_BSL|DMA Base and Counter Lo |
$FFFF860E.B|RW|WDC_FDN|Frequency and Density control %______FD |STE,F | | |Frequency 0:8MHz,1:16MHz--------------------+| | | | |Density 0:DD,1:HD----------------------------+ |
$FFFF860E WDC_FDN Frequency and Density control
Bit 1 Frequency 0 = 8MHz, 1 = 16MHz
Bit 0 Density 0 = DD (double), 1 = HD (high)
STE and Falcon only. Was previously labelled WDC_BSL here,
duplicating the label on $FFFF860D.
===========#==#=======#===============================================#=====
----------------------|DMA SCSI |-----
===========#==#=======#===============================================#=====
$FFFF8701.B|RW|SCS_DA0|DMA Address Pointer (Highest byte) |TT
$FFFF8703.B|RW|SCS_DA1|DMA Address Pointer (High byte) |TT
$FFFF8705.B|RW|SCS_DA2|DMA Address Pointer (Low byte) |TT
$FFFF8707.B|RW|SCS_DA3|DMA Address Pointer (Lowest byte) |TT
$FFFF8709.B|RW|SCS_BC0|DMA Byte Counter (Highest byte) |TT
$FFFF870B.B|RW|SCS_BC1|DMA Byte Counter (High byte) |TT
$FFFF870D.B|RW|SCS_BC2|DMA Byte Counter (Low byte) |TT
$FFFF870F.B|RW|SCS_BC3|DMA Byte Counter (Lowest byte) |TT
$FFFF8710.W|Rw|SCC_RD0|Rest data (High Word) |TT
$FFFF8712.W|Rw|SCC_RD1|Rest data (Low Word) |TT
$FFFF8714.W|Rw|SCS_CTL|DMA SCSI Control Register %________ BZ____DW |TT
| | | Bus Error 0:no,1:yes-----------------+| || |TT
| | | Byte Counter Zero 0:no,1:yes----------+ || |TT
| | | DMA 0:off,1:on-----------------------------+| |TT
| | | DMA 0:read,1:write--------------------------+ |TT
===========#==#=======#===============================================#=====
----------------------|5380 SCSI Drive Controller |-----
===========#==#=======#===============================================#=====
$FFFF8781.B|RW|SCS_CDB|Contents of SCSI-Data Buses |TT
$FFFF8783.B|RW|SCS_ICR|Init Command Register |TT
$FFFF8785.B|RW|SCS_TSR|Transfer Start Register |TT
$FFFF8787.B|RW|SCS_TCR|Target Command Register |TT
$FFFF8789.B|RW|SCS_BSR|Bus Status Register |TT
$FFFF878B.B|RW|SCS_DSR|Device Status Register |TT
$FFFF878D.B|RW|SCS_BCD|SCSI-Bus Command Data |TT
$FFFF878F.B|RW|SCS_RES|Reset Interrupts,Parity error,Start DMA-Action |TT