[Preface: It might be more appropriate to read the S100 standard documents instead]
The S-100 bus had 8 data lines, logically enough since it was originally used with the 8080 and then Z80 CPUs.
Yes ... err no. The original Altair-bus was made only for the 8080 (and the Altair), while S100 is the later standardization removing some unclear points and fixing all workings.
However, it actually had two sets of 8 data lines. [...] if I understand the answer correctly, the second set of data lines serves to allow the front panel to operate the system without disturbing the CPU.
Yes .. err no ... again :)) It was made that way not only that some (simple) front panel can handle the system without the CPU (essentially doing DMA), but more important to also 'emulate' reaction of device toward the CPU. So effectively one could operate a stand alone CPU without anything else (which the original Altair CPU was).
Later, when an updated version of the S-100 bus was used with 16-bit CPUs such as the 286, the two sets of data lines were amalgamated to a single 16-bit set.
Yes .. no ... in many way.
To start with, already the 8086 was a 16 bit CPU. But more important, the 16 bit extension was already part of the very first IEEE standard proposal for the S100 bus, published in 1978 and accepted with the 1979 standard (IEEE 969.1/D2) (*1). Seattle Computer Products, as one of the first (if not first) commercial provider of a S100 based 8086 card, the SCP-200B, did just followed the specs layed out in both documents.
That seems logical enough by sheer arithmetic, but how did it not break compatibility? Intuitively, it seems like existing 8-bit cards shouldn't be able to handle 16 bits.
Simply by being backward compatible due making each bus cycle start compatible with 8 bit definition and continuing that way if the target can't cope with a 16 bit access. In 8 bit mode it's two unidirectional sets of 8 bit, in 16 bit mode it's a 16 bit bidirectional data bus. Sequence in detail (from memory):
sSTVAL initiates a bus cycle with stable status/address signals.
- In addition
sXTRQ (Status eXTendedReQuest) is set when a 16 Bit access is intended
- If able to do 16 bit transfer for this address, the addressed card pulls
SIXTN (SIXTeeN bit)
- If not pulled in time,
sXTRQ is released and a (*2) regular 8 bit cycle is performed.
- If pulled in time,
sXTRQ stays for the whole 16 bit cycle following.
Done. Since basic signaling and addressing is not changed, any 8 bit card will work right away - with the CPU carrying the burden to turn a 16 bit access into two 8 bit ones (*3).
Was there some aspect of the design that made it possible for a 286 to still read/write 8 bits at a time to a card designed to work with 8-bit machines?
The CPU card has to do this - using 16 bit was optional anyway, no matter what CPU.
To take the simplest example, suppose you plugged a 16K 8-bit memory card into a 16-bit machine. Could you still read/write bytes to each of the 16384 consecutive memory locations?
Sure, as it's the default way
What would happen if you tried writing 16-bit words?
The glue logic on the CPU card will have to split it in two consecutive 8 bit cycles.
Would an attempt to read a 16-bit word get results with the upper half zero?
Depending on the CPU card glue logic there might be special cases (*4), but in general, it would issue two 8 bit reads before presenting the 16 bit result to the CPU.
So far above detailed description is about what the standard says. A real world CPU card (more exact its glue logic) had to do a bit more to make it work than detecting 16 bit and splitting access. SCP added a few configurations/ extra steps to their SCP-200B 8086 card:
Since some systems used prior unassigned lines for private usage, therefore the new signals (
SIXTN), could be cut and tied, effectively turning all cycles into compatible 8 bit cycles.
Basically a 8 bit cards just decoded the lower 16 address lines. The CPU thus assigned the
PHANTOM line whenever an address above 64 Ki was assigned, effectively mapping all old cards to the first 64 KiB (5)
The 8086 only supported a 20 bit address. To make it compatible with full 24 bit addressing the top 4 address bits where always set to zero.
Traditionally (aka on the Altair bus) an I/O address was only 8 bit but presented on both address bytes. A considerable number of cards used this to simplify layout and used either half - or worse, a mixture. To support this the SCP-200B could be jumpered to copy the lower 8 address bits as well into the upper (now mid) 8 address bits
Not all of these twists are realy cool, but quite helpful for users upgrading an existing S100 system - at least during a transition period.
Beside the standard conform ways, SCP also added some non standard interpretation, for example to select memory speed and alike.
*1 - Beside extending the data bus to 16 bit, the address bus was also widened to 24 lines.
*2 - Well, usually two 8 bit cycles.
*3 - Not much different from what IBM made when tuning the PC bus for use with the AT.
*4 - I/O might be one of these cases, as it's addressing was quite screwed.
*5 - Cards with 24 bit addressing ignored that signal (by default). Ofc, they still needed to be configured to higer addresses to work.