The 8087 floating-point coprocessor presumably used different ESC codes to the 8089 input/output coprocessor, since then they would be able to listen over the bus for their own ESC instructions. The opcodes of the ESC instructions are in the range 0xD8..0xDF, so did the 8087 use all those beginning with D8, for example, and the 8089 those beginning with another byte? Or was it more complicated than this?
[Ok, I did dig out the manual, now improved with details about the hardware part of the communication protocol]
Or was it more complicated than this?
No, it was completely different. The 8089 did not use any opcodes - at least not any within the 8086's instruction stream. The 8087 is an extension to the CPU, while the 8089 is a separate CPU with its own instruction set, its own programs and (depending on the setup) a different or even separate address space.
Jobs between the 8086 side and the 8089 are exchanged by the main CPU setting up a parameter block (CCB - Chanel Control Block) containing a command (CCW- Channel Controll Word) and the address of another Parameter Block (this time called as such: PB). If the command is about starting some 8089 program, PB will hold its address (*1) in the first (when in I/O Space) or first two (when in System Space) words. Followed by optional parameters. Usually at least containing some buffer address were data is to be found or returned.
The program to be executed (on the 8089 side) may or may not be part of the 8086' address space (*2). Similar for buffers, although, some shared memory does usually exist to speed up data exchange. The 8089 contains two channels which are operated in a hardware multiplexing scheme. Prioritisation between each channel and shared memory (the 8086) is configured within the CCW.
When all data structures are prepared (for the channel to be used), the 8086 selects either channel by setting the
SEL pin and pulling the
CA pin to get the 8089's attention (*3). These pins are usually hooked up to some I/O port (on the 8086 side).
CA goes low, the 8089 reads the CB for the channel addressed by
SEL and transfers all relevant date into internal registers. When done, it sets the Busy-Flag to 0FFh and executes whatever command is stored in the the CCW. The 8086 must wait for Busy before executing any other 8089 command.
When done, the 8089 will reset the Busy-Flag 0h, signalling that the channel is finished. The same happens as well when a channel program stops at a defined point (usually by a
HALT instruction). The Busy-Flag can be polled by the 8086 as the CB is always in shared memory. More commonly the interrupt facility is used. When enabled by the CCW, the coresponding interrupt pin (
SINTR2) is pulled, at the after Busy is reset.
HALT instruction allows very nifty communication schemes, starting from operator action ("Please Mount Disk xxxxxx") all the way to streaming like operation.
Overall, this concept is very much like that seen on classic mainframes. Here also, one or more IOCs handle one or more channels each. Each IOC operated independently of each other and the CPU(s), multiplexing all channels offered. Unlike mainframe channels, the Intel concept was much more flexible as the 8089 was a complete programmable CPU. Beside simple block I/O and collection of character I/O, much more could be offloaded.
*1 - Programs can reside in System Space (20 bit address space) or I/O-Space (16 Bit address space), always as seen from the 8089 side - wich may have a different mapping then the 8086.
*2 - Address space organisation is extreme flexible, thus hard to describe a default situation. In the most simple configuration it might be the same memory and I/O address spaces as the 8086 sees. Even in local configuration (that is when the bus is shared with the 8086) parts of the address space can be different. Much more so in remote configuration, like the 8089 being its own Multibus system, communicating only via a few shared memory sections.
*3 - This mechanic is as well used to select between multiple 8089 within the system during first time initialization after reset.
*4 - Depending on the machine design, this could instead be some memory flag to be polled. But I know of no system using an 8089 that wasted any resources here.