index

Notes on Apricot Winchester card and modern ATA commands

To use MFM Winchester card:

$ truncate -s $((306*4*16*512)) testhd.dsk
$ chdman createhd -c none -chs 306,4,16 -o testhd.chd -i testhd.dsk
$ mame apricotxi -flop1 dos2.mfi -window -exp:1 winchester -hard1 testhd.chd
B>msd  # use Rev007 and Rodime 352
B>format a:apricot /sb:

Apricot Xi retains the data but doesn't boot.

Resources

Commands

ID      WD1010              ATA
0x10    CMD_RESTORE         IDE_COMMAND_RECALIBRATE
0x20    CMD_READ_SECTOR     IDE_COMMAND_READ_SECTORS
0x30    CMD_WRITE_SECTOR    IDE_COMMAND_WRITE_SECTORS
0x40    CMD_SCAN_ID         IDE_COMMAND_VERIFY_SECTORS
0x50    CMD_WRITE_FORMAT    FORMAT TRACK
0x70    CMD_SEEK            IDE_COMMAND_SEEK

Taskfile and DATA PIO

On Apricot located at map(0x0e0, 0x0ef).umask16(0x00ff), i.e. 0,2,4..., on PCAT it is at 0x1F0-0x1F7. There are three differences:

  1. register 0 is used for DATA PIO in ATA, and is not available on WD1010, it is mapped on 0x1f0 on Apricot with automatic sequencing;
  2. register 1 is used to set features in ATA and to set write precompensation cylinder on WD1010 (it seems to be okay to ignore since it doesn't do anything in ATA if there was no command issued);
  3. SDH register is not wired on WD1010, Apricot is using LS259 for disk/head information (it is unclear if Apricot sets SDH for all operations or not).

Control registers on ATA

Might need to be implemented in Apricot BIOS to

Bus Addressable Latch LS259 on Apricot

Mapped to map(0x1e0, 0x1ef).umask16(0x00ff), used as follows

NO  ADDR    FLAG
0   1E0     HEAD0
1   1E2     HEAD1
2   1E4     HEAD2
3   1E6     DRIVE0
4   1E8     XFERD
5   1EA     HBCR
6   1EC     CLKSEL
7   1EE     DRIVE1

As per manual:

  1. HEAD[2..0] and DRIVE[1..0] are selecting one of 8 heads and 2 drives (1 and 2).
  2. CLKSEL defines if the system processor or the WD 1010-05 causes the sector pointer to be incremented, 0 allows data access to host, and 1 to WD1010.
  3. XFERD is a handshaking protocol informing the WD 1010-05 that data is available. Connected to BDRY.
  4. HBCR is used to reset both the sector pointer and the byte pointer to zero. It is controlled by the system processor.

It seems like the Apricot is making the weird dance with BDRQ/BDRY(XFERD) to handle multiple sectors read/write. Unfortunately, MAME doesn't seem to support to continue debugging. Needs validating.

Interrupt

Sends Apricot INT2 and also provides its value at 0x1e0.

Sequences

Test and read bad sectors list

MSD.EXE operations (it will fail at reading the status if the harddrive file is not specified)

writing 00 to 01EC      ; CLKSEL    host clocks data
writing 01 to 01EA      ; HBCR      up
writing 00 to 01EA      ; HBCR      reset counters
writing 55 to 01F0      ; DATA      fill buffer
...
writing 00 to 01EC  
writing 01 to 01EA
writing 00 to 01EA
reading 55 from 01F0    ; DATA      reading from buffer
writing 01 to 01E6      ; DRIVE0
writing 00 to 01EE      ; DRIVE1    select drive 1 out of 2

reading 50 from 00EE    ; STATUS    set irq to 0 and return status
                        ;           returns 00 if there is no drive


writing 00 to 01E0      ; HEAD0
writing 00 to 01E2      ; HEAD1
writing 00 to 01E4      ; HEAD2
writing FF to 00E2      ; PRECOMP   rwc always low
writing 01 to 00E4      ; SECCOUNT  1 sector
writing 00 to 00E6      ; SECNUM    sector 0
writing 00 to 00E8      ; CYLLOW    0
writing 00 to 00EA      ; CYLHI     0
writing 20 to 00EC      ; SDH       0 01 00 000: EXT=0(CRC is appended), SEC=1(512B), DRIVE=0(should be 1 but wk), HEAD=0
writing 10 to 00EE      ; COMMAND   READ
reading 50 from 00EE    ; STATUS    01010000 RDY SC(Seek Complete
reading 00 from 00E2    ; ERROR
reading 01 from 00E4    ; SECCOUNT
reading 00 from 00E6    ; SECNUM
reading 00 from 00E8    ; CYLLOW
reading 00 from 00EA    ; CYLHI
reading 20 from 00EC    ; SDH
reading 50 from 00EE    ; STATUS
writing 01 to 01E6      ; DRIVE0
writing 00 to 01EE      ; DRIVE1
writing 40 to 00EE      ; SCAN_ID
reading 50 from 00EE    ; STATUS
reading 00 from 00E2    ; ERROR
reading 01 from 00E4    ; SECCOUNT
reading 00 from 00E6    ; SECNUM
reading 00 from 00E8    ; CYLLOW
reading 00 from 00EA    ; CYLHI
reading 20 from 00EC    ; SDH
reading 50 from 00EE    ; STATUS
writing 01 to 01E6      ; DRIVE0
writing 00 to 01EE      ; DRIVE1
writing 01 to 01EC      ; CLKSEL    WD accesses buffer
writing 01 to 01EA      ; HBCR
writing 00 to 01EA      ; HBCR      reset counters
writing 01 to 01E8      ; XFERD     READY set?
reading 50 from 00EE    ; STATUS
writing 00 to 01E0      ; HEAD0
writing 00 to 01E2      ; HEAD1
writing 00 to 01E4      ; HEAD2
writing FF to 00E2      ; PRECOMP   rwc always low
writing 01 to 00E4      ; SECCOUNT  1 sector
writing 00 to 00E6      ; SECNUM    sector 0
writing 00 to 00E8      ; CYLLOW    0
writing 00 to 00EA      ; CYLHI     0
writing 20 to 00EC      ; SDH       0 01 00 000: EXT=0(CRC is appended), SEC=1(512B), DRIVE=0(should be 1 but wk), HEAD=0
writing 2C to 00EE      ; COMMAND   READ 00101100 Interrupt, Multiple
reading 50 from 00EE    ; STATUS
reading 00 from 00E2    ; ERROR
reading 01 from 00E4    ; SECCOUNT
reading 00 from 00E6    ; SECNUM
reading 00 from 00E8    ; CYLLOW
reading 00 from 00EA    ; CYLHI
reading 20 from 00EC    ; SDH
reading 50 from 00EE    ; STATUS
writing 00 to 01E8      ; XFERD     READY unset?
writing 00 to 01EC      ; CLKSEL    host clocks data
writing 01 to 01EA      ; HBCR      up
writing 00 to 01EA      ; HBCR      reset counters
reading 00 from 01F0    ; DATA      reads from buffer
...