

Before starting, please be aware: this is tentative information! No claims on correctness are provided. The prototyped interface was in fact quite different from the one outlined below, although I couldn't give you the exact details as it's been a good while. In the text below, ‘recently’ et cetera all refer to Spring 1996, when this design was made.
This is version 0.5 of the document.
You'll find loads of errors here. Rely on it. Having said that, I think I ought to warn anyone who reads this: the interface isn't likely to work at all! You could damage your machine if you implement it. And don't come crying to me then! :-)
In this case, of course, we're not dealing with an Intel bus. Actually, things are even worse, because the workings of the 6502 are quite different than those of Intel CPUs. This requires a bit more ‘glue’ (interface accompanying logic). Even then, though, the interface looks pretty simple: it needs no ROM (though one would be nice), and uses a minimum of cheap, off-the-shelf discrete TTL integrated circuits. You should be able to get all the components easily.
The IDE interface consists of 40 lines, of which some are used by the master device when ‘talking’ to its slave device. Up to two devices can be connected to the IDE bus; one is a master, the other a slave. The host talks to the master device alone. The slave is only accessed by the master. This is completely transparent to the host).
Most of the other lines are used for communicating with the host. Here are the most important connections:
| Line Name | Direction | Purpose |
|---|---|---|
| D0-D7 | From/To host | Data bus, lower 8 bits. |
| D8-D15 | From/To host | Data bus, higher 8 bits. Data on these lines is not always valid (e.g. when transmitting commands, only D0-D7 are used. When data is being moved around, all 16 bits are used). |
| -IOW | From host to IDE | The rising edge of this inverted signal latches data from the data bus to the device. |
| -IOR | From host to IDE | The falling edge of this inverted signal latches data from the device to the data bus. |
| -CS1FX, -CS3FX | From host to IDE | These inverted lines control which set (if any) of the IDE registers is used. |
| ADDR0-ADDR2 | From host to IDE | These select which register is used in the selected register set. |
| -RESET | From host to IDE | This inverted signal cold-resets the drive. |
| -DASP | From IDE to host | Used by the slave and master devices for handshaking purposes during reset. At all other times, this inverted signal indicates that either of the IDE devices is working. |
Note on register selection:
There two sets of registers: 1 and 3 (the strange numbering comes from their mapping on the PC I/O space at addresses 01Fx and 03Fx), hence the names of the two select lines. The IDE bus is chip-selected when either of the two lines gets asserted. The following table describes how to chip-select the IDE bus in detail:
| -IOR | -IOW | -CS1FX | -CS3FX | Register Set selected |
|---|---|---|---|---|
| 1 | 1 | X | X | IDE bus not selected. |
| X | X | 1 | 1 | IDE bus not selected. |
| 1 | 0 | 1 | 1 | IDE bus not selected. |
| 0 | 0 | X | X | Can't happen on an Intel bus; should be avoided. |
| 1 | 0 | 1 | 0 | Host writing to register set #3. |
| 1 | 0 | 0 | 1 | Host writing to register set #1 |
| 0 | 1 | 1 | 0 | Host reading from register set #3. |
| 0 | 1 | 0 | 1 | Host reading from register set #1. |
The IDE Interface consists of the following parts:

Lines A0 to A2 pass through a 74LS173, a quad D flip-flop. The outputs
are sent directly to the ADDR0-ADDR2 on the IDE bus to select
registers.
The I/O CONTROL line is an input to the Oric. It's connected to the CS (not -CS) line of the VIA. A high state enables the VIA; a low state disables it. The address decoder keeps this line at logic 1 at all times, except when the host is addressing the IDE interface. I/O CONTROL then drops to 0 to unmap the VIA (whose registers are otherwise mapped to all of the I/O page).
The following table describes how address decoding is done:
| Inputs | Outputs | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| A3 | A4 | A5 | A6 | A7 | -I/O | -CS1FX | -CS3FX | -MSB | I/O CTRL | Comments |
| 1 | X | X | X | X | X | 1 | 1 | 1 | 1 | Not selected. |
| X | X | X | X | 0 | X | 1 | 1 | 1 | 1 | Not selected. |
| X | X | X | X | X | 1 | 1 | 1 | 1 | 1 | Not selected. |
| 0 | 0 | X | X | 1 | 0 | 1 | 1 | 1 | 1 | Not selected. |
| 0 | 1 | 0 | 0 | 1 | 0 | 1 | 1 | 1 | 1 | Not selected. |
| 0 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | MSB register. |
| 0 | 1 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | Register set #1. |
| 0 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | 1 | 0 | Register set #3. |
The I/O memory mapping is as follows:
For a discussion of the actual IDE registers rather than their mapping on memory, please see the references at the end of this document.
The only problem with timings is also a problem that has to do with address decoding. Mainly, deciding when to assert -IOR and -IOW. The timing diagram below shows how timing should work (but take this with a pinch of salt):

-IOR latches data from the IDE device to the host at its falling edge. This, in effect, toggles data from the device the moment phi2 goes up. I don't know if this gives enough time for the IDE interface to enable itself. Maybe we shouldn't AND R/-W with phi2...
-IOW latches data from the host to the IDE device at its rising edge. This should be okay ― it more or less matches what the 6502 does, if I'm not mistaken. The equation for this signal is phi2 NAND (NOT R/-W).
The 646 is a very useful chip for asynchronous bus applications: it
has two 8-bit registers. Depending on the state of the control lines
(CPAB, SAB, CPBA, SBA, DIR and -G), the chip can isolate the two buses
(known as ports A and B), let data pass through in a specified
direction, store data in one of the two registers, and allow one part
of the bus to read the other part's register, so we can access data
even if we can't have control of the other end of the bus.
The following table describes the operation of the chip depending on the control inputs. States are described as 1, 0, X (don't care), 1/0 (high or low, but no transition allowed), or / (rising edge):
| Control Inputs | Data I/O | Function | ||||||
|---|---|---|---|---|---|---|---|---|
| -G | DIR | CPAB | CPBA | SAB | SBA | Port A | Port B | |
| 1 | X | 1/0 | 1/0 | X | X | Input | Input | Isolation. |
| 1 | X | / | X | X | X | Port A to Reg A. | ||
| 1 | X | X | / | X | X | Port B to Reg B. | ||
| 0 | 1 | X | X | 0 | X | Input | Output | A to B (Real Time). |
| 0 | 1 | / | X | 0 | X | Port A to Reg A. | ||
| 0 | 1 | 1/0 | X | 1 | X | Reg A to Port B. | ||
| 0 | 1 | X | X | 1 | X | Port A to Reg A and Port B. | ||
| 0 | 0 | X | X | X | 0 | Output | Input | B to A (Real Time). |
| 0 | 0 | X | / | X | 0 | Port B to Reg B. | ||
| 0 | 0 | X | 1/0 | X | 1 | Reg B to Port A. | ||
| 0 | 0 | X | X | X | 1 | Port B to Reg B and Port A. | ||
The control inputs do the following tasks:
The 74LS646 used for this purpose has its A port attached to the IDE bus. Its B port is the 6502 bus. Hence, DIR is the same as the 6502's R/-W line: when in the high state, direction is from IDE (A) to 6502 (B); when in the low stgate, direction is from 6502 (B) to IDE (A).
The following two cases are taken care of:
The MSB register is addressed in a lot of cases:
Because of all this, the software will have to be slightly careful of accessing the drive. Accesses to the MSB register do not clock data from/to the device. Only the LSB register can do this. Hence, to work with this scheme, we have to do the following:
Figure 3 depicts the four kinds of accesses needed to interface the Oric to an IDE 16-bit data bus.

The data bus registers use three signals to tell what to do with themselves:
| R/-W | -REG | -MSB | Action |
|---|---|---|---|
| 0 | 0 | 0 | Can't happen. |
| 0 | 0 | 1 | Write to LSB. |
| 0 | 1 | 0 | Write to MSB. |
| 0 | 1 | 1 | Interface not addressed. |
| 1 | 0 | 0 | Can't happen. |
| 1 | 0 | 1 | Read LSB. |
| 1 | 1 | 0 | Read MSB. |
| 1 | 1 | 1 | Interface not addressed. |
And this table shows the states of the various 74LS646 control lines depending on the values of R/-W, -REG and -MSB. As in previous truth tables, / signifies a rising edge.
| Inputs | LSB Register | MSB Register | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| R/-W | -REG | -MSB | CPAB | CPBA | SAB | SBA | -G | CPAB | CPBA | SAB | SBA | -G |
| 0 | 0 | 0 | Never happens. | |||||||||
| 0 | 0 | 1 | 0 | / | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 0 |
| 0 | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | / | 1 | 1 | 0 |
| 0 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 1 |
| 1 | 0 | 0 | Never happens. | |||||||||
| 1 | 0 | 1 | / | 0 | 1 | 1 | 0 | / | 0 | 1 | 1 | 1 |
| 1 | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 0 |
| 1 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 1 |
To ease the implementation of this table into hardware, I use another 74LS138 inverting multiplexer to decode the three input lines. Then it's trivial to tap desired output lines to get the equation we want.
And behold explanations for each case: