MS-DOS/v2.0/source/GETSET.ASM

627 lines
18 KiB
NASM
Raw Normal View History

1983-08-13 01:53:34 +01:00
TITLE GETSET - GETting and SETting MS-DOS system calls
NAME GETSET
;
; System Calls which get and set various things
;
; $GET_VERSION
; $GET_VERIFY_ON_WRITE
; $SET_VERIFY_ON_WRITE
; $SET_CTRL_C_TRAPPING
; $INTERNATIONAL
; $GET_DRIVE_FREESPACE
; $GET_DMA
; $SET_DMA
; $GET_DEFAULT_DRIVE
; $SET_DEFAULT_DRIVE
; $GET_INTERRUPT_VECTOR
; $SET_INTERRUPT_VECTOR
; RECSET
; $CHAR_OPER
;
.xlist
;
; get the appropriate segment definitions
;
INCLUDE DOSSEG.ASM
IFNDEF ALTVECT
ALTVECT EQU 0 ; FALSE
ENDIF
IFNDEF IBM
IBM EQU 0
ENDIF
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME SS:DOSGROUP,CS:DOSGROUP
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
.cref
.list
i_need VERFLG,BYTE
i_need CNTCFLAG,BYTE
i_need DMAADD,DWORD
i_need CURDRV,BYTE
i_need Current_Country,WORD
i_need international_table,BYTE
i_need INDOS,BYTE
i_need SYSINITVAR,WORD
i_need NUMIO,BYTE
i_need SWITCH_CHARACTER,BYTE
i_need DEVICE_AVAILABILITY,BYTE
USERNUM DW ? ; 24 bit user number
DB ?
IF IBM
OEMNUM DB 0 ; 8 bit OEM number
ELSE
OEMNUM DB 0FFH ; 8 bit OEM number
ENDIF
MSVERS EQU THIS WORD ; MS-DOS version in hex for $GET_VERSION
MSMAJOR DB DOS_MAJOR_VERSION
MSMINOR DB DOS_MINOR_VERSION
BREAK <$Get_Version -- Return MSDOS version number>
procedure $GET_VERSION,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; None
; Function:
; Return MS-DOS version number
; Outputs:
; OEM number in BH
; User number in BL:CX (24 bits)
; Version number as AL.AH in binary
; NOTE: On pre 1.28 DOSs AL will be zero
PUSH SS
POP DS
ASSUME DS:DOSGROUP
MOV BX,[USERNUM + 2]
MOV CX,[USERNUM]
MOV AX,[MSVERS]
invoke get_user_stack
ASSUME DS:NOTHING
MOV [SI.user_BX],BX
MOV [SI.user_CX],CX
MOV [SI.user_AX],AX ; Really only sets AH
return
$GET_VERSION ENDP
BREAK <$International - return country-dependent information>
;
; Inputs:
; DS:DX point to a block
; Function:
; give users an idea of what country the application is running
; Outputs:
; AX = number of bytes transferred
; DS:DX ->+---------------------------------+
; | WORD Date/time format |
; +---------------------------------+
; | BYTE ASCIZ currency symbol |
; +---------------------------------+
; | BYTE ASCIZ thousands separator |
; +---------------------------------+
; | BYTE ASCIZ decimal separator |
; +---------------------------------+
procedure $INTERNATIONAL,NEAR
ASSUME DS:NOTHING,ES:NOTHING
MOV BL,AL
PUSH DS
POP ES
PUSH DX
POP DI
PUSH SS
POP DS
ASSUME DS:DOSGROUP
CMP DI,-1
JZ international_set
OR BL,BL
JNZ international_find
MOV SI,[Current_Country]
MOV AX,WORD PTR [SI-2] ; Get size in AL, country code in AH
MOV BL,AH ; Set country code
JMP SHORT international_copy
international_find:
CALL international_get
JNC international_copy
error country_not_found
international_get:
MOV SI,OFFSET DOSGROUP:international_table
international_next:
LODSW ; Get size in AL, country code in AH
CMP AL,-1
JNZ check_code
STC
RET35:
RET
check_code:
CMP BL,AH
JZ RET35 ; Carry clear
XOR AH,AH
ADD SI,AX
JMP international_next
international_copy:
MOV CL,AL
XOR CH,CH
PUSH DI
REP MOVSB
POP DI
MOV WORD PTR ES:[DI.MAP_CALL + 2],CS ; Set segment for case map call
international_ok:
XOR AX,AX
MOV AL,BL ; Return country code in AX
transfer SYS_RET_OK
international_set:
CALL international_get
JNC international_store
error country_not_found
international_store:
MOV [Current_Country],SI
JMP international_ok
$INTERNATIONAL ENDP
BREAK <$Get_Verify_on_Write - return verify-after-write flag>
procedure $GET_VERIFY_ON_WRITE,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; none.
; Function:
; returns flag
; Returns:
; AL = value of VERIFY flag
MOV AL,[VERFLG]
return
$GET_VERIFY_ON_WRITE ENDP
BREAK <$Set_Verify_on_Write - Toggle verify-after-write flag>
procedure $SET_VERIFY_ON_WRITE,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; AL = desired value of VERIFY flag
; Function:
; Sets flag
; Returns:
; None
AND AL,1
MOV [VERFLG],AL
return
$SET_VERIFY_ON_WRITE ENDP
BREAK <$Set_CTRL_C_Trapping -- En/Disable ^C check in dispatcher>
procedure $SET_CTRL_C_TRAPPING,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; AL = 0 read ^C status
; AL = 1 Set ^C status, DL = 0/1 for ^C off/on
; Function:
; Enable disable ^C checking in dispatcher
; Outputs:
; If AL = 0 then DL = 0/1 for ^C off/on
OR AL,AL
JNZ CTRL_C_set
invoke get_user_stack
MOV AL,[CNTCFLAG]
MOV BYTE PTR [SI.user_DX],AL
return
CTRL_C_set:
DEC AL
JNZ bad_val
AND DL,01h
MOV [CNTCFLAG],DL
return
bad_val:
MOV AL,0FFH
return
$SET_CTRL_C_TRAPPING ENDP
BREAK <$Get_INDOS_Flag -- Return location of DOS critical-section flag>
procedure $GET_INDOS_FLAG,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; None
; Function:
; Returns location of DOS status for interrupt routines
; Returns:
; Flag location in ES:BX
invoke get_user_stack
MOV [SI.user_BX],OFFSET DOSGROUP:INDOS
MOV [SI.user_ES],SS
return
$GET_INDOS_FLAG ENDP
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
procedure $GET_IN_VARS,NEAR
; Return a pointer to interesting DOS variables This call is version
; dependent and is subject to change without notice in future versions.
; Use at risk.
invoke get_user_stack
MOV [SI.user_BX],OFFSET DOSGROUP:SYSINITVAR
MOV [SI.user_ES],SS
return
$GET_IN_VARS ENDP
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
BREAK <$Get_Drive_Freespace -- Return bytes of free disk space on a drive>
procedure $GET_DRIVE_FREESPACE,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DL = Drive number
; Function:
; Return number of free allocation units on drive
; Outputs:
; BX = Number of free allocation units
; DX = Total Number of allocation units on disk
; CX = Sector size
; AX = Sectors per allocation unit
; = -1 if bad drive specified
; This call returns the same info in the same registers (except for FAT pointer)
; as the old FAT pointer calls
PUSH SS
POP DS
ASSUME DS:DOSGROUP
MOV AL,DL
invoke GETTHISDRV
MOV AX,-1
JC BADFRDRIVE
invoke FATREAD
XOR DX,DX
MOV BX,2
MOV CX,ES:[BP.dpb_max_cluster]
DEC CX
PUSH CX ; Save Total
SCANFREE:
invoke UNPACK
JNZ NOTFREECLUS
INC DX
NOTFREECLUS:
INC BX
LOOP SCANFREE
POP BX ; Remember Total
MOV AL,ES:[BP.dpb_cluster_mask]
INC AL
XOR AH,AH
MOV CX,ES:[BP.dpb_sector_size]
BADFRDRIVE:
invoke get_user_stack
ASSUME DS:NOTHING
MOV [SI. user_CX],CX
MOV [SI.user_DX],BX
MOV [SI.user_BX],DX
MOV [SI.user_AX],AX
return
$GET_DRIVE_FREESPACE ENDP
BREAK <$Get_DMA, $Set_DMA -- Get/Set current DMA address>
procedure $GET_DMA,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; None
; Function:
; Get DISK TRANSFER ADDRESS
; Returns:
; ES:BX is current transfer address
MOV BX,WORD PTR [DMAADD]
MOV CX,WORD PTR [DMAADD+2]
invoke get_user_stack
MOV [SI.user_BX],BX
MOV [SI.user_ES],CX
return
$GET_DMA ENDP
procedure $SET_DMA,NEAR ; System call 26
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX is desired new disk transfer address
; Function:
; Set DISK TRANSFER ADDRESS
; Returns:
; None
MOV WORD PTR [DMAADD],DX
MOV WORD PTR [DMAADD+2],DS
return
$SET_DMA ENDP
BREAK <$Get_Default_DPB,$Get_DPB -- Return pointer to DPB>
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
procedure $GET_DEFAULT_DPB,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DL = Drive number (always default drive for call 31)
; Function:
; Return pointer to drive parameter table for default drive
; Returns:
; DS:BX points to the DPB
; AL = 0 If OK, = -1 if bad drive (call 50 only)
MOV DL,0
entry $GET_DPB
PUSH SS
POP DS
ASSUME DS:DOSGROUP
MOV AL,DL
invoke GETTHISDRV
JC ISNODRV
invoke FATREAD
invoke get_user_stack
ASSUME DS:NOTHING
MOV [SI.user_BX],BP
MOV [SI.user_DS],ES
XOR AL,AL
return
ISNODRV:
MOV AL,-1
return
$GET_Default_dpb ENDP
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
BREAK <$Get_Default_Drive, $Set_Default_Drive -- Set/Get default drive>
procedure $GET_DEFAULT_DRIVE,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; None
; Function:
; Return current drive number
; Returns:
; AL = drive number
MOV AL,[CURDRV]
return
$GET_DEFAULT_DRIVE ENDP
procedure $SET_DEFAULT_DRIVE,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DL = Drive number for new default drive
; Function:
; Set the default drive
; Returns:
; AL = Number of drives, NO ERROR RETURN IF DRIVE NUMBER BAD
MOV AL,[NUMIO]
CMP DL,AL
JNB RET17
MOV [CURDRV],DL
RET17: return
$SET_DEFAULT_DRIVE ENDP
BREAK <$Get_Interrupt_Vector - Get/Set interrupt vectors>
procedure $GET_INTERRUPT_VECTOR,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; AL = interrupt number
; Function:
; Get the interrupt vector
; Returns:
; ES:BX is current interrupt vector
CALL RECSET
LES BX,DWORD PTR ES:[BX]
invoke get_user_stack
MOV [SI.user_BX],BX
MOV [SI.user_ES],ES
return
$GET_INTERRUPT_VECTOR ENDP
procedure $SET_INTERRUPT_VECTOR,NEAR ; System call 37
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; AL = interrupt number
; DS:DX is desired new interrupt vector
; Function:
; Set the interrupt vector
; Returns:
; None
CALL RECSET
MOV ES:[BX],DX
MOV ES:[BX+2],DS
return
$SET_INTERRUPT_VECTOR ENDP
IF ALTVECT
VECIN: ; INPUT VECTORS
DB 22H ; Terminate
DB 23H ; ^C
DB 24H ; Hard error
DB 28H ; Spooler
LSTVEC DB ? ; ALL OTHER
VECOUT: ; GET MAPPED VECTOR
DB int_terminate
DB int_ctrl_c
DB int_fatal_abort
DB int_spooler
LSTVEC2 DB ? ; Map to itself
NUMVEC = VECOUT-VECIN
ENDIF
procedure RECSET,NEAR
IF ALTVECT
PUSH SS
POP ES
MOV [LSTVEC],AL ; Terminate list with real vector
MOV [LSTVEC2],AL ; Terminate list with real vector
MOV CX,NUMVEC ; Number of possible translations
MOV DI,OFFSET DOSGROUP:VECIN ; Point to vectors
REPNE SCASB
MOV AL,ES:[DI+NUMVEC-1] ; Get translation
ENDIF
XOR BX,BX
MOV ES,BX
MOV BL,AL
SHL BX,1
SHL BX,1
return
recset ENDP
BREAK <$Char_Oper - hack on paths, switches so that xenix can look like PCDOS>
;
; input: AL = function:
; 0 - read switch char
; 1 - set switch char (char in DL)
; 2 - read device availability
; 3 - set device availability (0/FF in DL)
; DL = 0 means /DEV/ must preceed device names
; DL = Non0 means /DEV/ need not preeceed
; output: (get) DL - character/flag
;
procedure $CHAR_OPER,NEAR
ASSUME DS:NOTHING,ES:NOTHING
PUSH SS
POP DS
ASSUME DS:DOSGROUP
OR AL,AL
JNZ char_oper_set_switch
MOV DL,[switch_character]
JMP SHORT char_oper_ret
char_oper_set_switch:
DEC AL
JNZ char_oper_read_avail
MOV [switch_character],DL
return
char_oper_read_avail:
DEC AL
JNZ char_oper_set_avail
MOV DL,[device_availability]
JMP SHORT char_oper_ret
char_oper_set_avail:
DEC AL
JNZ char_oper_bad_ret
MOV [device_availability],DL
return
char_oper_bad_ret:
MOV AL,0FFh
return
char_oper_ret:
invoke get_user_stack
MOV [SI.user_DX],DX
return
$CHAR_OPER ENDP
BREAK <$SetDPB - Create a valid DPB from a user-specified BPB>
procedure $SETDPB,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; ES:BP Points to DPB
; DS:SI Points to BPB
; Function:
; Build a correct DPB from the BPB
; Outputs:
; ES:BP and DS preserved all others destroyed
MOV DI,BP
ADD DI,2 ; Skip over dpb_drive and dpb_UNIT
LODSW
STOSW ; dpb_sector_size
MOV DX,AX
LODSB
DEC AL
STOSB ; dpb_cluster_mask
INC AL
XOR AH,AH
LOG2LOOP:
TEST AL,1
JNZ SAVLOG
INC AH
SHR AL,1
JMP SHORT LOG2LOOP
SAVLOG:
MOV AL,AH
STOSB ; dpb_cluster_shift
MOV BL,AL
MOVSW ; dpb_first_FAT Start of FAT (# of reserved sectors)
LODSB
STOSB ; dpb_FAT_count Number of FATs
MOV BH,AL
LODSW
STOSW ; dpb_root_entries Number of directory entries
MOV CL,5
SHR DX,CL ; Directory entries per sector
DEC AX
ADD AX,DX ; Cause Round Up
MOV CX,DX
XOR DX,DX
DIV CX
MOV CX,AX ; Number of directory sectors
INC DI
INC DI ; Skip dpb_first_sector
MOVSW ; Total number of sectors in DSKSIZ (temp as dpb_max_cluster)
LODSB
MOV ES:[BP.dpb_media],AL ; Media byte
LODSW ; Number of sectors in a FAT
STOSB ; dpb_FAT_size
MUL BH ; Space occupied by all FATs
ADD AX,ES:[BP.dpb_first_FAT]
STOSW ; dpb_dir_sector
ADD AX,CX ; Add number of directory sectors
MOV ES:[BP.dpb_first_sector],AX
SUB AX,ES:[BP.DSKSIZ]
NEG AX ; Sectors in data area
MOV CL,BL ; dpb_cluster_shift
SHR AX,CL ; Div by sectors/cluster
INC AX
MOV ES:[BP.dpb_max_cluster],AX
MOV ES:[BP.dpb_current_dir],0 ; Current directory is root
return
$SETDPB ENDP
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
do_ext
CODE ENDS
END