mirror of
https://github.com/SEPPDROID/DR-DOS-OpenDOS.git
synced 2025-10-22 16:04:20 +00:00
1029 lines
31 KiB
Plaintext
1029 lines
31 KiB
Plaintext
; File : $PCMIF.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: $
|
|
; PCMIF.A86 1.21 93/09/09 22:36:50
|
|
; Int 21/59 uses error stack
|
|
; PCMIF.A86 1.20 93/08/27 18:56:30
|
|
; Int 25/26 32 bit sector detection
|
|
; PCMIF.A86 1.19 93/07/22 19:30:54
|
|
; chnage int 25/26 support for NDD
|
|
; PCMIF.A86 1.18 93/07/20 22:47:54
|
|
; Even fewer checks on int 25/26
|
|
; PCMIF.A86 1.14 93/05/06 19:28:31
|
|
; Move int 23/28 support to CIO.
|
|
; PCMIF.A86 1.13 93/05/05 23:31:0
|
|
; int 2A/84 is now only generated on input-and-wait functions
|
|
; PCMIF.A86 1.12 93/03/25 15:06:48
|
|
; tweak int21 entry
|
|
; ENDLOG
|
|
;
|
|
; 24 Aug 87 The CARRY flag is now preserved for all DOS functions below
|
|
; 038h Get/Set Country Code.
|
|
; 04 Sep 87 Display the Interrupt Number and Registers when an illegal
|
|
; software interrupt is executed by an application. This
|
|
; is disabled by DBG OFF.
|
|
; 09 Sep 87 DDIO interface changed to support a Double Word sector
|
|
; number.
|
|
; 05 Oct 87 Critical Error abort routine now uses the correct
|
|
; terminate code.
|
|
; 14 Oct 87 INT2F responds like a Network Redirector
|
|
; 28 Oct 87 Preserve the state of the INDOS_INTERNAL flag during multiple
|
|
; calls through DOS_ENTRY
|
|
; 29 Oct 87 DS now points at the IBM PC ROS during an INT1B and INT1B
|
|
; moved into IBMROS.
|
|
; 7 Nov 87 Removal of development flags
|
|
; 5 Jan 88 Terminate CP/M applications making DOS Calls in Concurrent DOS
|
|
; 26 Feb 88 Terminate DOS applications making CP/M calls in DOSPLUS
|
|
; 26 Apr 88 INT25/26 error codes only translated for Concurrent
|
|
; 18 May 88 Prevent corruption of the EXIT_CODE by INT23 and INT24
|
|
; when the application does not return.
|
|
; 23 May 88 Prevent termination during CONFIG.SYS processing in DOSPLUS
|
|
; 26 May 88 Force INDOS and ERROR flags to ZERO on terminate
|
|
; 1 Jun 88 Modify INT28 to execute delays and work with SideKick.
|
|
; 15 Jul 88 Support the IDLECNT field in the Process Descriptor and
|
|
; CCB BUSY bit.
|
|
; 07 Sep 88 PolyTron PolyWindows make DOS functions calls whenever
|
|
; CS < SS. Therefore during the INT21 Entry and Exit code
|
|
; interrupts must be disabled untill the stack swap occurs
|
|
; even though the INDOS_FLAG is non-zero.
|
|
; 24 Oct 88 File Lock/Unlock is now treated as an INACTIVE function.
|
|
; 4 Nov 88 Correct the INT25/26 Error Translation Code
|
|
; 21 Nov 88 Make INt25/26 Error Translation even better.
|
|
; 29 Nov 88 Command Line Editor Insert on by default.
|
|
; 21 Dec 88 IJs IDLE detection improvement only DELAY if someone else is
|
|
; ready to run.
|
|
; 11 Jan 89 Inc/Dec INTERNAL_FLAG to support DOS_ENTRY reentrancy.
|
|
; 30 Jan 89 Inc/Dec INDOS_FLAG to INT25/26 Direct Disk I/O (CHKDSK/PRINT)
|
|
; 19 Feb 89 Check the SHARE_FLAG for SHARING status in DR DOS
|
|
; 9 Mar 89 Save/Restore PSP_USERSP/SS round int28's (SKPLUS/LINK/CTRL-C)
|
|
; 18 Apr 89 ij Maintain the INDOS_FLAG correctly while processing INT 24
|
|
; 18 Apr 89 Only take over INTs 5B and 5C for Debug Systems
|
|
; 22 May 89 Setup DS before testing the state of the Share Flag.
|
|
; 25 May 89 Support INT28_FLAG for functions 01 to 0C inclusive
|
|
; 31 May 89 Move break_sp into DOS internal data area
|
|
; 1 Jun 89 Save PSP_USERSS and SP during a critival Error (INT 24)
|
|
; 05 Jun 89 Return NOT present for ASSIGN command and TRUE state for APPEND
|
|
; 29 Jun 89 Save/restore retry_sp & retry_off around INT 24
|
|
; 10 Jul 89 INT27 corrected to handle memory size of XXX1 (INFORM)
|
|
; 31 Jul 89 Move stacks to DATA.PCM (CDROM support under way...)
|
|
; 11 Aug 89 Create INT2F.PCM to support real INT 2F functions
|
|
; 6 Sep 89 INT2A/84 keyboard busy loop added to do_int28
|
|
; 23 Oct 89 MON_PERM removed from func5D/func5E/func5F (pain with MSNET..)
|
|
; 9 Nov 89 Int 5B & 5C no longer taken over in DRDOS Debug versions
|
|
; (Conflicts with PC-Net)
|
|
; 15 Jan 90 pcmode_swapin/pcmode_swapout added for paged isr support
|
|
; 25/Jan/90 Support Idle Data Area
|
|
; 25/Jan/90 Add forth stack to support Japanese FEP and PTHOT.
|
|
; 29/Jan/90 keep int21 CS/IP/FLAGS on local stack
|
|
; 13/Feb/90 Added func63.
|
|
; 20/Feb/90 CDOS checks caller is DOS process and aborts if not.
|
|
; 22/Feb/90 Int25/26 checks disk label for passwords
|
|
; Also swaps to normal stack like others DOS's
|
|
; 7 Mar 90 Convert to register preserved function calls
|
|
; 16 Mar 90 Int25/26 checks out for Leopard Beta 2
|
|
; 4 Jun 90 Int21/25&35 don't swap stacks-ANSI.SYS Framework DOS window bug
|
|
; 7 Jun 90 Print Rite fix moves to init.pcm
|
|
; 29 Jun 90 CDOS idle detection uses timer info
|
|
; 9 Aug 90 Int 8 tick count packed in P_CMOD
|
|
; 19 Sep 90 load current_psp before checking PSP_PIDF (thanks Datapac)
|
|
; 4 Oct 90 improved control break handling
|
|
; 11 Oct 90 dev_map now supported to set LPTn/COMn mapping
|
|
; 1 Nov 90 default Int 24 handler returns "Fail"
|
|
; 19 feb 91 do_int28 calls read_time_and_date (BIOS CLOCK needs a call
|
|
; every day)
|
|
; 14 jun 91 copy user regs to local copy after int24 for pcshell
|
|
; 8 aug 91 SI preserved on Int25/26 for SCAN 7.7
|
|
|
|
include pcmode.equ
|
|
include fdos.def
|
|
include vectors.def
|
|
include i:msdos.equ
|
|
include i:mserror.equ
|
|
include i:psp.def
|
|
include i:fdos.equ
|
|
|
|
PCM_CODE CSEG BYTE
|
|
|
|
extrn pcmode_dseg:word
|
|
extrn break_check:near ; Control-C Check
|
|
extrn error_exit:near
|
|
extrn fdos_nocrit:near
|
|
extrn get_ddsc:near
|
|
|
|
eject
|
|
;
|
|
; This entry point is used when a CALLF PSP:0005 has been executed
|
|
; Here the function number is passed in CL and not AH and only
|
|
; functions 0 to 24 inclusive can be executed.
|
|
;
|
|
; Entry Stack -> INT 21 Stack
|
|
;
|
|
; SP + 04 Return Offset Current Flags
|
|
; SP + 02 PSP Segment PSP Segment
|
|
; SP + 00 000Ah Return Offset
|
|
;
|
|
Public call5_entry
|
|
call5_entry:
|
|
pop ax ; Remove 000Ah return Offset
|
|
pushf ; Save the Flags
|
|
push bp ! mov bp,sp ; Get Stack Frame Pointer
|
|
mov ax,02[bp] ; Get the FLAGS
|
|
xchg ax,06[bp] ; Swap with the return offset
|
|
mov 02[bp],ax ; and then save the return offset
|
|
pop bp ; Restore the BP register
|
|
mov ah,cl ; Make it look like an INT 21
|
|
cmp ah,024h ; Check for a valid function for this
|
|
jbe int21_entry ; entry technique if not return
|
|
illegal_iret:
|
|
mov al,0
|
|
iret
|
|
|
|
int21_e01:
|
|
mov ds,word ptr .INT31_SEGMENT
|
|
jmps int21_e02
|
|
|
|
eject
|
|
; ++++++++++++++++++++++++++
|
|
; Int 20 - Program Terminate
|
|
; ++++++++++++++++++++++++++
|
|
;
|
|
Public int20_entry
|
|
int20_entry:
|
|
mov ah,00h
|
|
; jmps int21_entry ; and jump to the standard entry point
|
|
|
|
eject
|
|
; +++++++++++++++++++++++++
|
|
; Int 21 - Function Request
|
|
; +++++++++++++++++++++++++
|
|
;
|
|
Public int21_entry
|
|
int21_entry:
|
|
cmp ah,pcmode_ftl ; is it in range ?
|
|
ja illegal_iret ; no, return BEFORE enabling ints
|
|
cld ; Clear the direction flag
|
|
PUSH$DOS ; Save User Registers
|
|
mov ds,pcmode_dseg ; get CS relative Data Segment
|
|
test pcmode_dseg,0FFFFh ; if Data Segment is zero then get
|
|
jz int21_e01 ; the Data segment address from
|
|
int21_e02: ; the segment portion of INT 31
|
|
|
|
;
|
|
; The following routines execute on the users stack without
|
|
; modifing the INDOS_FLAG etc. These routines should only read
|
|
; or update BASIC system variables.
|
|
;
|
|
cmp ah,33h ; Func 33h - Control Break
|
|
je int21_e10
|
|
cmp ah,50h ; Func 50h - Set PSP
|
|
jb int21_e20
|
|
cmp ah,51h ; Func 51h - Get PSP
|
|
jbe int21_e10
|
|
cmp ah,62h ; Func 62h - Get PSP
|
|
jne int21_e20
|
|
int21_e10:
|
|
mov bp,sp ; Calculate the Stack Frame address
|
|
call internal_func ; "jump" to appropriate routine
|
|
jmp int21_exit
|
|
|
|
int21_e20:
|
|
inc indos_flag ; Increment the INDOS Flag
|
|
|
|
mov int21AX,ax ; save function number
|
|
|
|
if DOS5
|
|
cmp WindowsHandleCheck,26h ; is windows active ?
|
|
jne int21_e30
|
|
mov ax,LocalMachineID ; get local machine ID (zero unless
|
|
mov machine_id,ax ; we are multi-tasking)
|
|
else
|
|
callf win386_local_machine
|
|
cmp machine_id,0 ; did it nobble the machine ID
|
|
jnz int21_e30 ; if so leave it alone
|
|
|
|
mov ax,LocalMachineID ; get local machine ID (zero unless
|
|
mov machine_id,ax ; we are multi-tasking)
|
|
endif
|
|
int21_e30:
|
|
mov ax,current_psp
|
|
mov owning_psp,ax
|
|
mov es,ax ; Get the PSP
|
|
|
|
mov ax,sp
|
|
mov PSP_USERSP,ax ; Save the SS:SP pointer to
|
|
mov PSP_USERSS,ss ; the register image ready for any
|
|
; Critical errors that might occur
|
|
|
|
xchg ax,int21regs_off ; point to callers registers
|
|
mov prev_int21regs_off,ax ; while saving current
|
|
mov ax,ss ; pointer to cater for
|
|
xchg ax,int21regs_seg ; re-entrancy
|
|
mov prev_int21regs_seg,ax
|
|
|
|
xor ax,ax
|
|
mov remote_call,ax ; indicate we are a local call
|
|
mov int28_flag,al ; Do NOT Generate INT 28s
|
|
|
|
mov ax,ds
|
|
mov ss,ax ; swap initially to the error
|
|
mov sp,offset error_stack ; stack until we know better
|
|
mov ax,int21AX ; reload AX
|
|
|
|
sti
|
|
cmp ah,59h ; Func 59h - Return Extended Error
|
|
je int21_e50 ; use the error stack
|
|
cmp ah,0Ch ; are we a character function
|
|
ja int21_e40 ; in range 01-0C ?
|
|
cmp ah,00h
|
|
je int21_e40
|
|
cmp error_flag,0 ; Use the "ERROR" Stack for the above
|
|
jnz int21_e50 ; functions 01-0C if error_flag set
|
|
mov sp,offset indos_stack ; else use the "INDOS" stack for these
|
|
mov int28_flag,TRUE ; functions and generate INT 28s
|
|
jmps int21_e50
|
|
|
|
int21_e40:
|
|
mov error_flag,0 ; clear the error flag in case someone
|
|
; hasn't returned from an Int 24
|
|
push ax ; save function on stack
|
|
mov ah,82h ; magic number in AH
|
|
int 2ah ; call server hook
|
|
pop ax ; recover function number
|
|
|
|
mov sp,offset normal_stack ; switch to the NORMAL stack
|
|
test break_flag,0FFh ; is the Break Flag ON
|
|
jz int21_e50 ; NO - So continue
|
|
call break_check ; Handle the Control-C
|
|
int21_e50:
|
|
if IDLE_DETECT
|
|
test idle_flags,IDLE_DISABLE ; don't break the pipeline unless
|
|
jz int21_idle ; IDLE checking enabled
|
|
int21_e60:
|
|
endif
|
|
call int21_func ; Execute the function
|
|
cli ; Stop anybody interfering
|
|
les bp,int21regs_ptr ; point to user stack
|
|
mov es:reg_AL[bp],al ; always return AL
|
|
mov ax,prev_int21regs_off
|
|
mov int21regs_off,ax
|
|
mov ax,prev_int21regs_seg
|
|
mov int21regs_seg,ax
|
|
mov ax,es
|
|
mov ss,ax ; back to users stack
|
|
mov sp,bp
|
|
dec indos_flag ; Decrement the INDOS_FLAG
|
|
; jmp int21_exit
|
|
|
|
Public int21_exit
|
|
int21_exit:
|
|
POP$DOS ; Restore Registers
|
|
iret
|
|
|
|
eject
|
|
if IDLE_DETECT
|
|
; Only called if Idle detection is enabled
|
|
; AH,DL as on Int 21 Entry
|
|
; Decide if function is active/inactive
|
|
|
|
int21_idle:
|
|
;----------
|
|
if IDLE_DETECT
|
|
mov bx,int28_reload ; reset the INT28 delay counter
|
|
mov int28_delay,bx ; with the Reload value
|
|
endif
|
|
cmp ah,5Ch ! je int21_inactive ; Treat Lock/Unlock as inactive some
|
|
; applications poll locked record.
|
|
cmp ah,44h ! je int21_inactive ; IO Control Treated as Inactive
|
|
cmp ah,2Ch ! ja int21_active ; > Get Current Time all active
|
|
je int21_inactive ; Get Current Time inactive
|
|
cmp ah,2Ah ! je int21_inactive ; Get Current Date inactive
|
|
cmp ah,0Bh ! je int21_inactive ; Console Status
|
|
cmp ah,0Ch ! je int21_inactive ; Flush and Invoke Treated as Inactive
|
|
cmp ah,19h ! je int21_inactive ; Get Current Disk
|
|
cmp ah,06h ! jne int21_active ; Treat RAW_IO Status as Inactive
|
|
cmp dl,0FFh ! je int21_inactive ;
|
|
|
|
int21_active: ; Active function Executed
|
|
or idle_flags,IDLE_DOSFUNC ; set DOSFUNC flag for BIOS
|
|
call active ; remember we were active
|
|
jmps int21_e60 ; continue execution
|
|
|
|
int21_inactive:
|
|
call inactive ; Process this INACTIVE function
|
|
jmps int21_e60
|
|
|
|
|
|
Public inactive
|
|
inactive:
|
|
push es ! push ax
|
|
|
|
dec active_cnt ; Decrement the count
|
|
jnz inactive_10 ; Return if Non-Zero
|
|
|
|
mov ax,idle_max ; Get the default count value
|
|
mov active_cnt,ax ; and reset the internal count
|
|
|
|
test idle_flags,IDLE_DISABLE ; Has Idle Checking been enabled
|
|
jnz inactive_10 ; Skip if NO.
|
|
mov ax,PROC_IDLE ; Process is IDLE
|
|
callf idle_vec ; Call the IDLE Handler
|
|
|
|
inactive_10:
|
|
pop ax ! pop es
|
|
ret
|
|
;
|
|
; This routine will reset the active count for functions which
|
|
; are treated as INACTIVE but which have active sub-functions.
|
|
;
|
|
Public active
|
|
active:
|
|
push ax
|
|
mov ax,idle_max ; Get the default count value
|
|
mov active_cnt,ax ; and reset the internal count
|
|
pop ax
|
|
ret
|
|
endif
|
|
;
|
|
;
|
|
; This function is invoked for functions number above the last
|
|
; supported function number. It forces AL to zero and returns.
|
|
; Just that and nothing more.
|
|
;
|
|
ms_zero_AL:
|
|
xor ax,ax ; AL = 0 for return
|
|
ret
|
|
|
|
eject
|
|
; DOS_ENTRY is used to call DOS functions internally.
|
|
; eg. Func4B (exec) calls MS_X_OPEN, MS_X_READ, MS_X_CLOSE etc.
|
|
; It is the responsibilty of the caller to make sure that no side
|
|
; effects exist if this entry point is used.
|
|
; eg. critical error handling
|
|
;
|
|
;
|
|
Public dos_entry
|
|
dos_entry:
|
|
clc
|
|
cld
|
|
pushf ; look like Int21 registers
|
|
pushf ! pushf ; fake CS/IP positions
|
|
push ds ! push es ; Save registers on the USER stack
|
|
push bp ; no Stack Swap is executed and DS
|
|
push di ! push si ; and ES are swapped.
|
|
push dx ! push cx
|
|
push bx ! push ax
|
|
mov bp,sp ; Initialise Stack Frame
|
|
|
|
call get_dseg ; Get our Data Area
|
|
|
|
inc internal_flag
|
|
|
|
push fdos_data+0*WORD ; save fdos pblk so we can
|
|
push fdos_data+1*WORD ; be re-entrant(ish)
|
|
push fdos_data+2*WORD
|
|
push fdos_data+3*WORD
|
|
push fdos_data+4*WORD
|
|
push fdos_data+5*WORD
|
|
push fdos_data+6*WORD
|
|
|
|
push int21regs_off
|
|
push int21regs_seg
|
|
|
|
mov int21regs_off,bp
|
|
mov int21regs_seg,ss
|
|
|
|
call internal_func ; Execute the function
|
|
mov reg_AL[bp],al ; always return AL to caller
|
|
|
|
pop int21regs_seg
|
|
pop int21regs_off ; restore previous pointer user REGS
|
|
|
|
pop fdos_data+6*WORD
|
|
pop fdos_data+5*WORD
|
|
pop fdos_data+4*WORD
|
|
pop fdos_data+3*WORD
|
|
pop fdos_data+2*WORD
|
|
pop fdos_data+1*WORD
|
|
pop fdos_data+0*WORD ; restore fdos_pb for nested calls
|
|
|
|
dec internal_flag
|
|
|
|
pop ax ! pop bx ; Update the registers then
|
|
pop cx ! pop dx ; set the flags and return
|
|
pop si ! pop di ; to the user
|
|
pop bp
|
|
pop es ! pop ds
|
|
popf ; discard dos_IP
|
|
popf ; and dos_CS
|
|
popf ; get result
|
|
jnc dos_entry10
|
|
neg ax ; return using our negative error
|
|
stc ; conventions
|
|
dos_entry10:
|
|
ret
|
|
|
|
Public int21_func
|
|
|
|
int21_func:
|
|
;----------
|
|
; On Entry:
|
|
; AX, CX, DX, SI, DI as per Int 21
|
|
; BX = ??
|
|
; BP = ??
|
|
; DS = pcmode data
|
|
; ES = ??
|
|
; On Exit:
|
|
; (to client function)
|
|
; All general purpose registers as per Int 21 entry
|
|
; ES = dos_DS
|
|
;
|
|
|
|
xor bx,bx ; BH = 0
|
|
mov bl,ah ; BX = function number
|
|
shl bx,1 ; make it a word offset
|
|
push pcmode_ft[bx] ; save address of Function
|
|
les bp,int21regs_ptr
|
|
mov bx,es:reg_BX[bp] ; reload from dos_BX,dos_BP,and dos_DS
|
|
les bp,es:dword ptr reg_BP[bp]
|
|
ret
|
|
|
|
|
|
internal_func:
|
|
;-------------
|
|
; On Entry:
|
|
; All registers as per Int 21 EXCEPT
|
|
; DS = pcmode data
|
|
; BP = dos_REGS stack frame
|
|
; On Exit:
|
|
; (to client function)
|
|
; ES = dos_DS
|
|
;
|
|
mov al,ah ; function number in AL
|
|
cbw ; AH = 0
|
|
xchg ax,bx ; get subfunction in BX
|
|
shl bx,1 ; make offset in the internal table
|
|
push pcmode_ft[bx] ; save address of Function
|
|
xchg ax,bx ; restore BX
|
|
mov ax,reg_AX[bp] ; recover function number
|
|
mov es,reg_DS[bp] ; ES = callers DS
|
|
ret ; "jump" to handler
|
|
|
|
eject
|
|
; INT25 and INT26 direct disk I/O interface
|
|
;
|
|
;Standard DOS 1.xx - 3.30 INT25/26 Interface
|
|
;===========================================
|
|
;
|
|
; entry: al = drive number
|
|
; ds = DMA segment
|
|
; bx = DMA offset
|
|
; cx = number of sectors
|
|
; dx = beginning relative sector
|
|
;
|
|
;
|
|
;Enhanced DOS 3.31 INT25/26 Interface
|
|
;====================================
|
|
;
|
|
; If CX == 0FFFFh then the application is using the enhanced
|
|
; INT25/INT26 interface which allows access to more than 64K
|
|
; sectors.
|
|
;
|
|
; entry: al = drive number
|
|
; bx = Parameter block Offset
|
|
; ds = Parameter block Segment
|
|
;
|
|
; Parameter Block Format
|
|
;DS:BX -> DD Starting Sector No.
|
|
; DW Number of Sectors
|
|
; DD Transfer Address
|
|
;
|
|
;
|
|
; exit: C flag = 0 if successful
|
|
; = 1 if unsuccessful
|
|
; ax = error code(if CF = 1)
|
|
; ah physical error
|
|
; al logical error
|
|
; Users orginal flags left on stack
|
|
;
|
|
;
|
|
eject
|
|
DDIO_INT13 equ 0
|
|
DDIO_READ_OP equ 1
|
|
DDIO_WRITE_OP equ 2
|
|
|
|
; ++++++++++++++++++++++++++++
|
|
; Int 26 - Absolute Disk Write
|
|
; ++++++++++++++++++++++++++++
|
|
;
|
|
Public int26_entry
|
|
int26_entry:
|
|
mov ah,DDIO_WRITE_OP ; This is a WRITE operation
|
|
jmps int26_10
|
|
|
|
|
|
; +++++++++++++++++++++++++++
|
|
; Int 25 - Absolute Disk Read
|
|
; +++++++++++++++++++++++++++
|
|
;
|
|
Public int25_entry
|
|
int25_entry:
|
|
mov ah,DDIO_READ_OP ; This is a READ operation
|
|
int26_10: ; Common Direct Disk I/O code
|
|
cld
|
|
push ds ! push es
|
|
push dx ; save DX for FLASHCARD
|
|
push ds ! pop es ; ES = callers DS
|
|
call get_dseg ; Get PCMODE Data Segment
|
|
inc indos_flag ; Update the INDOS_FLAG
|
|
mov normal_stack+2,ss ; save users SS:SP
|
|
mov normal_stack,sp
|
|
cli
|
|
push ds ! pop ss ; use normal stack when in here
|
|
mov sp,offset normal_stack
|
|
sti
|
|
inc cx ; CX = FFFF indicates this is
|
|
jz int26_30
|
|
; CHECK FOR PARITIONS > 32 MBytes...
|
|
dec cx ; CX restored
|
|
push es
|
|
push ax
|
|
push bx
|
|
push dx
|
|
call get_ddsc ; ES:BX -> DDSC_
|
|
mov di,0201h ; assume bad drive
|
|
jc int26_20
|
|
mov di,0207h ; assume large media, and this error
|
|
if 0
|
|
; This code works out the total number of sectors on a drive
|
|
mov ax,es:DDSC_NCLSTRS[bx] ; get last cluster #
|
|
dec ax ; make it # data clusters
|
|
xor dx,dx
|
|
mov dl,es:DDSC_CLMSK[bx] ; get sec/cluster -1
|
|
inc dx ; DX = sec/cluster
|
|
mul dx ; DX:AX = # data sectors
|
|
add ax,es:DDSC_DATADDR[bx] ; add in address of 1st data sector
|
|
adc dx,0
|
|
else
|
|
mov ax,es:DDSC_NCLSTRS[bx] ; get last cluster #
|
|
xor dx,dx
|
|
mov dl,es:DDSC_CLMSK[bx] ; get sec/cluster -1
|
|
inc dx ; DX = sec/cluster
|
|
mul dx ; DX:AX is vaguely the # sectors
|
|
test dx,dx ; close enough for bill
|
|
endif
|
|
stc ; assume an error
|
|
jnz int26_20
|
|
xor di,di ; DI = zero, no error
|
|
int26_20:
|
|
pop dx
|
|
pop bx
|
|
pop ax
|
|
pop es
|
|
jnc int26_40
|
|
xchg ax,di ; AX = error code
|
|
jmps int26_60 ; return it
|
|
int26_30:
|
|
mov dx,es:word ptr 0[bx] ; Get Starting Sector Low
|
|
mov di,es:word ptr 2[bx] ; Get Starting Sector High
|
|
mov cx,es:word ptr 4[bx] ; Get No. of sectors to transfer
|
|
les bx,es:dword ptr 6[bx] ; Tranfer Address Offset
|
|
int26_40:
|
|
mov FD_DDIO_DRV_OP,ax ; save drive and operation
|
|
mov FD_DDIO_NSECTORS,cx ; No. of Sectors
|
|
mov FD_DDIO_STARTLOW,dx ; Starting Sector No.
|
|
mov FD_DDIO_STARTHIGH,di ; High Word of Sector Number
|
|
mov FD_DDIO_DMAOFF,bx ; DMA Offset
|
|
mov FD_DDIO_DMASEG,es ; DMA Segment
|
|
|
|
mov FD_FUNC,FD_DDIO
|
|
call fdos_nocrit ; let the FDOS do the work
|
|
neg ax ; AX is DOS extended error
|
|
jz int26_exit
|
|
sub al,-ED_PROTECT ; get AL to Int24 error format
|
|
cmp al,-(ED_GENFAIL-ED_PROTECT)
|
|
jbe int26_50
|
|
mov al,-(ED_GENFAIL-ED_PROTECT)
|
|
int26_50: ; no, make it general failure
|
|
mov ah,al ; save error in AH
|
|
mov bx,offset int13_error
|
|
xlat int13_error ; convert error to int13 format
|
|
xchg al,ah ; get errors in correct registers
|
|
int26_60:
|
|
stc ; Set the Carry Flag when an error
|
|
int26_exit: ; Occurs and return to the calling app.
|
|
cli
|
|
mov ss,normal_stack+2 ; back to user stack
|
|
mov sp,normal_stack
|
|
sti
|
|
dec indos_flag ; Update the INDOS_FLAG
|
|
sti
|
|
pop dx
|
|
pop es ! pop ds ; restore callers registers
|
|
retf ; leave flags on stack
|
|
|
|
int13_error db 03h,02h,80h,01h,10h,02h,40h,02h,04h,02h,02h,02h,02h
|
|
|
|
eject
|
|
; ++++++++++++++++++++++++++++++++++++
|
|
; Int 27 - Terminate but Stay Resident
|
|
; ++++++++++++++++++++++++++++++++++++
|
|
;
|
|
Public int27_entry
|
|
int27_entry:
|
|
mov ax,3100h ; Convert this to a DOS 'Terminate and
|
|
add dx,15 ; Stay Resident' function by converting the
|
|
rcr dx,1 ; memory size in bytes to paragraphs.
|
|
shr dx,1 ; On entry DX == memsize + 1 bytes therefore
|
|
shr dx,1 ; round upto a paragraph boundary by adding
|
|
shr dx,1 ; 15 then divide by 16
|
|
jmp int21_entry
|
|
|
|
eject
|
|
;
|
|
; DO_INT24:
|
|
; On Entry:-
|
|
; AH Set for INT 24
|
|
; AL Drive Number (0 = A:)
|
|
; DI Error Code
|
|
; ES:SI Device Header Control Block
|
|
;
|
|
; On Exit:-
|
|
; AL Error Response Retry/Ignore/Fail
|
|
;
|
|
; INT 24 Critical Error:-
|
|
; On Entry:- AH/7 0 = Disk Device
|
|
; AH/5 0 = IGNORE is an Invalid Response
|
|
; AH/4 0 = RETRY in an Invalid Response
|
|
; AH/3 0 = FAIL is an Invalid Response
|
|
; AH/2-1 00= DOS Area
|
|
; 01= File Allocation Table
|
|
; 10= Directory
|
|
; 11= Data
|
|
; AH/0 0 = Read, 1 = Write
|
|
;
|
|
; AL 1 Retry the Operation
|
|
; BP:SI Device Header Control Block
|
|
; DI High Byte Undefined, Low Byte Error Code
|
|
;
|
|
; On Exit:- AL 0 = IGNORE Error
|
|
; 1 = RETRY the Operation
|
|
; 2 = TERMINATE using INT 23
|
|
; 3 = FAIL the current DOS function
|
|
;
|
|
Public do_int24
|
|
do_int24:
|
|
cmp error_flag,0 ; Skip the critical error routine
|
|
jz di24_05 ; if the handler is active
|
|
mov al,ERR_FAIL ; Then return the FAIL condition
|
|
ret ; to the calling routine
|
|
di24_05:
|
|
push ax ! push bp ; Save our Base Pointer and then the
|
|
cli ; Disable Interupts
|
|
|
|
mov bp,es ; BP:SI points to dev header
|
|
mov es,current_psp ; Get the current PSP and USER Stack
|
|
|
|
push PSP_USERSS ; Save the Users Real SS and SP
|
|
push PSP_USERSP ; on the internal Stack
|
|
push retry_sp ; also the retry info
|
|
push retry_off
|
|
push remote_call
|
|
push machine_id
|
|
|
|
mov critical_sp,sp ; Internal Stack Pointer Offset
|
|
|
|
inc error_flag ; Entering Critical Error Handler
|
|
dec indos_flag ; I may be gone some time....
|
|
; (an application error handler need
|
|
; never return so tidy up first)
|
|
|
|
mov ss,PSP_USERSS ; Switch to the Users Stack
|
|
mov sp,PSP_USERSP
|
|
|
|
int 24h ; Call the Critical Error Handler
|
|
|
|
cld
|
|
cli ; paranioa.....
|
|
call get_dseg ; Reload DS just in case someone at
|
|
; A-T or Lotus cannot read
|
|
|
|
push ds ! pop ss ; Swap back to the Internal stack
|
|
mov sp,critical_sp ; and process the returned info.
|
|
|
|
pop machine_id
|
|
pop remote_call
|
|
pop retry_off ; restore retry info
|
|
pop retry_sp
|
|
mov es,current_psp ; Restore the Users original SS and
|
|
pop PSP_USERSP ; SP registers from the Stack
|
|
pop PSP_USERSS
|
|
|
|
pop bp ! pop bx ; Restore BP and original AX
|
|
sti
|
|
|
|
mov error_flag,0
|
|
inc indos_flag
|
|
|
|
cmp al,ERR_IGNORE ! jnz di24_10 ; Check for IGNORE and force
|
|
test bh,OK_IGNORE ! jnz di24_10 ; to become a FAIL if its an
|
|
mov al,ERR_FAIL ; invalid response.
|
|
|
|
di24_10:
|
|
cmp al,ERR_RETRY ! jnz di24_20 ; Check for RETRY and force
|
|
test bh,OK_RETRY ! jnz di24_20 ; to become a FAIL if its an
|
|
mov al,ERR_FAIL ; invalid response.
|
|
|
|
di24_20:
|
|
cmp al,ERR_FAIL ! jnz di24_30 ; Check for FAIL and force
|
|
test bh,OK_FAIL ! jnz di24_30 ; to become a ABORT if its an
|
|
mov al,ERR_ABORT ; invalid response.
|
|
|
|
di24_30:
|
|
cmp al,ERR_ABORT ; Do not return if the ABORT option
|
|
jz di24_abort ; has been selected but execute
|
|
; INT 23 directly
|
|
cmp al,ERR_FAIL ; All invalid reponses are converted
|
|
ja di24_abort ; to ABORT
|
|
di24_40:
|
|
ret
|
|
|
|
di24_abort: ; Abort this Process
|
|
mov ax,current_psp ; check not root application because
|
|
mov es,ax ; it must not be terminated so force
|
|
cmp ax,PSP_PARENT ; Is this the root Process
|
|
mov al,ERR_FAIL ; convert the error to FAIL
|
|
je di24_40 ; if not we terminate
|
|
mov exit_type,TERM_ERROR ; Set the correct exit Type
|
|
mov ax,04C00h ; and return code.
|
|
mov int21AX,ax
|
|
jmp func4C ; Then terminate
|
|
|
|
eject
|
|
;
|
|
; Get the PCMODE Emulator data Segment from the PD
|
|
;
|
|
Public get_dseg
|
|
get_dseg:
|
|
mov ds,pcmode_dseg ; get CS relative Data Segment
|
|
test pcmode_dseg,0FFFFh ; If Data Segment is zero then get
|
|
jz get_d10 ; the Data segment address from
|
|
ret ; the segment portion of INT 31
|
|
get_d10:
|
|
mov ds,word ptr .INT31_SEGMENT
|
|
ret
|
|
|
|
|
|
;
|
|
;INVALID_FUNCTION is called when any unsupported function has been executed
|
|
;
|
|
Public invalid_function
|
|
invalid_function:
|
|
mov ax,ED_FUNCTION ; Mark as Invalid Function
|
|
jmp error_exit ; and Exit
|
|
|
|
|
|
eject
|
|
Public reload_registers
|
|
reload_registers:
|
|
;----------------
|
|
; This routine is called to reload the registers we expect to have correct
|
|
; at the start of a PCMODE function.
|
|
push ds
|
|
lds bp,int21regs_ptr
|
|
mov ax,ds:reg_AX[bp]
|
|
mov bx,ds:reg_BX[bp]
|
|
mov cx,ds:reg_CX[bp]
|
|
mov dx,ds:reg_DX[bp]
|
|
mov si,ds:reg_SI[bp]
|
|
mov di,ds:reg_DI[bp]
|
|
les bp,ds:dword ptr reg_BP[bp]
|
|
pop ds
|
|
ret
|
|
|
|
PCMODE_DATA DSEG WORD
|
|
|
|
extrn retry_sp:word
|
|
extrn retry_off:word
|
|
|
|
extrn break_flag:byte
|
|
extrn current_psp:word
|
|
extrn current_dsk:byte
|
|
extrn dma_offset:word
|
|
extrn dma_segment:word
|
|
extrn error_flag:byte
|
|
extrn error_stack:word
|
|
extrn exit_type:byte
|
|
extrn int21regs_ptr:dword
|
|
extrn int21regs_off:word
|
|
extrn int21regs_seg:word
|
|
extrn prev_int21regs_ptr:dword
|
|
extrn prev_int21regs_off:word
|
|
extrn prev_int21regs_seg:word
|
|
extrn indos_flag:byte
|
|
extrn indos_stack:word
|
|
extrn LocalMachineID:word
|
|
extrn machine_id:word
|
|
extrn int21AX:word
|
|
extrn normal_stack:word
|
|
extrn owning_psp:word
|
|
extrn remote_call:word
|
|
if DOS5
|
|
extrn WindowsHandleCheck:byte
|
|
else
|
|
extrn win386_local_machine:dword
|
|
endif
|
|
|
|
if IDLE_DETECT
|
|
extrn active_cnt:word
|
|
extrn idle_max:word
|
|
extrn idle_flags:word
|
|
extrn idle_vec:dword
|
|
extrn int28_delay:word
|
|
extrn int28_reload:word
|
|
endif
|
|
|
|
extrn critical_sp:word
|
|
extrn internal_flag:byte
|
|
extrn int28_flag:byte
|
|
|
|
PCM_CODE CSEG BYTE
|
|
;
|
|
; The following Function tables are forced onto a word boundary
|
|
; because of the word alignment of the PCMODE_RODATE segment.
|
|
; Only word based Read Only data is held in this segment.
|
|
;
|
|
extrn func00:near, func01:near, func02:near, func03:near
|
|
extrn func04:near, func05:near, func06:near, func07:near
|
|
extrn func08:near, func09:near, func0A:near, func0B:near
|
|
extrn func0C:near, func0D:near, func0E:near, func0F:near
|
|
extrn func10:near, func11:near, func12:near, func13:near
|
|
extrn func14:near, func15:near, func16:near, func17:near
|
|
extrn func19:near, func1A:near, func1B:near, func1C:near
|
|
extrn func1F:near, func21:near, func22:near, func23:near
|
|
extrn func24:near, func25:near, func26:near, func27:near
|
|
extrn func28:near, func29:near, func2A:near, func2B:near
|
|
extrn func2C:near, func2D:near, func2E:near, func2F:near
|
|
extrn func30:near, func31:near, func32:near, func33:near
|
|
extrn func34:near, func35:near, func36:near, func37:near
|
|
extrn func38:near, func39:near, func3A:near, func3B:near
|
|
extrn func3C:near, func3D:near, func3E:near, func3F:near
|
|
extrn func40:near, func41:near, func42:near, func43:near
|
|
extrn func44:near, func45:near, func46:near, func47:near
|
|
extrn func48:near, func49:near, func4A:near, func4B:near
|
|
extrn func4C:near, func4D:near, func4E:near, func4F:near
|
|
extrn func50:near, func51:near, func52:near, func53:near
|
|
extrn func54:near, func55:near, func56:near, func57:near
|
|
extrn func58:near, func59:near, func5A:near, func5B:near
|
|
extrn func5C:near, func5D:near, func5E:near, func5F:near
|
|
extrn func60:near, func62:near, func63:near, func65:near
|
|
extrn func66:near, func67:near, func68:near, func69:near
|
|
extrn func6C:near
|
|
|
|
PCM_RODATA CSEG WORD
|
|
Public pcmode_ft, pcmode_ftl
|
|
pcmode_ft rw 0
|
|
dw func00 ; (00) Terminate Program
|
|
dw func01 ; (01) Read Keyboard and Echo
|
|
dw func02 ; (02) Display Character
|
|
dw func03 ; (03) Auxilary Input
|
|
dw func04 ; (04) Auxilary Output
|
|
dw func05 ; (05) Print Character
|
|
dw func06 ; (06) Direct Console I/O
|
|
dw func07 ; (07) Direct Console Input
|
|
dw func08 ; (08) Read Keyboard
|
|
dw func09 ; (09) Display String
|
|
dw func0A ; (0A) Buffered Keyboard Input
|
|
dw func0B ; (0B) Check Keyboard Status
|
|
dw func0C ; (0C) Flush Buffer, Read Keyboard
|
|
dw func0D ; (0D) Reset Disk
|
|
dw func0E ; (0E) Select Disk
|
|
dw func0F ; (0F) Open File
|
|
dw func10 ; (10) Close File
|
|
dw func11 ; (11) Search for First
|
|
dw func12 ; (12) Search for Next
|
|
dw func13 ; (13) Delete File
|
|
dw func14 ; (14) Sequential Read
|
|
dw func15 ; (15) Sequential Write
|
|
dw func16 ; (16) Create File
|
|
dw func17 ; (17) Rename File
|
|
dw ms_zero_AL ; (18) Unused DOS function (AL = 0)
|
|
dw func19 ; (19) Current Disk
|
|
dw func1A ; (1A) Set Disk Transfer Address
|
|
dw func1B ; (1B) *Get Default Drive Data
|
|
dw func1C ; (1C) *Get Drive Data
|
|
dw ms_zero_AL ; (1D) Unused DOS function (AL = 0)
|
|
dw ms_zero_AL ; (1E) Unused DOS function (AL = 0)
|
|
dw func1F ; (1F) Get Default DPB
|
|
dw ms_zero_AL ; (20) Unused DOS function (AL = 0)
|
|
dw func21 ; (21) Random Read
|
|
dw func22 ; (22) Random Write
|
|
dw func23 ; (23) File Size
|
|
dw func24 ; (24) Set Relative Record
|
|
dw func25 ; (25) Set Interrupt Vector
|
|
dw func26 ; (26) Duplicate PSP
|
|
dw func27 ; (27) Random Block Read
|
|
dw func28 ; (28) Random Block Write
|
|
dw func29 ; (29) Parse File Name
|
|
dw func2A ; (2A) Get Date
|
|
dw func2B ; (2B) Set Date
|
|
dw func2C ; (2C) Get Time
|
|
dw func2D ; (2D) Set Time
|
|
dw func2E ; (2E) Set/Reset Verify Flag
|
|
dw func2F ; (2F) Get Disk Transfer Address
|
|
dw func30 ; (30) Get Version Number
|
|
dw func31 ; (31) Keep Process
|
|
dw func32 ; (32) Get DPB
|
|
dw func33 ; (33) CONTROL-C Check
|
|
dw func34 ; (34) Get the Indos Flag
|
|
dw func35 ; (35) Get Interrupt Vector
|
|
dw func36 ; (36) Get Disk Free Space
|
|
dw func37 ; (37) Get/Set Switch Character
|
|
dw func38 ; (38) Return Country Dependant Info
|
|
dw func39 ; (39) Create Sub-directory
|
|
dw func3A ; (3A) Remove Sub-directory
|
|
dw func3B ; (3B) Change Sub-directory
|
|
dw func3C ; (3C) Create a File
|
|
dw func3D ; (3D) Open a File Handle
|
|
dw func3E ; (3E) Close a File Handle
|
|
dw func3F ; (3F) Read from a File/Device
|
|
dw func40 ; (40) Write to a File/Device
|
|
dw func41 ; (41) Delete a Directory Entry
|
|
dw func42 ; (42) Move a File Pointer
|
|
dw func43 ; (43) Change Attributes
|
|
dw func44 ; (44) I/O Control
|
|
dw func45 ; (45) Duplicate File Handle
|
|
dw func46 ; (46) Force a Duplicate File Handle
|
|
dw func47 ; (47) Return Text of Current Directory
|
|
dw func48 ; (48) Allocate Memory
|
|
dw func49 ; (49) Free Allocated Memory
|
|
dw func4A ; (4A) Modify Allocated Memory
|
|
dw func4B ; (4B) Load and Execute Program
|
|
dw func4C ; (4C) Terminate a Process
|
|
dw func4D ; (4D) Get Return Code
|
|
dw func4E ; (4E) Find Matching File
|
|
dw func4F ; (4F) Find Next Matching File
|
|
dw func50 ; (50) Set Current PSP
|
|
dw func51 ; (51) Get Current PSP
|
|
dw func52 ; (52) *Get In Vars
|
|
dw func53 ; (53) *Build DPB from BPB
|
|
dw func54 ; (54) Return Verify State
|
|
dw func55 ; (55) Create a New PSP
|
|
dw func56 ; (56) Move a Directory Entry
|
|
dw func57 ; (57) Get/Set File Date and Time
|
|
dw func58 ; (58) Memory Allocation Strategy
|
|
dw func59 ; (59) Get Extended Error
|
|
dw func5A ; (5A) Create Temporary File
|
|
dw func5B ; (5B) Create New File
|
|
dw func5C ; (5C) File Lock Control
|
|
dw func5D ; (5D) Internal DOS Function
|
|
dw func5E ; (5E) Control Local Machine Data
|
|
dw func5F ; (5F) Get Network Assignments
|
|
dw func60 ; (60) Perform Name Processing
|
|
dw ms_zero_AL ; (61) ?? Parse Path (AL = 0)
|
|
dw func62 ; (62) Get Current PSP
|
|
dw func63 ; (63) Get Lead Byte Table
|
|
dw invalid_function ; (64) *Saves AL and Returns
|
|
dw func65 ; (65) Get Extended Country Information
|
|
dw func66 ; (66) Get/Set Global Code Page
|
|
dw func67 ; (67) Set Handle Count
|
|
dw func68 ; (68) Commit File
|
|
dw func69 ; (69) Get Serial number
|
|
dw func68 ; (6A) Commit File (again)
|
|
dw invalid_function ; (6B) Unknown DOS 4
|
|
dw func6C ; (6C) Extended Open/Create
|
|
pcmode_ftl equ (offset $ - offset pcmode_ft)/2
|
|
;**************************
|
|
;* Do Not Move This Entry *
|
|
;**************************
|
|
dw ms_zero_AL ; Illegal Function Handler
|
|
|
|
end
|