mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-25 09:24:19 +00:00
1670 lines
37 KiB
Plaintext
1670 lines
37 KiB
Plaintext
title 'CCP/M-86 Bdos Loader'
|
|
;*****************************************************************
|
|
;*****************************************************************
|
|
;** **
|
|
;** B a s i c D i s k O p e r a t i n g S y s t e m **
|
|
;** I n t e r f a c e M o d u l e **
|
|
;** **
|
|
;*****************************************************************
|
|
;*****************************************************************
|
|
;
|
|
; Copyright (c) 1983
|
|
; Digital Research
|
|
; Box 579, Pacific Grove
|
|
; California
|
|
;
|
|
; January 1983
|
|
;
|
|
;*****************************************************
|
|
;
|
|
bdosoffset equ 0000h ; offset of BDOS-86
|
|
ldroffset equ 0906h ; offset of CLDCCPM
|
|
biosoffset equ 0900h ; offset of BIOS-86
|
|
;
|
|
;******************* BDOS symbols: *******************
|
|
;
|
|
;
|
|
true equ 0ffffh
|
|
false equ not true
|
|
;
|
|
; Special 8086 symbols:
|
|
;
|
|
b equ byte ptr 0
|
|
w equ word ptr 0
|
|
;
|
|
;*****************************************************
|
|
;
|
|
; BIOS Function numbers
|
|
;
|
|
;io_const equ 0 ;console status function
|
|
;io_conin equ 1 ;console input function
|
|
;io_conout equ 2 ;console output function
|
|
;io_listst equ 3 ;list status function
|
|
;io_list equ 4 ;list output function
|
|
;io_auxin equ 5 ;aux input function
|
|
;io_auxout equ 6 ;aux output function
|
|
;io_ equ 7
|
|
;io_ equ 8
|
|
io_seldsk equ 9 ;select disk function
|
|
io_read equ 10 ;read disk function
|
|
;io_write equ 11 ;write disk function
|
|
;io_flush equ 12 ;flush buffers function
|
|
;io_ equ 13
|
|
|
|
;
|
|
; literal constants
|
|
;
|
|
enddir EQU 0ffffh ;end of directory
|
|
;
|
|
; file control block (fcb) constants
|
|
;
|
|
fcblen EQU 32 ;fcb length
|
|
;empty EQU 0e5h ;empty directory entry
|
|
recsiz EQU 128 ;record size
|
|
dirrec EQU recsiz/fcblen ;directory elts / record
|
|
dskshf EQU 2 ;log2(dirrec)
|
|
dskmsk EQU dirrec-1
|
|
fcbshf EQU 5 ;log2(fcblen)
|
|
maxext EQU 31 ;largest extent number
|
|
maxmod EQU 63 ;largest module number
|
|
namlen EQU 15 ;name length
|
|
;lstfcb EQU fcblen-1
|
|
|
|
;drv EQU 0 ;drive field
|
|
;f1 EQU 1 ;file name byte 1 to 8
|
|
;f2 EQU 2
|
|
;f3 EQU 3
|
|
;f4 EQU 4
|
|
;f5 EQU 5
|
|
;f6 EQU 6
|
|
f7 EQU 7
|
|
;f8 EQU 8
|
|
;
|
|
; reserved file indicators
|
|
;
|
|
;rofile EQU 9 ;t1' -> read/only file
|
|
;sysfil EQU 10 ;t2' -> system file
|
|
;ARCHIV EQU 11 ;t3' -> FILE HAS BEEN ARCHIVED
|
|
extnum EQU 12 ;extent number field
|
|
chksum EQU 13 ;unfilled bytes field
|
|
modnum EQU 14 ;data module number
|
|
reccnt EQU 15 ;record count field
|
|
dskmap EQU 16 ;disk map field
|
|
nxtrec EQU fcblen
|
|
;ranrec EQU nxtrec+1 ;random record field (3 bytes)
|
|
;
|
|
;
|
|
; interrupt control indicators
|
|
;
|
|
interruptbit equ 200h ; bit 9 of flag word
|
|
;
|
|
;
|
|
;**************** end of BDOS symbols ****************
|
|
|
|
;***************** BDOS entry module *****************
|
|
;
|
|
; Perform branching, error handling and special
|
|
; 8086 handling.
|
|
;
|
|
;
|
|
cseg
|
|
org ldroffset
|
|
ldr_entry:
|
|
;
|
|
org bdosoffset
|
|
os_init:
|
|
jmp user_init
|
|
os_entry:
|
|
jmp user_entry
|
|
|
|
sysdat dw 0 ;system data segment
|
|
|
|
;=========
|
|
user_init:
|
|
;=========
|
|
mov ax,cs
|
|
mov ds,ax
|
|
mov es,ax
|
|
mov ss,ax
|
|
mov sp,offset bdosstack
|
|
mov bioscs,cs
|
|
callf dword ptr iosentry
|
|
mov biosco,bios_offset+3 ;set io call to entry
|
|
xor ax,ax
|
|
push ds! mov ds,ax
|
|
mov word ptr .0380h,offset os_entry
|
|
mov .0382h,cs
|
|
pop ds
|
|
jmp ldr_entry
|
|
|
|
;
|
|
;-----------------------------------------------------
|
|
;==========
|
|
user_entry:
|
|
;==========
|
|
; User Entry Point - enter here from a INT 224
|
|
;
|
|
; REGISTER USAGE
|
|
; ENTRY EXIT
|
|
; ----- ----
|
|
; CL - Function Code AX - Copy of BX
|
|
; DX - Param BX - Return
|
|
; DS - Seg Addr CX - Error Code
|
|
; ES - Segment Return
|
|
;
|
|
; DS,SI,DI,BP preserved through call
|
|
;
|
|
; contents of users stack
|
|
; Flags
|
|
; CS
|
|
; IP <- u_stack_ss,_sp
|
|
; DS = Sysdat Segment
|
|
; u_wrkseg = user's DS
|
|
; u_retseg = user's ES
|
|
|
|
cld ! mov ax,ds ;AX = user's DS
|
|
push cs ! pop ds
|
|
mov u_retseg,es ;save user's ES
|
|
|
|
mov u_wrkseg,ax ;wipe out earlier work seg
|
|
|
|
mov bx,sp ;enable interrupt if it was on
|
|
test ss:word ptr 4[bx],interruptbit
|
|
jz bdose1
|
|
sti
|
|
bdose1:
|
|
push ds! pop es
|
|
push si! push di! push bp
|
|
|
|
call func ;chk netwrk, returns BX, ES, CX
|
|
|
|
pop bp! pop di! pop si ;setup user's environment and return
|
|
mov es,u_retseg ;restore user's ES
|
|
mov ds,u_wrkseg ;DS = user's entry DS
|
|
mov ax,bx ;parameter return BX = AX
|
|
iret ;back to user ...
|
|
|
|
|
|
func:
|
|
;----
|
|
cmp cl,14! jne fn1
|
|
mov si,offset bdofunc+0
|
|
jmp bdo_entry
|
|
fn1: cmp cl,15! jne fn2
|
|
mov si,offset bdofunc+3
|
|
jmp bdo_entry
|
|
fn2: cmp cl,20! jne fn3
|
|
mov si,offset bdofunc+6
|
|
jmp bdo_entry
|
|
fn3: cmp cl,26! je func26
|
|
cmp cl,32! je func32
|
|
cmp cl,44! je func44
|
|
cmp cl,51! je func51
|
|
badfunc:
|
|
mov bx,0ffffh ;return ffff for illegal function
|
|
ret
|
|
;
|
|
func26: ;set the subsequent dma address to info
|
|
;======
|
|
mov dmaad,dx ;dmaad = info
|
|
ret
|
|
|
|
func32: ;set user code
|
|
;======
|
|
|
|
mov al,dl
|
|
cmp al,0ffh
|
|
jnz setusrcode
|
|
mov bl,p_user ;interrogate user code instead
|
|
ret
|
|
setusrcode:
|
|
and al,0fh
|
|
mov p_user,al
|
|
ret ;jmp goback
|
|
|
|
func44: ;set multi-sector count
|
|
;======
|
|
mov al,dl
|
|
xor bx,bx
|
|
or al,al
|
|
jz return_not_ok
|
|
cmp al,129
|
|
jnb return_not_ok
|
|
mov u_mult_cnt,al
|
|
ret
|
|
return_not_ok:
|
|
dec bx ;BX = 0ffffh
|
|
ret
|
|
|
|
func51: ;set segment base for disk I/O
|
|
;======
|
|
mov dmabase,dx
|
|
ret
|
|
|
|
;
|
|
;*************** end BDOS entry module ***************
|
|
|
|
;**************** BDOS Disk Functions ****************
|
|
|
|
;*****************************************************
|
|
;*
|
|
;* bdos function table
|
|
;*
|
|
;*****************************************************
|
|
|
|
; structure of entry in functab
|
|
|
|
btab_addr equ word ptr 0
|
|
btab_flag equ byte ptr (btab_addr + word)
|
|
bf_getmx equ 001h ;get mxdisk queue
|
|
bf_cshell equ 002h ;conditional shell function
|
|
|
|
; bdos function table
|
|
|
|
bdofunc equ offset $
|
|
dw func14 ! db 0001b ; fxi14 equ 01h ;select disk
|
|
dw func15 ! db 0001b ; fxi15 equ 02h ;open file
|
|
dw func20 ! db 0011b ; fxi20 equ 07h ;read sequential
|
|
|
|
;========
|
|
bdoentry: ; bdos module entry point
|
|
;========
|
|
; entry: SI = offset of bdos functab entry
|
|
; DX = argument
|
|
; DS = ES = system data area
|
|
; exit: BX = return code
|
|
|
|
mov ax,word ptr p_dsk
|
|
mov word ptr seldsk,ax ;set default disk and user code
|
|
|
|
mov cx,zerolength ! xor ax,ax ;zero local variables
|
|
mov di,offset fcbdsk
|
|
rep stosb
|
|
|
|
mov info,dx ;info=dx
|
|
|
|
cmp mult_cnt,1 ! je noshell ;if mult_cnt <> 1 and
|
|
test cs:btabflag[si],bf_cshell ; func uses mult_cnt then
|
|
jnz shell ; use bdos multi sector shell
|
|
noshell:
|
|
call call_bdos
|
|
retmon:
|
|
mov bx,aret
|
|
ret
|
|
;
|
|
shell:
|
|
;-----
|
|
; entry: SI = offset of functab entry
|
|
|
|
mov shell_si,si
|
|
mov ax,dmaad! mov shell_dma,ax
|
|
mov ah,cs:btabflag[si]
|
|
call parsave33
|
|
mov shell_flag,true
|
|
|
|
mov al,mult_cnt
|
|
mult_io1:
|
|
MOV MULT_NUM,AL
|
|
push ax
|
|
mov si,shell_si
|
|
mov dx,info
|
|
call call_bdos
|
|
mov bl,byte ptr aret
|
|
or bl,bl
|
|
jz no_shell_err
|
|
mov bh,mult_cnt
|
|
pop ax
|
|
sub bh,al ;BH = # of successfull records
|
|
jmps shell03
|
|
no_shell_err:
|
|
add dmaad,80h
|
|
pop ax! dec al
|
|
jnz mult_io1
|
|
xor bx,bx
|
|
|
|
shell03:
|
|
mov aret,bx
|
|
mov ax,shell_dma! mov dmaad,ax
|
|
mov shell_flag,false
|
|
call parunsave
|
|
jmp retmon
|
|
;
|
|
call_bdos:
|
|
;---------
|
|
; entry: DX = argument
|
|
; SI = offset of bdos functab entry
|
|
|
|
call setdata ;ready to go to the function
|
|
mov savesp,sp
|
|
call cs:btab_addr[si]
|
|
bdos_return:
|
|
cmp resel,0
|
|
je retmon5
|
|
mov al,fcbdsk
|
|
mov info_fcb,al
|
|
retmon5:
|
|
cmp parcopfl,true
|
|
jne retmon6
|
|
call parunsave ;copy local vars to uda
|
|
retmon6:
|
|
ret
|
|
;
|
|
parsave33: ;copy 33 byte length FCB
|
|
;---------
|
|
mov cl,33
|
|
;jmps parsave
|
|
;
|
|
parsave: ;copy FCB from user segment to bdos segment
|
|
;-------
|
|
; entry: CL = length of FCB to save
|
|
|
|
test shell_flag,true
|
|
jnz parret
|
|
mov parcopfl,true
|
|
mov parlg,cl
|
|
xor ch,ch
|
|
mov si,info
|
|
mov di,offset info_fcb
|
|
push ds
|
|
mov ds,parametersegment
|
|
rep movsb
|
|
pop ds
|
|
parret:
|
|
ret
|
|
;
|
|
parunsave: ;copy local FCB to user segment
|
|
;---------
|
|
test shell_flag,true
|
|
jnz parret
|
|
mov cl,parlg
|
|
xor ch,ch
|
|
mov si,offset info_fcb
|
|
mov di,info
|
|
push es
|
|
mov es,parametersegment
|
|
rep movsb
|
|
pop es
|
|
ret
|
|
|
|
setlret1:
|
|
mov al,1
|
|
staret:
|
|
mov lret,al
|
|
ret
|
|
|
|
;these functions added for mpm interface
|
|
|
|
;*****************************************************
|
|
;*
|
|
;* bdos - xios interface
|
|
;*
|
|
;*****************************************************
|
|
|
|
;====== ========================
|
|
xiosif: ; xios interface routine
|
|
;====== ========================
|
|
; entry: AL = function number
|
|
; CX = argument 1
|
|
; DX = argument 2
|
|
; exit: AX = BX = output
|
|
|
|
push es
|
|
callf dword ptr iosentry
|
|
cld! pop es
|
|
ret
|
|
|
|
;======== ================================
|
|
rwxiosif: ; disk read/write xios interface
|
|
;======== ================================
|
|
; entry: AL = function number
|
|
; exit: AX = BX = output
|
|
|
|
mov dx,arecord
|
|
mov ch,byte ptr arecord+2
|
|
mov bl,curdsk
|
|
mov bh,1
|
|
xchg bh,mult_sec ;BH = multi sector count
|
|
; stack on entry to the xios
|
|
push bx ; +C | DRV | MCNT |
|
|
push track ; +C | TRACK |
|
|
push sector ; +8 | SECTOR |
|
|
push curdmabase ; +6 | DMA_SEG |
|
|
push curdma ; +4 | DMA_OFF |
|
|
; +2 | RET_SEG |
|
|
; SP+0 | RET_OFF |
|
|
callf dword ptr iosentry
|
|
add sp,10 ;remove parameters from stack
|
|
cld! push ds! pop es
|
|
ret
|
|
|
|
;*****************************************************************
|
|
;*****************************************************************
|
|
;** **
|
|
;** b a s i c d i s k o p e r a t i n g s y s t e m **
|
|
;** **
|
|
;*****************************************************************
|
|
;*****************************************************************
|
|
|
|
;***************** bdos file system ******************
|
|
|
|
; error message handlers
|
|
|
|
pererror: ;report permanent error
|
|
;--------
|
|
mov ch,1
|
|
jmps goerr
|
|
|
|
selerror: ;report select error
|
|
;--------
|
|
mov curdsk,0ffh
|
|
mov ch,4
|
|
goerr:
|
|
mov cl,0ffh
|
|
mov aret,cx ;set aret
|
|
goback:
|
|
mov sp,save_sp
|
|
jmp bdos_return
|
|
|
|
|
|
; local subroutines for bios interface
|
|
;-----------------------------------------------------
|
|
|
|
move: ;block move data
|
|
;----
|
|
; entry: CL = length of data to move
|
|
; DX = source offset
|
|
; BX = destination offset
|
|
|
|
xor ch,ch
|
|
mov si,dx
|
|
mov di,bx
|
|
rep movsb
|
|
ret
|
|
|
|
selectdisk:
|
|
;----------
|
|
; select the disk drive given in AL, and fill
|
|
; the base addresses curtrka - alloca, then fill
|
|
; the values of the disk parameter block
|
|
; entry: AL = disk to select
|
|
; exit: C flag set if no error
|
|
|
|
mov cl,al ;current disk# to cl
|
|
;lsb of dl = 0 if not yet
|
|
mov al,io_seldsk ;logged in
|
|
call xiosif ;bx filled by call
|
|
;bx = 0000 if error,
|
|
or bx,bx ;otherwise disk headers
|
|
jz ret4 ;rz - carry flag reset
|
|
add bx,8
|
|
mov si,bx
|
|
MOV di,OFFSET DPBADDR ;dx= source for move, bx=dest
|
|
mov cx,addlist ;addlist filled
|
|
rep movsb ;now fill the disk
|
|
mov si,dpbaddr ;parameter block
|
|
mov di,offset sectpt ;bx is destination
|
|
mov cx,dpblist
|
|
rep movsb ;data filled
|
|
mov cl,physhf ;convert # sectors per track
|
|
shl sectpt,cl ; from physical to logical
|
|
;set single/double map mode
|
|
mov al,byte ptr maxall+1 ;largest allocation number
|
|
or al,al
|
|
jz retselect
|
|
;if high order of maxall not
|
|
mov al,1 ;zero then use double disk map
|
|
retselect:
|
|
dec al
|
|
mov single,al ;true if single disk map mode
|
|
stc ;select disk function ok
|
|
ret4:
|
|
ret
|
|
|
|
rdbuff: ;read buffer and check if ok
|
|
;------
|
|
mov al,io_read
|
|
call rwxiosif ;current drive, track,....
|
|
|
|
diocomp: ;check for disk errors
|
|
;-------
|
|
; entry: AL = xios return code
|
|
|
|
or al,al! jz ret4 ;rz
|
|
jmp pererror ; no
|
|
|
|
seek: ;seek the track given by arecord (actual record)
|
|
;----
|
|
mov ax,arecord ;compute track/sector
|
|
xor dx,dx
|
|
mov dl,byte ptr arecord+2
|
|
div sectpt ;dx=sector, ax=track
|
|
add ax,offsetv
|
|
MOV TRACK,ax ;save bios/xios track
|
|
MOV CL,PHYSHF
|
|
SHR dx,CL ;PHY SECTOR = SHR(LOG SECTOR,PHYSHF)
|
|
MOV SECTOR,dx ;save bios/xios sector
|
|
ret
|
|
|
|
; utility functions for file access
|
|
|
|
dmposition: ;compute disk map position for vrecord
|
|
;----------
|
|
; exit: AL = disk map position of vrecord
|
|
|
|
mov cl,blkshf ;shift count to CL
|
|
mov ch,vrecord ;current virtual record to a
|
|
shr ch,cl ;CH = shr(vrecord,blkshf)
|
|
; = vrecord/2**(sect/block)
|
|
neg cl
|
|
add cl,7 ;CL = 7 - blkshf
|
|
mov al,extval ;extent value and extmsk
|
|
;blkshf = 3,4,5,6,7
|
|
;CL = 4,3,2,1,0
|
|
;shift is 4,3,2,1,0
|
|
shl al,cl ;AL = shl(ext and extmsk,7-blkshf)
|
|
add al,ch ;add the previous
|
|
;shr(vrecord,blkshf) value
|
|
;AL is one of the following
|
|
;values, depending upon alloc
|
|
;bks blkshf
|
|
;1k 3 v/8 + extval * 16
|
|
;2k 4 v/16+ extval * 8
|
|
;4k 5 v/32+ extval * 4
|
|
;8k 6 v/64+ extval * 2
|
|
;16k 7 v/128+extval * 1
|
|
ret ;with dm$position in a
|
|
|
|
getdm: ;return disk map value from position given by cx
|
|
;-----
|
|
; entry: CX = index into disk map
|
|
; exit: BX = disk map value at position CX
|
|
|
|
mov bx,offset info_fcb+dskmap
|
|
add bx,cx ;index by asingle byte value
|
|
cmp single,0 ;single byte/map entry?
|
|
jz getdmd ;get disk map single byte
|
|
mov bl,[bx]
|
|
xor bh,bh
|
|
ret ;with bx=00bb
|
|
getdmd:
|
|
add bx,cx ;bx=.fcb(dm+1*2)
|
|
mov bx,[bx] ;return double precision value
|
|
ret
|
|
|
|
index: ;compute disk block number from current fcb
|
|
;-----
|
|
; exit: BX = disk map value for vrecord in current fcb
|
|
; Z flag set according to value in BX
|
|
|
|
call dmposition ;0...15 in register al
|
|
MOV DMINX,AL
|
|
mov cl,al
|
|
xor ch,ch
|
|
call getdm ;value to bx
|
|
mov arecord,bx
|
|
or bx,bx
|
|
ret
|
|
|
|
atran: ;compute actual record address, assuming index called
|
|
;-----
|
|
mov cl,blkshf ;shift count to reg al
|
|
mov ax,arecord
|
|
xor bh,bh
|
|
mov bl,ah
|
|
shl ax,cl
|
|
shl bx,cl
|
|
xchg ax,bx
|
|
mov al,vrecord
|
|
and al,blkmsk ;masked value in al
|
|
mov blkoff,al
|
|
or bl,al
|
|
mov arecord,bx ;arecord=bx or
|
|
;(vrecord and blkmsk)
|
|
mov byte ptr arecord+2,ah
|
|
ret
|
|
|
|
getfcb: ;set local variables from currently addressed fcb
|
|
;------
|
|
mov al,info_fcb+nxtrec
|
|
mov vrecord,al ;vrecord=fcb(nxtrec)
|
|
cmp info_fcb+reccnt,0
|
|
jne getfcb0
|
|
call get_dir_ext
|
|
mov cl,al
|
|
call set_rc
|
|
getfcb0:
|
|
mov al,info_fcb+reccnt
|
|
cmp al,81h! jb getfcb1
|
|
mov al,80h
|
|
getfcb1:
|
|
mov rcount,al ;rcount=fcb(reccnt)
|
|
mov al,extmsk ;extent mask to a
|
|
and al,info_fcb+extnum ;fcb(extnum) and extmsk
|
|
mov extval,al
|
|
ret
|
|
|
|
setfcb: ;place local values back into current fcb
|
|
;------
|
|
mov al,1
|
|
add al,vrecord
|
|
mov info_fcb+nxtrec,al ;fcb(nxtrec)=vrecord+seqio
|
|
cmp info_fcb+reccnt,80h
|
|
jnb ret41 ;dont reset if fcb(rc) > 7fh
|
|
mov al,rcount
|
|
mov info_fcb+reccnt,al ;fcb(reccnt)=rcount
|
|
ret41: ret
|
|
|
|
getdptra:
|
|
;--------
|
|
; compute the address of a directory element at
|
|
; positon dptr in the buffer
|
|
; exit: BX = buffa + dptr
|
|
|
|
mov bl,dptr
|
|
xor bh,bh
|
|
add bx,buffa ;bx = buffa + dptr
|
|
ret
|
|
|
|
|
|
rddir: ;read the current directory record
|
|
;-----
|
|
MOV ax,DCNT ;seek the record containing
|
|
MOV CL,DSKSHF! SHR ax,CL ; the current dir entry
|
|
MOV ARECORD,ax ;ARECORD = SHR(DCNT,DSKSHF)
|
|
MOV BYTE PTR ARECORD+2,0
|
|
MOV AH,3 ;LOCATE COMMAND
|
|
CALL DEBLOCK_DIR
|
|
;JMPS SETDATA
|
|
|
|
setdata: ;set data dma address
|
|
;-------
|
|
MOV ax,DMABASE
|
|
MOV CUR_DMABASE,ax
|
|
MOV ax,DMAAD
|
|
MOV CURDMA,ax
|
|
RET
|
|
|
|
endofdir: ;check if end of directory (dcnt = 0ffffh)
|
|
;--------
|
|
; exit: Z flag set if at end of directory
|
|
|
|
mov bx,offset dcnt
|
|
|
|
test_ffff:
|
|
;---------
|
|
cmp w[bx],0ffffh
|
|
ret
|
|
|
|
setenddir: ;set dcnt to the end of directory (dcnt = 0ffffh)
|
|
;---------
|
|
mov dcnt,enddir
|
|
ret
|
|
|
|
read_dir: ;read next directory entry
|
|
;--------
|
|
|
|
mov dx,dirmax ;in preparation for subtract
|
|
mov bx,dcnt
|
|
inc bx
|
|
mov dcnt,bx ;dcnt=dcnt+1
|
|
;continue while dirmax >= dcnt
|
|
;(dirmax-dcnt no cy)
|
|
sub dx,bx
|
|
jb setenddir ;yes, set dcnt to end
|
|
;of directory
|
|
; not at end of directory, seek next element
|
|
;cl=initialization flag
|
|
mov al,ldcnt
|
|
and al,dskmsk ;low(dcnt) and dskmsk
|
|
mov cl,fcbshf ;to multiply by fcb size
|
|
shl al,cl
|
|
;a = (low(dcnt) and dskmsk)
|
|
;shl fcbshf
|
|
mov dptr,al ;ready for next dir operation
|
|
or al,al
|
|
jnz ret71 ;return if not a new record
|
|
call rddir ;read the directory record
|
|
ret71:
|
|
ret
|
|
|
|
compext: ;compare extent# in al with that in cl
|
|
;-------
|
|
; entry: AL,CL = extent numbers to compare
|
|
; exit: Z flag set if extent numbers match
|
|
; BX,CX,DX = preserved
|
|
|
|
push cx ;save cx's original value
|
|
mov ch,extmsk
|
|
not ch ;ch has negated form of
|
|
;extent mask
|
|
and cl,ch ;low bits removed from cl
|
|
and al,ch ;low bits removed from al
|
|
sub al,cl
|
|
and al,maxext ;set flags
|
|
pop cx ;restore cx
|
|
ret
|
|
|
|
get_dir_ext:
|
|
;-----------
|
|
; compute directory extent from fcb
|
|
; scan fcb disk map backwards
|
|
; upon return dminx = 0 if no blocks are in fcb
|
|
; exit: AL = directory extent number
|
|
; BX = .fcb(extnum)
|
|
|
|
mov bx,offset info_fcb+nxtrec ;BX = .fcb(vrecord)
|
|
mov dx,1001h ;DH = disk map position (rel to 1)
|
|
;DL = no blocks switch
|
|
get_de1:
|
|
dec dh
|
|
dec bx ;decrement disk map ptr
|
|
cmp b[bx],0 ;is disk map byte non-zero ?
|
|
jne get_de2 ; yes
|
|
or dh,dh ; no - continue scan
|
|
jnz get_de1
|
|
dec dl ;DL = 0 if no blocks found
|
|
get_de2:
|
|
mov dminx,dl ;dminx = 0 if no blocks in fcb
|
|
cmp single,true ;are disk block indexes single byte ?
|
|
mov al,dh ;al = block offset in disk map
|
|
jz get_de3 ;yes
|
|
shr al,1 ;divide block offset by 2
|
|
|
|
; al = last non-zero block index in fcb (rel to 0)
|
|
; compute ext offset from last non-zero block index by
|
|
; shifting block index right 7-blkshf
|
|
|
|
get_de3:
|
|
mov cl,7
|
|
sub cl,blkshf
|
|
shr al,cl ;al = ext offset
|
|
|
|
mov ah,extmsk ;if ext offset > extmsk then
|
|
cmp ah,al ; continue scan
|
|
jb get_de1
|
|
|
|
; dir ext = (fcb ext & (~extmsk) & maxext) | ext offset
|
|
|
|
mov bx,offset info_fcb+extnum ;bx = .fcb(ext)
|
|
mov cl,[bx] ;cl = fcb extent value
|
|
not ah ;ah = ~extmsk
|
|
and ah,maxext ;ah = ah & maxext
|
|
and ah,cl ;ah = ah & fcb extent
|
|
or al,ah ;al = dir ext
|
|
ret
|
|
|
|
searchi: ;search initialization
|
|
;-------
|
|
mov bx,offset info_fcb
|
|
mov srcha,bx ;searcha = .info_fcb
|
|
mov srchl,cl ;searchl = cl
|
|
ret
|
|
|
|
search_name: ;search matching name
|
|
;-----------
|
|
mov cl,namlen
|
|
;jmps search
|
|
|
|
search: ;search for directory element at .info_fcb
|
|
;------
|
|
; entry: CL = search length
|
|
|
|
call searchi
|
|
call setenddir ;dcnt = enddir
|
|
;to start at the beginning
|
|
;(drop through to searchn)
|
|
;
|
|
searchn:
|
|
;-------
|
|
; search for the next directory element, assuming
|
|
; a previous call on search which sets searcha and searchhl
|
|
; exit: Z flag = 0 for successful searches
|
|
|
|
call read_dir ;read next dir element
|
|
call endofdir
|
|
jz srchfin
|
|
;skip to end if so
|
|
;not end of directory,
|
|
;scan for match
|
|
mov dx,srcha ;dx=beginning of user fcb
|
|
call getdptra ;bx = buffa+dptr
|
|
mov cl,srchl ;length of search to cl
|
|
xor ch,ch ;ch counts up, cl counts down
|
|
|
|
mov al,[bx] ;is fcb an xfcb ?
|
|
and al,11101111b
|
|
cmp al,[bx]
|
|
je srch_loop ;no
|
|
jmps search_n
|
|
srchfin: ;end of directory, or empty name
|
|
lret_eq_ff:
|
|
mov al,255
|
|
mov ch,al
|
|
inc ch ;zero flag set on unsuccessful
|
|
jmp staret ;searches
|
|
|
|
srchloop:
|
|
or cl,cl
|
|
jz endsearch
|
|
mov si,dx
|
|
lods al ;fcb character
|
|
and al,07fh
|
|
;scan next character if not
|
|
;chksum byte
|
|
cmp ch,chksum
|
|
jz srchok
|
|
;not the ubytes field,
|
|
;extent field
|
|
cmp ch,extnum ;may be extent field
|
|
jz srchext ;skip to search extent
|
|
|
|
cmp ch,modnum ;is field module # ?
|
|
jnz $+4 ;no
|
|
and al,3fh ;yes - mask off high order bits
|
|
|
|
sub al,[bx]
|
|
and al,7fh ;mask-out flags/extent modulus
|
|
jnz searchn_jmp
|
|
jmps srchok ;matched character
|
|
|
|
srchext: ;AL = fcb character
|
|
;attempt an extent # match
|
|
push cx ;save counters
|
|
mov cl,[bx] ;directory character to c
|
|
call compext ;compare user/dir char
|
|
pop cx ;recall counters
|
|
jnz searchn_jmp ;skip if no match
|
|
|
|
srchok: ;current character matches
|
|
inc dx! inc bx
|
|
inc ch! dec cl
|
|
jmps srchloop
|
|
|
|
searchn_jmp:
|
|
jmp searchn
|
|
|
|
endsearch: ;entire name matches, return dir position
|
|
xor al,al
|
|
mov lret,al
|
|
mov ch,al
|
|
inc ch ;zero flag reset on successful
|
|
ret ;searches
|
|
|
|
check_wild: ;check for ? in file name or type
|
|
;----------
|
|
mov bx,offset info_fcb
|
|
call chk_wild
|
|
jnz ret10
|
|
mov al,9 ;extended error 9
|
|
jmp set_aret
|
|
|
|
chk_wild: ;check fcb for ? marks
|
|
;--------
|
|
; entry: BX = .fcb(0)
|
|
; exit: Z flag = 1 if ? mark found
|
|
|
|
mov cx,3f0bh ;ch = 3f, cl = 11
|
|
chk_wild1:
|
|
inc bx ;advance fcb ptr
|
|
mov al,ch
|
|
sub al,[bx]
|
|
and al,ch
|
|
jz ret10 ;rtn with z flag set if ? fnd
|
|
dec cl
|
|
jnz chk_wild1
|
|
or al,al ;rtn with z flag reset - no ?s
|
|
ret10: ret
|
|
|
|
open: ;search for the directory entry, copy to fcb
|
|
;----
|
|
call search_name
|
|
jz ret10 ;return with lret=255 if end
|
|
;not end of directory,copy fcb
|
|
opencopy:
|
|
;(referenced below to copy fcb
|
|
push bx ;bx = .fcb(modnum)
|
|
dec bx! dec bx
|
|
mov ah,[bx] ;ah = extnum
|
|
push ax ;save extnum & modnum
|
|
call getdptra
|
|
mov dx,bx ;dx = .buff(dptr)
|
|
mov bx,offset info_fcb ;bx=.fcb(0)
|
|
mov cl,nxtrec ;length of move operation
|
|
call move ;from .buff(dptr) to .fcb(0)
|
|
;note that entire fcb is
|
|
;copied, including indicators
|
|
call get_dir_ext
|
|
mov cl,al ;cl = dir_ext
|
|
pop ax! pop bx
|
|
mov [bx],al ;restore modnum
|
|
dec bx! dec bx
|
|
mov [bx],ah ;restore extnum number
|
|
|
|
; bx = .user extent#, cl = dir extent#
|
|
; if user ext < dir ext then user := 128 records
|
|
; if user ext = dir ext then user := dir records
|
|
; if user ext > dir ext then user := 0 records
|
|
|
|
set_rc:
|
|
;------
|
|
; entry: BX = .user extent #
|
|
; CL = dir extent #
|
|
|
|
xor ch,ch
|
|
mov si,offset info_fcb+reccnt
|
|
mov al,[bx] ;al = current extent
|
|
sub al,cl ;compare fcb ext to dir ext
|
|
jz set_rc2 ;fcb ext = dir ext
|
|
; actual_rc = 0, fcb(rc) = fcb(rc)
|
|
mov al,ch
|
|
jae set_rc1 ;fcb ext > dir ext
|
|
; actual_rc = 0, fcb(rc) = 0
|
|
|
|
mov al,128 ;fcb ext < dir ext
|
|
or al,[si] ; fcb(rc) = 128 | fcb(rc)
|
|
set_rc1:
|
|
mov [si],al
|
|
ret11: ret
|
|
|
|
set_rc2:
|
|
cmp b[si],al ;is fcb(rc) = 0?
|
|
jnz ret11 ;no
|
|
xor al,al ;AL = 0
|
|
mov b[si],al ;required by func 99
|
|
cmp dminx,al ;do blocks exist in fcb?
|
|
jz ret11 ;no
|
|
mov b[si],80h ;fcb(rc) = 80h
|
|
ret
|
|
|
|
restore_rc:
|
|
;----------
|
|
; if actual_rc ~= 0 then fcb(rc) = actual_rc
|
|
; entry: BX = .fcb(extnum)
|
|
|
|
mov al,info_fcb+reccnt
|
|
cmp al,81h
|
|
jb restore_rc1
|
|
and al,7fh
|
|
mov info_fcb+reccnt,al
|
|
restore_rc1:
|
|
ret
|
|
|
|
openreel:
|
|
;--------
|
|
; close the current extent, and open the next one
|
|
; if possible. rmf is true if in read mode.
|
|
; lret is set to 0 if successful
|
|
|
|
mov al,info_fcb+modnum
|
|
mov save_mod,al ;save current module #
|
|
mov bx,offset info_fcb+extnum
|
|
mov al,[bx]
|
|
mov cl,al
|
|
inc cl ;increment ext #
|
|
call comp_ext ;did we cross a dir fcb boundary ?
|
|
jnz $+5
|
|
jmp openr3 ;no
|
|
mov al,maxext
|
|
and al,cl
|
|
mov [bx],al ;update fcb extent field
|
|
jnz openr0 ;branch if in same module
|
|
|
|
; extent number overflow, go to next module
|
|
|
|
add bx,(modnum-extnum) ;bx=.fcb(modnum)
|
|
inc b[bx] ;fcb(modnum)=++1
|
|
;module number incremented,
|
|
;check for overflow
|
|
mov al,[bx]
|
|
and al,maxmod ;mask high order bits
|
|
jz openerr ;cannot overflow to 0
|
|
;otherwise, ok to continue
|
|
;with new module
|
|
openr0:
|
|
call search_name ;next extent found?
|
|
jz openerr ;end of file encountered
|
|
call opencopy
|
|
openr2:
|
|
call getfcb ;set parameters
|
|
xor al,al
|
|
mov vrecord,al
|
|
jmp staret ;lret = 0
|
|
;ret
|
|
|
|
openerr:
|
|
;-------
|
|
mov bx,offset info_fcb+extnum
|
|
mov al,save_mod
|
|
mov 2[bx],al
|
|
mov al,[bx]
|
|
dec al
|
|
and al,1fh
|
|
mov [bx],al
|
|
;cannot move to next extent
|
|
;of this file
|
|
jmp setlret1 ;lret = 1
|
|
;ret
|
|
openr3:
|
|
mov [bx],cl ;increment extent field
|
|
call get_dir_ext
|
|
mov cl,al
|
|
cmp al,[bx] ;is dir ext < fcb(ext)?
|
|
jae openr4 ;no
|
|
dec b[bx] ;decrement extent
|
|
jmp set_lret1 ;yes - reading unwritten data
|
|
openr4:
|
|
call restore_rc
|
|
call set_rc
|
|
jmps openr2
|
|
|
|
diskread: ;(may enter from seqdiskread)
|
|
;--------
|
|
;read the next record from
|
|
;the current fcb
|
|
call getfcb ;sets parameters for the read
|
|
mov al,vrecord
|
|
cmp al,rcount ;vrecord-rcount
|
|
;skip if rcount > vrecord
|
|
jb recordok
|
|
;not enough records in extent
|
|
;record count must be 128
|
|
;to continue
|
|
cmp al,128 ;vrecord = 128?
|
|
jnz diskeof ;skip if vrecord<>128
|
|
call openreel ;go to next extent if so
|
|
;now check for open ok
|
|
cmp lret,0 ;stop at eof
|
|
jnz diskeof
|
|
recordok: ;fcb addresses a record to read
|
|
call index ;error 2 if reading
|
|
;unwritten data
|
|
;(returns 1 to be compatible
|
|
;with 1.4)
|
|
;arecord=0000?
|
|
jz diskeof
|
|
call atran ;arecord now a disk address
|
|
CALL CHECK_NPRS
|
|
JC RECORDOK2
|
|
JNZ $+5
|
|
JMP READ_DEBLOCK
|
|
CALL SETDATA
|
|
call seek ;to proper track,sector
|
|
call rdbuff ;to dma address
|
|
RECORDOK2:
|
|
jmp setfcb ;replace parameter
|
|
|
|
diskeof:
|
|
jmp setlret1 ;lret = 1
|
|
;ret
|
|
|
|
CHECK_NPRS:
|
|
;----------
|
|
; DIR_CNT CONTAINS THE NUMBER OF 128 BYTE RECORDS
|
|
; TO TRANSFER DIRECTLY. THIS ROUTINE SET DIR_CNT
|
|
; WHEN INITIATING A SEQUENCE OF DIRECT PHYSICAL I/O
|
|
; OPERATIONS. DIR_CNT IS DECREMENTED EACH TIME CHECK_NPRS
|
|
; IS CALLED DURING SUCH A SEQUENCE.
|
|
; exit: ~C FLG & ~Z FLG - DIRECT PHYSICAL I/O OPERATION
|
|
; ~C FLG & Z FLG - INDIRECT(DEBLOCK) I/O OPERATION
|
|
; C FLG - NO PHYSICAL I/O OPERATION
|
|
|
|
MOV CH,blk_off ;CH = VRECORD & BLKMSK
|
|
MOV AL,DIR_CNT
|
|
CMP AL,2 ;IS DIR_CNT > 1?
|
|
JC CHECK_NPR1 ;NO
|
|
DEC AL ;DIR_CNT = DIR_CNT - 1
|
|
MOV DIR_CNT,AL ;we are in mid-multi sector i/o
|
|
STC
|
|
ret ;RETURN WITH C FLAG SET
|
|
CHECK_NPR1:
|
|
MOV AL,PHYMSK ;CL = PHYMSK
|
|
MOV CL,AL
|
|
AND AL,CH ;AL = VRECORD & PHYMSK
|
|
;ARE WE IN MID-PHYSICAL RECORD?
|
|
JZ CHECK_NPR11 ;NO
|
|
CHECK_NPR1X:
|
|
OR CL,CL ;IS PHYMSK = 0?
|
|
JZ CHECK_NPR1Y ;YES
|
|
XOR AL,AL ;RETURN WITH Z FLAG SET & C FLAG RESET
|
|
RET
|
|
CHECK_NPR1Y:
|
|
OR AL,1 ;RESET C & Z FLAGS
|
|
RET
|
|
CHECK_NPR11:
|
|
MOV DH,CL
|
|
not DH ;DH = ~ PHYMSK
|
|
MOV AL,MULTNUM
|
|
CMP AL,2 ;IS MULT_NUM < 2?
|
|
JC CHECK_NPR1X ;YES
|
|
MOV BX,OFFSET VRECORD
|
|
MOV AH,[BX] ;AH = VRECORD
|
|
ADD AL,ah
|
|
CMP AL,80H
|
|
JC CHECK_NPR2
|
|
MOV AL,80H
|
|
CHECK_NPR2: ;AL = MIN(VRECORD + MULT_NUM,80H) = X
|
|
PUSH CX ;SAVE VRECORD & BLKMSK, PHYMSK
|
|
MOV B[BX],7FH ;VRECORD = 7F
|
|
PUSH BX! PUSH AX
|
|
MOV BL,AL ;BL = X
|
|
MOV AL,BLKMSK
|
|
MOV DL,AL
|
|
INC DL ;DL = BLKMSK + 1
|
|
not AL
|
|
AND AH,AL ;AH = VRECORD & ~BLKMSK
|
|
MOV AL,RCOUNT
|
|
AND AL,DH ;AL = RCOUNT & ~PHYMSK
|
|
CMP AL,BL ;IS AL < X?
|
|
JC CHECK_NPR23 ;YES
|
|
MOV AL,BL ;AL = MIN(VRECORD + MULT_NUM,80H) = X
|
|
CHECK_NPR23:
|
|
SUB AL,AH ;AL = AL - VRECORD & ~BLKMSK
|
|
CMP AL,DL ;IS AL < BLKMSK + 1?
|
|
JC CHECK_NPR9 ;YES
|
|
PUSH AX ;AL = MAX # OF RECORDS
|
|
CALL DMPOSITION ;COMPUTE MAXIMUM DISK POSITION
|
|
MOV CH,AL ;CH = MAX DISK POS
|
|
MOV AL,DMINX ;AL = CURRENT DISK POS
|
|
CMP AL,CH ;IS CURR POS = MAX POS?
|
|
MOV DL,AL
|
|
JZ CHECK_NPR5 ;YES
|
|
MOV CL,AL
|
|
PUSH CX ;CL = CURR POS, CH = MAX POS
|
|
MOV CH,0
|
|
CALL GET_DM ;BX = BLOCK NUMBER (CURR POS)
|
|
CHECK_NPR4:
|
|
PUSH BX
|
|
INC CX ;CURR POS = CURR POS + 1
|
|
CALL GET_DM ;GET NEXT BLOCK(CURR POS)
|
|
POP DX
|
|
INC DX
|
|
CMP BX,DX ;DOES CURR BLK = LAST BLK + 1?
|
|
JZ CHECK_NPR4 ;YES
|
|
|
|
DEC CL ;CL = INDEX OF LAST SEQ BLK
|
|
POP DX
|
|
MOV AL,DH ;AL = MAX POS
|
|
CMP AL,CL ;IS AL < LAST SEQ BLK POS
|
|
JC CHECK_NPR5 ;YES
|
|
MOV AL,CL
|
|
CHECK_NPR5: ;AL = LAST BLK POS
|
|
SUB AL,DL ;AL = AL - STARTING POS
|
|
MOV CH,AL
|
|
INC CH ;CH = # OF CONSECUTIVE BLOCKS
|
|
MOV AL,BLKMSK
|
|
INC AL ;AL = BLKMSK + 1
|
|
MUL CH ;AL = # OF CONSECUTIVE LOGICAL RECS
|
|
POP CX ;CL = MAXIMUM # OF RECORDS
|
|
XCHG AL,CL
|
|
CMP AL,CL ;IS MAX < # OF CONS. RECS?
|
|
JC CHECK_NPR9 ;YES
|
|
MOV AL,CL
|
|
CHECK_NPR9: ;AL = # OF CONSECUTIVE RECS
|
|
POP CX
|
|
POP BX
|
|
MOV [BX],CH ;RESTORE VRECORD
|
|
POP CX
|
|
MOV DH,MULT_NUM
|
|
SUB AL,CH ;AL = AL - VRECORD & blkmsk
|
|
CMP AL,DH ;IS AL < MULT_NUM
|
|
JC CHECK_NPR10 ;YES
|
|
MOV AL,DH
|
|
CHECK_NPR10: ;AL = # OF CONSECUTIVE RECS
|
|
not CL
|
|
AND AL,CL ;IF DIR_CNT = 0 THEN
|
|
JZ RET13B ;RETURN WITH Z FLAG SET, C FLAG RESET
|
|
MOV DIR_CNT,AL ;DIR_CNT = AL & ~PHYMSK
|
|
MOV CL,PHYSHF
|
|
SHR AL,CL ;AL = # OF CONSECUTIVE PHYSICAL RECS
|
|
mov mult_sec,al ;save multisector count for r/w
|
|
OR AL,1 ;RETURN WITH C AND Z FLAGS RESET
|
|
RET13B: RET
|
|
|
|
tmp_select:
|
|
;----------
|
|
; entry: DL = drive to select (0-f)
|
|
|
|
mov seldsk,dl
|
|
|
|
curselect:
|
|
;---------
|
|
mov al,seldsk
|
|
cmp al,curdsk
|
|
jne select ;don't select if seldsk = curdsk
|
|
inc al! jz select0
|
|
ret
|
|
|
|
SELECT: ;select disk in info_fcb for subsequent input or output ops
|
|
;------
|
|
cmp al,16 ! jb disk_select
|
|
select0:
|
|
jmp selerror
|
|
disk_select:
|
|
;-----------
|
|
; entry: AL = disk to select
|
|
|
|
mov adrive,al
|
|
mov curdsk,al
|
|
xor dx,dx ;dl = 1 if drive logged in
|
|
call selectdisk
|
|
jnc select0 ;carry set if select ok
|
|
ret
|
|
|
|
parsave33r:
|
|
;----------
|
|
call parsave33
|
|
;jmps reselect
|
|
|
|
reselect:
|
|
;--------
|
|
mov cl,07fh
|
|
mov bx,offset info_fcb+f7
|
|
and [bx],cl ;fcb(7) = fcb(7) & 7fh
|
|
and 1[bx],cl
|
|
and byte ptr extnum-f7[bx],1fh ;fcb(ext) = fcb(ext) & 1fh
|
|
;check current fcb to see if reselection necessary
|
|
mov resel,true ;mark possible reselect
|
|
mov al,info_fcb ;drive select code
|
|
mov fcbdsk,al ;save drive
|
|
and al,00011111b ;non zero is auto drive select
|
|
dec al ;drive code normalized to
|
|
;0...30, or 255
|
|
cmp al,0ffh
|
|
jz noselect ;auto select function,
|
|
mov seldsk,al ;save seldsk
|
|
noselect:
|
|
call curselect
|
|
;set user code
|
|
mov al,usrcode ;0...31
|
|
mov info_fcb,al
|
|
ret
|
|
|
|
compare: ;compare strings
|
|
;-------
|
|
; entry: CL = length of strings
|
|
; BX,DX = offset of strings
|
|
; exit: Z flag set if strings match
|
|
|
|
mov ch,0
|
|
mov si,bx
|
|
mov di,dx
|
|
repe cmps al,al
|
|
ret
|
|
|
|
|
|
; individual function handlers
|
|
;-----------------------------------------------------
|
|
|
|
func14: ;select disk info
|
|
;======
|
|
call tmp_select
|
|
mov al,seldsk
|
|
mov p_dsk,al
|
|
ret
|
|
|
|
func15: ;open file
|
|
;======
|
|
call parsave33r ;copy fcb from user seg.
|
|
mov info_fcb+modnum,0 ;fcb(modnum)=0
|
|
call check_wild ;check for ?s in fcb
|
|
call open ;attempt to open fcb
|
|
call openx ;returns if unsuccessful
|
|
xor al,al
|
|
ret30: ret ;no - open failed
|
|
|
|
openx:
|
|
;-----
|
|
call end_of_dir ;was open successful
|
|
jz ret30 ;no
|
|
mov bx,offset info_fcb+nxtrec
|
|
cmp b[bx],0ffh
|
|
jne openxa
|
|
mov al,info_fcb+chksum
|
|
mov [bx],al
|
|
openxa:
|
|
pop bx ;discard return address
|
|
MOV CL,40H
|
|
ret
|
|
|
|
func20: ;read a file
|
|
;======
|
|
call parsave33r
|
|
jmp disk_read
|
|
;jmp goback
|
|
|
|
set_aret:
|
|
;--------
|
|
mov cl,al ;save error index
|
|
mov byte ptr aret+1,al ;aret+1 = extended errors
|
|
call lret_eq_ff
|
|
|
|
jmp goback ;return physical & extended errors
|
|
|
|
; BLOCKING/DEBLOCKING BUFFER CONTROL BLOCK (BCB) FORMAT
|
|
|
|
; +-------+-------+-------+-------+-------+-------+
|
|
; 00h | DRV | RECORD | PEND | SEQ |
|
|
; +-------+-------+-------+-------+-------+-------+
|
|
; 06h | TRACK | SECTOR | BUFFER_ADDR |
|
|
; +-------+-------+-------+-------+-------+-------+
|
|
; 0Ch | LINK | PROCESS_OFF |
|
|
; +-------+-------+-------+-------+
|
|
|
|
READ_DEBLOCK:
|
|
;------------
|
|
mov ah,1 ;AH = 1
|
|
CALL DEBLOCK_DTA
|
|
JMP SET_FCB
|
|
|
|
DEBLOCK_DIR:
|
|
;-----------
|
|
MOV CUR_DMABASE,DS ;BUFFERS IN SYSTEM DATA AREA
|
|
MOV BX,DIRBCBA
|
|
jmps DEBLOCK ;PREVIOUS LOCATE CALL
|
|
|
|
DEBLOCK_DTA:
|
|
;-----------
|
|
MOV BX,DTABCBA
|
|
MOV CUR_DMABASE,0 ;get segment from BCB
|
|
|
|
DEBLOCK: ;BDOS BLOCKING/DEBLOCKING ROUTINE
|
|
;-------
|
|
; entry: Z flag reset -> get new BCB address
|
|
; AH = 1 -> READ COMMAND
|
|
; = 2 -> WRITE COMMAND
|
|
; = 3 -> LOCATE COMMAND
|
|
; = 4 -> FLUSH COMMAND
|
|
; = 5 -> DIRECTORY UPDATE
|
|
|
|
MOV DEBLOCK_FX,AH ;SAVE DEBLOCK FX
|
|
mov cl,phymsk ;CL = PHYMSK
|
|
MOV AL,BYTE PTR ARECORD
|
|
AND AL,cl
|
|
MOV PHY_OFF,AL ;PHY_OFF = LOW(ARECORD) & PHYMSK
|
|
not cl ;CL = ~PHYMSK
|
|
and BYTE PTR ARECORD,cl ;LOW(ARECORD) = LOW(ARECORD) & ~PHYMSK
|
|
mov bx,[bx] ;GET BCB ADDRESS
|
|
MOV CURBCBA,BX ;BX = 1st curbcb
|
|
MOV ax,10[BX] ;dma address field - offset/segment
|
|
cmp cur_dmabase,0 ;if cur_dmabase <> 0, deblocking is
|
|
jne deblock0 ; for dir buf and addr is offset
|
|
mov cur_dmabase,ax ;else deblocking data buffer and
|
|
xor ax,ax ; addr is segment, offset = 0
|
|
deblock0:
|
|
MOV CURDMA,ax ;save current buffer address
|
|
CALL DEBLOCK9 ;BX=CURBCBA, DX=.ADRIVE, CL=4
|
|
cmp b[bx],0ffh! je deblock2
|
|
CALL COMPARE ;DOES BCB(0-3) = ADRIVE || ARECORD?
|
|
JZ DEBLOCK45 ;YES
|
|
DEBLOCK2:
|
|
mov bx,curbcba
|
|
mov b[bx],0ffh ;discard in case of error
|
|
MOV AL,2
|
|
CALL DEBLOCK_IO ;READ PHYSICAL RECORD
|
|
CALL DEBLOCK9 ;BX=CURBCBA, DX=.ADRIVE, CL=4
|
|
CALL MOVE
|
|
MOV B[DI],0 ;CURBCBA->BCB(4) = 0
|
|
DEBLOCK45:
|
|
xor al,al
|
|
MOV ah,PHY_OFF
|
|
shr ax,1 ;AX = phy_off * 080h
|
|
MOV SI,CURDMA
|
|
ADD SI,AX ;SI = CURDMA + PHY_OFF*80H
|
|
MOV al,DEBLOCK_FX
|
|
CMP al,3 ;IS DEBLOCK_FX = LOCATE?
|
|
JNZ DEBLOCK6 ;NO
|
|
MOV BUFFA,SI ;YES
|
|
RET
|
|
DEBLOCK6:
|
|
MOV CX,40H ;transfer 40h words
|
|
MOV DI,DMAAD
|
|
mov ax,dmabase
|
|
mov dx,cur_dmabase
|
|
push ds! push es
|
|
mov ds,dx ;setup source segment
|
|
mov es,ax ;setup destination segment
|
|
rep movsw ;transfer data
|
|
pop es! pop ds
|
|
RET
|
|
|
|
DEBLOCK9: ;SETUP FOR MOVE OR COMPARE
|
|
MOV BX,CURBCBA
|
|
MOV DX,OFFSET ADRIVE
|
|
MOV CL,4
|
|
RET
|
|
|
|
DEBLOCK_IO:
|
|
;----------
|
|
; entry: AL = 0 -> SEEK ONLY
|
|
; = 1 -> WRITE
|
|
; = 2 -> READ
|
|
|
|
PUSH AX
|
|
CALL SEEK
|
|
POP AX
|
|
DEC AL
|
|
JS deblk_io2
|
|
; JNZ deblk_io1
|
|
; mov cl,1
|
|
; JMP WRBUFF
|
|
;deblk_io1:
|
|
CALL RDBUFF
|
|
deblk_io2:
|
|
mov si,offset track
|
|
mov di,curbcba
|
|
add di,6 ;MOVE TRACK & SECTOR
|
|
mov cx,2 ;TO BCB
|
|
rep movsw
|
|
ret
|
|
|
|
|
|
endcode equ offset $
|
|
|
|
;*************** end bdos file system ****************
|
|
|
|
;****************** BDOS data area *******************
|
|
;
|
|
;
|
|
dseg
|
|
; Variables in data segment:
|
|
org endcode
|
|
|
|
iosentry rw 0
|
|
biosco dw biosoffset ;offset and
|
|
bioscs dw 0 ;segment for callf to BIOS
|
|
|
|
;
|
|
;*****************************************************
|
|
;
|
|
;*****************************************************
|
|
;*
|
|
;* bdos file system data area
|
|
;*
|
|
;*****************************************************
|
|
|
|
; variables in data segment:
|
|
;
|
|
|
|
;the following variables are set to zero upon entry to file system
|
|
|
|
fcbdsk db 0 ;disk named in fcb
|
|
parcopfl db 0 ;true if parameter block copied
|
|
aret dw 0 ;adr value to return
|
|
lret equ byte ptr aret ;low(aret)
|
|
resel db 0 ;reselection flag
|
|
DIR_CNT DB 0 ;DIRECT I/O COUNT
|
|
MULT_NUM DB 0 ;MULTI-SECTOR COUNT used in bdos
|
|
zerolength equ (offset $)-(offset fcbdsk)
|
|
mult_sec db 1 ;multi sector count passed to xios
|
|
|
|
BLK_OFF DB 0 ;RECORD OFFSET WITHIN BLOCK
|
|
;
|
|
|
|
DEBLOCK_FX DB 0 ;DEBLOCK FUNCTION #
|
|
PHY_OFF DB 0 ;RECORD OFFSET WITHIN PHYSICAL RECORD
|
|
CURBCBA DW 0 ;CURRENT BCB OFFSET
|
|
|
|
TRACK DW 0 ;BCB RECORD'S TRACK
|
|
SECTOR DW 0 ;BCB RECORD'S SECTOR
|
|
|
|
; seldsk,usrcode are initialized as a pair
|
|
p_dsk db 0 ;selected disk num
|
|
p_user db 0 ;curr user num
|
|
|
|
;info dw 0 ;info adr
|
|
srcha dw 0 ;search adr
|
|
|
|
;the following variable order is critical
|
|
|
|
;variables copied from uda for mp/m x
|
|
|
|
;variables included in fcb checksum for mp/m and cp/m x
|
|
|
|
;variables used to access system lock list for mp/m x
|
|
|
|
;dmaad dw 0 ;dma offset 1
|
|
;dmabase dw 0 ;dma base 2
|
|
;srchl db 0 ;search len 4
|
|
|
|
;dcnt dw 0 ;directory counter 7
|
|
;dblk dw 0 ;directory block 8 ?? - not used - ??
|
|
u_mult_cnt rb 0
|
|
mult_cnt db 1 ;bdos multi-sector cnt 10
|
|
;df_password rb 8 ;process default pw 11
|
|
|
|
;high_ext db 0 ;fcb high extent bits 2
|
|
;xfcb_read_only db 0 ;xfcb read only flag 3
|
|
curdsk db 0ffh ;current disk 4 1
|
|
|
|
org ((offset $) + 1) and 0fffeh
|
|
|
|
; curtrka - alloca are set upon disk select
|
|
; (data must be adjacent)
|
|
|
|
;cdrmaxa dw 0 ;ptr to cur dir max val
|
|
;drvlbla dw 0 ;drive label data byte addr
|
|
buffa dw 0 ;ptr to dir dma addr
|
|
dpbaddr dw 0 ;curr disk param block addr
|
|
checka dw 0 ;curr checksum vector addr
|
|
alloca dw 0 ;curr alloc vector addr
|
|
DIRBCBA DW 0 ;DIRECTORY BUFFER CONTROL BLOCK ADDR
|
|
DTABCBA dw 0 ;DATA BUFFER CONTROL BLOCK ADDR
|
|
addlist equ 10 ;"$-buffa" = addr list size
|
|
|
|
; sectpt - offset obtained from disk parm block at dpbaddr
|
|
; (data must be adjacent)
|
|
|
|
sectpt dw 0 ;sectors per track
|
|
blkshf db 0 ;block shift factor
|
|
blkmsk db 0 ;block mask
|
|
extmsk db 0 ;extent mask
|
|
maxall dw 0 ;max alloc num
|
|
dirmax dw 0 ;max dir num
|
|
dirblk dw 0 ;reserved alloc bits for dir
|
|
chksiz dw 0 ;size of checksum vector
|
|
offsetv dw 0 ;offset tracks at beginning
|
|
PHYSHF DB 0 ;PHYSICAL RECORD SHIFT FACTOR
|
|
PHYMSK DB 0 ;PHYSICAL RECORD MASK
|
|
endlist rs 0 ;end of list
|
|
dpblist equ (offset endlist)-(offset sectpt)
|
|
;size
|
|
|
|
; local variables
|
|
|
|
save_mod db 0 ;open_reel module save field
|
|
|
|
dminx db 0 ;local for diskwrite
|
|
single db 0 ;set true if single byte
|
|
;alloc map
|
|
rcount db 0 ;record count in curr fcb
|
|
extval db 0 ;extent num and extmsk
|
|
vrecord db 0 ;curr virtual record
|
|
ADRIVE DB 0 ;CURRENT DISK - must preceed arecord
|
|
arecord dw 0 ;curr actual record
|
|
db 0 ;curr actual record high byte
|
|
CUR_DMABASE DW 0
|
|
CUR_DMA DW 0
|
|
|
|
; local variables for directory access
|
|
|
|
dptr db 0 ;directory pointer 0,1,2,3
|
|
|
|
; shell variables
|
|
|
|
shell_si dw 0 ;bdos command offset
|
|
shell_dma dw 0 ;dmaad save area
|
|
shell_flag db 0 ;parsave shell flag
|
|
|
|
; special 8086 variables:
|
|
|
|
u_retseg dw 0 ;user return segment
|
|
|
|
parlg db 0 ;len of parameter block
|
|
|
|
|
|
; bdos stack switch variables and stack
|
|
; used for all bdos disk functions
|
|
|
|
org ((offset $) + 1) and 0fffeh
|
|
|
|
; 69 word bdos stack
|
|
|
|
dw 0cccch,0cccch,0cccch
|
|
dw 0cccch,0cccch,0cccch
|
|
dw 0cccch,0cccch,0cccch
|
|
dw 0cccch,0cccch,0cccch
|
|
dw 0cccch,0cccch,0cccch
|
|
dw 0cccch,0cccch,0cccch
|
|
dw 0cccch,0cccch,0cccch
|
|
dw 0cccch,0cccch,0cccch
|
|
dw 0cccch,0cccch,0cccch
|
|
dw 0cccch,0cccch,0cccch
|
|
dw 0cccch,0cccch,0cccch
|
|
dw 0cccch,0cccch,0cccch
|
|
dw 0cccch,0cccch,0cccch
|
|
dw 0cccch,0cccch,0cccch
|
|
dw 0cccch,0cccch,0cccch
|
|
dw 0cccch,0cccch,0cccch
|
|
dw 0cccch,0cccch,0cccch
|
|
dw 0cccch,0cccch,0cccch
|
|
dw 0cccch,0cccch,0cccch
|
|
dw 0cccch,0cccch,0cccch
|
|
dw 0cccch,0cccch,0cccch
|
|
dw 0cccch,0cccch,0cccch
|
|
dw 0cccch,0cccch,0cccch
|
|
bdosstack rw 0
|
|
|
|
save_sp rw 1
|
|
|
|
; local buffer area:
|
|
|
|
info_fcb rb 0;40 ;local user FCB
|
|
|
|
db 'COPYRIGHT(C)1983,'
|
|
db 'DIGITAL RESEARCH(01/26/83)'
|
|
db 'XXXX-0000-654321'
|
|
|
|
;
|
|
info dw 0 ;information address
|
|
;
|
|
u_wrkseg rw 0
|
|
parametersegment dw 0 ;user parameter segment
|
|
;
|
|
;
|
|
dmaad dw 0 ;user DMA address
|
|
dmabase dw 0 ;user DMA base
|
|
seldsk db 0 ;current user disk
|
|
usrcode db 0 ;current user number
|
|
dcnt dw 0 ;directory index
|
|
ldcnt equ byte ptr dcnt ;low(dcnt)
|
|
srchl db 0 ;search length
|
|
;
|
|
;
|
|
|
|
db 0 ;end of this data area
|
|
|
|
;***************** end BDOS data area ****************
|
|
|
|
;******************** end of BDOS ********************
|
|
end
|