Files
DR-DOS-OpenDOS/IBMDOS/FIOCTL.A86
2020-11-04 23:59:28 +01:00

504 lines
14 KiB
Plaintext

title 'FDOS IOCTL - DOS file system input/output control'
; File : $FIOCTL.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$
; FIOCTL.A86 1.18 93/12/09 23:39:17
; Move non-inherited bit to correct place in file handle
; FIOCTL.A86 1.17 93/11/03 13:38:29
; Int 21 4409 return 0x0080 if drive is joined
; FIOCTL.A86 1.16 93/11/02 18:04:17
; Int21/4400 from file returns AH=0
; FIOCTL.A86 1.15 93/09/14 20:03:15
; Trust LFLG_PHYSICAL
; FIOCTL.A86 1.12 93/06/17 22:11:50
; support for ioctl 10/11 query ioctl support
; FIOCTL.A86 1.11 93/06/16 16:21:37
; Codepage preparation bug fixed
; ENDLOG
; Date Modification
; --------- ---------------------------------------
; 29 Jun 89 Initial version splits from FDOS
; 21 Nov 89 iocE/F use relative unit number
; 12 Dec 89 ioc2/3 zero the unused portions of req hdr
; save a few bytes in other ioc's while I'm here
; 4 Jun 90 default file access permissions and user group support
; 5 Jun 90 ioc0/1 tidied up
; 12 Jun 90 get_doshndl parameter in BX not AX
; 2 Oct 90 net_vec moves to per-VC basis (info held in CCB_)
; 13 feb 91 ioc1 tests FHIO_DEV, not HM_DEV, (123 MSNet printing)
; 7 may 91 ioc2,ioc3,ioc6,ioc7,iocC destabilised for Lanstatic
; by-product is ioc6 for disks returns read-ahead char
; in AH
; 28 feb 92 ioctl C checks bit 6 not bit 14 in DH_ATTRIB
; 3 aug 92 ioctl C/D pass thru' SI/DI
; 5 aug 92 substatial ioctl rework saves a few bytes - ioctl
; request header now built by PCMODE
eject ! include i:fdos.equ
eject ! include rh.equ
eject ! include i:msdos.equ
eject ! include i:mserror.equ
eject ! include i:doshndl.def ; DOS Handle Structures
eject ! include i:driver.equ
eject ! include i:f52data.def ; DRDOS Structures
eject
PCMODE_DATA dseg BYTE
extrn ioctlRH:byte ; request header is build in PCMODE
; data area
BDOS_DATA dseg word
extrn fdos_pb:word
extrn fdos_ret:word
extrn last_drv:byte
extrn req_hdr:byte
if PASSWORD
extrn global_password:word
endif
BDOS_CODE cseg
extrn local_disk:near
extrn device_driver:near
extrn block_device_driver:near
extrn fdos_error:near
extrn fdos_ED_DRIVE:near
extrn fdos_ED_FUNCTION:near
extrn fdos_read:near
extrn get_ddsc:near
extrn vfy_dhndl_ptr:near
extrn get_pb2_drive:near
extrn ioc6_dev:near ; IOCTL(6): input status for device
extrn ioc7_dev:near ; IOCTL(7): output status for device
extrn vfy_dhndl_ptr:near
extrn verify_handle:near
extrn reload_registers:near
if JOIN
extrn get_ldt:near
endif
if PASSWORD
extrn hash_pwd:near
endif
public fdos_ioctl
eject
; INPUT/OUTPUT CONTROL (IOCTL)
; +----+----+----+----+----+----+----+----+----+----+
; | 26 | param | func | request header |
; +----+----+----+----+----+----+----+----+----+----+
; entry:
; ------
; param: handle/drive on some functions
; func: sub function (0-A)
; request header: far pointer to IOCTL request header
; exit:
; -----
; AX: return code or error code ( < 0)
; param: return value from some functions
ioctl_tbl dw ioctl0 ; 0-get handle status
dw ioctl1 ; 1-set handle status
dw ioctl2 ; 2-receive control string (handle)
dw ioctl3 ; 3-send control string (handle)
dw ioctl4 ; 4-receive control string (drive)
dw ioctl5 ; 5-send control string (drive)
dw ioctl6 ; 6-input status
dw ioctl7 ; 7-output status
dw ioctl8 ; 8-removable media check
dw ioctl9 ; 9-networked drive check
dw ioctlA ; A-networked handle check
if PASSWORD
dw ioctl54 ; B-set global password
else
dw device_ED_FUNCTION
endif
dw ioctlC ; C-code page support
dw ioctlD ; D-generic IOCTL disk i/o
dw ioctlE ; E-get logical drive
dw ioctlF ; F-set logical drive
dw ioctl10 ; 10-query IOCTL for char devs
dw ioctl11 ; 11-query IOCTL for disks
NUM_IOCTL equ (offset $ - offset ioctl_tbl)/WORD
fdos_ioctl:
;----------
mov bx,2[bp] ; BX -> parameter block
mov bx,4[bx] ; get I/O control subfunction
cmp bx,NUM_IOCTL ; is it in the supported range?
jae device_ED_FUNCTION ; skip if value too large
shl bx,1 ; else make it word index
jmp ioctl_tbl[bx] ; call the right function
device_ED_FUNCTION:
mov bx,ED_FUNCTION ; "invalid function"
ret
ioctl0: ; get device status
;------
; Note: We store the binary flag for the standard console
; handles in the console mode, not in the file handle,
; as the handles are shared across all consoles...
call vfy_dhndl_ptr ; check if good handle
mov ax,es:DHNDL_WATTR[bx] ; get attrib from doshndl
test ah,DHAT_REMOTE/256
mov ah,0 ; files/networks return 0 in AH/DH
jnz device_OK ; return attrib if network device
test al,DHAT_DEV ; or a file
jz device_OK
les bx,es:DHNDL_DEVPTR[bx] ; get real device driver address
mov ah,es:byte ptr 5[bx] ; get device driver attribute
; jmp device_OK
device_OK:
;---------
mov bx,2[bp] ; get parameter block address
mov 6[bx],ax ; save returned status
xor bx,bx ; successful return code
ret
ioctl1: ; set device status
;------
call vfy_dhndl_ptr ; make sure this is an open handle
test es:DHNDL_WATTR[bx],DHAT_DEV
jz device_ED_FUNCTION ; can't set status of disk files
mov ax,word ptr ioctlRH+14
; pick up new device status
test ah,ah ; test if high byte is zero
jnz device_ED_FUNCTION ; skip if O.K.
or al,DHAT_DEV ; make sure it stays a device
mov es:DHNDL_ATTR[bx],al ; store ioctl state in doshndl
jmps device_OK ; success
ioctl2: ; receive control string (devicehandle)
;------
ioctl3: ; send control string (device handle)
;------
ioctlC: ; generic ioctl (device handle)
;------
ioctl10: ; query ioctl support (device handle)
;-------
call vfy_dhndl_ptr ; check file handle #
call local_disk ; get MXdisk
call verify_handle ; make sure the handle is good
jnc short_fdos_ED_FUNCTION ; and is for a DEVICE
xor cx,cx ; device relative unit # always zero
les si,es:DHNDL_DEVPTR[bx] ; ES:SI -> device driver
jmps ioc2345CDcommon ; now use common code
ioctl4: ; receive control string (drive)
;------
ioctl5: ; send control string (drive)
;------
ioctlD: ; generic ioctl (drive)
;------
ioctl11: ; query ioctl support (drive)
;-------
call local_disk ; get MXdisk, switch stack
call get_pb2_ddsc ; get drives DDSC_
mov cl,es:DDSC_RUNIT[bx] ; get relative unit #
les si,es:DDSC_DEVHEAD[bx] ; ES:SI -> device header
; jmps ioctl2345Common ; now use common code
ioc2345CDcommon:
;---------------
; On Entry:
; ES:SI -> device driver header
; CL = media byte (0 if character device)
; CH = relative unit (0 if character device)
; MXDisk obtained
; On Exit:
; IOCTL performed
;
mov ax,fdos_pb+6 ; device driver support required
test es:DH_ATTRIB[si],ax ; does device driver support function ?
jz short_fdos_ED_FUNCTION
push ds
push es ! pop ds ; DS:SI -> device driver
push ss ! pop es
mov bx,offset ioctlRH ; ES:BX -> request header
mov es:RH_UNIT[bx],cl ; set relative unit for block devices
call device_driver ; call the device driver
pop ds ; check for errors on return
; jmp fdos_error_check
fdos_error_check:
;-------------
; On Entry:
; AX = Req Status
; On Exit:
; SIGN set if an error, AX&BX = Internal DOS error code
;
test ax,ax ; top bit == 1 if error
jns fdos_ioc_ec10 ; skip if no errors
xor ah,ah
add ax,-ED_PROTECT
neg ax
jmp fdos_error ; return critical error
fdos_ioc_ec10:
ret
; IOCTL subfunctions:
get_pb2_ddsc:
;------------
; On Entry:
; local_disk called, pick us drive from pb2
; On Exit:
; ES:BX -> DDSC_ for the drive
;
call get_pb2_drive ; get specified drive
cmp al,last_drv ; is it a valid drive
ja bad_drive
call get_ldt ; ES:BX -> LDT for this drive
jc get_pb2_ddsc10 ; no LDT, physical=logical
mov ax,es:LDT_FLAGS[bx]
test ah,LFLG_NETWRKD/256
jnz short_fdos_ED_FUNCTION ; reject network drives
test ah,LFLG_PHYSICAL/256
jz bad_drive
test ah,LFLG_JOINED/256
jnz bad_drive ; reject JOIN'd drives
mov al,es:LDT_NAME[bx] ; get physical drive from LDT
and al,1Fh ; convert to 1 based drive
dec ax ; make that zero based
get_pb2_ddsc10:
call get_ddsc ; ES:BX -> DDSC_
jc bad_drive ; or does it?
ret
bad_drive:
jmp fdos_ED_DRIVE ; invalid drive specified
short_fdos_ED_FUNCTION:
jmp fdos_ED_FUNCTION
ioctl8: ; removable media check
;------
call local_disk ; get MXdisk, switch stack
call get_pb2_ddsc ; get drives DDSC_
push ds
lds si,es:DDSC_DEVHEAD[bx] ; DS:SI -> device driver
test ds:DH_ATTRIB[si],DA_REMOVE
pop ds ; do we support the check ?
jz short_fdos_ED_FUNCTION ; if we don't then don't ask
mov req_hdr,RH15_LEN
mov req_hdr+2,CMD_FIXED_MEDIA
call block_device_driver ; call the device driver
js short_fdos_ED_FUNCTION
and ax,RHS_BUSY ; BUSY bit set if permanent - we just
xchg ah,al ; need to get bit in the right place
shr ax,1 ; now 1 if permanent media
mov fdos_pb+6,ax ; return status removable (=0)
ioctl8_10:
ret
ioctl6: ; file input status
;------
call vfy_dhndl_ptr ; make sure this is an open handle
mov ax,es:DHNDL_WATTR[bx]
test ax,DHAT_REMOTE
jnz ioctl6_10 ; always ask networked handles
test ax,DHAT_DEV
jz ioctl6_10 ; files are always askable
jmp ioc6_dev
ioctl6_10: ; disk files/network devices
push es:DHNDL_POSLO[bx] ; save current position in file
push es:DHNDL_POSHI[bx] ; so we can read ahead
push es
push bx ; save DHNDL_ too..
push bp ; save stack frame
mov si,2[bp] ; SI -> parameter block
mov ax,1
push ax ; read 1 byte ahead
push ds ; use fdos_pb as read-ahead
lea ax,6[si] ; buffer
push ax
push ds:word ptr 2[si] ; user file number
mov ax,MS_X_READ ; READ function #, so we create
push ax ; a dummy fdos_pb
mov bx,sp ; SS:BX -> dummy fdos_pb
mov cx,offset ioctl6_20 ; CX -> return address
push cx ; Return to here
push ss ; save parameter segment
push bx ; save parameter offset
push ax ; save sub-function
mov bp,sp ; SS:BP -> working variables
call fdos_read ; make FDOS_READ do the hard word
add sp,4*WORD ; discard param's on stack
ioctl6_20:
add sp,4*WORD ; discard most of dummy fdos_pb
pop cx ; return # read
cmp bx,ED_LASTERROR ; did we succeed ?
jb ioctl6_30 ; if so we can trust # read
xor cx,cx ; else in error assume nothing
ioctl6_30:
pop bp ; recover stack frame
pop bx ; rewind DHNDL_POS to where
pop es
pop es:DHNDL_POSHI[bx] ; it was before we started
pop es:DHNDL_POSLO[bx]
mov ax,1a00h ; assume not ready
jcxz ioctl6_40
dec ax ; AL = FF, ie. ready
mov si,2[bp] ; SI -> parameter block
mov ah,ds:byte ptr 6[si] ; get character we read
ioctl6_40:
jmp device_OK
ioctl7: ; file output status
;------
call vfy_dhndl_ptr ; make sure this is an open handle
mov ax,0FFh ; assume it's networked/disk
mov dx,es:DHNDL_WATTR[bx]
test dx,DHAT_REMOTE
jnz ioctl6_40 ; networked handles are always ready
test dx,DHAT_DEV
jz ioctl6_40 ; files are always ready
jmp ioc7_dev ; devices we ask...
ioctl9: ; networked drive check
;------
call local_disk ; get disk semaphore
call get_pb2_drive ; get specified drive
call get_ldt ; ES:BX -> LDT for this drive
jc ioctl940
mov ax,es:LDT_FLAGS[bx]
test ah,LFLG_NETWRKD/256
jz ioctl910
if 1
mov ax,1000h ; return drive as remote
else
les di,es:LDT_PDT[bx] ; pick up network internal pointer
mov ax,es:4[di] ; pick up garbage
or ah,10h ; return drive as remote
endif
jmps ioctl930
ioctl910:
test ah,LFLG_PHYSICAL/256
jz ioctl940
test ah,LFLG_SUBST/256
xchg ax,dx ; save flags
mov ax,8000h ; assume it's SUBST'd
jnz ioctl920
test dh,LFLG_JOINED/256
xchg al,ah ; assume it's JOIN'd
jnz ioctl930
xor ax,ax ; clear if not
ioctl920:
push ax
call get_pb2_ddsc ; get drives DDSC_
pop ax
les si,es:DDSC_DEVHEAD[bx] ; ES:SI -> device driver
or ax,es:4[si] ; get device attributes
ioctl930:
mov fdos_pb+6,ax ; return updated status
ret
ioctl940:
jmp fdos_ED_DRIVE ; return ED_DRIVE error
ioctlA: ; networked handle check
;------
call vfy_dhndl_ptr
mov ax,es:DHNDL_WATTR[bx]
jmp device_OK ; return attributes
ioctlE:
;------
call local_disk
mov al,CMD_GET_DEVICE ; get logical device
jmps iocEFcommon ; common code for IOCTL(E)/IOCTL(F)
ioctlF:
;------
call local_disk
mov al,CMD_SET_DEVICE ; set logical device
iocEFcommon:
mov req_hdr,RH24_LEN
mov req_hdr+2,al
call get_pb2_ddsc ; get drives DDSC_
inc ax ; make drive one-relative
mov req_hdr+13,al ; set this as new drive
xor ax,ax ; assume not supported
push ds
lds si,es:DDSC_DEVHEAD[bx] ; does device driver support function ?
test ds:DH_ATTRIB[si],DA_GETSET
pop ds
jz iocF_single ; skip if not supported
call block_device_driver ; call the device driver
call fdos_error_check ; return any errors
mov al,req_hdr+1 ; get returned drive
iocF_single: ; AX = return value
mov ah,7
mov fdos_pb+6,ax ; return the drive
ret
if PASSWORD
ioctl54: ; set global password
;-------
call local_disk ; get the MX disk
push ds
lds si,dword ptr ioctlRH+14
call hash_pwd ; encrypt new default password
pop ds
mov global_password,ax
ret
endif
end