Files
Digital-Research-Source-Code/MPM OPERATING SYSTEMS/MPM-86/MPM-86 2.0 SOURCES/04/LDMPM.A86
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

321 lines
7.8 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

title 'MP /M-86 Loader'
; The MPMLDR consists of this module along with the
; LDBDOS and LDBIOS. The LDBDOS is the same as for
; for CP/M-86, and the LDBIOS has only the login message
; changed.
; MPMLDR resides on the first two tracks of a
; MP/M-86 system diskette and is brought into memory
; by the ROM bootstrap loader to load initiate MP/M-86
; It opens the file 'MPM.SYS' using the LDBDOS and LDBIOS
; and then reads it into memory. The DS register is set
; to the start of the MPM DATA area, and a JMPF to the
; first byte of the MPM code is executed.
; The first 128 byte record of the MPM.SYS file is a header
; with the following format:
; ty rb 1 ;seg type
; len rw 1 ;length
; abs dw 1 ;absolute segment address for LOADER
; min rw 1 ;minimum mem
; max rw 1 ;max mem needed
; The code is expected first and then the data within MPM.SYS
; This header record is constructed automatically by the
; GENSYS-86 utility. See the variables declared at 'SEC1:'
; where the first sector of MPM.SYS will be read
; MPMLDR may be read into any segment that does not
; overlap the desired system load segment as it makes
; all memory references using copies of the CS: register
; it is entered with.
;
; For debugging under CP/M and DDT a 'IB' can be used to force a
; break to DDT just before 'Far Jumping' to MPM.
;
false equ 0
true equ not false
cr equ 0dh
lf equ 0ah
ldbdos_offset equ 406H ;offset of LDBDOS
mldbios_offset equ 1200h ;offset of LDBIOS
bdos_int equ 224 ;lbdos interrupt number
bootdrv equ 0 ; boot drive always zero
codetype equ 1 ; code type CMD header
datatype equ 2 ; data type CMD header
; dummy section for interrupt vectors
dseg 0
org 0
abs_zero rw 2*bdosint
bdos_offset rw 1
bdos_segment rw 1
fcb1 equ 5dh ; look here for 'B' to break
ddt_int equ 3 ; DDT interrupt
; bdos function numbers
coutf equ 2
pstrf equ 9
seldsk equ 14
openf equ 15
readsf equ 20
dmaf equ 26
dmabf equ 51
;*******************************
;*
;* MPMLDR starts here
;*
;*******************************
cseg ; JMPF to here from boot ROM
org 0
jmp start ; if loaded under DDT this
; gets overlayed and IP = 100H
; want 100h byte header for
; 'IB' option
db 'COPYRIGHT (C) 1981,' ; found by serial program
db ' DIGITAL RESEARCH '
db '654321'
db ' MP/M-86 Loader V2.0 (9/21/81)'
org 80H ; read first sector of MPM.SYS
sec1 rb 128 ; here
org offset sec1 ;CMD header fields
ctype rb 1 ;type
clen rw 1 ;length
cldseg rw 1 ;abs
cmin rw 1 ;minimum
cmax rw 1 ;maximum
dtype rb 1
dlen rw 1
dldseg rw 1
dmin rw 1
dmax rw 1
org 100H
start: ; execution begins here if DDT
jmp mldbios ; initialize mldbios
; mldbios returns here: 103H
xor ax,ax ! mov ds,ax ; temp DS at absolute zero
mov bdos_offset,offset ldbdos_offset ; to patch in interrupt table
mov bdos_segment,cs ; offset and segment
mov ax,cs ! mov ss,ax ; make ss, ds, es = cs
mov ds,ax ! mov es,ax
mov sp,offset(stack) ; set up local stack
mov dx,offset signon
call msg
call initlbdos ; warm up lbdos and lbios
call openfnc ; open MPM.SYS
cmp al,255 ! jne perr ; insure good file
mov dx,offset nofile ! call msg ; no MPM.SYS file
jmp stop ; then halt the machine
perr:
mov dx,cs ! call setdmab
mov dx,offset sec1 ! call setdma ; read first sector of MPM.SYS
call read
cmp ctype,codetype ; code should be first
jnz badhdr
cmp dtype,datatype ; then data
jnz badhdr
mov ax,cldseg ; code abs + code length
add ax,clen ; should be = to data abs
cmp ax,dldseg ! jnz badhdr
add ax,dlen ! cmp ax,cldseg ; check for wrap around
ja hdrok
badhdr:
mov dx,offset hdrerr ! call msg
jmp stop
hdrok:
mov dx,offset csegment ! call msg ; put memory map on console
mov ax,cldseg ! call phex ; print base code segment
mov dx,offset dsegment ! call msg ; print base data segment
mov ax,dldseg ! call phex
;
mov dx,cldseg
mov dmab,dx ; initial DMA segment
readit1:
call setdmab ; set DMA segment for disk IO
mov dx,0 ; offset of MPM in segment
readit2:
call setdma ; set DMA offset for
push dx ! call read ; next sector read
cmp al,01H ! je done ; check for EOF
cmp al,0 ! je prerr ; check for good write
mov dx,offset rerr ! call msg ; print READ ERROR message
jmp stop ; hard stop on any error
prerr: pop dx ! add dx,80H
cmp dx,0 ; more than 64K ?
jnz readit2
add dmab,1000h ; add 64K to base
mov dx,dmab
jmp readit1
done:
pop ax ; number of bytes read
mov cl,4
shr ax,cl ; number of paragraphs read
add ax,dmab ; number of 64K segments read
sub ax,cldseg ; (dmab - cldseg)
mov cx,clen
add cx,dlen
cmp ax,cx
jae lenok ; MPM.SYS at least as long
mov dx,offset shortmsg ; as header claims ?
call msg ! jmp stop
lenok:
push cx ; clen + dlen in cx
mov dx,offset lenmsg ! call msg ; print length message
pop ax
add ax,cldseg
dec ax ; last paragraph
call phex
call pcrlf ; and a crlf
mov ax,cldseg
mov mpmcseg,ax
mov ds,dldseg ; MP/M data segment
mov al, cs:.fcb1 ; must use CS over-ride
cmp al,'B'
jnz gompm
int ddt_int ; break to mpm
gompm:
jmpf mpm ; leap to MPM initialization
;*****************************
;*
;* subroutines
;*
;*****************************
;******
phex: ;print 4 hex characters from ax
mov cx,0404h ; 4 in both CH and CL
lhex:
rol ax,cl ; rotate left 4
push cx ! push ax ; save crucial registers
call pnib ; print hex nibble
pop ax ! pop cx ; restore registers
dec ch ! jnz lhex ; and loop four times
ret
pnib: ;print low nibble in AL as hex char
and al,0fh ! cmp al,9
ja p10 ;above 9 ?
add al,'0' ;digit
jmp prn
p10: add al,'A'-10 ;char a-e
prn: mov dl,al
;******
putchar:
mov cl,coutf
jmp sys_vec
;******
initlbdos:
mov cl,seldsk ! mov dx,bootdrv ; select boot disk
jmp sys_vec
;******
openfnc:
mov cl,openf ! mov dx,offset fcb ; fcb already initialized
mov cl,openf
jmp sys_vec
;********
;
setdma: ;set new dma addr in dx
mov cl,dmaf
jmp sys_vec
;********
;
setdmab: ; set new dma segment base from DX
mov cl,dmabf
jmp sys_vec
;******
;
pcrlf: mov dx,offset crlf ;print carriage return, line feed
;******
;
msg: ;print msg starting at dx until $
mov cl,pstrf ;print string function
jmp sys_vec
;*****
;
read:
mov dx,offset fcb ! mov cl,readsf
; jmp sys_vec
;******
;
sys_vec:
int bdos_int
ret
;******
;
stop: mov ax,0 ; hard stop 8086 for error
mov ds,ax
mov word ptr .8h,ax
mov word ptr .0ah,cs
stop2:
jmp stop2
;********************************
;*
;* DATA AREA
;*
;********************************
signon db cr,lf,lf,'MP/M-86 V2.0 Loader',cr,lf,'$'
nofile db cr,lf,'The File MPM.SYS Not Found On This Disk$'
rerr db cr,lf,'Error In Reading MPM.SYS$'
hdrerr db cr,lf,'Bad Header Record in MPM.SYS$'
shortmsg db cr,lf,'MPM.SYS Too Short $'
csegment db cr,lf,'Code Paragraph Address = $'
dsegment db cr,lf,'Data Paragraph Address = $'
lenmsg db cr,lf,'Last Paragragh = $'
crlf db cr,lf,'$'
; vector for jmpf indirect to start MP/M
mpm dd abs_zero ; (dummy value)
org offset mpm ; overlay preceding with DW's
mpmstart dw 0 ; first word of MPM code
mpmcseg rw 1 ; second is segmet of MPM code
dmab rw 1 ; current DMA segment
fcb db 0,'MPM ','SYS',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
; look on m disk first
org (offset $+1) and 0FFFEh ; even address for stack
rw 32
stack equ offset $
db 0
; dummy section for BIOS init label
org mldbios_offset
mldbios:
end