[comp.os.minix] NYUMINIX:MPX88.ASM

jai@lab.ultra.nyu.edu (Benchiao Jai) (02/24/91)

; This file is part of the lowest layer of the MINIX kernel.  All processing
; switching and message handling is done here and in file "proc.c".  This file
; is entered on every transition to the kernel, both for sending/receiving
; messages and for all interrupts.  In all cases, the trap or interrupt
; routine first calls save() to store the machine state in the proc table.
; Then the stack is switched to k_stack.  Finally, the real trap or interrupt
; handler (in C) is called.  When it returns, the interrupt routine jumps to
; restart, to run the process or task whose number is in 'cur_proc'.
;
; The external entry points into this file are:
;   s_call:	process or task wants to send or receive a message
;   tty_int:	interrupt routine for each key depression and release
;   rs232_int:	interrupt routine for each rs232 interrupt on port 1
;   secondary:	interrupt routine for each rs232 interrupt on port 2
;   lpr_int:	interrupt routine for each line printer interrupt
;   disk_int:	disk interrupt routine
;   clock_int:	clock interrupt routine (HZ times per second)
;   restart:	start running a task or process
;   reboot:	reboot for CTRL-ALT-DEL
;   wreboot:	wait for character then reboot
;   save_tty_vec: save tty interrupt vector 0x71 for PS/2

; These symbols MUST agree with the values in ../h/com.h to avoid disaster.
K_STACK_BYTES	=  256
FLOPPY		=   -5
CLOCK		=   -3
IDLE		= -999
DISKINT 	=    1
CLOCK_TICK	=    2

; The following procedures are defined in this file and called from outside it.
public _tty_int, _rs232_int, _lpr_int, _clock_int, _disk_int
public _s_call, _restart, _secondary_int
public _reboot, _wreboot, _save_tty_vec

; The following external procedures are called in this file.
extrn _main:near, _sys_call:near, _interupt:near, _keyboard:near
extrn _panic:near, _pr_char:near, _rs232:near

; Variables, data structures and miscellaneous.
extrn _cur_proc:word, _proc_ptr:word, _scan_code:word
extrn _int_mess:byte, _k_stack:byte, splimit:word, _port_65:word, _ps:word
extrn endtext:byte, enddata:byte, endbss:byte
public _sizes, begtext, begdata, begbss
public _vec_table

; The following constants are offsets into the proc table.
esreg = 14
dsreg = 16
csreg = 18
ssreg = 20
SPr   = 22
PC    = 24
PSW   = 28
SPLIM = 50
OFF   = 18
ROFF  = 12

DGROUP	GROUP	_TEXT, _DATA, _BSS

_TEXT	segment byte	public	'CODE'
	assume	cs:_TEXT, ds:DGROUP
begtext:
;*===========================================================================*
;*				MINIX					     *
;*===========================================================================*
MINIX:				; this is the entry point for the MINIX kernel.
	jmp short M0
	dw  DGROUP:begdata
	dw  DGROUP:endbss
M0:
	cli
	mov ax,cs		; only one segment
	mov ds,ax
	mov _scan_code, 13	; standard keyboard
	mov sssave,ss		; save old ss and sp for returning to MS-DOS
	mov spsave,sp
	mov ss,ax
	mov sp,offset _k_stack	; set sp to point to the top of the
	add sp, K_STACK_BYTES	;   kernel stack
	sti
	call _main		; start the main program of MINIX
M1:	jmp M1			; this should never be executed

;*===========================================================================*
;*				s_call					     *
;*===========================================================================*
_s_call:			; System calls are vectored here.
	call save		; save the machine state
	mov bp,_proc_ptr	; use bp to access sys call parameters
	push 2[bp]		; push(pointer to user message) (was bx)
	push [bp]		; push(src/dest) (was ax)
	push _cur_proc		; push caller
	push 4[bp]		; push(SEND/RECEIVE/BOTH) (was cx)
	call _sys_call		; sys_call(function, caller, src_dest, m_ptr)
	jmp _restart		; jump to code to restart proc/task running

;*===========================================================================*
;*				tty_int 				     *
;*===========================================================================*
_tty_int:			; Interrupt routine for terminal input.
	call save		; save the machine state
	call _keyboard		; process a keyboard interrupt
	jmp _restart		; continue execution

;*============================================================================
;*				rs232_int				     *
;*============================================================================
_rs232_int:			; Interrupt routine for rs232 I/O.
	call save		; save the machine state
	mov ax, 1		; which unit caused the interrupt
	push ax 		; pass it as a parameter
	call _rs232		; process a rs232 interrupt
	jmp _restart		; continue execution

;*============================================================================
;*				secondary_int				     *
;*============================================================================
_secondary_int: 		; Interrupt routine for rs232 port 2
	call save		; save the machine state
	mov ax, 2		; which unit caused the interrupt
	push ax 		; pass it as a parameter
	call _rs232		; process a rs232 interrupt
	jmp _restart		; continue execution

;*===========================================================================*
;*				lpr_int 				     *
;*===========================================================================*
_lpr_int:			; Interrupt routine for printer input.
	call save		; save the machine state
	call _pr_char		; process a line printer interrupt
	jmp _restart		; continue execution

;*===========================================================================*
;*				disk_int				     *
;*===========================================================================*
_disk_int:			; Interrupt routine for the floppy disk.
	call save		; save the machine state
	mov _int_mess+2, DISKINT; build message for disk task
	mov ax,offset _int_mess ; prepare to call interrupt(FLOPPY, &intmess)
	push ax 		; push second parameter
	mov ax, FLOPPY		; prepare to push first parameter
	push ax 		; push first parameter
	call _interupt		; this is the call
	jmp _restart		; continue execution

;*===========================================================================*
;*				clock_int				     *
;*===========================================================================*
_clock_int:			; Interrupt routine for the clock.
	call save		; save the machine state
	mov _int_mess+2, CLOCK_TICK	; build message for clock task
	mov ax,offset _int_mess ; prepare to call interrupt(CLOCK, &intmess)
	push ax 		; push second parameter
	mov ax, CLOCK		; prepare to push first parameter
	push ax 		; push first parameter
	call _interupt		; this is the call
	jmp _restart		; continue execution

;*===========================================================================*
;*				save					     *
;*===========================================================================*
save:				; save the machine state in the proc table.
	cld			; set direction flag to a known value
	mov cs:bx_save,bx	; save bx for later ; we need a free register
	mov cs:ds_save,ds	; stack: psw/cs/pc/ret addr
	mov bx,cs		; prepare to restore ds
	mov ds,bx		; ds has now been set to cs
	pop ret_save		; stack: psw/cs/pc
	mov bx,_proc_ptr	; start save set up; make bx point to save area
	add bx, OFF		; bx points to place to store cs
	pop PC-OFF[bx]		; store pc in proc table
	pop csreg-OFF[bx]	; store cs in proc table
	pop PSW-OFF[bx] 	; store psw
	mov ssreg-OFF[bx],ss	; store ss
	mov SPr-OFF[bx],sp	; sp as it was prior to interrupt
	mov sp,bx		; now use sp to point into proc table/task save
	mov bx,ds		; about to set ss
	mov ss,bx		; set ss
	push ds_save		; start saving all the registers, sp first
	push es 		; save es between sp and bp
	mov es,bx		; es now references kernel memory too
	push bp 		; save bp
	push di 		; save di
	push si 		; save si
	push dx 		; save dx
	push cx 		; save cx
	push bx_save		; save original bx
	push ax 		; all registers now saved
	mov sp,offset _k_stack	; temporary stack for interrupts
	add sp, K_STACK_BYTES	; set sp to top of temporary stack
	mov splimit,offset _k_stack	; limit for temporary stack
	add splimit, 8		; splimit checks for stack overflow
	cld
	mov ax,ret_save 	; ax = address to return to
	jmp ax			; return to caller; Note: sp points to saved ax


;*===========================================================================*
;*				restart 				     *
;*===========================================================================*
_restart:			; This routine sets up and runs a proc or task.
	cmp _cur_proc, IDLE	; restart user; if cur_proc = IDLE, go idle
	je idl			; no user is runnable, jump to idle routine
	cli			; disable interrupts
	mov sp,_proc_ptr	; return to user, fetch regs from proc table
	pop ax			; start restoring registers
	pop bx			; restore bx
	pop cx			; restore cx
	pop dx			; restore dx
	pop si			; restore si
	pop di			; restore di
	mov lds_low,bx		; lds_low contains bx
	mov bx,sp		; bx points to saved bp register
	mov bp,SPLIM-ROFF[bx]	; splimit = p_splimit
	mov splimit,bp		; ditto
	mov bp,dsreg-ROFF[bx]	; bp = ds
	mov lds_low+2,bp	; lds_low+2 contains ds
	pop bp			; restore bp
	pop es			; restore es
	mov sp,SPr-ROFF[bx]	; restore sp
	mov ss,ssreg-ROFF[bx]	; restore ss using the value of ds
	push PSW-ROFF[bx]	; push psw
	push csreg-ROFF[bx]	; push cs
	push PC-ROFF[bx]	; push pc
	lds bx,dword ptr lds_low; restore ds and bx in one fell swoop
	iret			; return to user or task

;*===========================================================================*
;*				idle					     *
;*===========================================================================*
idl:				; executed when there is no work
	sti			; enable interrupts
L3:	wait			; just idle while waiting for interrupt
	jmp L3			; loop until interrupt

;*===========================================================================*
;*				reboot & wreboot			     *
;*===========================================================================*
; This code reboots the PC

_reboot:
	cli			; disable interrupts
	mov ax, 20h		; re-enable interrupt controller
	out 20h,al
	call resvec		; restore the vectors in low core
r0:
	mov al,36h		; reset the timer to IBM freq.
	out 43h,al
	xor al,al
	out 40h,al
	out 40h,al
	mov ss,sssave
	mov sp,spsave

	test _ps,  0FFFFh
	jz  r1

	mov ax,tty_vec1 	; Restore keyboard interrupt vector for PS/2
	mov es:[452],ax
	mov ax,tty_vec2
	mov es:[454],ax
	mov ax,_port_65 	; restore port 0x65
	out 65h, al
	mov al, 0BCh
	out 21h, al
r1:
	sti
dummy	proc	far
	ret
dummy	endp

_wreboot:
	cli			; disable interrupts
	mov ax, 20h		; re-enable interrupt controller
	out 20h,al
	call resvec		; restore the vectors in low core

	xor ax,ax		; wait for character before continuing
	int   16h		; get char
	jmp r0

; Restore the interrupt vectors in low core.
resvec: cld
	mov cx, 2*33
	mov si,offset DGROUP:_vec_table
	xor di,di
	mov es,di
	rep movsw
	ret

;*===========================================================================*
;*				save_tty_vec				     *
;*===========================================================================*
; Save the tty vector 0x71 (PS/2)
_save_tty_vec:
	push es
	xor ax,ax
	mov es,ax
	mov ax,es:[452]
	mov tty_vec1,ax
	mov ax,es:[454]
	mov tty_vec2,ax
	pop es
	ret

_TEXT	ends

;*===========================================================================*
;*				data					     *
;*===========================================================================*
_DATA	segment word	public	'DATA'
begdata label	byte
_sizes	 dw	8 dup (0)	; load uses this space
bx_save  dw	0		; storage for bx
ds_save  dw	0		; storage for ds
ret_save dw	0		; storage for return address
lds_low  dw	0,0		; storage used for restoring bx
_vec_table dw	66 dup(0)	; storage for interrupt vectors
tty_vec1 dw	0		; sorage for vector 0x71 (offset)
tty_vec2 dw	0		; sorage for vector 0x71 (segment)
sssave	 dw	0		; save ss for returning to MS-DOS
spsave	 dw	0		; save sp for returning to MS-DOS
_DATA	ends

_BSS	segment word	public	'BSS'
begbss	label	byte
_BSS	ends

	end