• Please review our updated Terms and Rules here

Z80-in-PC: how to go further?

I agree, but Ruud has already developed the hardware now - so, unless he plans to make another iteration of the PCB, it is what it is.

Ruud has asked for some ideas for a software solution to run CP/M 3.0 on the hardware he has developed, using a PC as the 'server' and the Z80 as the 'client'.

Dave
 
You might want to look that up. Mode 2 is basically a bus interface, while mode 0 is equivalent to a few glorified latches. You are leaving a lot of functionality on the table for no good reason.
Indeed, and it has handshake lines too
In this case, the two 8255 are overkill. Two 74xx573 would suffice for Z80 status/control and do not require any software.
Or a 74xx646 register but it needs glue logic on both sides.
 
I know the AT bus has some provisions for slot busmasters (there’s a MASTER signal on the 16 bit extension, that everything I’ve read about it paints as notoriously difficult to use), but I’m pretty certain there’s no clean way to negotiate it on the XT bus?

1786884897659.png

With 8237 in cascade mode it should be possible to use a DMA channel signal pair to do bus mastering on the ISA card that hooks them, per 8237 sheet.
With card DREQ high, 8237 tristates the CPU and takes control, but in cascade mode, it should also float off its address, data and mem/IO ctrl signals leaving only the "bus mastering" signals active.
So in the DMA cycle the card is free to take over the control of the bus?

ISA DMA is only slow on systems faster than a non-turbo PC/XT. But because of its limitations and lack of DMA channels, I wouldn't bother.

For me chief limitation is prefetch size on the CPU. I'd like to be corrected here but since CPU can transfer data as fast as 8237 it makes no sense gating it off since it's not able to do much on itself.
 
With 8237 in cascade mode it should be possible to use a DMA channel signal pair to do bus mastering on the ISA card that hooks them, per 8237 sheet.
The 8237 datasheet does not account for how IBM wired the chips in the PC, so some configurations are simply not usable in a PC/XT (see [here] for an example). Having the DMA controller block the CPU from the bus (while not using it for DMA) to allow the Z80 access to it... feels wrong. :-)

For me chief limitation is prefetch size on the CPU. I'd like to be corrected here but since CPU can transfer data as fast as 8237 it makes no sense gating it off since it's not able to do much on itself.
The 8237 can transfer data faster than the 8088 in a PC/XT, so starving the CPU while DMA does its thing is still a net win... of course, some of that disappears due to configuration and interrupt overhead, so it isn't great. But memory-to-memory transfers, which we would want here to load the Z80 memory quickly, are not possible. On a PC/AT or later, the 286/386 transfers data substantially faster than the 8237, so using DMA actually reduces bus bandwidth.

For hardware which is both low-bandwidth and timing-sensitive (floppy controller and digital audio), the DMA cycles are far apart and very short, so they don't impact the CPU prefetch queue much. But they decouple the CPU execution speed from the device transfer rate, which simplifies the code (no need to "race the beam" so to speak).

On the PC/XT (and most 8080/Z80 systems), timed code to keep up with the floppy disk controller is not feasible, so DMA was necessary. Anything faster could do (and sometimes did) without.
 
The 8237 datasheet does not account for how IBM wired the chips in the PC, so some configurations are simply not usable in a PC/XT (see [here] for an example). Having the DMA controller block the CPU from the bus (while not using it for DMA) to allow the Z80 access to it... feels wrong.

In AT the primary DMA controller blocks the CPU from the bus, and blocks itself from driving it, to allow cascaded DMA controller to take over the bus.
I don't see why the cascaded 'controller' couldn't be on a peripheral card.

But memory-to-memory transfers, which we would want here to load the Z80 memory quickly, are not possible

What about this approach - https://forum.vcfed.org/index.php?threads/memory-to-memory-dma-on-the-ibm-pc-pc-xt.1256277/
 
I don't see why the cascaded 'controller' couldn't be on a peripheral card.
I did not consider this. Not sure whether the PC/XT can support this, and whether clones do.

The process starts with "disable RAM refresh", which is a good indicator that it may not be a great idea. The caveat about PC/XT clones (with chipsets combining the original chips) still applies, and of course it is totally pointless on PC/AT and newer systems (edit: and likely even Turbo PC/XT systems). :-)
 
Remember, in the XT the 8237 isn’t the only thing driving the bus; the top four address bits are driven by the 74LS670 addressable latch that’s necessary to allow that chip to access the full address range, and my (no doubt incomplete) scan of the XT schematic made it look like to me that even if the 8237 put *itself* to sleep by trying to cascade itself it wouldn’t put that to sleep. And then there’s the additional question of if the buffers for the control signals to allow a card to drive them would tristate because, again, the XT doesn’t have a specific line to signal and coordinate this handover. If the 8237 says adios to responsibility for driving the bus after trying to cascade to another busmaster I’m going to guess things will just hang forever… but, I dunno, if you want to try to build a proof of concept it would be interesting to see if you can do it without physically hacking the motherboard.

Or to put it another way, sure, if the XT had a full MultiBus-style arbitration system implemented that extended to the bus then you could do it, but I’m at least 90% sure the 8-bit subset limits busmasters to the CPU socket(s)* and the DMA controller.

(* the 8087 is its own can of worms)

To put this another way: if this worked why did XT accelerator cards universally need a cable going to the 8088 socket?
 
In this case, the two 8255 are overkill. Two 74xx573 would suffice for Z80 status/control and do not require any software.
I partly disagree. You are correct about the software. But using 573s means you also need counterparts, like the 541, to read the data. Two ICs means 40 pins = equivalent to the 8255. And now I have eight extra pins for handshaking etc.
 
I partly disagree. You are correct about the software. But using 573s means you also need counterparts, like the 541, to read the data. Two ICs means 40 pins = equivalent to the 8255. And now I have eight extra pins for handshaking etc.
The 573 has tri-state outputs so why would you need an extra 541?

BTW in the Philips Videopac+ Basic module (and also to some extent the Chess module) there is a similar double latch construction to get the 8048 in the console communicating to the external Z80 in the Basic module.
Some years ago I replicated the Basic module (which are hard to find) with an ARM chip and replaced the double latch construction with a single 74xx646 register. Still needed all the handshake lines so it really did not accomplish much in terms of number of chips. The ARM chip was 5 Volt tolerant so no need to convert the levels of that but it did reduce the complete Z80 side to a single 'chip' (well really a single NXP mbed module)...
 
I am on a business trip at the moment, but I have sketched some code out for you and will post it when I get some time.

The two low-level subroutines are PUTBYTE and GETBYTE that send (and receive) a byte respectively between the Z80 and the PC using your back-to-back 8255 arrangement in 'poll' mode (no interrupts).

On the Z80 side:

Port A is used to output data from the 'A' register to the PC.

Port B is used to receive data from the PC to the Z80's 'A' register.

Port C is used as 4 input and 4 output bits (2 input and 2 output bits forming the handshake signals).

The Z80 BIOS skeleton is based upon calling these two low-level subroutines.

There are a corresponding set of low-level subroutines on the PC side.

Dave
 
Other Z80 retro board projects use serial console, so I assume this kind of stuff is text mode, CP/M only? I'm not very well versed in the ecosystem. For me Z80 rings ZX Spectrum.

If so, adding an interrupt line on the PC side seems good choice, so the PC can break anytime there is CP/M "console output" byte on the port A.

Remember, in the XT the 8237 isn’t the only thing driving the bus; the top four address bits are driven by the 74LS670 addressable latch that’s necessary to allow that chip to access the full address range, and my (no doubt incomplete) scan of the XT schematic made it look like to me that even if the 8237 put *itself* to sleep by trying to cascade itself it wouldn’t put that to sleep.

It looks AEN is connected to its /GR over inverter, cascade mode 8237 drops AEN, /GR is high and 670 is in high-Z?

The 8237 can transfer data faster than the 8088 in a PC/XT, so starving the CPU while DMA does its thing is still a net win...

The 8237 in my XT clone works at /2 of the system frequency, so the A-5 chip can work normally under 8 MHz. I don't think it is specified anywhere that DMA has to run at 4.77 MHz, that number is the ceiling.

Looks like it comes down to if CPU and DMA are both 4.77 MHz then DMA is more efficient.
 
The PC only needs to 'break' if it has something else better to do.

In the case the OP has postulated, the PC is acting as nothing more than a dedicated "CP/M server" so it is purely sitting and waiting for something to do from the Z80.

And yes, largely text mode.

But 'extensions' could open up the world of graphics!

Dave
 
I partly disagree. You are correct about the software. But using 573s means you also need counterparts, like the 541, to read the data. Two ICs means 40 pins = equivalent to the 8255. And now I have eight extra pins for handshaking etc.
The '573 are tristate, so the buffer is built-in. The Z80 has 256 I/O ports (ignoring the 16-bit I/O), which gets you 8 address lines you can use directly as chip selects. Your design has very few I/O ports, so there is no need for clean address decoding. (Ben Eater's 6502 system works similarly.) The glue logic to separate memory, I/O and interrupt acknowledgement cycles is necessary anyway, whether you use an 8255 or not.

By using two 8255 as advanced '573, you are just wasting them. Which is especially tragic because each 8255 is powerful enough to interface to the ISA bus and handle most handshaking for both directions on its own.

Other Z80 retro board projects use serial console, so I assume this kind of stuff is text mode, CP/M only? I'm not very well versed in the ecosystem. For me Z80 rings ZX Spectrum.
Yes, CP/M is strictly text-only and designed for teletypewriters or serial terminals. Most standalone CP/M systems contain actual terminal hardware in their case or emulate one in their BIOS code.

I don't think it is specified anywhere that DMA has to run at 4.77 MHz, that number is the ceiling.
The 8237 was only produced in 3 MHz and 5 MHz variants... that is why it's the ceiling. While some clones (e.g. from NEC) could operate faster, doing so was not compatible.
 
A GSX forwarder that took GSX-80 calls and had the host PC execute them under GSX-86 or GEM sounds feasible, if you wanted graphics.
 
It looks AEN is connected to its /GR over inverter, cascade mode 8237 drops AEN, /GR is high and 670 is in high-Z?

I'm looking at sheet 3 of the XT schematic, and the OE on the '670 is driven by DMAAEN'. (This is also the output enable on the '244 address buffer and '373 address latch for the bottom 16 address bits from the 8237.) This same signal appears to drive the LS243 buffer U13 on sheet 5 that gates whether the MEM and IOR/W signals are gated to XMEM/XIO or not. (There are pull-ups on those so they'll be high if they're completely undriven.) This seems to imply to me that *if* attempting a cascade on one of the existing channels through the DRQ/DACK signals that are present on the expansion bus were to result in a drop in the signal that drives the '670 it would *also* cause the control lines to be driven by that buffer, which would imply you'd get a bus conflict if a card that was driving the address bus in this condition were to actually try doing an I/O or memory request?

The thing I definitely do not have the mental bandwidth to figure out right now is the mess of logic on sheet two that is the relationship between DMAAEN and AENBRD. (The latter is what controls the CPU's address buffers.) They *kind* of look like they're just inversions of each other, which would also imply that if the cascade mode resulted in the DMA components *not* driving the address bus the drivers in front of the CPU *would* light up, but there's special cases in this that don't make me entirely confident to say that. But the control buffer conflict looks real to me.
 
I'm looking at sheet 3 of the XT schematic…

FWIW, if you look at what the “MASTER16” signal does on the 5170’s schematic it’s basically an override for buffers I enumerated above. So… it looks to me unless you want to hack your XT motherboard to add the equivalent functionality bus mastering by cascading the channel to a card isn’t going to work?
 
The 573 has tri-state outputs so why would you need an extra 541?
Because I never thought about that. Never too old to learn something new. The 646 idea could work as well but the needed decoding/glue logic put me off.

I am on a business trip at the moment, but I have sketched some code out for you and will post it when I get some time.

The two low-level subroutines are PUTBYTE and GETBYTE that send (and receive) a byte respectively between the Z80 and the PC using your back-to-back 8255 arrangement in 'poll' mode (no interrupts).
......
Thank you very much but I have various working projects I can use as base for my own routines.

The Z80 has 256 I/O ports (ignoring the 16-bit I/O), which gets you 8 address lines you can use directly as chip selects.
I know what you mean: use A4 for IC1, A5 for IC2, etc. This idea has been used by Commodore for the CBM 30xx and 80xx series to decode the various I/O ICs. And I hated it because the available I/O area is completely used up now, no room left for new I/O.
I mentioned creating a Z80 card for the CBM 8032 and ran again into this problem. I solved it by using one of the two free 4 KB memory ranges meant for EPROMs. This leaves me the second 4 KB range for the terminal program (by lack of another name). Certainly not ideal but I'm only in the design phase so things can be changed yet.
The only other solution IMHO is changing the hardware of the board. But that conflicts with the idea that the Z80 board should be add-on only. I found two other challenges: 1) the 8032 has two rows of power pins. But only yesterday evening I found out there is no +5V present and 2) the expansion bus has no +5V pins either :( This means I have to provide power in another way. Three solutions:
- Add +5V to three unused pins of the expansion bus.
- Tap +5V from an accessible point of the board and feed it with a line to the board.
- Add a 7805 to the design and use one of those rows with power pins.

FYI: there exists a CP/M card for the CBM 8032, I had one but gave it away to Mike Naberezny two years before he found out what is was: the Z-RAM card. The main reason I gave it away was the missing chip. He found out by running into the original manual, software and missing IC.
This board was attached to the 8032 board by replacing the 6502. Here was a PIO and this unknown IC used for exchanging data. Power was acquired by connecting the original power connector to this board and using an extension to feed the 8032 board. Here is the link to Mike's page but (at this moment) it seems it is not accessible for what ever reason.
 
I know what you mean: use A4 for IC1, A5 for IC2, etc. This idea has been used by Commodore for the CBM 30xx and 80xx series to decode the various I/O ICs. And I hated it because the available I/O area is completely used up now, no room left for new I/O.
A basic Z80 ISA card only needs one bidirectional I/O port (or two unidirectional ones), so you don't need to decode anything. But since you complained about needing additional glue logic, I mentioned how you can get away without it. Personally, I'd use a single '138 to deal with bus cycles.
 
If the z80 is essentially self-contained, eg has it's own RAM, all you need is a communication method between Z80 and 8088; if there is shared memory, even better.

Write the z80 BIOS as an "API" to talk through a common 8 bit (plus busy/done) port, the two CPUs comunicate through that, like talking to a serial chip or whatever. If there is shared memory, then that port can signal what to do with the shared block (read/write sectors, CRT screen locations, etc).

You don't need to have interlocking hardware for this; with modern CPUs being so stupidly fast you could poll the z80 port!

I did exactly this with the 8086 card that went into the Otrona Attache 8:16. In that specific case, the two CPUs were reversed in role; the Z80 owned all the hardware (every Zilog chip in the catalog...) and the 8088 was in a small board inserted into the "expansion port". It had only one 8-bit port to talk to the Z80. Performance was truly awful; the host being a 4MHz Z80 was just too slow. But with roles reversed, and the x86 running at current zillion-megahertz speeds, should be fast enough to keep up with the z80.

These days, skeletal hardware and fancy software is often as fast as hardware-intensive solutions. A 256 byte bidir FIFO plus an 8-bit bidir IO port I bet would be as fast as DMA, in use. 256 bytes of shared memory would be as fast as anything, even if you had to halt the Z80 to write to it.

What did the Baby Blue CPU Plus do?
 
What did the Baby Blue CPU Plus do?

It used the shared memory model. The manual specifically notes that the card can double as a 64K memory expansion; if you already have 640K then it goes in upper memory somewhere. (Factory default is E0000.)

Something I've thought might be fun to do if you had a card like this would be to emulate *other* Z80 platforms on it. Specifically I think it'd be pretty easy to do a minimal TRS-80 emulation; load the 12K TRS-80 ROM into the bottom of memory, and have your driver software periodically read the memory mapped video buffer at 3C00-3FFF and copy it to the video buffer. (If you were running this on an EGA, VGA, or other video card with user definable character sets you could even load a TRS-80 font so you could do TRS-80 semigraphics directly; that should speed things up significantly over having to draw them in graphics mode.) The TRS-80 also has a memory-mapped keyboard at 3800, which would let you simulate keypresses by writing values into the RAM on the Z80 card at the corresponding keyboard row addresses. (This does get a little hairy, though, because the way the TRS-80's keyboard scan works lets it read multiple rows at once.)

(The Model I even has a memory-mapped disk controller and printer port, so in *theory* at least you could even have the driver software emulate those, although, again, there are asterisks here that would probably require you to add hardware to the card to make it halt/wait when certain addresses are written and trigger an interrupt.)
 
Back
Top