FCBS.A86
资源名称:drdossrc.zip [点击查看]
上传用户:xiaogehua
上传日期:2007-01-08
资源大小:1183k
文件大小:25k
源码类别:
操作系统开发
开发平台:
Asm
- 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