• Please review our updated Terms and Rules here

Writing a custom BIOS for CP/M

Mike_Z

Veteran Member
Joined
Dec 1, 2013
Messages
1,713
Location
Near Milwaukee Wisconsin
I am building a 8272 based FDC board for my 8080A computer. I want to be able to load CP/M 2.2, which I have the DRI license. The last few days I have been reading the DRI CP/M Operating Manual with respect to the cold start loader and the CBIOS. My questions are about the 8272 commands and the CBIOS calls. Seems that the CP/M jump table will only a few of the 8272 commands.

CP/M Jump HOME could use the 8272 Recalibrate, or the Seek commands (probably the seek).

CP/M Jump SELDDSK, Jump SETTRK, Jump SETSEC & Jump SETDMA would only set data for 8272 Seek, Read or Write

CP/M Jump READ would do a 8272 read

CP/M jump write would do a 8272 write.

The 8272 specify and recalibrate commands would be used in initialization.

The 8272 Sense drive status would be used to poll the 8272 prior to reading or writing to the MSR.

The remaining 8272 commands would not be used at all. Although I'm not sure about Sense interrupt status.

I'm guessing that the Cold Starter would need some rudimentary seek and read routines that would be stored in ROM on the computer. The CBIOS would then have these and the other 8272 commands which would be loaded from the disk. Am I correct in my thinking?

How does CP/M format a disk? Does it just use the write command, rather than the 8272 format a track command?

Mike
 
A cold start will mainly (after setting everything CBIOS related up) just load the first few sectors into memory and jump to the start of the code, and it is indeed likely to use the CBIOS commands for this.

CP/M disk-format programs are custom made to each system. They speak directly to the floppy-controller, and typically use special commands in the controller spesifically meant for formatting. An example from the FD1797 is the "write-track" command, but the 8272 must as you suggest use the more high-level format-track command. The standard read and write commands typically looks for a sector before the read/write is performed, but that's not possible on an unformatted disk; there simply aren't any sector information to look for!
 
This topic is also interesting for me as my Olivetti ETV 250 does not have a format utility. Would it possible to modify an existing format utility if I can provide the geometry of the format from existing floppy disks and the type of floppy controller? Maybe you also need something else, like base address of the controler, or whatever?
 
Last edited:
I might be over thinking this. Other than initialization, maybe all I need is a read and write command. The format can be accomplished with a write. Mike
 
The reasons for having format support outside of the BIOS is that you want CP/M to have the critical stuff without wasting memory space at the top of your 64KByte memory. The bigger CP/M gets, the less space is available for bigger games, programs and files you may edit.

CP/M therefore includes the FDC support to manage the directory, load from and write to floppies. With that you can load and execute programs to do other things from floppy. That also gives those floppy resident programs, the entire TPA memory block to utilize, allowing them to give better prompts, status and process displays.

So if you want a program to format new floppies or a utility to diagnose a floppy or drive, CP/M has enough in its BIOS and BDOS to load the file from floppy and execute it in the TPA memory block. Its a more sensible solution.

However.. systems designed for CP/M could have been improved if CP/M had written a version for banked shadow Eprom in say the top 4KB of memory. In this case CP/M would exist among several switchable pages of the Eprom and only occupy 4KB or the 64KB memory. In this case, given enough Eprom capacity and more banks, you could incorporate more of the CP/M commands in silicon, rather than needing a SYSTEM disk in one drive. Obviously you could boot CP/M from ROM too.

That would have been a nicer approach.
 
Last edited:
Currently I have a 2k editor at 62-64k of memory. The editor is something I wrote many years ago. It works nice for checking new things etc. The plan would be to modify it so that it will work with CP/M. Since most of the service routines are in this already, I can modify them a little and then add the read and write and initialization stuff for the BIOS. I'm just struggling a little with what commands I need from the 8272. Since the read and write need the track, head and sector info, I'm thinking that the 8272 seek command will not be needed at all. And should I need to format a disk I can write a separate utility for that and use it when necessary.

So I'm down to Initialization, which would be specify, recalibrate and sense drive.

Then just a read and write callable routine.

Mike
 
However.. systems designed for CP/M could have been improved if CP/M had written a version for banked shadow Eprom in say the top 4KB of memory. In this case CP/M would exist among several switchable pages of the Eprom and only occupy 4KB or the 64KB memory. In this case, given enough Eprom capacity and more banks, you could incorporate more of the CP/M commands in silicon, rather than needing a SYSTEM disk in one drive. Obviously you could boot CP/M from ROM too.

Isn't that what CP/M 3 and, for that matter, MP/M is all about? Put the complicated BIOS stuff in the XIOS region and then apply bankswitching?

But the awkward problem with PROM-ing big sections of the CBIOS is that if your peripherals change, it's not a matter of just booting a different CBIOS; you have to burn a new PROM--a much bigger undertaking. And you can't easily patch a PROM on-the-fly.

We used the PROM for the basic "load one sector" code and a set of diagnostics for the basic hardware. It used a 2732; 2764s hadn't been invented yet. In fact, with a good boot loader, you can even implement loadable device drivers and relocate the main OS code to fit optimally. We didn't do that with CP/M, but with our own OS, though doing it with CP/M is not beyond the realm of possibility.
 
Here is the 64K memory map that I think will work for my 8080A. Does this look correct? The top 2k contains my homemade editor which will also contain the cold starter code. Please forgive my Octal numbers, but it was how I was raised.

8080 Memory map (Octal)

000 000 - 000 002 Jump instruction to warm start entry point 362 003 b = 250 000
000 003 I/O BYTE
000 004 Current Drive number
000 005 - 000 007 Jump instruction to DBOS
000 010 - 000 017 Interrupt 1
000 020 - 000 027 Interrupt 2
000 030 - 000 037 Interrupt 3
000 040 - 000 047 Interrupt 4
000 050 - 000 057 Interrupt 5
000 060 - 000 067 Interrupt 6
000 070 - 000 077 Interrupt 7
000 100 - 000 117 Scratch area for CBIOS
000 120 - 000 133 Not Used
000 134 - 000 174 File Control Block
000 175 - 000 177 Default Random Record location
000 200 - 000 377 128 byte disk buffer
001 000 - 323 377 Transient Program Area
324 000 - 333 377 Command Line Interpreter
334 000 - 351 377 BDOS
352 000 - 367 377 CBIOS
370 000 - 377 377 MY Editor

Thanks Mike
 
Mike_Z said:
...I have a 2k editor at 62-64k of memory...

They used to be called "Monitor" programs, usually residing in the boot rom.

On power-up or reset, my Cromemco ZPU board forces three instructions into the Z80, "C3.00.XX" to immediately jump to dip-switch selected address XX00h for a Eprom/Rom to initialize and then offer a Monitor program for use.

As 64KBytes of ram became feasible, it was better to design shadow-roms to be enabled on power-up or reset and after it initialized the board, it would transfer a Monitor program assembled to run in high ram memory, and then jump to that Monitor. One of the first things it would do is disable the shadow-rom (put it back into the shadows) so that the memory was 100% ram which usually had no wait states.

That offered the user the chance to work from the Monitor or use a command to then launch CP/M from the floppy. That gave you a base level to work with if for example your floppy drive was not working. My Xerox 820s worked that way too.

The Osborne-1 uses a shadow-rom in its second bank that is capable of operating the floppy disk controller. The CBIOS can flip in that bank and use code in that rom, and thus reduce the size of the necessary BIOS.

That might be something to consider with your design.

JDallas said:
...However.. systems designed for CP/M could have been improved if CP/M had written a version for banked shadow Eprom in say the top 4KB of memory...
Chuck(G) said:
...Isn't that what CP/M 3...is all about?...

No.

...Prom-ing big sections of the CBIOS...you have to burn a new PROM--a much bigger undertaking...

RomDisks managed it. And people had to pay money to get them. Maybe the purchase was "a much bigger undertaking?"

Actually, I described CP/M itself being programmed so it could be Prom'd in, not just the CBIOS.

Think of it as CP/M organized like 2KB eprom flash-cards in a 4KByte high memory window including 2KB of system ram for CP/M to use. 60KBytes of ram for the everything else.

0000-EFFF: 60KB - System ram or TPA+page 0
F000-F7FF: 2KB - System ram used by CP/M
F800-FFFF: 2KB - Many selectable pages of 2K eprom running CP/M

That combined 4KByte window could support very large versions of CP/M without all the sacrifices DRI used to keep the CP/M code small. With flash-carding it, CP/M could get bigger and the TPA would always be 60KBytes. Those sacrifices would have been made moot and TSRs would have been a waste of time.

It would have removed the basic problem of CP/M being resident in ram memory.

Mike_Z said:
...Here is the 64K memory map...Please forgive my Octal numbers, but it was how I was raised...

Octal is like entering machine code onto an abacus. :)

Being a hardware engineer, I consider a memory map to be a good, necessary document to have - but it doesn't mean that the circuit is really doing what is intended. If you're having problems with a LSI chip, particularly when another LSI chip is also strangely affected, in my book you check the addressing circuitry first, and assume a bad chip needs to be replaced, last.

Check the schematic first (the plan), then check the circuitry (the implementation).

"Shotgunning" a new FDC chip in can be a shortcut... but that's a better bet with a proven design or board.
 
Last edited:
Well, the bankswitching scheme that I used a Fairchild 64x9 bipolar RAM (that was about the only thing fast enough in 1979); memory was mapped as 1K pages for the full 64K space; possibility to support 256K using 4116s, with an 8202 controller. If you can switch RAM pages in and out, why bother with ROM? The advantage is that you can put your BIOS and your BDOS+CCP pretty much outside of the TPA of the executing program. All you need is a short jump table to swap the correct bank in. Even CP/M 3 does it in banked mode, requiring less than 4K for the resident BIOS and BDOS (and that's a much augmented BDOS, with time and date functions).
 
I appreciate that bank switching is neat stuff and will provide more memory, but it's a complication that I don't need right now. So maybe after I get this thing working I can always make an improvement like this. I'm struggling with exactly how a sector read will be accomplished with the 8272. The 8272 read needs 9 commands input-ed prior to the execution phase. Prior to this all the information needs to be set. Track, sector, drive, DMA address, etal. Once in the execution phase the 8272 and DMA controller should move data to memory. When the 128 bytes are transferred the 8272 should issue an interrupt indicating that the execution phase has ended and the result response is needed. I'm confused as to what to do here. The documentation says that a Sense Interrupt Command is needed here, maybe multiple SIC's to service all interrupts, but shouldn't the results of the read be serviced also? Which should be done first, or is the fact that a physical interrupt is serviced negate the need for the Sense Interrupt command? Does the physical interrupt routine handle all the result stuff and clear all the interrupt requests? Thanks for all the input, Mike
 
Chuck(G) said:
...If you can switch RAM pages in and out, why bother with ROM?...

Eproms are non-volatile storage whereas ram is volatile. If you want it there when you power up, you use roms.

The ultimate goal of this discussed Never-Version of CP/M is to (1) avoid the need of a system floppy in the floppy drive used to access commands that could be included in this rom based implementation and (2) to remove the CP/M grow-down infection into system ram. Rom-based full CP/M also provides immediate power-up access.

This may even have made single drive systems useful and thus offset the cost of the rom, though I think a two disk system would be better for job tasking like Word-Processor Package in A:, Files workspace in B:.

In this discussed design, for DRI to have supported back in the day, eprom would have held the size-unlimited tiny-portal-rom-bank version of CP/M for its non-volatile storage. A Rom/RamDisk board from 1986 that I studied recently, provided 512KB of eprom and dram in 128Byte pages in the 64KB address space and proves the technology was system-cost-effective then. It could even use the dram 256KB to run without wait states.

JDallas said:
...However systems designed for CP/M could have been improved if CP/M had written a version for banked shadow Eprom in say the top 4KB of memory...
Chuck(G) said:
...The advantage is that you can put your BIOS and your BDOS+CCP pretty much outside of the TPA...
Yes, that's what I said. Resident CP/M is the BIOS+BDOS+CCP. What I've described in my messages herein is that it could hold all of that and the system disk utilities as well, since the banked roms can be very deep and never encroach upon the TPA. The TPA in my example would always be 60KBytes, even if CP/M wrote a version twice as big.

...Even CP/M 3 does it in banked mode, requiring less than 4K...

Actually the spec of banked CP/M was quite loose on configurations. The common bank was limited to 32KB or less, and the number of RAM bank pages were limited with 16 to 3 of size 64KB minus the common bank.

I think banked CP/M was more of a pipe-dream to make CP/M relevant for the future. The allocations in banked CP/M are not particularly well thought out, being a lot of buffers and stream reserved space.

Mike_Z said:
...I appreciate that bank switching is neat stuff and will provide more memory, but it's a complication that I don't need right now...

I agree about it being an unnecessary complication now but its not complicated circuitry. All you need to change a page, is a latch to set the upper address lines of the rom-space.

In a simplified example you'd use a '374 to set 8 high address lines from values 00 to FF (256 pages) and change the '374 value via I/O port preferably of even memory-mapped. The lower address lines would be of the portal size (2KB = A00-A10) and the rest of the A11-A15 of the system address would by to detect the 2KB block in high memory... in my example the 5 most significant address lines of the address F8 all being high to CS the rom-space.

Of course as your design is a modern design, you'd just use Nor Flash Rom (externally addressable) rather than vintage obtuse Eproms of that era. I use several 8MBytes Nor Flash Roms in my project simply because at $1.84 a chip, it would be foolish not to use them as they're faster than just relying on the more copious storage of the Nand Flash Roms (GByte range but not directly addressable).

That one cheap chip 8MB Flash rom would use latched bank selects providing the Flash rom's A11-A22 address lines. Giving you 2K pages from 11 latched bank address lines. (I'll correct that later if I messed up the numbers.)

A 8MByte Flash rom would hold the 16KB+ CP/M with CBIOS with a 1.2MB system floppy with all of CP/M and tons of useful stuff filling the floppy up, plus about 4 more 1.2MByte floppies of stuff.

$1.84 for Five 1.2MB floppies in flash rom and no moving parts to maintain.
 
Last edited:
Of course as your design is a modern design, you'd just use Nor Flash Rom (externally addressable) rather than vintage obtuse Eproms of that era. I use several 8MBytes Nor Flash Roms in my project simply because at $1.84 a chip, it would be foolish not to use them as they're faster than just relying on the more copious storage of the Nand Flash Roms (GByte range but not directly addressable).

I think that Mike would agree that it's not a "modern" design. Were it so, he'd be just as well off running an emulator on a Raspberry Pi, which would have all sorts of advantages over crufty old hardware. I mean, good grief, if his is a modern design, why use 8" floppies or SSI TTL? On a good emulator, your BIOS is scarcely more than a jump table. And, while you're at it, the BDOS and CCP have source code available, so you may as well move them mostly out of the emulated memory space and run them in native mode.

I'm trying to limit discussion of hardware to the release dates of the software involved. So, 1978-1979 for CP/M 2.0-2.2, maybe 1982 for CP/M 3.0, about 1981 (I'll have to look to be sure) for MP/M.
 
Chuck(G) said:
...you have to burn a new PROM--a much bigger undertaking...
JDallas said:
...as your design is a modern design, you'd just use Nor Flash Rom...
Chuck(G) said:
...Mike would agree that it's not a "modern" design...

Its a modern design... he's doing it now; no time-machines are involved. It is "retro" in that it uses the classical constructs of the past. What that means is that he has options on a modern design that were not available in the '80s. Its his personal choice in a modern design, but you can't choose unless you're aware of the modern choices. Presenting the modern choice to use Nor Flash Roms instead of Proms allows a choice to avoid what your term "a much bigger undertaking."

Using Nor Flash Rom instead of Prom simplifies the design, even if its retro. Less parts to fail, no bother with special Prom programming sequences, less bother finding Eprom erasers, it can be rewritten quickly and easier to map into memory.

...I'm trying to limit discussion of hardware to the release dates of the software involved. So, 1978-1979 for CP/M 2.0-2.2, maybe 1982 for CP/M 3.0, about 1981 (I'll have to look to be sure) for MP/M.

As the discussion is about a version of CP/M that was never made, though feasible in 1986, you'll have a hard time documenting when DRI never did it.
 
As I said earlier, I appreciate the discussion regrading bank switching and maybe after I get this thing to work, I'll look into it. But now I have other fish to fry. This morning I re-tested my 8259 PIC. I have only one PIC and have set the FDC interrupt to IR1 which will jump to 000 010 Octal. Using a simple program I tested it and it works. After reading the documentation again for the 8259, I see that a End Of Interrupt is needed in the Interrupt Service routine, which I had forgotten about. Got that to work also.

Currently my 'Monitor' program is in EPROM 2716. It is a pain to reprogram but I can and have done it dozens of times. I recently ordered a couple of 28C16 EEPROM's and hope to figure out how they work and use them instead of the 2716 for the Monitor program. Kinda 'Modernizing' the machine.

Reading more about the 8272 read command, I think my understanding is that when the 8272 issues an interrupt, indicating that the execution phase has ended. The CPU jumps to the interrupt service routine which issues a Sense Interrupt Status Command. The results of this command then describes the type of result phase response is needed. Am I thinking correctly?

Thanks Mike
 
Yup, you've got it pretty much. Note that the data transfer commands deliver status results right after the interrupt--there's no need to issue s SIS--just read the results. However, you do want to do a SIS with seek commands (includes restore) to clear the interrupt.

The best way I've found to handle this is to unmask the FDC interrupt and clear a memory fllag when issuing a command. When you get an interrupt, mask the FDC interrupt again, set the flag issue the EOI and return from interrupt. That removes the possibility of spurious interrupts and makes your ISR very short and sweet. Needless to say, you poll for the in-memory interrupt flag and assume you have a hang or not-ready condition if too much time elapses.

Also note that generally, you can't fire out a SIS and read immediately--I think it's 50 usec. has to delay between the command issue and readable results.
 
Dallas, I don't have a URL, just a paper copy of Intel Peripheral Design Handbook August 1981. My cpu is a 8080A. I only have use for one interrupt, the one for the FDC. My DMA 8237 will transfer the data to memory.
Chuck, a 8272 read command has the track, sector info in it, does this negate the need to do a seek altogether? I figure that a recalibrate command right after initialization will set track 00, then a read or write will move to that track and sector? Mike
 
Seeks must be explicit on the 765/8272. Later incarnations of the chip feature implied seek, but that's not what you're working with here.

A restore (assuming that it results in the track 0 flag being set) puts you right in the place to load from the first track--i.e. no explicit seek required. Note that the cylinder number in a sector address header need not have any particular relationship to the physical cylinder number. This is used to advantage in the PC-AT in "360K" mode on a high density drive--the physical cylinder number is double that of the "logical" cylinder number recorded in 360K address ID fields.

Which reminds me--after a reset, the 765 does a restore on each of the 4 unit selects. So it's necessary to wait for them to complete and then issue a SIS to clear any pending interrupt. The 765 also polls each of the 4 drive ready signals after that. Note that you can issue seeks for 4 drives at the same time--they happen concurrently.

The 765/8272 is the cat's meow for 8" drives. 5.25" not so much. I don't know if you have an external register that allows you to toggle the reset line on the 765; it's worth having, to kick an unresponsive chip into action again.
 
Last edited:
Excuse me, I have not really digested your last post, but I'm tickled to say, I received a couple of 28C16 EEPROM's in the mail today. I made a change to my memory board. So I can either connect the 28C16 Pin 20 OE to ground (Normal) or to the MEMR. I wrote a short program and I successfully programed the EEPROM with my monitor program. I've got to say pretty slick, cookin with gas! Thanks for the suggestion. I'll read your post after supper. Mike
 
Went back to the book. I found where they say the FDC can not do implied Seeks. Apparently a cylinder error will occur. Have not found any thing about the RESET doing a restore. Not to say that isn't true. Well, my replacment 8272 didn't come today so I can only read and think about it. Maybe next week I can try some real stuff. I'm sure i have a million questions to ask. Thanks Mike.
 
Back
Top