FreeDOS/kernel/int2f.asm

617 lines
19 KiB
NASM
Raw Normal View History

2012-10-15 02:08:06 +02:00
;
; File:
; int2f.asm
; Description:
; multiplex interrupt support code
;
; Copyright (c) 1996, 1998
; Pasquale J. Villani
; All Rights Reserved
;
; This file is part of DOS-C.
;
; DOS-C is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version
; 2, or (at your option) any later version.
;
; DOS-C is distributed in the hope that it will be useful, but
; WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
; the GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public
; License along with DOS-C; see the file COPYING. If not,
; write to the Free Software Foundation, 675 Mass Ave,
; Cambridge, MA 02139, USA.
;
; $Id: int2f.asm 1591 2011-05-06 01:46:55Z bartoldeman $
;
%include "segs.inc"
%include "stacks.inc"
; macro to switch to an internal stack (if necessary), set DS == SS == DGROUP,
; and push the old SS:SP onto the internal stack
;
; destroys AX, SI, BP; turns on IRQs
;
; int2f does not really need to switch to a separate stack for MS-DOS
; compatibility; this is mainly to work around the C code's assumption
; that SS == DGROUP
;
; TODO: remove the need for this hackery -- tkchia
%macro SwitchToInt2fStack 0
mov ax,[cs:_DGROUP_]
mov ds,ax
mov si,ss
mov bp,sp
cmp ax,si
jz %%already
cli
mov ss,ax
extern int2f_stk_top
mov sp,int2f_stk_top
sti
%%already:
; well, GCC does not currently clobber function parameters passed on the
; stack; but just in case it decides to do that in the future, we push _two_
; copies of the old SS:SP:
; - the second copy can be passed as a pointer parameter to a C function
; - the first copy is used to actually restore the user stack later
push si
push bp
push si
push bp
%endmacro
; macro to switch back from an internal stack, i.e. undo SwitchToInt2fStack
;
; destroys BP; turns on IRQs -- tkchia
%macro DoneInt2fStack 0
pop bp
pop bp
pop bp
cli
pop ss
mov sp,bp
sti
%endmacro
2012-10-15 02:08:06 +02:00
segment HMA_TEXT
extern _cu_psp
extern _HaltCpuWhileIdle
2012-10-15 02:08:06 +02:00
extern _syscall_MUX14
extern _DGROUP_
global reloc_call_int2f_handler
reloc_call_int2f_handler:
sti ; Enable interrupts
cmp ah,11h ; Network interrupt?
jne Int2f3 ; No, continue
Int2f1:
or al,al ; Installation check?
jz FarTabRetn ; yes, just return
Int2f2:
mov ax,1 ; TE 07/13/01
; at least for redirected INT21/5F44
; --> 2f/111e
; the error code is AX=0001 = unknown function
stc
FarTabRetn:
retf 2 ; Return far
WinIdle: ; only HLT if at haltlevel 2+
push ds
mov ds, [cs:_DGROUP_]
cmp byte [_HaltCpuWhileIdle],2
pop ds
jb FarTabRetn
pushf
sti
hlt ; save some energy :-)
popf
push ds
mov ds, [cs:_DGROUP_]
cmp byte [_HaltCpuWhileIdle],3
pop ds
jb FarTabRetn
mov al,0 ; even admit we HLTed ;-)
jmp short FarTabRetn
Int2f3: cmp ax,1680h ; Win "release time slice"
je WinIdle
cmp ah,12h
je IntDosCal ; Dos Internal calls
cmp ah,13h
je IntDosCal ; Install Int13h Hook
cmp ah,16h
je IntDosCal ; Win (Multitasking) Hook
cmp ah,46h
je IntDosCal ; Win Hook to avoid MCB corruption
2012-10-15 02:08:06 +02:00
cmp ax,4a01h
je IntDosCal ; Dos Internal calls
cmp ax,4a02h
je IntDosCal ; Dos Internal calls
%ifdef WITHFAT32
cmp ax,4a33h ; Check DOS version 7
jne Check4Share
xor ax,ax ; no undocumented shell strings
xor bx,bx ; RBIL undoc BX = ?? (0h)
; " DS:DX ASCIIZ shell exe name
; " DS:SI SHELL= line
2012-10-15 02:08:06 +02:00
iret
Check4Share:
%endif
cmp ah,10h ; SHARE.EXE interrupt?
je Int2f1 ; yes, do installation check
cmp ah,08h
je DriverSysCal ; DRIVER.SYS calls
cmp ah,14h ; NLSFUNC.EXE interrupt?
jne Int2f?iret ; yes, do installation check
Int2f?14: ;; MUX-14 -- NLSFUNC API
;; all functions are passed to syscall_MUX14
push bp ; Preserve BP later on
Protect386Registers
PUSH$ALL
SwitchToInt2fStack
2012-10-15 02:08:06 +02:00
call _syscall_MUX14
DoneInt2fStack
2012-10-15 02:08:06 +02:00
pop bp ; Discard incoming AX
push ax ; Correct stack for POP$ALL
POP$ALL
Restore386Registers
mov bp, sp
or ax, ax
jnz Int2f?14?1 ; must return set carry
;; -6 == -2 (CS), -2 (IP), -2 (flags)
;; current SP = on old_BP
and BYTE [bp-6], 0feh ; clear carry as no error condition
pop bp
iret
Int2f?14?1: or BYTE [bp-6], 1
pop bp
Int2f?iret:
iret
; DRIVER.SYS calls - now only 0803.
DriverSysCal:
extern _Dyn
2012-10-15 02:08:06 +02:00
cmp al, 3
jne Int2f?iret
mov ds, [cs:_DGROUP_]
mov di, _Dyn+2
jmp short Int2f?iret
;**********************************************************************
; internal dos calls INT2F/12xx and INT2F/4A01,4A02 - handled through C
;**********************************************************************
IntDosCal:
; set up register structure
2012-10-15 02:08:06 +02:00
;struct int2f12regs
;{
; [space for 386 regs]
; UWORD es,ds;
; UWORD di,si,bp,bx,dx,cx,ax;
; UWORD ip,cs,flags;
; UWORD callerARG1;
;}
push ax
push cx
push dx
push bx
push bp
push si
push di
push ds
push es
cld
%if XCPU >= 386
%ifdef WATCOM
mov si,fs
mov di,gs
%else
Protect386Registers
%endif
%endif
SwitchToInt2fStack
2012-10-15 02:08:06 +02:00
extern _int2F_12_handler
call _int2F_12_handler
DoneInt2fStack
2012-10-15 02:08:06 +02:00
%if XCPU >= 386
%ifdef WATCOM
mov fs,si
mov gs,di
%else
Restore386Registers
%endif
%endif
pop es
pop ds
pop di
pop si
pop bp
pop bx
pop dx
pop cx
pop ax
iret
global SHARE_CHECK
SHARE_CHECK:
mov ax, 0x1000
int 0x2f
test ax, "US" ; Uninstallable SHARE signature
2012-10-15 02:08:06 +02:00
ret
; DOS calls this to see if it's okay to open the file.
; Returns a file_table entry number to use (>= 0) if okay
; to open. Otherwise returns < 0 and may generate a critical
; error. If < 0 is returned, it is the negated error return
; code, so DOS simply negates this value and returns it in
; AX.
; STATIC int share_open_check(const char FAR * filename,
2012-10-15 02:08:06 +02:00
; /* pointer to fully qualified filename */
; unsigned short pspseg,
; /* psp segment address of owner process */
; int openmode,
; /* 0=read-only, 1=write-only, 2=read-write */
; int sharemode) /* SHARE_COMPAT, etc... */
global SHARE_OPEN_CHECK
SHARE_OPEN_CHECK:
push ds
pop es ; save ds
mov di, si ; save si
2012-10-15 02:08:06 +02:00
pop ax ; return address
popargs {ds,si},bx,cx,dx; filename,pspseg,openmode,sharemode;
2012-10-15 02:08:06 +02:00
push ax ; return address
mov ax, 0x10a0
int 0x2f ; returns ax
mov si, di ; restore si
push es
pop ds ; restore ds
2012-10-15 02:08:06 +02:00
ret
; DOS calls this to record the fact that it has successfully
; closed a file, or the fact that the open for this file failed.
; STATIC void share_close_file(int fileno) /* file_table entry number */
global SHARE_CLOSE_FILE
SHARE_CLOSE_FILE:
pop ax
pop bx
push ax
mov ax, 0x10a1
int 0x2f
ret
; DOS calls this to determine whether it can access (read or
; write) a specific section of a file. We call it internally
; from lock_unlock (only when locking) to see if any portion
; of the requested region is already locked. If pspseg is zero,
; then it matches any pspseg in the lock table. Otherwise, only
; locks which DO NOT belong to pspseg will be considered.
; Returns zero if okay to access or lock (no portion of the
; region is already locked). Otherwise returns non-zero and
; generates a critical error (if allowcriter is non-zero).
; If non-zero is returned, it is the negated return value for
; the DOS call.
;STATIC int share_access_check(unsigned short pspseg,
; /* psp segment address of owner process */
; int fileno, /* file_table entry number */
; unsigned long ofs, /* offset into file */
; unsigned long len, /* length (in bytes) of region to access */
; int allowcriter) /* allow a critical error to be generated */
global SHARE_ACCESS_CHECK
SHARE_ACCESS_CHECK:
mov ax, 0x10a2
share_common:
push bp
mov bp, sp
push si
push di
arg pspseg, fileno, {ofs,4}, {len,4}, allowcriter
mov bx, [.pspseg] ; pspseg
mov cx, [.fileno] ; fileno
mov si, [.ofs+2] ; high word of ofs
mov di, [.ofs] ; low word of ofs
les dx, [.len] ; len
or ax, [.allowcriter] ; allowcriter/unlock
2012-10-15 02:08:06 +02:00
int 0x2f
pop di
pop si
pop bp
ret 14 ; returns ax
; DOS calls this to lock or unlock a specific section of a file.
; Returns zero if successfully locked or unlocked. Otherwise
; returns non-zero.
; If the return value is non-zero, it is the negated error
; return code for the DOS 0x5c call. */
;STATIC int share_lock_unlock(unsigned short pspseg, /* psp segment address of owner process */
; int fileno, /* file_table entry number */
; unsigned long ofs, /* offset into file */
; unsigned long len, /* length (in bytes) of region to lock or unlock */
; int unlock) /* one to unlock; zero to lock */
global SHARE_LOCK_UNLOCK
SHARE_LOCK_UNLOCK:
mov ax,0x10a4
jmp short share_common
; DOS calls this to see if share already has the file marked as open.
; Returns:
; 1 if open
; 0 if not
; STATIC WORD share_is_file_open(const char far *filename) /* pointer to fully qualified filename */
global SHARE_IS_FILE_OPEN
SHARE_IS_FILE_OPEN:
mov si, ds
mov es, si ; save ds
pop ax ; save return address
pop si ; filename
pop ds ; SEG filename
push ax ; restore return address
mov ax, 0x10a6
int 0x2f ; returns ax
mov si, es ; restore ds
mov ds, si
ret
2012-10-15 02:08:06 +02:00
; Int 2F Multipurpose Remote System Calls
;
; added by James Tabor jimtabor@infohwy.com
; changed by Bart Oldeman
;
; assume ss == ds after setup of stack in entry
; sumtimes return data *ptr is the push stack word
;
remote_lseek: ; arg is a pointer to the long seek value
mov bx, cx
mov dx, [bx]
mov cx, [bx+2]
; "fall through"
remote_getfattr:
clc ; set to succeed
int 2fh
jc ret_neg_ax
jmp short ret_int2f
remote_lock_unlock:
mov dx, cx ; parameter block (dx) in arg
mov bx, cx
mov bl, [bx + 8] ; unlock or not
mov cx, 1
int 0x2f
jnc ret_set_ax_to_carry
mov ah, 0
jmp short ret_neg_ax
;long ASMPASCAL network_redirector_mx(unsigned cmd, void far *s, void *arg)
global NETWORK_REDIRECTOR_MX
NETWORK_REDIRECTOR_MX:
pop bx ; ret address
popargs ax,{es,dx},cx ; cmd (ax), seg:off s
; stack value (arg); cx in remote_rw
2012-10-15 02:08:06 +02:00
push bx ; ret address
call_int2f:
push bp
push si
push di
cmp al, 0fh
je remote_getfattr
mov di, dx ; es:di -> s and dx is used for 1125!
cmp al, 08h
je remote_rw
cmp al, 09h
je remote_rw
cmp al, 0ah
je remote_lock_unlock
cmp al, 21h
je remote_lseek
cmp al, 22h
je remote_process_end
cmp al, 23h
je qremote_fn
push cx ; arg
cmp al, 0ch
je remote_getfree
cmp al, 1eh
je remote_print_doredir
cmp al, 1fh
je remote_print_doredir
int2f_call:
xor cx, cx ; set to succeed; clear carry and CX
int 2fh
pop bx
jnc ret_set_ax_to_cx
ret_neg_ax:
neg ax
ret_int2f:
pop di
pop si
pop bp
ret
ret_set_ax_to_cx: ; ext_open or rw -> status from CX in AX
; otherwise CX was set to zero above
xchg ax, cx ; set ax:=cx (one byte shorter than mov)
jmp short ret_int2f
remote_print_doredir: ; di points to an lregs structure
mov es,[di+0xe]
mov bx,[di+2]
mov cx,[di+4]
mov dx,[di+6]
mov si,[di+8]
lds di,[di+0xa]
clc ; set to succeed
int 2fh
pop bx ; restore stack and ds=ss
push ss
pop ds
jc ret_neg_ax
ret_set_ax_to_carry: ; carry => -1 else 0 (SUCCESS)
sbb ax, ax
jmp short ret_int2f
remote_getfree:
clc ; set to succeed
int 2fh
pop di ; retrieve pushed pointer arg
jc ret_set_ax_to_carry
mov [di],ax
mov [di+2],bx
mov [di+4],cx
mov [di+6],dx
jmp short ret_set_ax_to_carry
remote_rw:
clc ; set to succeed
int 2fh
jc ret_min_dx_ax
xor dx, dx ; dx:ax := dx:cx = bytes read
jmp short ret_set_ax_to_cx
ret_min_dx_ax: neg ax
cwd
jmp short ret_int2f
qremote_fn:
mov bx, cx
lds si, [bx]
jmp short int2f_restore_ds
remote_process_end: ; Terminate process
mov ds, [_cu_psp]
int2f_restore_ds:
clc
int 2fh
push ss
pop ds
jmp short ret_set_ax_to_carry
; extern UWORD ASMPASCAL call_nls(UWORD bp, UWORD FAR *buf,
; UWORD subfct, UWORD cp, UWORD cntry, UWORD bufsize);
extern _nlsInfo
2012-10-15 02:08:06 +02:00
global CALL_NLS
CALL_NLS:
pop es ; ret addr
pop cx ; bufsize
pop dx ; cntry
pop bx ; cp
pop ax ; sub fct
mov ah, 0x14
push es ; ret addr
push bp
mov bp, sp
push si
push di
mov si, _nlsInfo ; nlsinfo
les di, [bp + 4] ; buf
mov bp, [bp + 8] ; bp
int 0x2f
mov dx, bx ; return id in high word
pop di
pop si
pop bp
ret 6
; extern UWORD ASMPASCAL floppy_change(UWORD drives)
global FLOPPY_CHANGE
FLOPPY_CHANGE:
pop cx ; ret addr
pop dx ; drives
push cx ; ret addr
mov ax, 0x4a00
xor cx, cx
int 0x2f
mov ax, cx ; return
ret
;
; Test to see if a umb driver has been loaded.
; if so, retrieve largest available block+size
;
; From RB list and Dosemu xms.c.
;
; Call the XMS driver "Request upper memory block" function with:
; AH = 10h
; DX = size of block in paragraphs
; Return: AX = status
; 0001h success
; BX = segment address of UMB
; DX = actual size of block
; 0000h failure
; BL = error code (80h,B0h,B1h) (see #02775)
; DX = largest available block
;
; (Table 02775)
; Values for XMS error code returned in BL:
; 00h successful
; 80h function not implemented
; B0h only a smaller UMB is available
; B1h no UMBs are available
; B2h UMB segment number is invalid
;
segment INIT_TEXT
; int ASMPASCAL UMB_get_largest(void FAR * driverAddress,
; UCOUNT * seg, UCOUNT * size);
arg {driverAddress,4}, argseg, size
global UMB_GET_LARGEST
2012-10-15 02:08:06 +02:00
UMB_GET_LARGEST:
push bp
mov bp,sp
mov dx,0xffff ; go for broke!
mov ax,1000h ; get the UMBs
call far [.driverAddress] ; Call the driver
2012-10-15 02:08:06 +02:00
;
; bl = 0xB0 and ax = 0 so do it again.
;
cmp bl,0xb0 ; fail safe
jne umbt_error
and dx,dx ; if it returns a size of zero.
je umbt_error
mov ax,1000h ; dx set with largest size
call far [.driverAddress] ; Call the driver
2012-10-15 02:08:06 +02:00
cmp ax,1
jne umbt_error
; now return the segment
; and the size
mov cx,bx ; *seg = segment
mov bx, [.argseg]
2012-10-15 02:08:06 +02:00
mov [bx],cx
mov bx, [.size] ; *size = size
2012-10-15 02:08:06 +02:00
mov [bx],dx
umbt_ret:
pop bp
ret 8 ; this was called NEAR!!
umbt_error: xor ax,ax
jmp short umbt_ret