mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-25 17:34:06 +00:00
1686 lines
38 KiB
Plaintext
1686 lines
38 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
|
||
jmp patch ; code for patch 6
|
||
done:
|
||
; 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
|
||
;
|
||
;
|
||
|
||
startpat equ offset $
|
||
|
||
cseg
|
||
org startpat
|
||
|
||
patch:
|
||
mov bx,0894h
|
||
mov al,[bx]
|
||
push bx
|
||
dec bx
|
||
dec bx
|
||
jmp done
|
||
|
||
|
||
; db 0 ;end of this data area
|
||
|
||
;***************** end BDOS data area ****************
|
||
|
||
;******************** end of BDOS ********************
|
||
end
|
||
|