Metropoli BBS
VIEWER: kernel.asm MODE: TEXT (ASCII)
;
; File:
;			   kernel.asm
; Description:
;			kernel start-up code
;
;		     Copyright (c) 1995, 1996
;			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.
;
; $Logfile:   D:/dos-c/src/kernel/kernel.asv  $
;
; $Header:   D:/dos-c/src/kernel/kernel.asv   1.3   29 May 1996 21:03:44   patv  $
;
; $Log:   D:/dos-c/src/kernel/kernel.asv  $
;
;   Rev 1.3   29 May 1996 21:03:44   patv
;bug fixes for v0.91a
;
;   Rev 1.2   19 Feb 1996  3:24:06   patv
;Added NLS, int2f and config.sys processing
;
;   Rev 1.1   01 Sep 1995 17:54:24   patv
;First GPL release.
;
;   Rev 1.0   02 Jul 1995  9:05:44   patv
;Initial revision.
;

		page	60,132
		title	kernel start-up code

IFDEF ??version
_TEXT		segment	byte public 'CODE'
DGROUP		group	_DATA,_BSS,_BSSEND		; small model
		assume	cs:_TEXT,ds:DGROUP,ss:DGROUP
_TEXT		ends

_DATA		segment word public 'DATA'
_DATA		ends

_BSS		segment word public 'BSS'
_BSS		ends

_BSSEND		segment byte public 'STACK'
_BSSEND		ends

ELSE
_TEXT		segment	byte public 'CODE'
_TEXT		ends

_DATA		segment word public 'DATA'
_DATA		ends

CONST		segment word public 'CONST'
CONST		ends

_BSS		segment word public 'BSS'
_BSS		ends

_BSSEND		segment byte public 'STACK'
_BSSEND		ends

DGROUP		group	CONST,_DATA,_BSS,_BSSEND	; small/tiny model
		assume	ds:DGROUP, ss:DGROUP
ENDIF


_DATA		segment word public 'DATA'
		db '$Header:   D:/dos-c/src/kernel/kernel.asv   1.3   29 May 1996 21:03:44   patv  $'
_DATA		ends

_TEXT		segment	byte public 'CODE'
		assume	cs:_TEXT

		extrn	_main:near
		extrn	_con_driver:near
		extrn	_blk_driver:near
		extrn	_clk_driver:near

;STANDALONE equ 0
		

;---------------------------------------------------
;
; Device entry points
;
cmdlen	equ	0			; Length of this command
unit	equ	1			; Subunit Specified
cmd	equ	2			; Command Code
status	equ	3			; Status
media	equ	13			; Media Descriptor
trans	equ	14			; Transfer Address
count	equ	18			; Count of blocks or characters
start	equ	20			; First block to transfer

IFNDEF ??version
 IF STANDALONE EQ 1
PUBLIC	__acrtused 		; trick used by MSC to force in startup
	__acrtused = 9876h
 ENDIF
ENDIF
		;
		;
		page
		;
		;
entry		proc	near
IF STANDALONE EQ 1
		jmp	short kernel_start
ENDIF

		;
		; The "CON" device
		;
		; This device is the standard console device used by
		; XDOS and kernel
		;
		public	_con_dev
_con_dev	label	far
		dd	-1
		dw	8003h		; con device (stdin & stdout)
		dw	offset con_strategy
		dw	offset con_entry
		db	'CON     '

		;
		; Header for device
		;
		public	_blk_dev
_blk_dev	label	far
		dd	-1
		dw	0000h		; block device
		dw	offset blk_strategy
		dw	offset blk_entry
		db	4
		db	0,0,0,0,0,0,0

		;
		; Header for device
		;
		public	_clk_dev
_clk_dev	label	far
		dd	-1
		dw	8004h		; clock device
		dw	offset clk_strategy
		dw	offset clk_entry
		db	'CLOCK$  '

		page
		;
		; kernel start-up
		;
IF STANDALONE EQ 1
kernel_start:	cli			; prevent interrupts while starting
		mov	ax,DGROUP
		mov	ss,ax
		mov	sp,offset DGROUP:tos
		mov	ds,ax
		mov	es,ax
		mov	bp,sp		; and set up stack frame for c
		sti			; now enable them
		mov	_BootDrive,bx	; tell where we came from
		mov	_NumFloppies,cx	; and how many
		call	_main
		mov	ax,0
		push	ax
		call	_exit
		jmp	$
ENDIF
entry		endp


		;
		; _exit
		;	perform an "exit" and quit
		;
		; exit(code)
		; int code;
		;
IF STANDALONE EQ 1
_exit		proc	near
		public	_exit
		
		cli
		hlt
		jmp	_exit

_exit		endp
ENDIF
		page
		;
		; NUL device strategy
		;
_nul_strtgy	proc	far
		public _nul_strtgy
		mov	word ptr rqhdr,bx	;save rq headr
		mov	word ptr rqhdr+2,es
		ret
_nul_strtgy	endp

		;
		; NUL device interrupt
		;
_nul_intr	proc	far
		public _nul_intr
		push	es
		push	bx
		les	bx,rqhdr		;es:bx--> rqheadr
		or	word ptr es:[bx+3],100h	;set "done" flag
		pop	bx
		pop	es
		ret
_nul_intr	endp

 		page

		;
		; con device strategy
		;
		; NOTE: This code is not standard device driver handlers
		; It is written for sperate code and data space.
		;
con_strategy	proc	far
		push	ds
		push	ax
		; small model
		mov	ax,DGROUP		; small model - cs != ds
		mov	ds,ax
		mov	word ptr DGROUP:con_rp+2,es
		mov	word ptr DGROUP:con_rp,bx
		pop	ax
		pop	ds
		ret	
con_strategy	endp


		;
		; con device interrupt
		;
		; NOTE: This code is not standard device driver handlers
		; It is written for sperate code and data space.
		;
con_entry	proc	far
		push	si
		push	ax
		push	cx
		push	dx
		push	di
		push	bp
		push	ds
		push	es
		push	bx

		; small model
		mov	ax,DGROUP			; correct for segments
		mov	ds,ax				; ax to carry segment
		mov	word ptr DGROUP:con_dos_stk,sp	; use internal stack
		mov	word ptr DGROUP:con_dos_seg,ss
		pushf					; put flags in bx
		pop	bx
		cli					; no interrupts
		mov	ss,ax
		mov	sp,offset DGROUP:con_stk_top
		push	bx
		popf					; restore interrupt flag
		mov	bp,sp				; make a c frame
		push	word ptr con_rp+2
		push	word ptr con_rp
		call	_con_driver
		pop	cx
		pop	cx
		les	bx,dword ptr con_rp		; now return completion code
		mov	word ptr es:[bx].status,ax	; mark operation complete
		pushf
		pop	bx
		cli					; no interrupts
		mov	sp,word ptr DGROUP:con_dos_stk	; use dos stack
		mov	ss,word ptr DGROUP:con_dos_seg
		push	bx
		popf					; restore interrupt flag
		pop	bx
		pop	es
		pop	ds
		pop	bp
		pop	di
		pop	dx
		pop	cx
		pop	ax
		pop	si
		ret	
con_entry	endp

		;
		; block device strategy
		;
		; NOTE: This code is not standard device driver handlers
		; It is written for sperate code and data space.
		;
blk_strategy	proc	far
		push	ds
		push	ax
		; small model
		mov	ax,DGROUP			; small model - cs != ds
		mov	ds,ax
		mov	word ptr DGROUP:blk_rp+2,es
		mov	word ptr DGROUP:blk_rp,bx
		pop	ax
		pop	ds
		ret	
blk_strategy	endp

		;
		; block device interrupt
		;
		; NOTE: This code is not standard device driver handlers
		; It is written for sperate code and data space.
		;
blk_entry	proc	far
		pushf
		push	ax
		push	bx
		push	cx
		push	dx
		push	bp
		push	si
		push	di
		push	ds
		push	es

		; small model
		mov	ax,DGROUP			; correct for segments
		mov	ds,ax				; ax to carry segment
		mov	word ptr DGROUP:blk_dos_stk,sp	; use internal stack
		mov	word ptr DGROUP:blk_dos_seg,ss
		pushf					; put flags in bx
		pop	bx
		cli					; no interrupts
		mov	ss,ax
		mov	sp,offset DGROUP:blk_stk_top
		push	bx
		popf					; restore interrupt flag
		mov	bp,sp				; make a c frame
		push	word ptr blk_rp+2
		push	word ptr blk_rp
		call	_blk_driver
		pop	cx
		pop	cx
		les	bx,dword ptr blk_rp			; now return completion code
		mov	word ptr es:[bx].status,ax	; mark operation complete
		cli					; no interrupts
		mov	sp,word ptr DGROUP:blk_dos_stk	; use dos stack
		mov	ss,word ptr DGROUP:blk_dos_seg
		pop	es
		pop	ds
		pop	di
		pop	si
		pop	bp
		pop	dx
		pop	cx
		pop	bx
		pop	ax
		popf
		ret	
blk_entry	endp


		page

		;
		; clock device strategy
		;
		; NOTE: This code is not standard device driver handlers
		; It is written for sperate code and data space.
		;
clk_strategy	proc	far
		push	ds
		push	ax
		; small model
		mov	ax,DGROUP			; small model - cs != ds
		mov	ds,ax
		mov	word ptr DGROUP:clk_rp+2,es
		mov	word ptr DGROUP:clk_rp,bx
		pop	ax
		pop	ds
		ret	
clk_strategy	endp

		;
		; clock device interrupt
		;
		; NOTE: This code is not standard device driver handlers
		; It is written for sperate code and data space.
		;
clk_entry	proc	far
		pushf
		push	ax
		push	bx
		push	cx
		push	dx
		push	bp
		push	si
		push	di
		push	ds
		push	es

		; small model
		mov	ax,DGROUP			; correct for segments
		mov	ds,ax				; ax to carry segment
		mov	word ptr DGROUP:clk_dos_stk,sp	; use internal stack
		mov	word ptr DGROUP:clk_dos_seg,ss
		pushf					; put flags in bx
		pop	bx
		cli					; no interrupts
		mov	ss,ax
		mov	sp,offset DGROUP:clk_stk_top
		push	bx
		popf					; restore interrupt flag
		mov	bp,sp				; make a c frame
		push	word ptr clk_rp+2
		push	word ptr clk_rp
		call	_clk_driver
		pop	cx
		pop	cx
		les	bx,dword ptr clk_rp		; now return completion code
		mov	word ptr es:[bx].status,ax	; mark operation complete
		cli					; no interrupts
		mov	sp,word ptr DGROUP:clk_dos_stk	; use dos stack
		mov	ss,word ptr DGROUP:clk_dos_seg
		pop	es
		pop	ds
		pop	di
		pop	si
		pop	bp
		pop	dx
		pop	cx
		pop	bx
		pop	ax
		popf
		ret	
clk_entry	endp


		page
;
; special interrupt routine for break key handling
;


;
; i_save
;	save machine context on stack after an interrupt
;	does not save ss and sp
;
;	assumes flags and cs:ip are on stack from interrupt
;
i_save	proc	near
	public	i_save
	push	bp		; start saving bp
	mov	bp,sp		; and mark frame for exit
	push	di		; save the rest of the registers
	push	si
	push	bx
	push	cx
	push	dx
	push	ds
	push	es
	xchg	ax,[bp+2]	; swap return address with ax
	push	ax		; put it back
	mov	ax,[bp+2]	; recover ax from entry
	mov	bp,[bp]		; and bp
	ret
i_save	endp


;
; i_exit
;	recovers context from i_save and does interrupt return
;	must be jumped to
;
;	warning - make sure you're using the right stack
;
i_exit	proc	near
	public	i_exit
	pop	es		; recover context
	pop	ds
	pop	dx
	pop	cx
	pop	bx
	pop	si
	pop	di
	pop	bp
	pop	ax
	iret			; and make like a tree (leave)
i_exit	endp


	extrn	_break_handler:near

_break_key	proc	near
		public	_break_key
		call	i_save			; save context
		mov	ax,cs			; correct for segments
		mov	ds,ax			; ax to carry segment
		mov	word ptr DGROUP:intr_dos_stk,sp	; use internal stack
		mov	word ptr DGROUP:intr_dos_seg,ss
		pushf				; put flags in bx
		pop	bx
		cli				; no interrupts
		mov	ss,ax
		mov	sp,offset DGROUP:intr_stk_top
		push	bx
		popf				; restore interrupt flag
		mov	bp,sp			; make a c frame
		call	_break_handler		; call handler
		les	bx,dword ptr con_rp	; now return completion code
		pushf
		pop	bx
		cli				; no interrupts
		mov	sp,word ptr DGROUP:intr_dos_stk	; use dos stack
		mov	ss,word ptr DGROUP:intr_dos_seg
		push	bx
		popf
		jmp	i_exit			; and restore & exit
_break_key	endp

_TEXT		ends


_DATA		segment word public 'DATA'
; Globally referenced variables - WARNING: DO NOT CHANGE ORDER
; BECAUSE THEY ARE DOCUMENTED AS UNDOCUMENTED (?) AND HAVE
; MANY MULTIPLEX PROGRAMS AND TSR'S ACCESSING THEM
		public	_first_mcb
_first_mcb	dw	(?)		; Start of user memory
		public	_DPBp
_DPBp		dd	(?)		; First drive Parameter Block
		public	_sfthead
_sfthead	dd	(?)		; System File Table head
		public	_clock
_clock		dd	(?)		; CLOCK$ device
		public	_syscon
_syscon		dd	(?)		; console device
		public	_maxbksize
_maxbksize	dw	(?)		; Number of Drives in system
		public	_firstbuf;
_firstbuf	dd	(?)	    	; head of buffers linked list
		public	_CDSp
_CDSp		dd	(?)		; Current Directory Structure
		public	_FCBp
_FCBp		dd	(?)		; FCB table pointer
		public	_nprotfcb
_nprotfcb	dw	(?)		; number of protected fcbs
		public	_nblkdev
_nblkdev	db	(?)		; number of block devices
		public	_lastdrive
_lastdrive	db	(?)		; value of last drive
		public	_nul_dev
_nul_dev	label	dword
;_nul_dev	label	far
		dd	-1
		dw	8004h		; attributes = char device, NUL bit set
		dw	offset _nul_strtgy
		dw	offset _nul_intr
		db	'NUL     '
		public	_njoined
_njoined	db	(?)		; number of joined devices
;
; end of controlled variables
;
_DATA		ends

_BSS		segment word public 'BSS'
		public	_BootDrive
_BootDrive	dw	(?)
		public	_NumFloppies
_NumFloppies	dw	(?)
rqhdr		dd	(?)
con_rp		dd	(?)
blk_rp		dd	(?)
clk_rp		dd	(?)
con_dos_stk	dw	(?)
con_dos_seg	dw	(?)
blk_dos_stk	dw	(?)
blk_dos_seg	dw	(?)
clk_dos_stk	dw	(?)
clk_dos_seg	dw	(?)
intr_dos_stk	dw	(?)
intr_dos_seg	dw	(?)


		public	_api_sp
_api_sp		dw	(?)		; api stacks - for context
		public	_api_ss
_api_ss		dw	(?)		; switching
		public	_usr_sp
_usr_sp		dw	(?)		; user stacks
		public	_usr_ss
_usr_ss		dw	(?)
		public	_ram_top
_ram_top	dw	(?)

_BSS		ends



_BSSEND		segment byte public 'STACK'
; kernel private stack arear
IF STANDALONE EQ 1
		dw	512 dup (?)
ELSE
		dw	4096 dup (?)
ENDIF
tos		label	byte

; condev private stack
		dw	1024 dup (?)
con_stk_top	label	byte

; blockdev private stack
		dw	1024 dup (?)
blk_stk_top	label	byte

; clockdev private stack
		dw	1024 dup (?)
clk_stk_top	label	byte

; interrupt stack
		dw	1024 dup (?)
intr_stk_top	label	byte

; int 21 api stack area
		dw	1024 dup (?)
		public	_error_tos
_error_tos	label	word
		dw	4096 dup (?)
		public	_char_api_tos
_char_api_tos	label	word
		dw	4096 dup (?)
		public	_disk_api_tos
_disk_api_tos	label	word
		public	last
last		label	word			; must always be end of stack area
		public	_last
_last		label	byte			; and c version

_BSSEND		ends


		end	entry


[ RETURN TO DIRECTORY ]