.MB +5
.MT -3
.LL 65
.PN 85
.HE MP/M User's Guide
.FT   (All Information Herein is Proprietary to Digital Research.)
.sp 2
3.  MP/M ALTERATION GUIDE
.sp
.pp
3.1 Introduction
.pp
The standard MP/M system assumes operation on an Intel MDS-800
microcomputer development system, but is designed so that the user
can alter a specific set of subroutines which define the hardware
operating environment.  In this way, the user can produce a diskette
which operates with any IBM-3741 format compatible diskette subsystem
and other peripheral devices.
.pp
Although standard MP/M is configured for single density
floppy disks, field-alteration features allow adaptation to
a wide variety of disk subsystems from single drive minidisks
through high-capacity "hard disk" systems.
.pp
In order to achieve device independence, MP/M is distinctly separated
into an XIOS module which is hardware environment dependent and
several other modules which are not dependent upon the hardware
configuration.
.pp
The user can rewrite the distribution version of the
MP/M XIOS to provide a new XIOS which provides a customized interface
between the remaining MP/M modules and the user's own hardware
system.  The user can also rewrite the distribution version of the
LDRBIOS which is used to load the MP/M system from disk.
.pp
The purpose of this section is to provide the following step-by-step
procedure for writing both your LDRBIOS and new XIOS for MP/M:
.sp 2
(1)  Implement CP/M 2.0 on the target computer
.pp
To simplify the MP/M adaptation process, we assume (and STRONGLY
recommend) that CP/M 2.0
has already been implemented on the target MP/M machine.
If this is not the case it will be necessary for the user to
implement the CP/M 2.0 BIOS as described in the Digital Research
document titled "CP/M 2.0 Alteration Guide" in addition to the
MP/M XIOS.
The reason that both the BIOS and XIOS have to be implemented is
that the MP/M loader uses the CP/M 2.0 BIOS to load and relocate
MP/M.  Once loaded, MP/M uses the XIOS and not the BIOS.
The CP/M 2.0 BIOS used by the MP/M loader is called the LDRBIOS.
.pp
Another good reason for implementing CP/M 2.0 on the target MP/M
machine is that debugging your XIOS is greatly simplified by
bringing up MP/M while running SID or DDT under a CP/M 2.0 system.
.sp 2
(2)  Prepare your custom MPMLDR by writing a LDRBIOS
.pp
Study the BIOS given in the "CP/M 2.0 Alteration Guide"
and write a version which has a ORG of 1700H.
Call this new BIOS by the
name LDRBIOS (loader BIOS).  Implement only the primitive disk
read operations on a single drive, and console output
functions.
.pp
The first LDRBIOS call made by the MPMLDR is SELDSK: select
disk.  If there are devices which require initialization a
call to the LDRBIOS cold start or other initialization code
should be placed at the beginning of the SELDSK handler.
.pp
Note:  The MPMLDR uses 4000H - 6FFFH as a buffer area  when
loading and relocating the MPM.SYS file.
.pp
Test LDRBIOS completely to ensure that it properly performs
console character output and disk reads.  Be especially
careful to ensure that no disk write operations occur accidently
during read operations, and check that the proper track and sectors
are addressed on all reads.  Failure to make these checks
may cause destruction of the initialized MP/M system after it is patched.
.pp
The following steps can be used to integrate a custom LDRBIOS
into the MPMLDR.COM:
.pp
A.)  Obtain access to CP/M version 1.4 or 2.0 and prepare the
LDRBIOS.HEX file.
.pp
B.)  Read the MPMLDR.COM file into memory using either DDT
or SID.
.li

               A>DDT MPMLDR.COM
               DDT VERS 2.0
               NEXT  PC
               1A00 0100
.ad
.pp
C.)  Using the input command ('I') specify that the LDRBIOS.HEX
file is to be read in and then read ('R') in the file.  The effect
of this operation is to overlay the BIOS portion of the MP/M
loader.
.li

               -ILDRBIOS.HEX
               -R
               NEXT  PC
               1A00 0000
.ad
.pp
D.)  Return to the CP/M console command processor (CCP) by
executing a jump to location zero.
.li

               -G0

.ad
.pp
E.)  Write the updated memory image onto a disk file using
the CP/M 'SAVE' command.  The 'X' placed in front of the file
name is used simply to designate an experimental version, preserving
the orginal.
.li

	       A>SAVE 26 XMPMLDR.COM
.ad
.pp
F.)  Test XMPMLDR.COM and then rename it to MPMLDR.COM.
.sp 2
(3)  Prepare your custom XIOS
.pp
If MP/M is being tailored to your computer system for the first
time,
the new XIOS requires some relatively simple software development and
testing.  The standard XIOS is listed in APPENDIX I, and can be used as
a model for the customized package.
.pp
The XIOS entry points, including both basic and extended, are described
in sections 3.2 and 3.3.  These sections along with APPENDIX I
provides you with the necessary information to write your XIOS.
We suggest that your initial implementation of an XIOS utilize polled
I/O without any interrupts.  The system will run without even a clock
interrupt.
The origin of your XIOS should be 0000H.  Note the two equates needed
to access the dispatcher and XDOS from the XIOS:
.li

	       		ORG	0000H
	       PDISP	EQU	$-3
	       XDOS	EQU	PDISP-3
.ad
.pp
The procedure to prepare an XIOS.SPR file from your customized XIOS
is as follows:
.pp
A.)  Assemble your XIOS.ASM and then rename the XIOS.HEX file to
XIOS.HX0.
.pp
B.)  Assemble your XIOS.ASM again specifying the +R option which
offsets the ORG statements by 100H bytes.  Or, edit your XIOS.ASM
and change the initial ORG 000H to an ORG 100H and assemble it again.
.pp
C.)  Use PIP to concatenate your two HEX files:
.li

	       A>PIP XIOS.HEX=XIOS.HX0,XIOS.HEX
.ad
.pp
D.)  Run the GENMOD program to produce the XIOS.SPR file from the
concatenated HEX files.
.li

	       A>GENMOD XIOS.HEX XIOS.SPR

.ad
.cp 15
.ce
*** Warning ***
.pp
Make  certain  that your XIOS.ASM file contains  a  defined
byte  of zero at the end.  This is especially critical  if
your XIOS.ASM file ends with a defined storage.  The reason
for  this requirement is that there are no HEX file records
produced  for defined storge (DS)  statements.  Thus, the
output HEX file is misleading because it does not  identify
the  true  lenth  of  your  XIOS.  The  following  example
illustrates a properly terminated XIOS:
.li

	       begdat  equ     $
	       dirbuf: ds      128
	       alv0:   ds      31
	       csv0:   ds      16

	               db      0     ; force out hex record at end
	               end
.ad
.pp
Note  that  this  same technique must  be  applied  to  any
other PRL or RSP programs that you prepare.
.sp 2
(4)  Debug your XIOS
.pp
An XIOS or a resident system process can be debugged using
DDT or SID running under CP/M 1.4 or 2.0.  The debugging
technique is outlined in the following steps:
.pp
A.)  Determine the amount of memory which is available to MP/M
with the debugger and the CP/M operating system resident.  This
can be done by loading the debugger and then listing the jump
instruction at location 0005H.  This jump is to the base of
the debugger.
.li

	       A>DDT
	       DDT VERS 2.0

	       -L5

	       0005  JMP D800
.ad
.pp
B.)  Using GENSYS running under CP/M, generate
a MPM.SYS file which specifies the top of memory determined by
the previous step, allowing at least 256 bytes for a patch area.
.li

               ...
               Top page of memory = D6
               ...
.ad
.pp
Also while executing GENSYS specify the breakpoint
restart number as that used by the CP/M SID or DDT which you
will be executing.  This restart is usually #7.
.li

               ...
               Breakpoint RST #  = 7
               ...
.ad
.pp
C.)  If a resident system process is being debugged make
certain that it is selected for inclusion in MPM.SYS.
.pp
D.)  Using CP/M 1.4 or 2.0, load the MPMLDR.COM file into
memory.
.li

               A>DDT MPMLDR.COM
               DDT VERS 2.0
               NEXT  PC
               1A00 0100
.ad
.pp
E.)  Place a 'B' character into the second position of
default FCB.  This operation can be done with the 'I' command:
.li

               -IB
.ad
.pp
F.)  Execute the MPMLDR.COM program by entering a 'G'
command:
.li

               -G
.ad
.pp
G.)  At point the MP/M loader will load the MP/M operating
system into memory, displaying a memory map.
.pp
H.)  If you are debugging an XIOS, note the address of the
XIOS.SPR memory segment.  If you are debugging a resident system
process, note the address of the resident system process.  This
address is the relative 0000H address of the code being debugged.
You must also note the address of SYSTEM.DAT.
.pp
I.)  Using the 'S' command, set the byte at SYSTEM.DAT + 2
to the restart number which you want the MP/M debugger to use.
Do not select the same restart as that being used by the CP/M
debugger.
.li

               ...
               Memory Segment Table:
               SYSTEM  DAT  D600H  0100H
               ...

               -SD602
               D602 07 05
.ad
.pp
J.)  Using the 'X' command, determine the MP/M beginning
execution address.  The address is the first location past
the current program counter.
.li

               -X
               ....................... P = 0A93 .....
.ad
.pp
K.)  Begin execution of MP/M using the 'G' command, specifying
any breakpoints which you need in your code.  Actual memory address
can be determined using the 'H' command to add the code segment
base address given in the memory map to the relative displacement
address in your XIOS or resident system process listing.
.pp
The following example shows how to set a breakpoint to
debug an XIOS list subroutine given the memory map:
.li

               ...
               XIOS    SPR  CD00H  0500H


               -GA94,CD0F
.ad
.pp
L.)  At this point you have MP/M running with CP/M and its
debugger also in memory.  Since interrupts are left enabled during
operation of the CP/M debugger, care
must be taken to ensure that interrupt driven code does not
execute through a point at which you have broken.
.pp
Since the CP/M debugger operates with interrupts
left enabled it is a somewhat difficult task to debug an interrupt
driven console handler.  This problem can be approached by leaving
console #0 in a polled mode while debugging the other consoles
in an interrupt driven mode.  Once this is done very little, if any,
debugging would be required to adapt the interrupt driven code from
another console to console #0.  It is further recommended that you
maintain a debug version of your XIOS which has polled I/O for
console #0.
Otherwise it will not be possible to run the CP/M debugger underneath
the MP/M system because the CP/M debugger will not be able to get
any console input, as it will all go to the MP/M interrupt driven
console #0 handler.
.sp 2
(5)  Directly booting MP/M from a cold start
.pp
In systems
where MP/M is to be booted directly at cold start rather than loaded
and run as a transient program under CP/M, the customized MPMLDR.COM
file and cold start loader can be placed on the first two tracks of a diskette.
If a CP/M SYSGEN.COM program is available it can
be used to write the MPMLDR.COM file on the first two tracks.
If a SYSGEN.COM program is not available, or if SYSGEN.COM will not
work because a different media such as a mini-diskette or "hard" disk
is to be used, the user must write a simple memory loader,
called GETSYS, which brings the MP/M loader into memory and a
program called PUTSYS, which places the MPMLDR on the first two tracks
of a diskette.
.pp
Either the SID or DDT debugger can be used in place of writing a
GETSYS program as is shown in the following example which also
uses SYSGEN in place of PUTSYS.
Sample skeletal GETSYS and PUTSYS programs are described
later in this section (for a more detailed description of
GETSYS and PUTSYS see the "CP/M 2.0 Alteration Guide").
.pp
In order to make the MP/M system load and run
automatically, the user must also supply a cold start loader, similar
to the one described in the "CP/M 2.0 Alteration Guide".
The purpose of the cold start loader is to load the MP/M loader into
memory from the first two tracks of the diskette.
The CP/M 2.0 cold start loader must be modified in the following
manner: the load address must be changed to 0100H and the execution
address must also be changed to 0100H.
.pp
The following techniques are specifically for the MDS-800 which has
a boot ROM that loads the first track into location 3000H.  However,
the steps shown can be applied in general to any hardware.
.pp
If a SYSGEN program is available, the following steps can be used to
prepare a diskette that cold starts MP/M:
.pp
A.)  Prepare the MPMLDR.COM file by integrating your custom
LDRBIOS as described earlier in this section.  Test the MPMLDR.COM
and verify that it operates properly.
.pp
B.)  Execute either DDT or SID.
.li

               A>DDT
               DDT VERS 2.0
.ad
.pp
C.)  Using the input command ('I') specify that the MPMLDR.COM
file is to be read in and then read ('R') in the file with an
offset of 880H bytes.
.li

               -IMPMLDR.COM
               -R880
               NEXT  PC
               2480 0100
.ad
.pp
D.)  Using the 'I' command specify that the BOOT.HEX file is to
be read in and then read in the file with an offset that will load
the boot into memory at 900H.  The 'H' command can be used to
calculate the offset.
.li

               -H900 3000
               3900 D900

               -IBOOT.HEX
               -RD900
               NEXT  PC
               2480 0000
.ad
.pp
E.)  Return to the CP/M console command processor (CCP) by
jumping to location zero.
.li

               -G0
.ad
.pp
F.)  Use the SYSGEN program to write the new cold start loader
onto the first two tracks of the diskette.
.li

               A>SYSGEN
               SYSGEN VER 2.0
               SOURCE DRIVE NAME (OR RETURN TO SKIP)<cr>
               DESTINATION DRIVE NAME (OR RETURN TO REBOOT)B
               DESTINATION ON B, THEN TYPE RETURN<cr>
               FUNCTION COMPLETE
.ad
.sp 2
If a SYSGEN program is not available then the following steps can
be used to prepare a diskette that cold starts MP/M:
.pp
A.)  Write a GETSYS program which reads the
custom MPMLDR.COM file into location 3380H and the cold start
loader (or boot program) into location 3300H.
Code GETSYS so that it starts
at location 100H (base of the TPA).
.pp
As in the previous example, note that SID or DDT can be used to
perform this function instead of writing a GETSYS program.
.pp
B.)  Run the GETSYS program using an initialized MP/M diskette to see
if GETSYS loads the MP/M loader starting at 3380H (the operating
system actually
starts 128 bytes later at 3400H).
.pp
C.)  Write the PUTSYS program which writes
memory starting at 3380H back onto the first two tracks of the
diskette.  The PUTSYS program should be located at 200H.
.pp
D.)  Test the PUTSYS program using a blank uninitialized diskette by
writing a portion of memory to the first two tracks; clear memory
and read it back.  Test PUTSYS completely, since this program will
be used to alter the MP/M system diskette.
.pp
E.)  Use PUTSYS to place the MP/M loader and cold start loader
onto the first two tracks of a blank diskette.
.sp 2
.ce
SAMPLE PUTSYS PROGRAM
.pp
The following program provides a framework for the PUTSYS program.
The WRITESEC subroutine must be inserted by the user to write the
specific sectors.
.cp 52
.li


    ;   PUTSYS PROGRAM - WRITE TRACKS 0 AND 1 FROM MEMORY AT 3380H
    ;   REGISTER                 USE
    ;      A             (SCRATCH REGISTER)
    ;      B             TRACK COUNT (0, 1)
    ;      C             SECTOR COUNT (1,2,...,26)
    ;      DE            (SCRATCH REGISTER PAIR)
    ;      HL            LOAD ADDRESS
    ;      SP            SET TO STACK ADDRESS
    ;
    START: LXI   SP,3380H    ;SET STACK POINTER TO SCRATCH AREA
           LXI   H, 3380H    ;SET BASE LOAD ADDRESS
           MVI   B, 0        ;START WITH TRACK 0
    WRTRK:                   ;WRITE NEXT TRACK (INITIALLY 0)
           MVI   C,1         ;WRITE STARTING WITH SECTOR 1
    WRSEC:                   ;WRITE NEXT SECTOR
           CALL  WRITESEC     ;USER-SUPPLIED SUBROUTINE
           LXI   D,128       ;MOVE LOAD ADDRESS TO NEXT 1/2 PAGE
           DAD   D           ;HL = HL + 128
           INR   C           ;SECTOR = SECTOR + 1
           MOV   A,C         ;CHECK FOR END OF TRACK
           CPI   27
           JC    WRSEC       ;CARRY GENERATED IF SECTOR < 27
    ;
    ;   ARRIVE HERE AT END OF TRACK, MOVE TO NEXT TRACK
           INR   B
           MOV   A,B         ;TEST FOR LAST TRACK
           CPI   2
           JC    WRTRK       ;CARRY GENERATED IF TRACK < 2
    ;
    ;   ARRIVE HERE AT END OF LOAD, HALT FOR NOW
           HLT
    ;
    ;   USER-SUPPLIED SUBROUTINE TO WRITE THE DISK
    WRITESEC:
    ;   ENTER WITH TRACK NUMBER IN REGISTER B,
    ;         SECTOR NUMBER IN REGISTER C, AND
    ;         ADDRESS TO FILL IN HL
    ;
           PUSH   B          ;SAVE B AND C REGISTERS
           PUSH   H          ;SAVE HL REGISTERS
           ..........................................
           perform disk write at this point, branch to

           label START if an error occurs
           ..........................................
           POP    H          ;RECOVER HL
           POP    B          ;RECOVER B AND C REGISTERS
           RET               ;BACK TO MAIN PROGRAM

           END    START
.ad
.bp
.ce
DIGITAL RESEARCH COPYRIGHT
.pp
Read your MP/M Licensing Agreement; it specifies your legal
responsibilities when copying the MP/M system.  Place the copyright notice
.sp
.ce 2
Copyright (c), 1980
Digital Research
.sp
on each copy which is made of your customized MP/M diskette.
.sp 2
.ce
DISKETTE ORGANIZATION
.sp
.pp
The sector allocation for the standard distribution version of MP/M is
given here for reference purposes.  The first sector (see table on the following page)
contains an optional software boot section.  Disk controllers are often
set up to bring track 0, sector 1 into memory at a specific location
(often location 0000H).  The program in this sector, called BOOT, has
the responsibility of bringing the remaining sectors into memory
starting at location 0100H.  If your controller does not have a
built-in sector load, you can ignore the program in track 0, sector 1,
and begin the load from track 0 sector 2 to location 0100H.
.pp
As an example, the Intel MDS-800 hardware cold start loader brings
track 0, sector 1 into absolute address 3000H.
Upon loading this sector, control transfers to location 3000H, where
the bootstrap operation commences
by loading the remainder of track 0, and all of track 1 into
memory, starting at 0100H.  The user should note that this bootstrap loader
is of little use in a non-MDS environment, although it is useful to
examine it since some of the boot actions will have to be duplicated in
your cold start loader.
.bp
.li
     Track#  Sector#   Page#    Memory Address    MP/M Module name
       00      01               (boot address)    Cold Start Loader
       00      02       00          0100H              MPMLDR
        "      03        "          0180H               "
        "      04       01          0200H               "
        "      05        "          0280H               "
        "      06       02          0300H               "
        "      07        "          0380H               "
        "      08       03          0400H               "
        "      09        "          0480H               "
        "      10       04          0500H               "
        "      11        "          0580H               "
        "      12       05          0600H               "
        "      13        "          0680H               "
        "      14       06          0700H               "
        "      15        "          0780H               "
        "      16       07          0800H               "
        "      17        "          0880H               "
        "      18       08          0900H               "
        "      19        "          0980H               "
        "      20       09          0A00H               "
        "      21        "          0A80H               "
        "      22       10          0B00H               "
        "      23        "          0B80H               "
        "      24       11          0C00H               "
       00      25        "          0C80H              MPMLDR
       00      26       12          0D00H              LDRBDOS
       01      01        "          0D80H               "
        "      02       13          0E00H               "
        "      03        "          0E80H               "
        "      04       14          0F00H               "
        "      05        "          0F80H               "
        "      06       15          1000H               "
        "      07        "          1080H               "
        "      08       16          1100H               "
        "      09        "          1180H               "
        "      10       17          1200H               "
        "      11        "          1280H               "
        "      12       18          1300H               "
        "      13        "          1380H               "
        "      14       19          1400H               "
        "      15        "          1480H               "
        "      16       20          1500H               "
        "      17        "          1580H               "
        "      18       21          1600H               "
        01     19        "          1680H              LDRBDOS
        01     20       22          1700H              LDRBIOS
        "      21        "          1780H               "
        "      22       23          1800H               "
        "      23        "          1880H               "
        "      24       24          1900H               "
        "      25        "          1980H               "
        01     26       25          1A00H              LDRBIOS
.br
