⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tskdos.asm

📁 一个嵌入式实时操作系统源码
💻 ASM
📖 第 1 页 / 共 3 页
字号:
;
;	--- 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 + -