• Please review our updated Terms and Rules here

Experience of a DMA-less Tandy 1000

Great Hierophant

Veteran Member
Joined
Mar 22, 2006
Messages
1,928
Location
Massachusetts, USA
All my Tandy 1000s have a DMA chip built in which cannot be disabled. I have never experienced a DMA-less Tandy, which are the 1000/A/HD/EX/HX. I would like to know if there are any differences between a DMA and a DMA-less system.

The Tandy was derived from the PCjr., which eliminated the DMA chip found in the IBM PC. In the IBM PC, the DMA chip served two purposes. First, it was programmed to access the memory every so often to refresh the contents of the DRAM chips using DMA Channel 0. DMA Channels 1, 2 and 3 were available for use by expansion cards on the ISA bus. IBM's floppy controller used DMA Channel 2 to allow the floppy drive controller to transfer data to and from RAM with minimal CPU intervention, so essentially that channel was reserved.

On the IBM PCjr., RAM refresh is handled by the video controller for the internal RAM and a refresh controller for expansion RAM. This causes internal RAM performance to be very poor because the CPU and the Video Controller are always in contention for access. Expansion RAM is not affected by this issue. As far as the floppy controller goes, the CPU must devote its attention to data transfers due to the lack of DMA. It ignores keyboard input during a floppy controller to ensure it has enough time to service the floppy controller's datastream. In another machine, this may not have been an issue, but in the PCjr., the CPU must also deserialize the keyboard data. This function was performed by a serial to parallel decoding chip in the IBM PC. Upgrades that offer DMA functionality are not the most reliable on a PCjr.

The Tandy 1000's video controller is designed to refresh the 128KB on its motherboard. I believe that the video controller on the EX, HX and SX can refresh 128KB or 256KB. Tandy indicates that any memory upgrade above 128KB must have a DMA controller, which takes over the refresh for the extra RAM. If you only have DMA-less memory expansions, they may not work reliably in the absence of a regular refresh signal provided by the DMA chip. However, an upgrade like this : http://www.ebay.com/itm/Duo-Slot-51...00-1000A-or-1000HD-Memory-Board-/272770380504 should not be affected because it uses SRAM, which can hold its contents as long as it has power.

The Tandy has dual ported RAM, so there are no issues with performance loss in a system that must share RAM access between CPU and DMA controller. It also does not need the CPU to deserialize keyboard data. I am not sure that DMA speeds up disk access, and given the single-task nature of DOS, if you are waiting on disk access, you are not doing much else. So is the only issue people likely to encounter some dropped keystrokes during disk access?

Obviously, some expansion cards, like 8-bit MFM and RLL hard drive controllers and Sound Blaster cards, are not going to work in a DMA-less Tandy. But a Sound Blaster does not fit in an EX or HX and XT-IDE does not require a DMA channel. There are only 3 expansion slots on an 1000/A/HD and there are better upgrades for a system of that speed.
 
Your experience matches mine and I believe your summary and conclusions are 100% accurate. I've never noticed lost keystrokes on a 1000A during disk access, but I can't imagine many situations where I would have been typing while doing floppy I/O.

DMA is more critical for performance on multi-tasking OSs. A process blocked on disk I/O can sleep while a DMA transfer is happening and the CPU can devote it's time to another task. In DOS, an 8237 is pretty pointless for anything other than fire and forget I/O like pushing buffers to a sound card; especially with it's memory to memory limitations. Int 13h routines are blocking synchronous calls by nature. Most int 13h routines either a) spin-loop checking disk status, b) perform a PIO transfer directly with a rep or loop, c) program DMA and spin-loop checking transfer complete, or d) a combination. You could get some bus cycle efficiency with DMA if you halted the CPU while transferring waiting on an interrupt from the disk controller to indicate completion. I believe James Pierce demonstrated this with a DMA based XT-IDE. However... disk I/O is still a blocking synchronous call in DOS. DMA doesn't buy much.
 
Your experience matches mine and I believe your summary and conclusions are 100% accurate. I've never noticed lost keystrokes on a 1000A during disk access, but I can't imagine many situations where I would have been typing while doing floppy I/O.

DMA is more critical for performance on multi-tasking OSs. A process blocked on disk I/O can sleep while a DMA transfer is happening and the CPU can devote it's time to another task. In DOS, an 8237 is pretty pointless for anything other than fire and forget I/O like pushing buffers to a sound card; especially with it's memory to memory limitations. Int 13h routines are blocking synchronous calls by nature. Most int 13h routines either a) spin-loop checking disk status, b) perform a PIO transfer directly with a rep or loop, c) program DMA and spin-loop checking transfer complete, or d) a combination. You could get some bus cycle efficiency with DMA if you halted the CPU while transferring waiting on an interrupt from the disk controller to indicate completion. I believe James Pierce demonstrated this with a DMA based XT-IDE. However... disk I/O is still a blocking synchronous call in DOS. DMA doesn't buy much.

Any word processor implementing a virtual memory system could lose characters while trying to save the entered data to free up space. No autosave either.

The intractable problem with the lack of DMA is that it is impossible to log incoming data onto disk. That had to make using CompuServe expensive since the cheap way to browse a forum was to send a bunch of commands, grab all the data, log off and then start reading.
 
With my XT-IDE and any Tandy I own, when I do a first DIR, DOS will calculate the free space and make me wait until it is done. I can type anything I want, but once I hit the keyboard buffer's limit (16 characters), I will lose anything else after that. My XT-IDE CF does not support DMA transfers.

However, with my IBM PC-XT, I have an MFM controller card, the WD W1002-WX1, attached to an ST-225. The card is common and supports DMA transfers. I believe the same result occurs, even though the time is shorter because DOS has to calculate the number of free sectors of a 20MB drive instead of a 512MB drive.
 
I ran a BBS off an HX with one floppy drive (Searchlight, earlier version) and 256k of RAM. I didn't have a clue what I was missing, but that was the last non DMA machine I owned.
 
I don't think it's possible to use a high-density floppy controller on a DMA-less machine. Micro Solutions, for example, pretty much said "forget it".
 
So is the only issue people likely to encounter some dropped keystrokes during disk access?

Well, in 8088 MPH we exploit the fact that floppy transfers run 'in the background' via DMA, so that we can play our music and show some bouncing text on screen while the next part is loading (on the PCjr it will just freeze while the floppy is running).
This kind of thing was very common with many other computers, such as C64 and Amiga, but I don't think many PC games did this.
With DMA you can even perform streaming audio from floppy or HDD on an 8088 machine.
Here's a Tandy/PCjr VGM player that streams from disk (but some parts are too sample-heavy for the floppy to keep up), allowing you to play music files that are larger than would fit into memory:
I've done a similar thing for streaming PCM/PWM data to PC speaker or Covox.
So you'd be missing out on this sort of stuff with a PCjr or DMA-less Tandy.
But I don't know of any games or other software that did this sort of thing back in the day.
 
Scali,

How are you getting floppy access to background with int 13h being a blocking synchronous call? Are you going directly to the floppy controller?

And as long as the floppy routines can keep up with your program and not let buffers underflow, if you are transferring audio buffers via DMA to a sound card (not possible on PCjr) via an ISR and calling int 13h in the foreground, why would anything lock up?
 
What about the parallel port-style floppy drives? They can't access a DMA channel from that port.

True, but if you'll take a look inside, say, a Micro Solutions Backpack drive, you'll see an MCU, a floppy controller and a 16KB SRAM chip. Disk data transfers occur between the SRAM buffer and the FDC. The MCU handles the conversation between the host PC and the FDC and the SRAM.

So basically, one of these parallel port drives already has its own processor--and that's what you're talking to. It would certainly be possible to implement an ISA or PCI floppy board that worked the same way, thus removing the issue of legacy DMA, but I doubt that will ever happen.
 
I've never noticed lost keystrokes on a 1000A during disk access, but I can't imagine many situations where I would have been typing while doing floppy I/O.

That's not related to DMA; it's because the PCjr does not have a dedicated keyboard controller (the CPU did all the work), while the Tandy 1000 series does. A real PCjr will absolutely not even try to read the keyboard during disk access; the ISR is changed to one that just beeps at you and returns.

How are you getting floppy access to background with int 13h being a blocking synchronous call? Are you going directly to the floppy controller?

(8088 MPH loader writer here) No, it's flipped: The display routines and music are the background processes, serviced by an interrupt. The load-and-execute is the foreground process. The appearance to the user is that the loading and executing is in the background because they're watching bouncing letters and music while it loads, but I/O is actually the foreground process. This was done intentionally to maximize compatibility with unknown controller configurations and storage devices by using bog-standard INT 13h calls, although in the end the decision was moot because we had focused on a very specific performance target (4.77 MHz 8088, floppy disk).

That doesn't mean you can't make I/O a background process -- you can, even with BIOS calls. You just have to be crazy careful about re-entrancy, and DMA is practically a requirement for it to be seamless.

Direct drive access through the NEC765 controller can also be true background transfers. For brilliantly-engineered program examples that do this very well, try the original Norton Backup or the original Fastback. They format+write to floppies while simultaneously reading from the hard drive and compressing the data before it gets to the floppies, all on stock hardware.

And as long as the floppy routines can keep up with your program and not let buffers underflow, if you are transferring audio buffers via DMA to a sound card (not possible on PCjr) via an ISR and calling int 13h in the foreground, why would anything lock up?

It doesn't; I've successfully read audio data from a floppy disk (IRQ 1, DMA 2) and piped it to a Sound Blaster (IRQ 7, DMA 1) realtime on a 5160 without any issues. Of course, you need a buffer area to account for uneven floppy transfer times.
 
Background diskette access--my old CONFMT program was pretty cool in its day. Then, of course, there's SYDUPE - able to run three floppy controllers simultaneously. It sort of became a fossil when Windows took over.

It's all in the software. :)
 
(8088 MPH loader writer here) No, it's flipped: The display routines and music are the background processes, serviced by an interrupt. The load-and-execute is the foreground process. The appearance to the user is that the loading and executing is in the background because they're watching bouncing letters and music while it loads, but I/O is actually the foreground process. This was done intentionally to maximize compatibility with unknown controller configurations and storage devices by using bog-standard INT 13h calls, although in the end the decision was moot because we had focused on a very specific performance target (4.77 MHz 8088, floppy disk).

Indeed, to add to that: the 'background' is not really a process, but a timer interrupt handler.
For the 8088 MPH loader we just fire at 60 Hz for the music, and every other tick, the screen is updated (so 30 fps).

My VGM player and PCM/PWM routines also use the timer interrupt, but at much higher rates than 60 Hz. Depending on the speed of your HDD, you can play 8-10 kHz PWM data to the speaker in realtime, perhaps even more, on standard IBM 5160.
The VGM player does not have a fixed rate. Instead the VGM is preprocessed into PIT ticks and command blobs. It sends a blob of SN76489 commands, then reprograms the timer interrupt for the next blob (you have to be 'one ahead' to get around the fact that the PIT is latched, so it will countdown to 0 before the new countdown value becomes active). More information can be found here: https://scalibq.wordpress.com/2017/02/24/putting-the-things-together/
This works well enough to even play the Skate or Die music, which uses a combination of samples and 'regular' SN76489 channels (it plays the samples on the SN76489 as well, so it does not require a Tandy DAC or anything). I haven't analyzed the data in great detail, but I suppose the samples played will be at least 3-4 kHz, possibly more.

And yes, DMA is pretty much a requirement, because the DMA controller will get precedence over the CPU on the bus. This ensures that you do not lose any data.
Another requirement is that the disk transfer routines enable interrupts. If they didn't, then the timer interrupt could not have been serviced.

An additional trick I use here is that I put the PIT in auto-EOI mode. This means that I don't have to manually send the EOI command to the PIT after every timer interrupt, which saves a few precious cycles.
And yet another trick is that the data is loaded into a 64k segment, which is basically a circular buffer, with the 16-bit pointer automatically wrapping around. The interrupt handler is actually placed inside that 64k segment, so that you can access the data directly with cs:, saving more cycles (not having to save and restore ds to access the data).
This means that periodically you have to move the handler to another part of the buffer, because it will get overwritten with data.
Remarkably everything just works.

But sadly you can't do any of that if you don't have a DMA controller. There's no way to get new data in there 'for free'. On a PCjr the floppy routines do not enable interrupts (which they can't, because they have to poll the floppy controller for every single byte that comes in). I assume the same goes for the Tandy. So that means you can't keep your timer interrupt going during disk access.
Which means you'll have to turn things around, and try to do the disk access itself on a timer interrupt. I want to try that someday. In theory it should be possible to synchronize a timer interrupt to the incoming data, and make some kind of 're-entrant' disk reading routine, which wakes up shortly before a byte comes under the head, then polls the status register to wait for the exact moment, grab a single byte, and return.
A 5.25" DSDD floppy is:
- 300 rpm
- 40 tracks
- 9 sectors per track
- 512 bytes per sector
- 2 sides
- 368640 bytes

So that would mean a data rate of ~(300 * 9 * 512) / 60 ~= 23040 bytes/second.
Keeping up with every single byte is not realistic, but if you can get it to read every 3rd or every 4th byte or so, then that may just be possible.
I wonder how well the PC floppy interface can deal with that.
I know on C64, Amiga and Atari ST they could do pretty crazy things with the floppy controller and custom disk arrangements, like writing data to the disk in a way that they would read from a single side first, in one go, stepping to the next track everytime in one fluid motion. Then going back on the other side in the same way.
So you would actually hear it 'ticking' away at 5 tracks per second or so.
 
Scali said:
I wonder how well the PC floppy interface can deal with that.

Not well--the first "lost data" occurrence with cause the current operation to be aborted. I've tried.

It's undoubtedly why legacy DMA hung on so long. On modern systems without a floppy controller, I think that capability has totally disappeared.
 
Legacy DMA is still present on modern motherboards with parallel ports. DMA channel 3 is still used by the ECP mode.
 
Not well--the first "lost data" occurrence with cause the current operation to be aborted. I've tried.

Ah, that's a shame.
Do you know when the controller concludes "lost data"? As in, is it when it sees nobody polling the status register, or is it when there's a byte available which has not been read?
As in, in the latter case you might get away with not polling the status register, but just doing 'dummy' reads.
 
Back
Top