📄 tskdos.asm
字号:
;
; --- Version 2.2 93-06-08 10:18 ---
;
; CTask - DOS access module.
;
; Public Domain Software written by
; Thomas Wagner
; Ferrari electronic Gmbh
; Beusselstrasse 27
; D-1000 Berlin 21
; Germany
;
; NOTE: Some routines have been moved to "tsksec.asm" in Version 2.1
; to support a minimal secondary kernel.
;
; The support for the critical section interrupt was dropped in
; version 2.1. Swapping the DOS variable area eliminates
; the need for maintaining critical sections across calls.
;
; The DOS interrupt (and the related direct disk I/O interrupts) are
; not reentrant. Access to DOS thus has to be channelled such that no
; two tasks use DOS services simultaneously. However, there is one
; exception to this rule. Whenever DOS is waiting for the keyboard, it
; issues a special interrupt, INT 28h, to signal that background
; processing for functions > 0Ch may be performed. This is used in the
; DOS interface for CTask in the following manner:
;
; A task issuing a DOS interrupt will request one of two resources:
; "lower_dos" for functions <= 0C, "upper_dos" for functions > 0C.
; If a task gets access to "lower_dos", it will also request the
; "upper_dos" resource to lock out other tasks from interrupting.
; This "upper_dos" resource is shortly released on each INT 28, and
; then immediately reclaimed, with task priority temporarily raised
; to the maximum value. The first task waiting to execute a
; function > 0C will thus be scheduled to execute the request, but
; the resource will be reassigned to the INT 28 handler as soon as
; this request terminates, so the waiting task will not be delayed too
; long.
;
; There are two additional safety measures which have to be taken to
; avoid getting into conflicts with other resident background programs,
; especially the DOS PRINT background spooler:
;
; Before actually executing the request, the status of the DOS in-use
; flag is checked. If this flag is set, the task enters a busy waiting
; loop, calling the scheduler so that the processor is not tied up.
;
; NOTE: The method for checking the status of DOS is described in-depth
; in the book "The MS-DOS Encyclopedia" from Microsoft Press, in
; the chapter on TSR programming. The logic in this module was
; developed without the help of this book, so if you compare
; the code here with the routines in the Encyclopedia, you may
; notice that not all re-entry conditions are checked here.
; According to my experience with debugging TSR's and CTask, the
; logic should be sufficient for all but the most obscure TSR's.
; If you want to be completely on the safe side, you might consider
; adding the more thorough checks listed in the Encyclopedia.
;
; CAUTION: This module is not ROMable, and it can only be
; installed in the primary kernel.
;
name tskdos
;
include tsk.mac
;
IF DOS
fatal_pmd = 1
;
.tsk_model
;
include tskdeb.h
;
Pubfunc tsk_install_dos
Pubfunc tsk_remove_dos
Pubfunc tsk_fatal
;
IF CHECKING
Pubfunc tsk_fatal_pmd
Globext tsk_set_currdis
Globext tsk_set_dualdis
Globext tsk_rputc
Globext tsk_rputs
Globext tsk_vrprintf
CGlbext tsk_rprintf
ENDIF
;
IF DEBUG AND DEB_DOSTRBUF
Pubfunc dump_dostrace
ENDIF
IF DEBUG AND (DEB_DOSTRACE OR DEB_DOSTRBUF)
CGlbext tsk_cprintf
CGlbext tsk_vcprintf
ENDIF
;
public tsk_emergency_exit
;
Globext create_resource
Globext delete_resource
Globext request_resource
Globext request_cresource
Globext release_resource
Globext create_flag
Globext delete_flag
Globext set_flag
Globext clear_flag
Globext wait_flag_clear
Globext schedule
Globext yield
Globext preempt_off
;
Locext tsk_switch_stack
Locext tsk_old_stack
Locext tsk_remove_group
Locext tsk_kill_group
Globext tsk_remove_tasker
;
extrn tsk_instflags: word
;
extrn tsk_glob_rec: byte
IF NOT SINGLE_DATA
extrn tsk_global: dword
ENDIF
;;
IF DEBUG AND DEB_DOSTRBUF
public i2fcount,i31count
ENDIF
;
; Special function range
;
MIN_SPFUNC = 2300h
MAX_SPFUNC = 2301h
;
;
get_in_use_flag = 34h ; DOS-function to get in_use_flag address
get_invars = 5d06h ; DOS-function to get DOS-variables area
;
psp_offset = 10h-2 ; Offset of current PSP in DOS save area
; ; (-2 because we add 2 to the start)
;
; Structure of the start of a PSP, including undocumented fields
;
psp_record struc
;
dw ? ; INT 20
dw ? ; alloc block end
db ? ; reserved
db 5 dup(?) ; system call
psp_exit_addr dd ? ; exit routine address
psp_ctlc_addr dd ? ; control C routine address
psp_cerr_addr dd ? ; critical error routine address
parent_psp dw ? ; PSP of parent process
db 20 dup(?) ; files table
psp_envseg dw ? ; environment segment
psp_ustack dd ? ; ss/sp of caller
dw ? ; file table length
dd ? ; file table pointer
dd ? ; pointer to nested PSP (?)
;
psp_record ends
;
;
intseg segment at 0
org 10h*4
vidoff dw ? ; video interrupt
vidseg dw ?
org 13h*4
diskoff dw ? ; disk i/o interrupt
diskseg dw ?
org 20h*4
termoff dw ? ; program terminate vector
termseg dw ?
org 21h*4
idosoff dw ? ; dos interrupt
idosseg dw ?
org 25h*4
absreadoff dw ? ; absolute disk read
absreadseg dw ?
org 26h*4
abswriteoff dw ? ; absolute disk write
abswriteseg dw ?
org 27h*4
keepoff dw ? ; Terminate but stay resident
keepseg dw ?
org 28h*4
idleoff dw ? ; dos idle interrupt
idleseg dw ?
org 2ah*4
csectoff dw ? ; dos critical section
csectseg dw ?
org 2fh*4
muxoff dw ? ; multiplex int
muxseg dw ?
org 31h*4
dpmioff dw ? ; DPMI services
dpmiseg dw ?
org 40h*4
fdiskoff dw ? ; redirected floppy disk I/O interrupt
fdiskseg dw ?
;
intseg ends
;
;----------------------------------------------------------------------------
;
; Variables
;
.tsk_data
;
idle_active db 0 ; Idle-Interrupt active
dos310 db 0 ; DOS version >= 3.10
;
IF TSK_NAMEPAR
udos_name db "DOSUPPER",0
ldos_name db "DOSLOWER",0
hdio_name db "HARDDISK",0
fdio_name db "FLEXDISK",0
vid_name db "VIDEO",0
ENDIF
;
;
in_error dd ? ; Adress of DOS error-mode-flag
;
lower_dos resource <>
upper_dos resource <>
hdisk_io resource <>
fdisk_io resource <>
video resource <>
;
vid_flags dw ?
i13h_flags dw ?
i13f_flags dw ?
;
IF DEBUG AND (DEB_DOSTRACE OR DEB_DOSTRBUF)
;
IF DEBUG AND DEB_DOSTRBUF
TR_ENTRIES = 32
ELSE
TR_ENTRIES = 1
ENDIF
;
tr_none db "No "
tr_head db "DOS Calls",0ah,0
tr_string db "AX=%04X BX=%04X DS=%04X PSP=%04X TCB=%FP Tb=%02HX Bs=%02HX Er=%02HX Id=%02HX Fl=%02HX",0ah,0
;AX=1234 BX=1234 DS=1234 PSP=1234 TCB=1234:1234 Tb=12 Bs=12 Er=12 Id=12 Fl=1234\n",0
;
trrec struc
tr_ax dw ? ; AX on entry
tr_bx dw ? ; BX on entry
tr_ds dw ? ; DS on entry
tr_psp dw ? ; current PSP
tr_tcb_o dw ? ; TCB pointer
tr_tcb_s dw ?
tr_tindos db ? ; Task in-DOS flag
tr_indos db ? ; DOS Busy flag
tr_inerr db ? ; Critical error flag
tr_idle db ?
tr_flags db ?
;
; 01: Doslower busy
; 02: Task owns doslower
; 04: Dosupper busy
; 08: Task owns dosupper
trrec ends
;
tr_ptr dw 0
tr_count dw 0
tr_buffer trrec TR_ENTRIES dup(<>)
;
ENDIF
;
.tsk_edata
.tsk_code
;;
IF DEBUG AND DEB_DOSTRBUF
i2fcount dw 0
i31count dw 0
ENDIF
;
;---------------------------------------------------------------------------
;
; Original Interrupt-Entries
;
savvid label dword ; original Video entry
savvidoff dw ?
savvidseg dw ?
;
savdisk label dword ; original Disk I/O entry
savdiskoff dw ?
savdiskseg dw ?
;
savfdisk label dword ; original Floppy Disk I/O entry
savfdiskoff dw ?
savfdiskseg dw ?
;
savterm label dword
savtermoff dw ? ; Terminate vector save
savtermseg dw ?
;
savdos label dword ; original DOS-Entry
savdosoff dw ?
savdosseg dw ?
;
savidle label dword ; original IDLE-Entry
savidleoff dw ?
savidleseg dw ?
;
savcsect label dword ; Critical Section save
savcsectoff dw ?
savcsectseg dw ?
;
savabsread label dword ; Absolute Disk Read save
savabsreadoff dw ?
savabsreadseg dw ?
;
savabswrite label dword ; Absolute Disk Write save
savabswriteoff dw ?
savabswriteseg dw ?
;
savkeep label dword
savkeepoff dw ? ; Terminate resident vector save
savkeepseg dw ?
;
IF (DEBUG AND DEB_DOSTRBUF)
savmux label dword ; Multiplex int save
savmuxoff dw ?
savmuxseg dw ?
ENDIF
;
IF DEBUG AND DEB_DOSTRBUF
savdpmi label dword ; DPMI int save
savdpmioff dw ?
savdpmiseg dw ?
ENDIF
;
dos_version dw ? ; DOS version
;
temp_1 dw ?
;
tsk_dgroup dw @CTASK_DATA
;
zero db 0
;
calldos macro
pushf
cli
call cs:savdos
endm
;
;---------------------------------------------------------------------------
;
; void tsk_install_dos (void)
;
; Install DOS handler
;
Localfunc tsk_install_dos,<uses si>
;
; create needed resources & flags
;
IFDEF LOAD_DS
push ds
mov ax,@CTASK_DATA
mov ds,ax
ENDIF
;
IF TSK_NAMEPAR
callp create_resource,<<ds,#upper_dos>,<ds,#udos_name>>
ELSE
callp create_resource,<<ds,#upper_dos>>
ENDIF
;
IF TSK_NAMEPAR
callp create_resource,<<ds,#lower_dos>,<ds,#ldos_name>>
ELSE
callp create_resource,<<ds,#lower_dos>>
ENDIF
;
test tsk_instflags,IFL_DISK
jz inst_nodsk1
IF TSK_NAMEPAR
callp create_resource,<<ds,#hdisk_io>,<ds,#hdio_name>>
ELSE
callp create_resource,<<ds,#hdisk_io>>
ENDIF
;
IF TSK_NAMEPAR
callp create_resource,<<ds,#fdisk_io>,<ds,#fdio_name>>
ELSE
callp create_resource,<<ds,#fdisk_io>>
ENDIF
;
inst_nodsk1:
test tsk_instflags,IFL_VIDEO
jz inst_novid1
IF TSK_NAMEPAR
callp create_resource,<<ds,#video>,<ds,#vid_name>>
ELSE
callp create_resource,<<ds,#video>>
ENDIF
;
inst_novid1:
;
mov tsk_glob_rec.l_swap,0 ; init swap area length to 0
;
; Get the DOS version. Only versions 3.1 and up support the
; DOS variable swap, so disable swapping if it's an earlier version,
; or if it's the OS/2 box.
;
mov ah,30h
int 21h
mov cs:dos_version,ax
cmp al,3
jb not_dos3
cmp al,0ah
je not_dos3 ; OS/2 compatibility box
cmp al,3
jne is_dos3 ; DOS 4.x
cmp ah,10
jb not_dos3
is_dos3:
inc dos310
;
; Get address and length of the DOS internal variable area.
; This call is not documented, and not available in versions
; prior to 3.1. It returns the address of the area in DS:SI,
; and the length of the area that must be swapped between calls
; from different groups in DX.
; Additionally, the total length of the area, including
; the DOS-stacks, minus the length in DX, is returned in CX.
;
; The DOS in_error flag is at the start of this area, the
; in_use flag is the second byte. Both bytes are excluded
; from the swap.
;
test tsk_instflags,IFL_NODOSVARS
jnz not_dos3
;
push ds
mov ax,get_invars
int 21h
mov ax,ds
pop ds
mov word ptr in_error,si
mov word ptr in_error+2,ax
inc si
mov word ptr tsk_glob_rec.dos_in_use,si
mov word ptr tsk_glob_rec.dos_in_use+2,ax
inc si
mov word ptr tsk_glob_rec.dos_vars,si
mov word ptr tsk_glob_rec.dos_vars+2,ax
sub dx,2
mov tsk_glob_rec.l_swap,dx
jmp short save_ints
;
; For versions < 3.10, and if the IFL_NODOSVARS flag is set,
; get the address of DOS's in_use-flag. This flag indicates that
; DOS is already active. This might happen if there are other
; background tasks, like popups or print spoolers, active in
; parallel to CTask.
; This is also the address of the critical error flag in DOS. Beginning
; with DOS 3.10 the flag is located one byte before the in_use_flag.
; With older DOS versions, we would have to search through DOS for the
; address. This is omitted here, but you could include the code
; for pre 3.1 versions from pages 378-379 of the MS-DOS Encyclopedia.
;
not_dos3:
mov ah,get_in_use_flag
int 21h
mov word ptr tsk_glob_rec.dos_in_use,bx
mov word ptr tsk_glob_rec.dos_in_use+2,es
mov word ptr in_error+2,es
dec bx
mov word ptr in_error,bx
cmp dos310,0
jne save_ints ; OK for DOS >= 3.10
;
; For DOS < 3.1, we simply ignore the error flag.
; CTask's DOS handler will not work that great anyway with older
; versions.
;
mov word ptr in_error,offset zero
mov word ptr in_error+2,cs
;
; Save old interrupt vectors
;
save_ints:
push es
xor ax,ax
mov es,ax
;
assume es:intseg
;
test tsk_instflags,IFL_VIDEO
jz inst_novid2
mov ax,vidoff ; video
mov savvidoff,ax
mov ax,vidseg
mov savvidseg,ax
;
inst_novid2:
test tsk_instflags,IFL_DISK
jz inst_nodsk2
mov ax,diskoff ; Disk I/O
mov savdiskoff,ax
mov ax,diskseg
mov savdiskseg,ax
mov ax,fdiskoff ; Floppy Disk I/O
mov savfdiskoff,ax
mov ax,fdiskseg
mov savfdiskseg,ax
;
inst_nodsk2:
mov ax,termoff ; DOS
mov savtermoff,ax
mov ax,termseg
mov savtermseg,ax
;
mov ax,idosoff ; DOS
mov savdosoff,ax
mov ax,idosseg
mov savdosseg,ax
;
mov ax,idleoff ; IDLE
mov savidleoff,ax
mov ax,idleseg
mov savidleseg,ax
;
mov ax,csectoff ; Critical Section
mov savcsectoff,ax
mov ax,csectseg
mov savcsectseg,ax
;
mov ax,absreadoff ; Absolute Disk read
mov savabsreadoff,ax
mov ax,absreadseg
mov savabsreadseg,ax
;
mov ax,abswriteoff ; Absolute Disk write
mov savabswriteoff,ax
mov ax,abswriteseg
mov savabswriteseg,ax
;
mov ax,keepoff ; Terminate Resident
mov savkeepoff,ax
mov ax,keepseg
mov savkeepseg,ax
;
IF (DEBUG AND DEB_DOSTRBUF)
mov ax,muxoff ; Multiplex
mov savmuxoff,ax
mov ax,muxseg
mov savmuxseg,ax
ENDIF
;
IF DEBUG AND DEB_DOSTRBUF
mov ax,dpmioff ; Multiplex
mov savdpmioff,ax
mov ax,dpmiseg
mov savdpmiseg,ax
ENDIF
;
; Enter new Interrupt-Entries
;
cli
test tsk_instflags,IFL_VIDEO
jz inst_novid3
mov vidoff,offset @videntry ; Video Entry
mov vidseg,cs
;
inst_novid3:
test tsk_instflags,IFL_DISK
jz inst_nodsk3
mov diskoff,offset @diskentry ; Disk I/O Entry
mov diskseg,cs
mov fdiskoff,offset @fdiskentry ; Floppy Disk I/O Entry
mov fdiskseg,cs
;
inst_nodsk3:
mov idosoff,offset @dosentry ; DOS-Entry
mov idosseg,cs
mov idleoff,offset @idleentry ; Idle-Entry
mov idleseg,cs
mov termoff,offset terminate_int ; Terminate Process Entry
mov termseg,cs
mov csectoff,offset @critsectint ; Critical Section Entry
mov csectseg,cs
mov keepoff,offset keep_int ; Keep Process Entry
mov keepseg,cs
mov absreadoff,offset absread_int ; Absolute Disk Read Entry
mov absreadseg,cs
mov abswriteoff,offset abswrite_int ; Absolute Disk Write Entry
mov abswriteseg,cs
IF (DEBUG AND DEB_DOSTRBUF)
mov muxoff,offset multiplex_int ; Multiplex Int Entry
mov muxseg,cs
ENDIF
IF DEBUG AND DEB_DOSTRBUF
mov dpmioff,offset multiplex_int ; Multiplex Int Entry
mov dpmiseg,cs
ENDIF
sti
;
assume es:nothing
;
pop es
IFDEF LOAD_DS
pop ds
ENDIF
ret
;
;
tsk_install_dos endp
;
;---------------------------------------------------------------------------
;
; void tsk_remove_dos (void)
;
; Un-install DOS handler
;
Localfunc tsk_remove_dos
;
IFDEF LOAD_DS
push ds
mov ax,@CTASK_DATA
mov ds,ax
ENDIF
;
; Delete resources & flags
;
callp delete_resource,<<ds,#upper_dos>>
callp delete_resource,<<ds,#lower_dos>>
;
test tsk_instflags,IFL_DISK
jz rem_nodsk1
callp delete_resource,<<ds,#hdisk_io>>
callp delete_resource,<<ds,#fdisk_io>>
;
rem_nodsk1:
test tsk_instflags,IFL_VIDEO
jz rem_novid1
callp delete_resource,<<ds,#video>>
;
rem_novid1:
push es
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -