S100 Computers

Home S-100 Boards History New Boards Software Boards For Sale
Forum Other Web Sites News Index    
  
Bringing Up CPM86+ for the First Time
Bringing up CPM86 (using an 8086 S-100 Board) can be a somewhat daunting task for beginners.  Not only is the hardware different and you have to worry about its (often untested) functionality, but the software is an order of magnitude more complex.  On top of that you have a kind of chicken and egg situation in that you need a functional running 8086 system to build a system.

Way back in the early 1980's Digital Research put out its CPM86 (V1.0) operating system to run on such 8086 systems.  It was functional, reliable, but was really just a warmed over CPM (V2.1).  There were none of the very nice "extras" you had in CPM3 (also called CPM+).  Once the latter was published there was a ground swell for the equivalent operating system for the 8086. It was developed in 1983 and was called CPM86+ or CPM86 Plus.   It had all the nice interactive features of CPM+.
These features included:-

Disk performance, especially random I/O, was improved over that of CP/M-86 v1.0 by hash coding the directory entries and Least Recently Used (LRU) buffering of directory and file data.

The BDOS performed auto-login of removable media drives. The implementation of door open interrupts on removable media drives was highly recommended as an additional check on data integrity and for providing disk I/O performance improvements of up to 30%. The door open interrupt information allowed the BDOS to treat removable media drives in a manner similar to permanent media drives.

The file system capacity was larger allowing a storage capacity of up to 512 megabytes for each of the 16 possible logical drives, and the maximum file size was 32 megabytes. The file system also provided time and date stamping.


Live control characters and type-ahead were supported by cooperating routines in the BDOS and BIOS. The live control characters were CTRL-C, CTRL-S, CTRL-Q, and CTRL-P and their functions were performed when a keyboard interrupt occurred.

The CCP could be a permanent part of the system or loaded as a transient program. When the CCP was a transient, it  was loaded and remained in memory until the memory was needed by another transient program.

The mapping of the logical devices CONIN:, CONOUT:, AUXIN;, AUXOUT:, and LST: onto different physical devices was standardized and made more flexible. This allowed the dynamic remapping of the console to another device, such as a graphics console. Logical device output could be directed to several physical devices at once.

CP/M86+  could run up to four programs (processes) at once, one in the foreground and up to three in the background. However only the foreground program had access to the physical console; the background programs had to have console I/O redirected from and to files.

The interface to hardware drivers was greatly simplified and improved by use of a BIOS Kernel. The Kernel was intended for unchanged use in any BIOS implementation. However, the source was provided if you need to alter the Kernel.

The BDOS performed Blocking/Deblocking instead of the BIOS. BIOS disk reads and writes transferred physical sectors and up to 16 Kbytes on each call.$ GENCPM created the CP/M86+ image contained in the CPM3.SYS file and provided many configuration options. GENCPM could automatically all allocates buffers while building the system image. This allowed the testing of many combinations of disk and directory buffers enabling the system implementer to optimize disk performance and memory usage.


For a single user efficient operating system this really was what CPM should have been all along.  As we shall see below it was a joy to write a BIOS for its very simple and symmetrical interface. 

However there was one very serious disadvantage -- you had to have a functional CPM86 (V1.0) system up and running to build a CPM86+ system.  This is because the building process requires RASM86 & LINK86 (a CPM86 reloadable assembler & linker) and it also needs CPM86 to run the program "GENCPM" which actually splices together the code modules (interactively) to make the final operating system.

This means you must first build a CPM86 (V1.0) operating system. That thing is primitive, I can assure you, you will count the hours until you have a CPM86+ system going and never go back!   However the one thing CPM86 (V1.0) had going for it was you could construct a CPM86 BIOS on a Z80/8080 CPM system. Digital Research  provided ASM86.COM, an 8086/8080 cross assembler for this purpose. They went even further and provided XLT86, an 8080 program that (crudely) converted 8080 assembly source (but not Z80) code listings into the equivalent 8686 ones. Useful for writing your first 8086 CPM BIOS.

Build CPM86 Plus - The Process
So this is the process: We will construct an absolutely stripped down version of CPM86 utilizing our ZFDC Floppy disk controller board utilizing only 128 byte sectors on a  SSSD IBM format 8" disk.  We will allow for two disks A: & B:

The reason we don't utilize the faster IDE board (or other larger disk formats) is that CPM86 requires sector buffering for sectors larger that 128 bytes in the BIOS. This is somewhat complicate for beginners.   We will then utilize this basic CPM86 system to construct a CPM86+ system on our Dual IDE board system.  From then on all CPM86+ system improvements/disk additions will be from that board. CPM86+ handles any disk format with any sector size within its own DOS kernel -- you never have to worry about those things in CPM86+ as we will see below.

Now there is one possible shortcut.  If you can find a CPM86 system (on the web) that runs on an old IBM-PC box and it boots OK you can go directly to the second step below.   While I did not look extensively, I did not find a good CPM86 (or emulator) that would work with my current Windows 7 hardware.  BTW, your system must have a 1.2M 5" floppy disk (CPM86 came out before 1.4M, 3" floppies).

One final unusual twist on this story....  It turns out that Digital Research never actually officially released CPM86-Plus.  Because of competition from MS-DOS at the time, they wend directly to "Concurrent CPM86".  This was a more powerful operating system allowing multiple independent tasks to be run at once.  However it is much more difficult to implement and probably not for most beginners, certainly not for a non IBM-PC box initially anyway.  BTW, our CPM86+ signs on with a serial number of 0000-00000-0000!

Nevertheless the "unofficial" CPM86+ version has been around for years and is quite popular. I looks like it was released in some kind of official version in Europe with a few different non IBM-PC machines. It behaves at a user level almost identically to CPM3.  Most importantly both operating systems can share the SAME disk and files.  Documentation however was less common. I managed to track down a hard copy of the (unpublished) CPM86+ Installation Guide I had from 30 years back!  Here is the .PDF file:-

CPM86 Plus Operating System Installation Guide.

You really must read this (well documented) guide very carefully to understand the BIOS.  It contains everything you need to know to put together a very fast and efficient disk operating system and unlike earlier Digital Researches earlier documentation is well written.

Step 1:  Building CPM86 (V1.0)
The BIOS for CPM86 is very similar to the CPM (V2.0) BIOS.  As I said  above, both the systems assume all disk sectors are 128 bytes in size. If you use larger sectors you must do a two step process of working with larger sector in memory and then passing 128 byte sections of it to/from the BIOS.  Since we are going to using a one time only "quick & dirty" system, we will utilize only the very standard CPM 8" SSSD 128 byte floppy disks on our ZFDC.  This approach should work for any S-100 FDC board.

The source listing for this BIOS can be obtained here.
All the files necessary to build the operating system can be downloaded here
There is there a submit file (FBIOS.SUB) that does everything automatically for you under CPM using the Altair CPM3 Emulator (see here).

If you have written CPM V1.0 BIOS's you will see there is nothing spectacular about the CPM86 BIOS code.

You will end up with a file FBIOS.HEX.  This is the "converted" .H86 File.  (Remember  the HEX file spewed out by ASM86 is not the usual Intel 8 bit standard HEX file but a ".H86" file that also contains segment information for the CPM86 linker).

However there is a bug in my H86TOHEX program that I have not had time to track down, (perhaps somebody else can).  The last line of the HEX file (still) contains segment information that confuses SID (see below). With an editor, you need to delete the last line of the FBIOS.HEX file and in its place put:-

:00000001FF

Then save the file as FBIOS.HEX.

Then run the MAKE86.SUB file.  FYI,  this submit file contains :-

SID CPM86-.COM
<RFBIOS.HEX,600
<WCPM86T.COM,100,3FFF
<^C

(then run) CPM86T.COM


Running CPM86T under CPM will launch your new CPM86 Operating system!

There is a little more to this this than appears on the surface. The image of CPM86-.COM actually begins at 600H in RAM. This is Digital Researches' true CPM86. We splice the BIOS directly on top of that and then save the whole image (100H to ~3FFFH) as CPM86T.COM.  Note how it is a CPM80 .COM file.  This means we can load it directly from any CPM80 disk with a Z80. When that is done the CPM80 jumps to 100H in RAM (just like any other CPM80 .COM file). Here it finds:-

JMP    4F0H 

at that location the Z80 will find:-

IN    EDH

This will cause the 8086 to take over the S-100 bus and put the Z80 is a hold state (at location 4F3H). 

The 8086 monitor check's to see if there are 90H's (8086 NOP's) in RAM  at 500H (indicating that CPM86 has probably been loaded) and then does a Far Jump to 500H in RAM.  The 8086 is in control now. It plows through some more NOP's until it gets to 580H in RAM. There it does a Far Jump into CPM86 itself (to 600H + 2500H or CPMINIT in the BIOS) never to return.

The reason for this somewhat roundabout process is that the first 400H bytes of RAM are always reserved for the 8086 Interrupt vectors. For the 8086, no practical code can be below 400H in RAM.   The reason for the gap between 400H and 600H (where CPM86 begins) is we need space to switch CPU and check CPM86 is in fact loaded.  This clearly would only take a few bytes, but in an early system I had I also utilized the powerful Intel 8089 I/O co-processor. A discussion on this is beyond the scope of this article, suffice to say the 8089 co-processor needed RAM as well.  The rest is history!

OK we are almost there.  Next we take a clean formatted IBM 8" SSSD disk and load a simple text file on it. The above FBIOS.A86 is a good one.  Then launch the CPM86T.COM  program from whatever CPM or CPM3 (Z80) you normally use. After some disk grinding, CPM86 should appear on your screen then following some disk grinding the A: should appear on the screen.

Enter TYPE FBIOS.A86   (or whatever test file you loaded on the disk). 

The file should display correctly with all the lines in the correct order.  If they are out of order, your sector/track numbering code is incorrect. 

Next rename the file.  It goes through correctly and you can still read the file with its new name your write sector function is probably OK.

Next reboot your old CPM system and load across the CPM86 files
PIP(V1).CMD
DD.CMD

and reboot COM86 again as above.

Check you can:-

PIP(V1) A:xxx.A86=FBIOS.A86[V]

If no errors you are in good shape.

Display the directory with

DD.CMD

The files sizes should match.

At this stage you probably have a correct and basically functional CPM86 system. Good enough to build CPM86+ on those 8" disks!

In case you run into problems I have written a self contained Diagnostic program to Read/Write to sectors on an 8" disk using the ZFDC Board.  That program ZFDCTEST.A86 can be seen and downloaded here. Neither the BIOS of Diagnostic program is "bullet proof", they are one time affairs, so don't assume everything has been tested. 

Here are the relevant files mentioned above:-
To view the FBIOS.A86 please click here
To download all components mentioned above click here


Step 2 Building CPM86+
We now use the above crude CPM86 Operating System to build our CPM86+ system.  This as I have to say above can be  a frustrating experience because disk space is limited and slow. You may have to switch files back and forth between your CPM80 disk(s) and the above floppies to get the job done.  [I have to admit here, I first used a 1MG memory disk (with 128 byte sectors), to do everything described below. I will not describe that here because these boards are not common, and writing an CPM86(V1.0)  8086 BIOS is more difficulty than that for a standard 8" floppy].

Before we get started however read the Digital Research Documentation one more time. It will save you a lot of headaches later!
Also, if you are not familiar with Digital Researches concept of Disk Parameter Tables (DPB's) and Disk Parameter Headers (DPH's) go to my section on Bringing Up CPM3 where these are explained in detail.  It is very important you understand the relevance of the DPH and DPB tables in CPM86+.

Load all the files here on to your CPM86(V1.0) Floppy.

Let us look at the files we are going to work with in the submit file on that disk to build CPM86+:-

rasm86 bioskrnl $$szpz
rasm86 init $$szpz
rasm86 chario $$szpz
rasm86 clock $$szpz
rasm86 disk3 $$szpz
;
link86 bios-F[i]
;
GENCPM [AUTO]


We normally don't touch the bioskrnl.A86 file
The first thing we will do is edit the CPM86 modules INIT.A86 and CHARIO.A86.  You can look through the source code I supply. There is nothing special or unusual there.

The module CLOCK.A86 takes care of system interrupts and the Time/Date functions. We will leave them unused at this point.  BTW, CPM86+ really shines when certain interrupts are used . That said,  they are tricky to implement and definitely should not be in early versions of your system.

The main file is disk3.a86.   This file contains the complete CPM86+ BIOS module for the Dual IDE Board.  Please look through the code first by clicking here.

At the bottom you will see the two DPH tables for the two Disk Drives; Here is the one for the A: drive:-

@DPHA        EQU    OFFSET $
             DW     0000H        ;TRANSLATE TABLE (NONE FOR HARD DISK\CFCARD 0)
             DB     0,0,0H       ;SCRATCH AREA
             DB     0H           ;DOOR OPEN FLAG
             DB     0,0H         ;SCRATCH AREA
             DW     DPB0         ;DISK PARAMETER TABLE
             DW     0FFFFH,0FFFFH ;CHECKSUM, ALLOCATION VECTOR
             DW     0FFFFH       ;DIRECTORY BCB
             DW     0FFFFH       ;DATA BCB
             DW     0FFFFH       ;HASH TABLE
             DW     HDINIT0
             DW     HDLOGIN0
             DW     HDRD
             DW     HDWRT
             DB     0            ;UNIT 0 ON THIS CONTROLLER
             DB     0            ;ALWAYS CHANNEL 0
             DB     0            ;ZERO FLAGS AT THE MOMENT

If you have worked with CPM3 BIOS'es you will see this table is very similar.  We enter 0FFFFH's for the disk checksum vectors etc and allow GENCPM (see below) to calculate the values for you.

You will notice below the pointers to:-
The disk/hardware initialization routine for that particular disk
The disk login routine for that particular disk
The sector read routine for that particular disk
The sector write routine for that particular disk.

Different disks can utilize the same routines (or in the case of disk initialization, just return back to the BDOS). Two subtle points to keep in mind. The call to disk login is made only once (or after a ^C) and it is primarily there for hardware cases to determine and flag disk densities. It is NOT called for each sector read/write.

For sector reads and writes Digital Research took advantage of the 8086's ability to utilize the stack to pass values. As you can see all sector parameters are passed to the bios using the SS:[BP+Offset]. This is very clean and efficient. The offset values are:-
 
iopb_mcnt equ byte ptr 15     ;Sector count for multi sector R/W's
iopb_drive equ byte ptr 14    ;Selected Drive
iopb_track equ word ptr 12    ;Selected track
iopb_sector equ word ptr 10   ;Selected Sector
iopb_dmaseg equ word ptr 8    ;Selected DMA Segment
iopb_dmaoff equ word ptr 6    ;Selected Segment offset


So in a sector read routine if you wish to get the requested Drive you would in effect have-
 
 
MOV    AL, Byte Ptr 14 [BP]

What is really nice is that you can check and modify the value at the memory pointer directly.  CPM86+ utilizes the concept of multi sector reads and writes.  So instead or writing one sector at a time with each BIOS call, you can write a number of contiguous sectors to a disk all at once. The count of sectors to be written is passed as iopb_mcnt. We just decrease this value with each sector transferred.  Again see my code in the above example to better understand this.

The other table we need to construct in the BIOS is the DPB table.  This table describes the layout of each disk (sectors, tracks etc).  I describe it in detail in the CPM3 write-up, see here.   

For our first IDE Drive it looks like this:-

DPB0 EQU OFFSET $ ;DISK PARAMETER BLOCK
    DW 61         ;PHYSICAL SECTORS/TRACK (Note CPM3 uses LOGICAL 128 byte sectors)
    DB 4H         ;BLOCK SHIFT
    DB 0FH        ;BLOCK MASK (15)
    DB 0H         ;EXTNT MASK
    DW 0F2FH      ;DISK SIZE - 1 (3887)
    DW 3FFH       ;DIRECTORY MAX (1023)
    DB 0FFH       ;ALLOC0
    DB 0FFH       ;ALLOC1
    DW 8000H      ;CHECK SIZE (NONE)
    DW 1H         ;OFFSET
    DB 02H        ;PHYSICAL RECORD SHIFT FACTOR


Now there is no equivalent  RASM86 DISKDEF macro like there is for CPM3 to calculate these values.   The good news is that (with the exception of the first entry) the values are the same as those calculate for CPM3.  These values are in fact difficult to calculate for beginners. So the easiest thing to do is put together a macro for CPM3 (a 2 line assembly file) and use RMAC to run the macro. Look at the .PRN file and pick up the values.  For my IDE board with a CF card the macro is:-

DISKDEF 512,61,256,2048,1024,1,8000H
 
The above macro will generate the above table.  There is one highly critical difference between the two systems. In the case of CPM86+ the first entry is always the number of actual Physical sectors/track. ( In our case these sectors are 512 bytes in size).

In the case of CPM3 (and the macro generated),  the first entry is the number of Logical 128 byte sectors/track. In our case it would be 61X4 = 244.    This is a very common error beginners make.

The first entry aside, the DPB table values in your CPM86+ table must be EXACTLY the same as the DPB table values in your CPM3 system if both operating systems are to share the same disk(s).   If there are differences you will have untold problems in the future.  Often they don't show up immediately but over time, so be very careful.

Two other points while I am on sharing system disks:  CPM86+ can work with disk sizes up to 512MG/disk. The normal (DISKDEF) generated max size for CPM3 is 8MG.  Digital Research says you can "hand do" larger  CPM3 disks. I have never done this and would be interested if somebody else did.

Second, in their wisdom!, Digital Research names the final GENCPM generate operating file "CPM3.sys".  This of course is the same name as that of the CPM3 system file required to boot that system.  So... if you are building CPM86+ make sure not to have it in User 0 of your boot disk. Otherwise you will blow yourself out of the water on the next CPM3 boot.  Why the CPM86+ file was not called CPM86.sys is a complete mystery to me.

OK, so assuming we have assembled all our BIOS modules into .OBJ files. We next need to link them together.  We use the CPM86 (V1.0) LINK86 and an input file which I call BIOS-H.INP

The line:-

LINK86 BIOS-H[I]

reads the following (text) file:-

bios3.sys=
bioskrnl,
init,
chario,
clock,
disk3,
zero.l86[s,data [origin[0F00]]]


Don't worry about zero.l86 for now.  We end up with our critical CPM3.sys file (on the same A: floppy disk).

To make life easy Digital Research then provided a CPM86 based program called "GENCPM" that interactively configures the above CPM3.SYS file for your exact hardware makeup.  Its very similar the equivalent program in CPM3. It allows you for example to you to define your boot disk, how much memory to set aside for buffers etc.  The program will use a file called GENCPM.DAT as your default input values if you type :-

GENCPM [AUTO]

It will use the parameters in that file instead of you having to type them in each time.  Its intelligent enough that if you add a new disk, of make disk parameter changes, it will ask you for new GENCPM parameters.

The program will rename the above CPM3.sys to CPM3.old and write a new file CPM3.SYS containing all your updated parameters.

Again we are almost there! If you load this CPM3.sys file into RAM at 480H  with SID and have your 8086 after a reset do a far jump to 600H in RAM, CPM86+ will boot and you will have a perfectly operating system.  But that would be too simple!  We want to have the CPM3.sys file be bootable from CPM3 and do the switching in software.   So we pull the same stunt we did above for CPM86 (V1.0) above. 

My CPM3 MPATCH.SUB file will do all this for you and write the file CPM86x.COM on the floppy disk A:. Note it's now a .COM file and can be launched from any CPM (v1.2 or 3) system.  Its counting on two things. Your 8086 takes control of the S100 Bus whenever you input from port EDH and in doing so always does a far jump to 500H in RAM.

The first time you bring this IDE Board based CPN86+ system up be careful. Don't do anything that writes sectors to the disk. Read a file with text to be sure the sector read order is correct. Preferably a large file.  Next just rename a file. This writes to just one sector (minimizing potential damage). Check the file is gone.   Then PIP one file to another using a different name and the [V] (verify) option. Lastly put in a blank CF-Card in tee second drive and copy with verify a whole user group. It that is OK you probably have a basic CPM86+ operating system up and running. Enjoy!

With this functional CPM86+ system on your IDE drive you can now move everything across to a unique user number on your CF Card/Disk.

Step 3:  Adding Floppy Disks To CPM86+
Finally we will add floppy disk capability to our CPM86+ system.   You must first write a BIOS module exactly along the lines we described above for the IDE drives.  I have written one for a system containing two 8" IBM 128 byte sectors SSSD on drives B: and C: , a 5" disk on Drive D: (using the standard IBM-PC CPM86 Format) and a 1.44M 512 byte sectors DDDS disk on drive H: utilizing our ZFDC Board.  Note how simple it is to write such a BIOS using the ZFDC Board. We just send simple commands to the board. The onboard Z80/WD2793 does the rest!

The Source code for this ZFDC based BIOS (FLOPPY.A86) can be seen here.
All files necessary to construct a IDE + ZFDC CPM86+ system can be downloaded from here.
The CPM86+ Plus Operating System Installation Guide can be obtained here.
The CPM86 (V1.0), Systems Guide can be obtained here.

The links below will contain the most recent versions of the above software.
Note, it may change over time and may not correlate exactly with the text in the article above.

MOST CURRENT CPM86 (V1.0) SOFTWARE (06/21/2011)
MOST CURRENT CPM86+ (For IDE Drives Only) SOFTWARE (06/21/2011)
MOST CURRENT CPM86+ (For IDE & ZFDS Floppy Drives) SOFTWARE (06/21/2011)
CPM86+ CMD Files (06/21/2011)

This page was last modified on 02/04/2021