mirror of
https://github.com/SEPPDROID/DR-DOS-OpenDOS.git
synced 2025-10-22 16:04:20 +00:00
Upload
This commit is contained in:
960
IBMDOS/FCBS.A86
Normal file
960
IBMDOS/FCBS.A86
Normal file
@@ -0,0 +1,960 @@
|
||||
title 'FCB - DOS file system FCB support'
|
||||
; File : $FCBS.A86$
|
||||
;
|
||||
; Description :
|
||||
;
|
||||
; Original Author : DIGITAL RESEARCH
|
||||
;
|
||||
; Last Edited By : $CALDERA$
|
||||
;
|
||||
;-----------------------------------------------------------------------;
|
||||
; Copyright Work of Caldera, Inc. All Rights Reserved.
|
||||
;
|
||||
; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
|
||||
; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
|
||||
; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
|
||||
; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
|
||||
; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
|
||||
; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
|
||||
; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
|
||||
; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
|
||||
; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
|
||||
; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
|
||||
; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
|
||||
; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
|
||||
; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
|
||||
; CIVIL LIABILITY.
|
||||
;-----------------------------------------------------------------------;
|
||||
;
|
||||
; *** Current Edit History ***
|
||||
; *** End of Current Edit History ***
|
||||
; $Log$
|
||||
; FCBS.A86 1.10 93/11/11 15:38:14
|
||||
; Chart Master fix - fcb_readblk over > 64k is truncated to 64k and
|
||||
; error 2 (Segment boundry overlap) is returned
|
||||
; FCBS.A86 1.9 93/10/18 17:37:06
|
||||
; fix for >255 open files (PNW Server)
|
||||
; ENDLOG
|
||||
|
||||
eject ! include i:fdos.equ
|
||||
eject ! include i:msdos.equ
|
||||
eject ! include i:mserror.equ
|
||||
eject ! include i:doshndl.def ; DOS Handle Structures
|
||||
eject
|
||||
|
||||
|
||||
BDOS_DATA dseg word
|
||||
|
||||
BDOS_CODE cseg
|
||||
|
||||
extrn ifn2dhndl:near
|
||||
extrn parse_one:near
|
||||
extrn fdos_entry:near
|
||||
|
||||
Public fdos_exit
|
||||
|
||||
eject
|
||||
; TERMINATE CHILD (EXIT)
|
||||
|
||||
; +----+----+
|
||||
; | 24 |
|
||||
; +----+----+
|
||||
|
||||
; entry:
|
||||
; ------
|
||||
; -none-
|
||||
|
||||
; exit:
|
||||
; -----
|
||||
; -none-
|
||||
|
||||
; Close down all FCB handles associated with the current PSP
|
||||
;
|
||||
fdos_exit:
|
||||
;---------
|
||||
push ds
|
||||
push ss ! pop ds ; DS -> PCM_DSEG
|
||||
sub ax,ax ; start with first DHNDL_
|
||||
fdos_exit10:
|
||||
call ifn2dhndl ; get DHNDL_
|
||||
jc fdos_exit40 ; stop if we have run out
|
||||
mov fcb_pb+2,ax ; we may close this IFN
|
||||
push ax
|
||||
mov cx,es:DHNDL_COUNT[bx] ; get the open count
|
||||
jcxz fdos_exit30 ; skip if nothing to do
|
||||
mov ax,current_psp ; get current PSP
|
||||
cmp ax,es:DHNDL_PSP[bx] ; does it belong to this PSP
|
||||
jne fdos_exit30
|
||||
mov ax,ss:machine_id ; get current process
|
||||
cmp ax,es:DHNDL_UID[bx]
|
||||
jne fdos_exit30
|
||||
test es:DHNDL_MODE[bx],DHM_FCB
|
||||
jz fdos_exit20 ; skip close if not FCB
|
||||
push es
|
||||
push bx ; save the DHNDL
|
||||
mov ax,MS_X_CLOSE
|
||||
call fcb_fdos ; make the FDOS do the work
|
||||
pop bx
|
||||
pop es ; recover the DHNDL
|
||||
fdos_exit20:
|
||||
mov es:DHNDL_COUNT[bx],0 ; always free the handle if it's ours
|
||||
fdos_exit30:
|
||||
pop ax
|
||||
inc al ; onto next IFN
|
||||
jnz fdos_exit10
|
||||
fdos_exit40:
|
||||
pop ds
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Public fdos_fcb
|
||||
|
||||
eject
|
||||
; GENERIC FCB FUNCTION (FCB)
|
||||
|
||||
; +----+----+----+----+----+----+----+----+
|
||||
; | 22 | fcbadr | count |
|
||||
; +----+----+----+----+----+----+----+----+
|
||||
; | func |
|
||||
; +----+----+
|
||||
|
||||
; entry:
|
||||
; ------
|
||||
; fcbadr: FCB address
|
||||
; count: multi-sector count for read/write
|
||||
; func: FCB sub-function
|
||||
|
||||
; exit:
|
||||
; -----
|
||||
; AX: return code or error code ( < 0)
|
||||
|
||||
fdos_fcb:
|
||||
;--------
|
||||
mov bx,2[bp] ; BX -> parameter block
|
||||
mov bx,8[bx] ; get subfunction code
|
||||
shl bx,1 ; make it word index
|
||||
sub bl,15*WORD ; adjust to base address
|
||||
jc fcb_error ; reject if too low
|
||||
cmp bl,FCB_MAX1 ; is it in 1st block
|
||||
jb fdos_fcb10
|
||||
sub bl,(33-24)*WORD ; adjust for gap
|
||||
jc fcb_error
|
||||
cmp bl,FCB_MAX2 ; is it in 2nd block
|
||||
jb fdos_fcb10
|
||||
sub bl,(39-37)*WORD ; adjust for gap
|
||||
jc fcb_error
|
||||
fdos_fcb10:
|
||||
cmp bx,FCB_MAX3 ; check the range
|
||||
jae fcb_error ; skip if invalid function
|
||||
jmp fcb_table[bx] ; call the right function
|
||||
|
||||
fcb_error:
|
||||
mov bx,ED_FUNCTION
|
||||
ret
|
||||
|
||||
fcb_table dw fcb_open ; 15-open file
|
||||
dw fcb_close ; 16-close file
|
||||
dw fcb_first ; 17-find first
|
||||
dw fcb_next ; 18-find next
|
||||
dw fcb_delete ; 19-delete file
|
||||
dw fcb_read ; 20-read from file
|
||||
dw fcb_write ; 21-write to file
|
||||
dw fcb_make ; 22-make file
|
||||
dw fcb_rename ; 23-rename file
|
||||
FCB_MAX1 equ (offset $ - offset fcb_table)
|
||||
dw fcb_readrand ; 33-read from file
|
||||
dw fcb_writerand ; 34-write to file
|
||||
dw fcb_size ; 35-compute file size
|
||||
dw fcb_setrecord ; 36-set relative record
|
||||
FCB_MAX2 equ (offset $ - offset fcb_table)
|
||||
dw fcb_readblk ; 39-read from file
|
||||
dw fcb_writeblk ; 40-write to file
|
||||
FCB_MAX3 equ (offset $ - offset fcb_table)
|
||||
|
||||
fcb_make:
|
||||
;--------
|
||||
call fcb_path_prep ; build pathname
|
||||
mov ax,MS_X_CREAT
|
||||
jmps fcb_open_make_common
|
||||
|
||||
fcb_open:
|
||||
;--------
|
||||
call fcb_path_prep ; build pathname
|
||||
mov ax,MS_X_OPEN
|
||||
fcb_open_make_common:
|
||||
mov fcb_pb+6,DHM_RW+DHM_FCB ; open as an FCB for read/write
|
||||
call fcb_fdos ; lets try and open the file
|
||||
jnc fcb_open10 ; skip if we can't
|
||||
ret
|
||||
fcb_open10:
|
||||
call ifn2dhndl ; ES:BX -> DHNDL_ we have opened
|
||||
push ds
|
||||
push es ! push bx ; save DHNDL_
|
||||
call fcb_point ; ES:BX = FCB
|
||||
pop si ! pop ds ; DS:SI -> DHNDL_
|
||||
mov es:MSF_IFN[bx],al ; store IFN away
|
||||
mov es:MSF_BLOCK[bx],0 ; current block number
|
||||
mov es:MSF_RECSIZE[bx],128 ; current logical record size
|
||||
call fcb_update ; update misc changing fields
|
||||
mov ax,ds:DHNDL_DEVOFF[si]
|
||||
mov es:word ptr MSF_DEVPTR[bx],ax
|
||||
mov ax,ds:DHNDL_DEVSEG[si]
|
||||
mov es:word ptr MSF_DEVPTR+2[bx],ax
|
||||
mov ax,ds:DHNDL_BLK1[si]
|
||||
mov es:MSF_BLOCK1[bx],ax
|
||||
mov al,ds:DHNDL_ATTR[si]
|
||||
mov es:MSF_IOCTL[bx],al
|
||||
mov al,es:MSF_DRIVE[bx] ; get drive from FCB
|
||||
dec al ; was absolute drive specified ?
|
||||
jns fcb_open20 ; if so use it
|
||||
mov al,ss:current_dsk ; else use default drive
|
||||
fcb_open20:
|
||||
inc al ; make drive 1 rather than 0 based
|
||||
mov es:MSF_DRIVE[bx],al ; drive code
|
||||
if 0
|
||||
test ds:DHNDL_DATRB[si],DA_VOLUME
|
||||
else
|
||||
test ss:fcb_pb+8,DA_VOLUME
|
||||
endif
|
||||
pop ds
|
||||
jnz fcb_close ; don't leave VOL label's open
|
||||
xor bx,bx ; no errors !
|
||||
ret
|
||||
|
||||
|
||||
fcb_update:
|
||||
;----------
|
||||
; On Entry:
|
||||
; DS:SI -> DHNDL_
|
||||
; ES:BX -> FCB
|
||||
; On Exit:
|
||||
; DATE/TIME/SIZE/DBLK/DCNT fields updated
|
||||
;
|
||||
mov ax,ds:DHNDL_TIME[si]
|
||||
mov es:MSF_TIME[bx],ax
|
||||
mov ax,ds:DHNDL_DATE[si]
|
||||
mov es:MSF_DATE[bx],ax
|
||||
mov ax,ds:DHNDL_SIZELO[si]
|
||||
mov es:MSF_SIZE[bx],ax
|
||||
mov ax,ds:DHNDL_SIZEHI[si]
|
||||
mov es:MSF_SIZE+2[bx],ax
|
||||
mov ax,ds:DHNDL_DBLK[si]
|
||||
mov es:MSF_DBLK[bx],ax
|
||||
mov al,ds:DHNDL_DCNTLO[si]
|
||||
mov ah,ds:DHNDL_DCNTHI[si]
|
||||
mov es:MSF_DCNT[bx],ax
|
||||
ret
|
||||
|
||||
fcb_close:
|
||||
;---------
|
||||
; close file (DOS function 10h)
|
||||
call fcb_point ; ES:BX -> FCB
|
||||
mov al,0FFh
|
||||
cmp al,es:MSF_IFN[bx] ; is it a multiple close ?
|
||||
je fcb_fdos_common10 ; don't re-open for this...
|
||||
call fcb_handle_vfy ; verify we have a sensible handle
|
||||
mov es:MSF_IFN[bx],al ; mark FCB as closed (it will be)
|
||||
mov ax,MS_X_CLOSE ; now close it
|
||||
; jmps fcb_fdos_common
|
||||
|
||||
fcb_fdos_common:
|
||||
;---------------
|
||||
call fcb_fdos ; make the FDOS do the work
|
||||
jc fcb_fdos_common20 ; return any error codes
|
||||
fcb_fdos_common10:
|
||||
xor bx,bx ; else return zero
|
||||
fcb_fdos_common20:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
fcb_rename:
|
||||
;----------
|
||||
call fcb_path_prep
|
||||
call fcb_path2_prep
|
||||
mov ax,MS_X_RENAME ; it's a rename
|
||||
jmps fcb_fdos_common
|
||||
|
||||
fcb_delete:
|
||||
;----------
|
||||
call fcb_path_prep
|
||||
mov ax,MS_X_UNLINK ; it's a delete
|
||||
jmps fcb_fdos_common
|
||||
|
||||
|
||||
fcb_first:
|
||||
;---------
|
||||
call fcb_path_prep ; prepare pathname
|
||||
mov ax,MS_X_FIRST ; we want to search 1st
|
||||
jmps fcb_search_common
|
||||
|
||||
fcb_next:
|
||||
;--------
|
||||
call fcb_restore_search_state
|
||||
mov ax,MS_X_NEXT
|
||||
fcb_search_common:
|
||||
call fcb_search ; 0 of OK, otherwise ED_..
|
||||
jc fcb_search_common10
|
||||
call fcb_save_search_state ; save sucessful state
|
||||
xor bx,bx ; return code in BX
|
||||
fcb_search_common10:
|
||||
ret
|
||||
|
||||
|
||||
fcb_setrecord:
|
||||
;-------------
|
||||
call fcb_point ; ES:BX -> FCB
|
||||
mov ax,128 ; multiply current block by 128
|
||||
mul es:MSF_BLOCK[bx] ; to give current record number
|
||||
xor cx,cx
|
||||
mov cl,es:MSF_CR[bx] ; Add in the current record
|
||||
add ax,cx ; to DX:AX to give the
|
||||
adc dx,0 ; relative record
|
||||
mov es:MSF_RR[bx],ax ; save the result
|
||||
mov es:MSF_RR2[bx],dl
|
||||
xor bx,bx ; we did OK
|
||||
ret
|
||||
|
||||
fcb_write:
|
||||
;---------
|
||||
mov ax,MS_X_WRITE ; make it a write
|
||||
jmps fcb_seq_rw
|
||||
|
||||
fcb_read:
|
||||
;--------
|
||||
mov ax,MS_X_READ ; make it a read
|
||||
fcb_seq_rw:
|
||||
call fcb_handle_vfy ; verify we have a sensible handle
|
||||
push ax ; save the operation
|
||||
call fcb_get_count ; AX = bytes to read
|
||||
push ax ; save byte count
|
||||
call fcb_seek_seq ; Seek to position in the file
|
||||
pop cx ; recover byte to xfer
|
||||
pop ax ; and the Operation Code
|
||||
jc fcb_seq_rw10
|
||||
call fcb_rw ; do the Op
|
||||
jc fcb_seq_rw10
|
||||
push bx ; save the error code
|
||||
call fcb_update_seq ; update FCB filepos
|
||||
pop bx ; recover error
|
||||
fcb_seq_rw10:
|
||||
ret
|
||||
|
||||
fcb_rw:
|
||||
; On Entry:
|
||||
; AX = operation code
|
||||
; CX = count
|
||||
; fcb_pb+2 = IFN
|
||||
; On Exit:
|
||||
; BX = error code
|
||||
les dx,ss:dword ptr dma_offset
|
||||
add cx,dx ; see if we overflow
|
||||
jc fcb_rw20
|
||||
sub cx,dx ; count back to normal
|
||||
push cx ; save target count
|
||||
mov fcb_pb+4,dx
|
||||
mov fcb_pb+6,es ; setup buffer address
|
||||
mov fcb_pb+8,cx ; and target count
|
||||
call fcb_fdos ; ask the FDOS to do the read/write
|
||||
jc fcb_rw10 ; we got a real error...
|
||||
push ds
|
||||
push es
|
||||
mov ax,fcb_pb+2 ; get IFN
|
||||
call ifn2dhndl ; ES:BX -> DHNDL_ we have open
|
||||
push es ! push bx ; save DHNDL_
|
||||
call fcb_point ; ES:BX = FCB
|
||||
pop si ! pop ds ; DS:SI -> DHNDL_
|
||||
call fcb_update ; update file size/time-stamp
|
||||
pop es
|
||||
pop ds
|
||||
pop ax ; recover target count
|
||||
mov cx,fcb_pb+8 ; we xfered this much
|
||||
cmp cx,ax ; did we xfer enough
|
||||
jb fcb_rw30 ; nope..
|
||||
xor bx,bx ; xfer went OK
|
||||
ret
|
||||
|
||||
fcb_rw10:
|
||||
pop ax ; discard target count
|
||||
ret
|
||||
|
||||
fcb_rw20:
|
||||
; Our DTA is too small - return 2
|
||||
mov bx,2 ; indicate the DTA is too small
|
||||
; stc ; error - don't update FCB
|
||||
ret
|
||||
|
||||
fcb_rw30:
|
||||
; We have some form of EOF - lets look into it
|
||||
call fcb_point ; ES:BX = FCB
|
||||
mov bx,es:MSF_RECSIZE[bx] ; BX = record size
|
||||
mov ax,cx
|
||||
xor dx,dx ; DX:AX = bytes xfer'd
|
||||
div bx ; did we xfer a complete
|
||||
test dx,dx ; number of records ?
|
||||
jz fcb_rw40 ; if so return 1
|
||||
; Partial data was read - fill out with zero's and return 3
|
||||
inc ax ; allow for incomplete record
|
||||
push ax ; save rounded up xfer count
|
||||
les di,ss:dword ptr dma_offset
|
||||
add di,cx ; point to 1st byte after xfer
|
||||
mov cx,bx ; this many in a record
|
||||
sub cx,dx ; so this many weren't xfer'd
|
||||
xor ax,ax ; fill them with zero's
|
||||
rep stosb ; zap the bytes we didn't xfer to
|
||||
pop ax ; recover xfer count
|
||||
mul bx ; and work out # bytes xfered
|
||||
xchg ax,cx ; return bytes in CX
|
||||
mov bx,3 ; indicate EOF (partial read)
|
||||
; clc ; update FCB
|
||||
ret
|
||||
|
||||
fcb_rw40:
|
||||
; No Data was xfered - return 1
|
||||
mov bx,1 ; indicate EOF (no data read)
|
||||
; clc ; update FCB
|
||||
ret
|
||||
|
||||
fcb_writerand:
|
||||
;-------------
|
||||
mov ax,MS_X_WRITE ; make it a write
|
||||
jmps fcb_random_rw
|
||||
|
||||
fcb_readrand:
|
||||
;------------
|
||||
mov ax,MS_X_READ ; make it a read
|
||||
fcb_random_rw:
|
||||
call fcb_handle_vfy ; check the handle is OK
|
||||
push ax ; save the code
|
||||
call fcb_get_count ; AX = bytes to read
|
||||
push ax ; save byte count
|
||||
xor cx,cx ; cause update of seq posn from
|
||||
call fcb_update_rr ; random record position
|
||||
call fcb_seek_rr ; Seek to position in the file
|
||||
pop cx ; recover byte to xfer
|
||||
pop ax ; and the Operation Code
|
||||
jc fcb_random_rw10
|
||||
call fcb_rw ; do the Op
|
||||
fcb_random_rw10:
|
||||
ret
|
||||
|
||||
|
||||
fcb_writeblk:
|
||||
;------------
|
||||
mov ax,MS_X_WRITE ; make it a write
|
||||
jmps fcb_block_rw
|
||||
|
||||
fcb_readblk:
|
||||
;-----------
|
||||
mov ax,MS_X_READ ; make it a read
|
||||
fcb_block_rw:
|
||||
call fcb_handle_vfy ; check the handle is OK
|
||||
push ax ; save the code
|
||||
call fcb_get_count ; AX = bytes per record, CX = # records
|
||||
xchg ax,cx ; CX = bytes per record
|
||||
mul cx ; AX = bytes to xfer
|
||||
test dx,dx ; more than 64K ?
|
||||
jz fcb_block_rw10 ; then we should truncate it
|
||||
mov ax,15 ; AX = handy mask
|
||||
cwd ; DX = 0
|
||||
and ax,ss:dma_offset ; get dma offset for para
|
||||
not ax ; DX/AX = maximum bytes we can xfer
|
||||
div cx ; AX = maximum blocks we can xfer
|
||||
mul cx ; AX = bytes to xfer (now < 64K)
|
||||
fcb_block_rw10:
|
||||
push ax ; save byte count
|
||||
call fcb_seek_rr ; Seek to position in the file
|
||||
pop cx ; recover byte to xfer
|
||||
pop ax ; and the Operation Code
|
||||
jc fcb_block_rw20
|
||||
call fcb_rw ; do the Op
|
||||
jc fcb_block_rw20
|
||||
push bx ; save the error code
|
||||
call fcb_update_rr ; update FCB filepos, get records xferd
|
||||
mov bx,2[bp] ; BX -> parameter block
|
||||
xchg cx,6[bx] ; update amount xfered
|
||||
sub cx,6[bx] ; CX = # we didn't xfer (normally 0)
|
||||
pop bx ; recover (possible) error
|
||||
jcxz fcb_block_rw20 ; skip if we read all we wanted to
|
||||
test bx,bx ; did we have a partial read for
|
||||
jnz fcb_block_rw20 ; a reason like EOF ?
|
||||
mov bx,2 ; no, we must have truncated it
|
||||
fcb_block_rw20:
|
||||
ret
|
||||
|
||||
|
||||
fcb_size:
|
||||
;--------
|
||||
call fcb_path_prep
|
||||
mov ax,MS_X_CHMOD ; it's a get info
|
||||
mov fcb_pb+6,0
|
||||
call fcb_fdos
|
||||
jc fcb_size40
|
||||
call fcb_point ; ES:BX = FCB
|
||||
mov cx,es:MSF_RECSIZE[bx] ; get the record size
|
||||
test cx,cx ; is it non-zero ?
|
||||
jnz fcb_size10 ; if not
|
||||
mov cx,128 ; make it 128 bytes
|
||||
fcb_size10:
|
||||
mov ax,fcb_pb+10
|
||||
mov dx,fcb_pb+12 ; DX:AX = file length in bytes
|
||||
call div_32 ; DX:AX = file length in records
|
||||
jcxz fcb_size20 ; was there an overflow
|
||||
add ax,1
|
||||
adc dx,0 ; include an extra record
|
||||
fcb_size20:
|
||||
call fcb_point ; ES:BX = FCB
|
||||
mov es:MSF_RR[bx],ax ; low word of size
|
||||
mov es:MSF_RR2[bx],dl ; hi byte of size
|
||||
cmp es:MSF_RECSIZE[bx],64 ; if record size < 64 bytes
|
||||
jae fcb_size30 ; then we use a 4 byte
|
||||
mov es:MSF_RR2+1[bx],dh ; random record position
|
||||
fcb_size30:
|
||||
xor bx,bx ; good return
|
||||
fcb_size40:
|
||||
ret
|
||||
|
||||
|
||||
; Utility FCB subroutines
|
||||
;========================
|
||||
|
||||
fcb_handle_vfy:
|
||||
;--------------
|
||||
; Verify FCB is valid and open, do not return if it isn't
|
||||
; nb. Called with nothing on stack
|
||||
;
|
||||
; On Entry:
|
||||
; FCB address in parameter block
|
||||
; On Exit:
|
||||
; AX preserved
|
||||
; ES:BX -> FCB (skipping EXT bit if present)
|
||||
; fcb_pb+2 = IFN of handle
|
||||
; On Error - blow away caller and return error in BX
|
||||
;
|
||||
|
||||
; DEBUG - on reopen we could do more checks to ensure we are re-opening the
|
||||
; same file
|
||||
push ax
|
||||
call fcb_point
|
||||
cmp es:MSF_RECSIZE[bx],0
|
||||
jne fcb_handle_vfy10
|
||||
mov es:MSF_RECSIZE[bx],128
|
||||
fcb_handle_vfy10:
|
||||
mov al,es:MSF_IFN[bx] ; get IFN
|
||||
call ifn2dhndl ; ES:BX -> DHNDL_
|
||||
jc fcb_handle_vfy20 ; it must be a valid IFN
|
||||
test es:DHNDL_MODE[bx],DHM_FCB
|
||||
jz fcb_handle_vfy20 ; it must be an FCB..
|
||||
cmp es:DHNDL_COUNT[bx],0
|
||||
jne fcb_handle_vfy30 ; it must also be open..
|
||||
fcb_handle_vfy20:
|
||||
call fcb_point
|
||||
push es:MSF_RECSIZE[bx] ; save current record size
|
||||
push es:MSF_BLOCK[bx] ; save current block number
|
||||
push es ! push bx
|
||||
call fcb_open ; try to re-open the file
|
||||
pop bx ! pop es ; point back at FCB
|
||||
pop es:MSF_BLOCK[bx] ; restore current block number
|
||||
pop es:MSF_RECSIZE[bx] ; restore record size
|
||||
jc fcb_handle_err
|
||||
mov al,es:MSF_IFN[bx] ; get new IFN
|
||||
fcb_handle_vfy30:
|
||||
xor ah,ah
|
||||
mov fcb_pb+2,ax ; set parameter block accordingly
|
||||
call fcb_point ; ES:BX -> MSF_
|
||||
pop ax
|
||||
clc
|
||||
ret
|
||||
|
||||
fcb_handle_err:
|
||||
add sp,2*WORD ; discard AX and near return address
|
||||
cmp ax,ED_HANDLE ; if we have run out of handles then
|
||||
jne fcb_handle_err10 ; say no FCB's, else return error
|
||||
mov ax,ED_NOFCBS
|
||||
fcb_handle_err10:
|
||||
xchg ax,bx ; error code in BX
|
||||
stc
|
||||
ret
|
||||
|
||||
|
||||
fcb_path2_prep:
|
||||
;--------------
|
||||
; On Entry:
|
||||
; FCB address in parameter block
|
||||
; On Exit:
|
||||
; ES:BX -> FCB (skipping EXT bit if present)
|
||||
; fcb_pb+6/8 -> unparse name from FCB
|
||||
;
|
||||
call fcb_point ; point at the FCB
|
||||
mov al,es:MSF_DRIVE[bx] ; get drive
|
||||
add bx,16 ; point at 2nd name in FCB
|
||||
mov di,offset fcb_path2
|
||||
mov fcb_pb+6,di
|
||||
mov fcb_pb+8,ds ; point at buffer we want
|
||||
jmps fcb_path_prep_common
|
||||
|
||||
fcb_path_prep:
|
||||
;-------------
|
||||
; On Entry:
|
||||
; FCB address in parameter block
|
||||
; On Exit:
|
||||
; ES:BX -> FCB (skipping EXT bit if present)
|
||||
; fcb_pb+2/4 -> unparse name from FCB
|
||||
;
|
||||
xor ax,ax ; assume no attribute
|
||||
mov bx,2[bp] ; BX -> parameter block
|
||||
les bx,2[bx] ; ES:BX -> FCB
|
||||
cmp es:MSF_EXTFLG[bx],0ffh ; is it an extended FCB
|
||||
jne fcb_path_prep10
|
||||
or al,es:MSF_ATTRIB[bx] ; we can use file mode from XFCB
|
||||
add bx,7 ; skip EXT bit of FCB
|
||||
fcb_path_prep10:
|
||||
mov fcb_pb+8,ax ; remember the attribute
|
||||
mov al,es:MSF_DRIVE[bx] ; get drive
|
||||
mov di,offset fcb_path
|
||||
mov fcb_pb+2,di
|
||||
mov fcb_pb+4,ds ; point at buffer we want
|
||||
fcb_path_prep_common:
|
||||
dec al ; 0 = default drive
|
||||
jns fcb_path_prep20
|
||||
mov al,current_dsk ; use default drive
|
||||
fcb_path_prep20:
|
||||
push ds
|
||||
push ds ! push es
|
||||
pop ds ! pop es ; ES:DI -> name buffer
|
||||
add al,'A' ; make drive ASCII
|
||||
stosb
|
||||
mov al,':'
|
||||
stosb ; now we have 'd:'
|
||||
lea si,MSF_NAME[bx] ; DS:SI -> source name
|
||||
movsw ! movsw
|
||||
movsw ! movsw ; copy the name leaving spaces intact
|
||||
mov al,'.'
|
||||
stosb
|
||||
movsw ! movsb ; copy the extention
|
||||
pop ds
|
||||
; jmps fcb_point ; point ES:BX at FCB again
|
||||
|
||||
|
||||
fcb_point:
|
||||
;---------
|
||||
; On Entry:
|
||||
; FCB address in parameter block
|
||||
; On Exit:
|
||||
; ES:BX -> FCB (skipping EXT bit if present)
|
||||
; (All other regs preserved)
|
||||
;
|
||||
mov bx,2[bp] ; BX -> parameter block
|
||||
les bx,2[bx] ; ES:BX -> FCB
|
||||
cmp es:MSF_EXTFLG[bx],0ffh ; is it an extended FCB
|
||||
jne fcb_point10
|
||||
add bx,7 ; skip EXT bit of FCB
|
||||
fcb_point10:
|
||||
ret
|
||||
|
||||
fcb_get_count:
|
||||
;-------------
|
||||
; On Entry:
|
||||
; none
|
||||
; On Exit:
|
||||
; AX = bytes per record
|
||||
; CX = callers CX count
|
||||
; All regs fair game
|
||||
;
|
||||
call fcb_point ; ES:BX -> FCB
|
||||
mov si,2[bp] ; SI -> parameter block
|
||||
mov cx,6[si] ; CX = count
|
||||
mov ax,es:MSF_RECSIZE[bx] ; get record size
|
||||
ret
|
||||
|
||||
fcb_update_seq:
|
||||
;--------------
|
||||
; On Entry:
|
||||
; CX = byte count actually transferred
|
||||
; On Exit:
|
||||
; CX = record count transferred
|
||||
; All other regs fair game
|
||||
; CR/BLOCK updated with new value
|
||||
;
|
||||
mov ax,cx
|
||||
xor dx,dx ; DX:AX = byte count transfered
|
||||
call fcb_point ; ES:BX -> FCB
|
||||
div es:MSF_RECSIZE[bx] ; make records xfered
|
||||
push ax ; save records xfered
|
||||
xchg ax,cx ; also in CX for later
|
||||
mov ax,128
|
||||
mul es:MSF_BLOCK[bx] ; DX:AX = record of block
|
||||
add ax,cx
|
||||
adc dx,0 ; add in amount just xfered
|
||||
mov cl,es:MSF_CR[bx]
|
||||
xor ch,ch ; now add in CR as a word
|
||||
add ax,cx
|
||||
adc dx,0 ; DX:AX = record
|
||||
mov dh,dl ; DH:AX = record for common code
|
||||
jmps fcb_update_common
|
||||
|
||||
|
||||
fcb_update_rr:
|
||||
;-------------
|
||||
; On Entry:
|
||||
; CX = byte count actually transferred
|
||||
; On Exit:
|
||||
; CX = record count transferred
|
||||
; All other regs fair game
|
||||
; Random Record and CR/BLOCK updated with new value
|
||||
;
|
||||
xchg ax,cx
|
||||
xor dx,dx ; DX:AX = byte count transfered
|
||||
call fcb_point ; ES:BX -> FCB
|
||||
div es:MSF_RECSIZE[bx] ; make records xfered
|
||||
push ax ; save records xfered
|
||||
add es:MSF_RR[bx],ax ; update the RR field
|
||||
adc es:MSF_RR2[bx],0 ; and the overflow
|
||||
mov ax,es:MSF_RR[bx] ; get low part of RR
|
||||
mov dh,es:MSF_RR2[bx] ; and the hi part
|
||||
fcb_update_common:
|
||||
mov dl,ah ; DX will be block number
|
||||
shl al,1 ; get top bit of CR into CY
|
||||
adc dx,dx ; then into DX
|
||||
shr al,1 ; AL = CR (remember mod 128)
|
||||
mov es:MSF_CR[bx],al ; set the CR field
|
||||
mov es:MSF_BLOCK[bx],dx ; and the block field
|
||||
pop cx ; recover records xfered
|
||||
ret
|
||||
|
||||
|
||||
fcb_seek_seq:
|
||||
;------------
|
||||
; Seek to position in file indicated by the RR position
|
||||
; On Entry:
|
||||
; ES:BX -> FCB_
|
||||
; On Exit:
|
||||
; CY clear if no problem, fcb_pb+2=IFN
|
||||
; else
|
||||
; CY set, AX = BX = error code
|
||||
; All other regs fair game
|
||||
;
|
||||
call fcb_point ; ES:BX -> FCB_
|
||||
mov ax,128
|
||||
mul es:MSF_BLOCK[bx] ; get record in DX:AX
|
||||
mov cl,es:MSF_CR[bx]
|
||||
xor ch,ch
|
||||
add ax,cx ; add in CR
|
||||
adc dx,0 ; so DX:AX is really the record
|
||||
push ax ; save low word of record
|
||||
mov ax,dx
|
||||
mul es:MSF_RECSIZE[bx] ; DX:AX = byte offset in file/10000h
|
||||
mov cx,ax ; save the important word
|
||||
pop ax ; recover low word of record
|
||||
jmps fcb_seek_common
|
||||
|
||||
fcb_seek_rr:
|
||||
;-----------
|
||||
; Seek to position in file indicated by the RR position
|
||||
; On Entry:
|
||||
; ES:BX -> FCB_
|
||||
; On Exit:
|
||||
; CY clear if no problem, fcb_pb+2=IFN
|
||||
; else
|
||||
; CY set, AX = BX = error code
|
||||
; All other regs fair game
|
||||
;
|
||||
call fcb_point ; ES:BX -> FCB_
|
||||
mov al,es:MSF_RR2[bx]
|
||||
xor ah,ah
|
||||
mul es:MSF_RECSIZE[bx] ; DX:AX = byte offset in file/10000h
|
||||
mov cx,ax ; save the important word
|
||||
mov ax,es:MSF_RR[bx]
|
||||
fcb_seek_common:
|
||||
mul es:MSF_RECSIZE[bx] ; DX:AX = byte offset in file
|
||||
add dx,cx ; add the two bits together
|
||||
mov fcb_pb+4,ax
|
||||
mov fcb_pb+6,dx ; save position
|
||||
mov fcb_pb+8,0 ; seek from start
|
||||
xor ax,ax
|
||||
mov al,es:MSF_IFN[bx] ; AX = IFN
|
||||
mov fcb_pb+2,ax ; save IFN
|
||||
mov ax,MS_X_LSEEK
|
||||
jmp fcb_fdos ; try and seek to this position
|
||||
|
||||
|
||||
fcb_search:
|
||||
;----------
|
||||
; On Entry:
|
||||
; AX = operation to perform
|
||||
; On Exit:
|
||||
; AX = 0, or ED_ error code (CY set if error)
|
||||
push dma_offset
|
||||
push dma_segment
|
||||
mov dma_offset,offset fcb_search_buf
|
||||
mov dma_segment,ds
|
||||
call fcb_fdos ; do the search
|
||||
pop dma_segment
|
||||
pop dma_offset
|
||||
test ax,ax ; was there an error
|
||||
stc ; assume there was
|
||||
js fcb_search10 ; return the error
|
||||
xor ax,ax ; no problems
|
||||
fcb_search10:
|
||||
ret
|
||||
|
||||
fcb_save_search_state:
|
||||
;---------------------
|
||||
; On entry DS=PCMODE
|
||||
|
||||
call fcb_point
|
||||
lea di,MSF_NAME[bx] ; ES:DI -> FCB name
|
||||
mov si,offset fcb_search_buf
|
||||
lodsb ; get 1st byte = drive info
|
||||
mov cx,20/WORD ; copy 20 bytes to FCB
|
||||
rep movsw ; (the rest of the search template)
|
||||
stosb ; drive info byte follow them
|
||||
|
||||
les di,dword ptr dma_offset ; ES:DI -> search state in DMA address
|
||||
mov si,2[bp] ; SI -> parameter block
|
||||
lds si,2[si] ; DS:SI -> FCB_
|
||||
cmp ds:MSF_EXTFLG[si],0ffh ; extended FCB ?
|
||||
jne fcb_sss10
|
||||
mov cx,7 ; copy extended FCB portions too
|
||||
rep movsb ; we have copied up to name
|
||||
fcb_sss10:
|
||||
stosb ; save drive byte info
|
||||
push di
|
||||
mov al,' ' ; space fill name
|
||||
mov cx,11
|
||||
rep stosb ; all blanks now
|
||||
pop di
|
||||
push ss ! pop ds ; DS:SI -> pathname
|
||||
mov si,offset fcb_search_buf+1Eh
|
||||
|
||||
push di ; unparse knowing name is good
|
||||
mov cx,8 ; length of name field
|
||||
fcb_sss20:
|
||||
lodsb ; treat '.' and '..' specially
|
||||
cmp al,'.' ; is either possible ?
|
||||
jne fcb_sss30 ; no, continue as normal
|
||||
stosb ; copy the '.'
|
||||
loop fcb_sss20 ; go around for another '.'
|
||||
jmps fcb_sss40 ; this name is rubbish!!
|
||||
fcb_sss30:
|
||||
dec si ; forget the non '.'
|
||||
call parse_one ; parse just the name
|
||||
fcb_sss40:
|
||||
pop di
|
||||
add di,8 ; di -> fcb ext field
|
||||
cmp al,'.' ; do we have an extention ?
|
||||
jne fcb_sss50
|
||||
mov cx,3 ; length of ext field
|
||||
push di
|
||||
call parse_one ; parse just extension
|
||||
pop di
|
||||
fcb_sss50:
|
||||
add di,3 ; di -> rest of fcb
|
||||
mov si,offset fcb_search_buf+15h
|
||||
movsb ; copy the attribute field
|
||||
xor ax,ax
|
||||
mov cx,10/WORD
|
||||
rep stosw ; 10 bytes of zeros
|
||||
movsw ; copy time
|
||||
movsw ; copy date
|
||||
mov ax,word ptr srch_buf+21+DBLOCK1
|
||||
stosw ; 1st block
|
||||
movsw ! movsw ; copy filesize
|
||||
ret
|
||||
|
||||
fcb_restore_search_state:
|
||||
;------------------------
|
||||
; On entry DS=PCMODE
|
||||
push ds
|
||||
call fcb_point ; ES:BX -> FCB_
|
||||
push es ! push ds
|
||||
pop es ! pop ds ; swap DS/ES
|
||||
mov di,offset fcb_search_buf+1
|
||||
; ES:DI -> internal state
|
||||
lea si,1[bx] ; DS:SI -> FCB+1
|
||||
mov cx,10
|
||||
rep movsw ; copy info from FCB
|
||||
lodsb ; get "drive" info
|
||||
mov es:fcb_search_buf,al ; it's the 1st byte in the srch state
|
||||
pop ds
|
||||
ret
|
||||
|
||||
fcb_fdos:
|
||||
;--------
|
||||
; Make an FDOS call (NB. We don't have MX here, so it's OK)
|
||||
; Set top bit of remote_call flag so we use IFN's not XFN's
|
||||
; On Entry:
|
||||
; AX = FDOS operation
|
||||
; fcb_pb -> FDOS parameter block
|
||||
; On Exit:
|
||||
; As FDOS call
|
||||
;
|
||||
mov fcb_pb,ax ; save operation type
|
||||
or remote_call,DHM_FCB ; forget about PSP during FCB call
|
||||
mov dx,offset fcb_pb ; DS:DX -> parameter block
|
||||
push ds
|
||||
push bp
|
||||
call fdos_entry ; call the FDOS
|
||||
pop bp
|
||||
pop ds
|
||||
and remote_call,not DHM_FCB ; FCB operation over
|
||||
cmp ax,ED_LASTERROR
|
||||
cmc ; CY set if an error occurred
|
||||
ret
|
||||
|
||||
div_32:
|
||||
; Entry: DX,AX = long dividend
|
||||
; CX = word divisor
|
||||
; Exit: DX,AX = long result
|
||||
; CX = remainder
|
||||
|
||||
jcxz div0 ; divide by 0
|
||||
cmp cx,1
|
||||
je div1 ; divide by 1
|
||||
push di
|
||||
push bx
|
||||
xor bx,bx ; BX = 0
|
||||
xchg ax,bx ; low word in BX, AX = 0
|
||||
xchg ax,dx ; high word in DX:AX
|
||||
push ax ; save high word
|
||||
div cx ; divide high part
|
||||
mov di,ax ; save result
|
||||
mul cx ; AX = even divisor part
|
||||
pop dx ; old high in DX
|
||||
sub dx,ax ; eliminate even part
|
||||
xchg ax,bx ; AX = low word
|
||||
div cx ; low part in AX
|
||||
mov cx,dx ; CX = remainder
|
||||
mov dx,di ; high result in DX
|
||||
pop bx
|
||||
pop di
|
||||
ret
|
||||
|
||||
div0:
|
||||
mov ax,-1
|
||||
mov dx,ax
|
||||
ret
|
||||
div1:
|
||||
dec cx ; CX = remainder = 0
|
||||
ret
|
||||
|
||||
|
||||
PCMODE_DATA DSEG WORD
|
||||
|
||||
extrn fcb_pb:word
|
||||
extrn fcb_path:byte
|
||||
extrn fcb_path2:byte
|
||||
extrn fcb_search_buf:byte
|
||||
|
||||
extrn current_dsk:byte
|
||||
extrn current_psp:word
|
||||
extrn dma_offset:word
|
||||
extrn dma_segment:word
|
||||
extrn machine_id:word
|
||||
extrn remote_call:word
|
||||
extrn srch_buf:byte
|
||||
|
||||
end
|
Reference in New Issue
Block a user