mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-26 01:44:21 +00:00
903 lines
21 KiB
Plaintext
903 lines
21 KiB
Plaintext
;*****************************************************
|
|
;*
|
|
;* Program Load
|
|
;*
|
|
;*****************************************************
|
|
;
|
|
; LDTAB Entry Format:
|
|
; 0 2 4 6 8
|
|
; +-----+-----+-----+-----+-----+-----+-----+-----+
|
|
; | START | MIN | MAX | PD |
|
|
; +-----+-----+-----+-----+-----+-----+-----+-----+
|
|
;
|
|
; 8 10(A) 12(C) 14(E) 16(10) 17(11)
|
|
; +-----+-----+-----+-----+-----+-----+-----+-----+-----+
|
|
; | ATR | FSTRT | FLEN | TYPE| ID |
|
|
; +-----+-----+-----+-----+-----+-----+-----+-----+-----+
|
|
;
|
|
;
|
|
; start Absolute Address requested
|
|
; min Min memory wanted
|
|
; max Max memory wanted
|
|
; pd PD to allocate to
|
|
; atr Attributes, Memory Flags
|
|
; fstrt Starting paragraph in File
|
|
; flen # of paragraphs in file
|
|
; type Group type
|
|
; id Segment Address of this group
|
|
;
|
|
; The Load Table contains 9 entries, One for each
|
|
; potential Group in Command File and One extra
|
|
; for Independent Memory Allocations.
|
|
|
|
ldt_start equ word ptr 0
|
|
ldt_min equ word ptr ldt_start + word
|
|
ldt_max equ word ptr ldt_min + word
|
|
ldt_pd equ word ptr ldt_max + word
|
|
ldt_atr equ word ptr ldt_pd + word
|
|
ldt_fstrt equ word ptr ldt_atr + word
|
|
ldt_flen equ word ptr ldt_fstrt + word
|
|
ldt_type equ byte ptr ldt_flen + word
|
|
ldt_id equ word ptr ldt_type + byte
|
|
ldtlen equ ldt_id + word
|
|
|
|
|
|
|
|
;=========
|
|
cload_ent: ; entry point to load for a chain command
|
|
;=========
|
|
; Assumes UDA is set in passed PD.
|
|
|
|
push bx ! mov bx,1
|
|
jmps load
|
|
|
|
;========
|
|
load_ent: ; User entry point to load .CMD file for execution
|
|
;========
|
|
; input: DX = address of open FCB in u_wrkseg
|
|
; output: BX = segment addr of Base Page
|
|
; = 0ffffh if error
|
|
; CX = Error Code
|
|
|
|
sub bx,bx
|
|
;jmp load
|
|
;====
|
|
load: ; Intermodule entry point to load .CMD file
|
|
;====
|
|
; input: DX = addr of open FCB in u_wrkseg
|
|
; BX = addr of unused PD to initialize
|
|
; 0 - do not init PD
|
|
; 1 - chain load (PD addr on stack)
|
|
; output: BX = seg addr of Base Page
|
|
; = 0ffffh if error
|
|
; CX = Error Code
|
|
|
|
; Get MXLoad Queue
|
|
|
|
push dx ! push bx
|
|
mov cx,f_qread ! mov dx,offset mxloadqpb
|
|
call osif
|
|
mov lod_chain,false
|
|
pop lod_pd ! pop si
|
|
cmp lod_pd,1 ! jne ld_cf
|
|
pop lod_pd ! mov lod_chain,true
|
|
|
|
; Copy FCB into lod_fcb
|
|
; SI-> user FCB in u_wrkseg
|
|
|
|
ld_cf: mov cx,fcblen/2 ! mov di,offset lod_fcb
|
|
push es ! push ds ! push ds
|
|
mov ds,u_wrkseg ! pop es
|
|
rep movsw
|
|
pop ds ! pop es
|
|
|
|
|
|
; Read the Header
|
|
|
|
mov bx,offset lod_fcb
|
|
mov byte ptr fcb_r0+2[bx],0
|
|
mov ax,0 ;record #
|
|
mov bx,1 ;# of sectors
|
|
mov dx,offset lod_dma ;DMA offset
|
|
mov cx,sysdat ;DMA segment
|
|
call drd ! jcxz h_hdr
|
|
jmp lod_exit
|
|
h_hdr:
|
|
mov lod_indma,0
|
|
|
|
; initialize Load Disk and User
|
|
; from FCB
|
|
|
|
mov bx,rlr
|
|
mov al,p_user[bx]
|
|
mov lod_user,al
|
|
mov al,p_dsk[bx] ;default disk of calling PD
|
|
mov lod_disk,al ;1-15 -> A-P
|
|
mov bx,offset lod_fcb
|
|
mov al,fcb_dr[bx]
|
|
mov lod_fifty,al ;base page address 50H, 0=default
|
|
test al,al ! jz use_ddsk
|
|
dec al ;1-15 -> A-P
|
|
mov lod_disk,al
|
|
use_ddsk:
|
|
test byte ptr fcb_name+7[bx],080h ! jz use_dusr
|
|
|
|
mov lod_user,0
|
|
use_dusr:
|
|
|
|
; Initialize ldtab
|
|
|
|
; Zero ldtab
|
|
mov cx,ldtabsiz/2 ! sub ax,ax
|
|
mov di,offset ldtab
|
|
push es ! mov es,sysdat
|
|
rep stos ax ! pop es
|
|
|
|
; 1st ldtab entry is UDA and LSTK
|
|
; if a PD was specified...
|
|
|
|
mov lod_nldt,0
|
|
mov si,offset ldtab
|
|
cmp lod_pd,0 ! jne form_uda
|
|
jmp gc_ifo
|
|
form_uda: mov ldt_min[si],(lstklen+ulen)/16 ;min=max=UDA+STK paragraphs
|
|
mov ldt_max[si],(lstklen+ulen)/16
|
|
mov ax,lod_pd ! mov ldt_pd[si],ax
|
|
mov ldt_atr[si],mf_load
|
|
add si,ldtlen
|
|
inc lod_nldt
|
|
cmp lod_chain,true ! jne gc_ifo
|
|
|
|
;We are CHAINING. Free all memory
|
|
; except UDA area and LDSTK. This will keep
|
|
; the first partition for the chain
|
|
; as well as not crash the system.
|
|
|
|
push si
|
|
mov cx,f_freeall ! call osif
|
|
|
|
;transfer memory to new pd
|
|
|
|
mov bx,rlr
|
|
mov ax,p_mem[bx] ! mov p_mem[bx],0
|
|
mov bx,lod_pd ! mov p_mem[bx],ax
|
|
pop si
|
|
|
|
gc_ifo:
|
|
;go through CMD header and init
|
|
;a ldtab entry per header entry.
|
|
;alloc abs mem
|
|
|
|
mov bx,offset lod_dma
|
|
mov al,ch_lbyte[bx] ; save fixup flag
|
|
mov lod_lbyte,al
|
|
mov ax,ch_fixrec[bx] ; save record # of fixups, if any
|
|
mov lod_fixrec,ax
|
|
mov lod_fixrec1,ax
|
|
|
|
mov cx,ch_entmax ; BX = offset LOD_DMA
|
|
mov dx,8 ; DX = position in file
|
|
ch_more:cmp ch_form[bx],0 ! jne ch_doit
|
|
jmp ch_next
|
|
ch_doit: mov al,ch_form[bx] ! mov ldt_type[si],al ;type of seg
|
|
mov ax,ch_length[bx] ! mov ldt_flen[si],ax ;length
|
|
mov ldt_fstrt[si],dx ! add dx,ax ;pos in file
|
|
mov ax,ch_base[bx] ! mov ldt_start[si],ax ;abs seg
|
|
mov ax,ch_min[bx] ! mov ldt_min[si],ax ;min needed
|
|
mov ax,ch_max[bx]
|
|
cmp ax,0 ! jne setmax
|
|
mov ax,ch_min[bx]
|
|
setmax: mov ldt_max[si],ax ;max wanted
|
|
mov ax,lod_pd ! mov ldt_pd[si],ax ;pd to alloc to
|
|
cmp ax,0 ! je not_load
|
|
mov ax,mf_load
|
|
|
|
jmps not_load
|
|
skipjmp:jmps ch_more
|
|
|
|
if mpm
|
|
|
|
not_load: cmp ch_form[bx],1 ! jne try_sh
|
|
add ax,mf_code ! jmps s_atr
|
|
try_sh: cmp ch_form[bx],9 ! jne s_atr
|
|
add ax,mf_code+mf_share
|
|
s_atr: mov ldt_atr[si],ax ;memory flags
|
|
|
|
;if abs, allocate memory
|
|
cmp ldt_start[si],0 ! je ch_nabs ;see if abs mem
|
|
jmps ch_al
|
|
ch_nabs: cmp ldt_type[si],9
|
|
jne ch_nxt ;see if shared code
|
|
push cx
|
|
push bx ! push dx ;save load DMA and position in file
|
|
call get_sh
|
|
|
|
pop dx ! pop bx
|
|
cmp cx,0 ! pop cx
|
|
je ch_nxt
|
|
jmp ld_out
|
|
ch_al: push bx ! push dx ! push cx ! push si
|
|
mov cx,f_malloc ! mov dx,si
|
|
call osif ! pop si
|
|
mov ax,ldt_start[si] ! mov ldt_id[si],ax
|
|
cmp cx,0 ! pop cx ! pop dx ! pop bx
|
|
je ch_nxt
|
|
;couldn't find memory
|
|
mov bx,0ffffh ! mov cx,e_no_memory
|
|
jmp ld_out
|
|
|
|
endif
|
|
|
|
if ccpm
|
|
|
|
not_load: cmp ch_form[bx],9 ! jne try_code
|
|
mov ch_form[bx],1
|
|
mov ldt_type[si],1
|
|
try_code: cmp ch_form[bx],1 ! jne s_atr
|
|
add ax,mf_code
|
|
s_atr: mov ldt_atr[si],ax ;memory flags
|
|
|
|
;if abs, allocate memory
|
|
cmp ldt_start[si],0 ! je ch_nxt ;see if abs mem
|
|
ch_al: push bx ! push dx ! push cx ! push si
|
|
mov cx,f_malloc ! mov dx,si
|
|
call osif ! pop si
|
|
mov ax,ldt_start[si] ! mov ldt_id[si],ax
|
|
cmp cx,0 ! pop cx ! pop dx ! pop bx
|
|
je ch_nxt
|
|
;couldn't find memory
|
|
mov bx,0ffffh ! mov cx,e_no_memory
|
|
jmp ld_out
|
|
|
|
endif
|
|
|
|
ch_nxt: add si,ldtlen
|
|
inc lod_nldt
|
|
ch_next:add bx,chlen
|
|
loop skipjmp
|
|
|
|
; alloc all other memory
|
|
; SI -> mpb for non_abs mem req.
|
|
;add all parts together for a single malloc
|
|
mov bx,offset ldtab
|
|
mov cx,lod_nldt
|
|
mov lod_nrels,0
|
|
lt_more:cmp ldt_min[bx],0 ! je lt_next
|
|
cmp ldt_start[bx],0 ! jne lt_next
|
|
mov ax,ldt_min[bx]
|
|
mov dx,ax
|
|
add ldt_min[si],ax
|
|
cmp dx,ldt_min[si] ! jbe lt_m ; check for ovrflw
|
|
mov ldt_min[si],0ffffh
|
|
lt_m: mov ax,ldt_max[bx]
|
|
mov dx,ax
|
|
add ldt_max[si],ax
|
|
cmp dx,ldt_max[si] ! jbe lt_m1 ; check for ovrflw
|
|
mov ldt_max[si],0ffffh
|
|
lt_m1: inc lod_nrels
|
|
lt_next:add bx,ldtlen ! loop lt_more
|
|
|
|
;malloc
|
|
cmp lod_pd,0 ! je noloadf
|
|
mov ldt_atr[si],mf_load
|
|
noloadf:mov ax,lod_pd ! mov ldt_pd[si],ax
|
|
push si ! mov dx,si ! mov cx,f_malloc
|
|
call osif ! pop si
|
|
mov ax,ldt_start[si] ! mov ldt_id[si],ax
|
|
cmp bx,0ffffh ! jne lt_sprd
|
|
|
|
;Not Enough Memory - release any
|
|
; memory already allocated
|
|
ld_out: push cx
|
|
mov bx,offset ldtab
|
|
mov cx,lod_nldt ! inc cx
|
|
lg_more: cmp ldt_id[bx],0 ! je lg_next
|
|
push cx ! push bx ! push ds
|
|
;push MFPB on stack
|
|
push ldt_pd[bx]
|
|
push ldt_id[bx]
|
|
mov dx,sp ! push ss ! pop ds
|
|
mov cx,f_memfree
|
|
call osif
|
|
pop cx ! pop cx
|
|
|
|
pop ds ! pop bx ! pop cx
|
|
lg_next: add bx,ldtlen ! loop lg_more
|
|
mov bx,0ffffh ! pop cx ! jmp lod_exit
|
|
|
|
lt_sprd:
|
|
;spread the memory allocated
|
|
;amongst the nrels
|
|
;1st give everyone the minimum
|
|
mov bx,offset ldtab
|
|
mov cx,lod_nldt
|
|
ls_more:cmp ldt_start[bx],0 ! jne ls_next
|
|
mov ax,ldt_min[bx]
|
|
sub ldt_min[si],ax
|
|
cmp ax,ldt_max[bx] ! jne ls_next
|
|
mov dx,ldt_start[si] ! mov ldt_start[bx],dx
|
|
add ldt_start[si],ax
|
|
dec lod_nrels
|
|
ls_next:add bx,ldtlen ! loop ls_more
|
|
|
|
;spread whats left amongst those that need more
|
|
mov bx,offset ldtab
|
|
mov cx,lod_nldt
|
|
lsl_mre:cmp ldt_start[bx],0 ! jne lsl_nxt
|
|
mov ax,ldt_start[si] ! mov ldt_start[bx],ax
|
|
mov ax,ldt_min[si]
|
|
cmp ax,0 ! je adj_start
|
|
push cx ! sub cx,cx
|
|
mov dx,cx ! mov cl,lod_nrels
|
|
div cx ! pop cx
|
|
cmp dx,0 ! je evendiv
|
|
inc ax
|
|
evendiv: mov dx,ldt_max[bx] ! sub dx,ldt_min[bx]
|
|
cmp ax,dx ! jbe nottoomuch
|
|
mov ax,dx
|
|
nottoomuch: add ldt_min[bx],ax ! sub ldt_min[si],ax
|
|
adj_start: mov ax,ldt_min[bx] ! add ldt_start[si],ax
|
|
dec lod_nrels
|
|
lsl_nxt:add bx,ldtlen ! loop lsl_mre
|
|
|
|
; fill memory from file
|
|
|
|
mov si,offset ldtab
|
|
mov cx,lod_nldt
|
|
lf_mre: cmp ldt_flen[si],0 ! je lf_nxt
|
|
push cx ! push ldt_start[si] ! push si
|
|
call lod_group
|
|
pop si ! pop ldt_start[si]
|
|
cmp cx,0 ! pop cx
|
|
je lf_nxt
|
|
|
|
if ccpm
|
|
|
|
jmp ld_out
|
|
endif
|
|
|
|
if mpm
|
|
|
|
; error in lod_group
|
|
; if loading shared code we also
|
|
; have to release Shared Code from SCL.
|
|
; It will be the top item in the list.
|
|
|
|
cmp ldt_atr[si],mf_load+mf_code+mf_share
|
|
je rm_sh
|
|
jmp ld_out
|
|
rm_sh: push cx ; remember Err Code
|
|
|
|
; Remove PD from SCL
|
|
pushf ! cli
|
|
mov bx,scl
|
|
mov ax,p_thread[bx]
|
|
mov scl,ax
|
|
popf
|
|
|
|
; Release the memory
|
|
|
|
push ds ! push bx
|
|
mov bx,p_mem[bx] ! push ms_start[bx]
|
|
mov ax,ss ! mov ds,ax
|
|
mov dx,sp ! mov cx,f_memfree
|
|
call osif
|
|
pop ax ! pop bx ! pop ds
|
|
|
|
; Place PD on PUL
|
|
|
|
pushf ! cli
|
|
mov ax,pul
|
|
mov pul,bx
|
|
mov p_link[bx],ax
|
|
popf
|
|
|
|
pop cx
|
|
jmp ld_out
|
|
endif
|
|
|
|
lf_nxt: add si,ldtlen ! loop lf_mre
|
|
|
|
|
|
; Check for fixup records and do fixups
|
|
|
|
test lod_lbyte,80h ; hi bit of last byte in cmd header
|
|
jz init_base ; is set if fixups
|
|
fx_read:
|
|
mov ax,lod_fixrec ; get record # of fixups in file
|
|
mov bx,1 ; read one record
|
|
mov cx,ds
|
|
mov dx, offset lod_dma
|
|
call drd ; do random read
|
|
jcxz fx_read_ok ; 0=ok,CL=0ff if EOF
|
|
inc cl ; EOF ?
|
|
jnz fx_err ; some read error, not EOF
|
|
mov ax,lod_fixrec1 ; make sure one fixup
|
|
cmp ax,lod_fixrec ; record was read since cmd header
|
|
je fx_err ; said we needed them
|
|
jmps init_base
|
|
|
|
fx_read_ok: ; go look for fixup records
|
|
mov bx,offset lod_dma ; BX-> at fixup records
|
|
fx_chk:
|
|
mov al,fix_grp[bx] ; any more fixups?
|
|
test al,al
|
|
jz init_base
|
|
and al,0fh ; low nibble is target group
|
|
call tblsrch ; find target group in load table
|
|
mov dx,ldt_start[di] ; DX = target segment, this is
|
|
; what we add to the load image
|
|
mov al,fix_grp[bx] ; location group is high nibble
|
|
mov cl,4 ; put in low nibble of AL
|
|
shr al,cl
|
|
call tblsrch ; DI = location load table entry
|
|
mov ax,ldt_start[di] ; AX = base segment of location
|
|
add ax,fix_para[bx] ; add paragraph offset
|
|
|
|
push es ; absolute paragraph in memory
|
|
mov es,ax
|
|
xor ax,ax
|
|
mov al,fix_offs[bx] ; get offset of fixup location
|
|
mov di,ax
|
|
add es:[di],dx ; make the fixup (finally)
|
|
pop es
|
|
|
|
add bx,fixlen ; do next fixup
|
|
cmp bx,offset lod_dma + dskrecl ; end of this record ?
|
|
jne fx_chk
|
|
inc lod_fixrec ; read another record
|
|
jmps fx_read ; of fixups
|
|
|
|
tblsrch:
|
|
;-------
|
|
; Search for group in load table
|
|
; entry: AL = group # to match on
|
|
; exit: DI = load group entry that matches or
|
|
; pop return and exit loader
|
|
; BX,DX preserved
|
|
|
|
mov cx,lod_nldt ; # entries in table
|
|
mov di,offset ldtab
|
|
srchloop:
|
|
cmp al,ldt_type[di]
|
|
je srchdn ; found group's entry
|
|
add di,ldtlen
|
|
loop srchloop
|
|
pop ax
|
|
jmps fx_err
|
|
srchdn:
|
|
ret
|
|
|
|
fx_err:
|
|
mov cx,e_fixuprec
|
|
jmp ld_out
|
|
|
|
|
|
|
|
; init Base Page
|
|
; 1st Data Group has Base Page
|
|
; if none then first nonshared
|
|
; Code Group (8080 model)
|
|
init_base:
|
|
mov lod_8080,0
|
|
mov si,offset ldtab
|
|
mov cx,lod_nldt
|
|
lb_more:cmp ldt_type[si],2 ! je lb_fnd
|
|
add si,ldtlen ! loop lb_more
|
|
mov si,offset ldtab
|
|
mov cx,lod_nldt
|
|
lbc_mre: cmp ldt_type[si],1 ! je lb_fnd80
|
|
add si,ldtlen ! loop lbc_mre
|
|
mov cx,e_no_cseg ! jmp ld_out
|
|
lb_fnd80: mov lod_8080,1
|
|
lb_fnd:
|
|
push es ! mov es,ldt_start[si]
|
|
mov lod_basep,es
|
|
sub ax,ax ! mov di,ax
|
|
mov cx,05bh/2 ! rep stos ax
|
|
mov al,lod_8080 ! mov es:.5,al
|
|
mov si,offset ldtab
|
|
mov cx,lod_nldt
|
|
lbb_mre:cmp ldt_type[si],0 ! je lbb_nxt
|
|
mov ax,6 ! mov bl,ldt_type[si]
|
|
cmp bl,9 ! jne lbb_nsh
|
|
mov bl,1
|
|
lbb_nsh: dec bl ! mul bl ! mov bx,ax
|
|
|
|
;calculate last byte (3 byte value)
|
|
; =(paragraphs*16)-1
|
|
push cx ! mov dx,ldt_min[si]
|
|
push dx ! mov cl,4 ! shl dx,cl
|
|
push dx ! dec dx ! mov es:[bx],dx
|
|
pop cx ! pop dx ! push cx
|
|
mov cl,12 ! shr dx,cl ! pop cx
|
|
cmp cx,0 ! jne lbb_nzer
|
|
cmp dx,0 ! je lbb_zer
|
|
dec dl ! jmps lbb_nzer
|
|
lbb_zer: mov es:word ptr [bx],0
|
|
lbb_nzer: mov es:2[bx],dl ! pop cx
|
|
|
|
;put starting paragraph in place
|
|
mov ax,ldt_start[si] ! mov es:3[bx],ax
|
|
|
|
lbb_nxt:add si,ldtlen ! loop lbb_mre
|
|
|
|
;if 8080 model, copy CS info into DS info
|
|
|
|
cmp lod_8080,1 ! jne lnot80
|
|
push ds ! push es ! pop ds ! mov si,0
|
|
mov di,6 ! mov cx,3
|
|
rep movsw ! pop ds
|
|
lnot80:
|
|
mov al,lod_fifty ;initialize base page load disk
|
|
mov es:.50H,al
|
|
pop es
|
|
|
|
; init PD ,UDA and LDSTK
|
|
|
|
mov bx,lod_basep
|
|
cmp lod_pd,0 ! jne lip_1
|
|
jmp lod_exit
|
|
lip_1: mov si,offset ldtab
|
|
mov bx,lod_pd
|
|
mov ax,ldt_start[si]
|
|
mov p_uda[bx],ax
|
|
; remember where lstk,uda are
|
|
mov lod_uda,ax
|
|
push es ! mov es,ax
|
|
add ax,(ulen/16) ! mov lod_lstk,ax
|
|
; initialize UDA,LDSTK with zeros
|
|
xor di,di ! mov ax,di
|
|
mov cx,(ulen + lstklen)/2
|
|
rep stos ax ! pop es
|
|
|
|
; setup p_uda for creat_proc
|
|
|
|
mov ax,sysdat
|
|
sub p_uda[bx],ax
|
|
mov p_stat[bx],ps_run
|
|
mov p_prior[bx],200
|
|
|
|
; init load disk/user
|
|
|
|
mov al,lod_user ! mov p_luser[bx],al
|
|
mov al,lod_disk ! mov p_ldsk[bx],al
|
|
|
|
; init UDA
|
|
|
|
push es ! mov es,lod_uda
|
|
mov u_dma_ofst,(offset bpg_dma)
|
|
mov bx,lod_basep
|
|
|
|
mov u_dma_seg,bx
|
|
mov ax,lod_lstk
|
|
push ds ! mov ds,bx
|
|
mov u_initds,bx
|
|
mov u_inites,bx
|
|
mov u_initss,ax
|
|
mov ax,bpg_cseg
|
|
cmp ax,0 ! jne h_cs
|
|
pop ds ! pop es ! mov cx,e_no_cseg
|
|
jmp ld_out
|
|
h_cs: mov u_initcs,ax
|
|
mov ax,bpg_eseg
|
|
cmp ax,0 ! je noes
|
|
mov u_inites,ax
|
|
noes: mov u_stack_sp,(offset ls_sp)
|
|
sub dx,dx ! mov al,bpg_8080
|
|
cmp al,0 ! je n80m
|
|
mov dx,0100h
|
|
n80m:
|
|
mov ds,u_initss
|
|
mov ls_offset,dx ;set up initial stack
|
|
mov ls_flags,0200h ;for a RETF from user
|
|
mov ls_roffset,offset user_retf ;process, see SUPIF.SUP
|
|
mov ls_rcseg,cs ;module for USER_RETF:
|
|
pop ds ! pop es ;code
|
|
|
|
mov bx,lod_basep
|
|
sub cx,cx
|
|
lod_exit:
|
|
push cx ! push bx
|
|
mov cx,f_qwrite ! mov dx,offset mxloadqpb
|
|
call osif ! pop bx ! pop cx ! ret
|
|
|
|
|
|
lod_group: ;load a group described in ldtab
|
|
;----------
|
|
; input: SI = addr of ldtab entry
|
|
; output: CX = Error Code
|
|
|
|
; see if first part already in DMA
|
|
mov bx,si
|
|
mov ax,lod_indma ;starting paragraph in dma
|
|
mov cx,ldt_fstrt[bx]
|
|
;AX = starting paragraph in local DMA
|
|
;CX = starting paragraph to transfer
|
|
;BX -> ldtab entry
|
|
cmp cx,ax ! jb rd_first
|
|
;starts at or after the pp. in dma
|
|
sub cx,ax
|
|
cmp cx,8 ! jae rd_first
|
|
;starts in the dma
|
|
mov dx,8 ! sub dx,cx
|
|
;CX = # of pp. to skip
|
|
;DX = length of remaining buffer
|
|
cmp dx,ldt_flen[bx] ! jbe xfer
|
|
mov dx,ldt_flen[bx]
|
|
xfer: mov si,offset lod_dma
|
|
mov ax,cx ! mov cl,4 ! shl ax,cl
|
|
add si,ax
|
|
;SI -> beginning of transfer area
|
|
; in lod_dma
|
|
mov ax,dx ! mov cl,3 ! shl ax,cl
|
|
mov cx,ax
|
|
;CX = number of words to transfer
|
|
xor di,di
|
|
push es ! mov es,ldt_start[bx]
|
|
rep movsw ! pop es
|
|
add ldt_start[bx],dx
|
|
sub ldt_flen[bx],dx ! add ldt_fstrt[bx],dx
|
|
rd_first:
|
|
cmp ldt_flen[bx],0 ! jne rd_1st
|
|
sub cx,cx ! ret
|
|
rd_1st:
|
|
test ldt_fstrt[bx],07h ! jnz rd_indma
|
|
cmp ldt_flen[bx],8 ! jae xf_d
|
|
rd_indma:
|
|
push bx
|
|
mov ax,ldt_fstrt[bx]
|
|
shr ax,1 ! shr ax,1 ! shr ax,1 ; Record #
|
|
mov bx,1 ; read 1 record
|
|
mov dx,offset lod_dma ; DMA offset
|
|
mov cx,sysdat ; DMA segment
|
|
call drd
|
|
pop bx
|
|
jcxz rd_agn
|
|
cmp cx,0ffh ! jne rd_r3
|
|
mov cx,0
|
|
rd_r3: ret
|
|
rd_agn: mov ax,ldt_fstrt[bx]
|
|
and ax,0fff8h ; note starting paragraph
|
|
mov lod_indma,ax ; in DMA
|
|
mov si,bx ! jmp lod_group
|
|
|
|
; We are at a Sector Boundary with at least
|
|
; a sector to place into the user area
|
|
xf_d:
|
|
push bx
|
|
sub dx,dx ; DMA offset
|
|
mov cx,ldt_start[bx] ; DMA segment
|
|
|
|
mov ax,ldt_fstrt[bx]
|
|
shr ax,1 ! shr ax,1 ! shr ax,1 ; Record #
|
|
mov bx,ldt_flen[bx]
|
|
shr bx,1 ! shr bx,1 ! shr bx,1 ; # of records
|
|
push bx
|
|
call drd
|
|
pop ax ! pop bx
|
|
jcxz xfer_n
|
|
cmp cx,0ffh ! jne rd_r4
|
|
xor cx,cx
|
|
rd_r4: ret
|
|
xfer_n: shl ax,1 ! shl ax,1 ! shl ax,1
|
|
add ldt_start[bx],ax
|
|
add ldt_fstrt[bx],ax
|
|
sub ldt_flen[bx],ax
|
|
jmp rd_first
|
|
|
|
drd:
|
|
; input: AX = Record Number
|
|
; BX = Number of Sectors
|
|
; CX = dma segment
|
|
; DX = dma offset
|
|
; output: CX = 0 if okay
|
|
; CX = 0FFH if End of File
|
|
; else Error Code
|
|
|
|
mov u_dma_ofst,dx
|
|
mov u_dma_seg,cx
|
|
|
|
; read BX sectors starting at Record AX
|
|
drd_lp:
|
|
push bx ;old # sectors
|
|
push ax ;old record #
|
|
cmp bx,128 ! jbe drd_r
|
|
mov bx,128
|
|
|
|
; Max Mulit-sector count is 128
|
|
|
|
drd_r: mov cl,u_mult_cnt
|
|
push cx
|
|
mov u_mult_cnt,bl
|
|
push bx
|
|
mov si,offset lod_fcb
|
|
mov fcb_r0[si],ax
|
|
mov cx,f_freadrdm ! mov dx,si
|
|
push es ! call osif ! pop es
|
|
pop dx ;multi_cnt used
|
|
pop cx ! mov u_mult_cnt,cl
|
|
cmp bl,1 ! jbe dr_r2
|
|
mov cx,e_bad_read ! mov bx,0ffffh
|
|
pop ax ! pop ax ! ret
|
|
dr_r2: mov cl,bl
|
|
pop ax ! add ax,dx ;adjust record #
|
|
pop bx ! sub bx,dx ;adjust # sectors
|
|
shl dx,1 ! shl dx,1 ! shl dx,1
|
|
add u_dma_seg,dx
|
|
|
|
; check for CTRL C. If hit while loading
|
|
; last set of characters, this is the place to
|
|
; clean things up...
|
|
|
|
push cx ! push ax ! push bx
|
|
mov cx,f_ciostat ! call osif
|
|
pop bx ! pop ax ! pop cx
|
|
|
|
; Now see if CTRL C was hit during the
|
|
; the load.
|
|
|
|
mov si,rlr
|
|
test p_flag[si],pf_ctlc ! jz dr_r1
|
|
mov cx,e_abort ! mov bx,0ffffh
|
|
ret
|
|
dr_r1: cmp cl,0 ! je dr_r5
|
|
mov cx,0ffh ! ret
|
|
dr_r5: cmp bx,0 ! jne drd_lp
|
|
xor cx,cx
|
|
ret
|
|
|
|
if mpm
|
|
|
|
get_sh:
|
|
;------
|
|
; Allocate memory for shared code. If memory already
|
|
; exists then mark LDTAB entry with FLEN=0 for no load.
|
|
; START must be non-zero on success.
|
|
;
|
|
|
|
; input: SI = LDTAB Entry for shared code
|
|
; output: CX = 0 on success
|
|
; = 0ffffh on failure
|
|
; SI is unchanged
|
|
;
|
|
|
|
; 1. Look for PD Name on SCL, making sure
|
|
; LDSK and LUSER are the same.
|
|
|
|
mov bx,(offset scl)-p_thread
|
|
gs_nxt: push si
|
|
mov dx,offset lod_fcb ! add dx,fcb_name
|
|
mov cx,f_findpdname ! call osif
|
|
; BX=pd found or 0ffffh
|
|
pop si
|
|
cmp bx,0ffffh ! je no_sh
|
|
mov al,lod_disk
|
|
cmp p_ldsk[bx],al ! jne gs_nxt
|
|
mov al,lod_user
|
|
cmp p_luser[bx],al ! jne gs_nxt
|
|
|
|
; 2. if (1.) then Share the Memory.
|
|
; 2.1 Set FLEN=0
|
|
|
|
push bx ! push si
|
|
call shmem
|
|
pop si ! pop bx
|
|
cmp cx,0ffffh ! je no_sh
|
|
mov ldt_flen[si],0
|
|
|
|
; Put SHARE PD on end of SCL
|
|
; BX = SHARE PD
|
|
|
|
pushf ! cli
|
|
mov di,(offset SCL)-p_thread
|
|
sh_nin1: cmp p_thread[di],bx ! je sh_rm ;look for share PD
|
|
mov di,p_thread[di] ! jmps sh_nin1
|
|
sh_rm: mov ax,p_thread[bx] ;take it off the list
|
|
mov p_thread[di],ax
|
|
sh_in: cmp p_thread[di],0 ! je sh_end ;look for the end
|
|
mov di,p_thread[di] ! jmps sh_in
|
|
sh_end: mov p_thread[di],bx ;insert share PD on end
|
|
xor cx,cx
|
|
mov p_thread[bx],cx
|
|
popf ! ret ;success
|
|
|
|
; 3. if (NOT 1.) allocate memory to NEW PD
|
|
no_sh:
|
|
|
|
; get new PD
|
|
|
|
pushf ! cli
|
|
mov bx,pul
|
|
cmp bx,0 ! je sherr
|
|
mov ax,p_link[bx] ! mov pul,ax
|
|
popf
|
|
|
|
; alloc memory for code segment
|
|
|
|
push bx ! push si
|
|
mov cx,f_malloc
|
|
mov dx,si
|
|
call osif
|
|
pop si ! pop bx
|
|
cmp cx,0 ! jne merr
|
|
|
|
; initialize new PD name
|
|
; BX = New PD
|
|
push si
|
|
mov si,ldt_pd[si] ;SI=old pd
|
|
push si
|
|
mov di,bx
|
|
add si,p_name ! add di,p_name
|
|
mov cx,4
|
|
push es ! mov ax,ds ! mov es,ax
|
|
rep movsw
|
|
pop es ! pop di ! pop si
|
|
|
|
; DI = old PD, BX=New PD
|
|
|
|
mov al,lod_user ! mov p_luser[bx],al
|
|
mov al,lod_disk ! mov p_ldsk[bx],al
|
|
|
|
; share w/new PD
|
|
|
|
mov ax,ldt_start[si]
|
|
push bx ! push si ! push ds
|
|
push ax ! push bx ! push di
|
|
mov ax,ss ! mov ds,ax
|
|
mov dx,sp ! mov cx,f_share
|
|
call osif
|
|
add sp,6
|
|
pop ds ! pop si ! pop bx
|
|
|
|
; put new PD on SCL
|
|
|
|
pushf ! cli
|
|
mov di,(offset SCL)-p_thread
|
|
sh_nin: cmp p_thread[di],0 ! je sh_doit
|
|
mov di,p_thread[di] ! jmps sh_nin
|
|
sh_doit: mov p_thread[di],bx ;insert new share PD
|
|
xor cx,cx
|
|
mov p_thread[bx],cx
|
|
popf ! ret ;success
|
|
merr: pushf ! cli
|
|
mov ax,pul
|
|
mov p_link[bx],ax
|
|
mov pul,bx
|
|
sherr: popf
|
|
mov cx,0ffffh ! ret
|
|
|
|
shmem:
|
|
;-----
|
|
;input: SI = LDTAB
|
|
; BX = Owner PD
|
|
; Load_pd = Requestor
|
|
; Have to set LDT_START
|
|
;
|
|
|
|
lea di,(p_mem-ms_link)[bx]
|
|
sm_nxt:
|
|
mov di,ms_link[di]
|
|
cmp di,0 ! je sm_no
|
|
mov ax,ms_flags[di]
|
|
and ax,mf_share+mf_code+mf_load
|
|
cmp ax,mf_share+mf_code+mf_load ! jne sm_nxt
|
|
push si ! push ds
|
|
push ms_start[di]
|
|
push ms_start[di]
|
|
push lod_pd
|
|
push bx
|
|
mov ax,ss ! mov ds,ax
|
|
mov dx,sp ! mov cx,f_share
|
|
call osif
|
|
|
|
; This will always work.
|
|
|
|
pop ax ! pop ax ! pop ax
|
|
pop dx ! pop ds ! pop si
|
|
mov ldt_start[si],dx
|
|
ret
|
|
sm_no: mov cx,0ffffh ! ret
|
|
|
|
endif
|