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

📄 mpx88.s

📁 MINIX2.0操作系统源码 MINIX2.0操作系统源码
💻 S
📖 第 1 页 / 共 2 页
字号:
#
! This file contains the assembler startup code for Minix and the 16-bit
! interrupt handlers.  It cooperates with cstart.c to set up a good
! environment for main().

! This file is part of the lowest layer of the MINIX kernel.  The other part
! is "proc.c".  The lowest layer does process switching and message handling.

! Every transition to the kernel goes through this file.  Transitions are
! caused by sending/receiving messages and by most interrupts.  (RS232
! interrupts may be handled in the file "rs2.s" and then they rarely enter
! the kernel.)

! Transitions to the kernel may be nested.  The initial entry may be with a
! system call, exception or hardware interrupt; reentries may only be made
! by hardware interrupts.  The count of reentries is kept in "k_reenter".
! It is important for deciding whether to switch to the kernel stack and
! for protecting the message passing code in "proc.c".

! For the message passing trap, most of the machine state is saved in the
! proc table.  (Some of the registers need not be saved.)  Then the stack is
! switched to "k_stack", and interrupts are reenabled.  Finally, the system
! call handler (in C) is called.  When it returns, interrupts are disabled
! again and the code falls into the restart routine, to finish off held-up
! interrupts and run the process or task whose pointer is in "proc_ptr".

! Hardware interrupt handlers do the same, except  (1) The entire state must
! be saved.  (2) There are too many handlers to do this inline, so the save
! routine is called.  A few cycles are saved by pushing the address of the
! appropiate restart routine for a return later.  (3) A stack switch is
! avoided when the stack is already switched.  (4) The (master) 8259 interrupt
! controller is reenabled centrally in save().  (5) Each interrupt handler
! masks its interrupt line using the 8259 before enabling (other unmasked)
! interrupts, and unmasks it after servicing the interrupt.  This limits the
! nest level to the number of lines and protects the handler from itself.

! For communication with the boot monitor at startup time some constant
! data are compiled into the beginning of the text segment. This facilitates 
! reading the data at the start of the boot process, since only the first
! sector of the file needs to be read.

! Some data storage is also allocated at the end of this file. This data 
! will be at the start of the data segment of the kernel and will be read
! and modified by the boot monitor before the kernel starts.

#include <minix/config.h>
#include <minix/const.h>
#include <minix/com.h>
#include "const.h"
#include "sconst.h"
#include "protect.h"

! The external entry points into this file are:
! Note: in assembly language the .define statement applied to a function name 
! is loosely equivalent to a prototype in C code -- it makes it possible to
! link to an entity declared in the assembly code but does not create
! the entity.

.define	_idle_task	! executed when there is no work
.define	_int00		! handlers for traps and exceptions
.define	_int01
.define	_int02
.define	_int03
.define	_int04
.define	_int05
.define	_int06
.define	_int07
.define _hwint00	! handlers for hardware interrupts
.define _hwint01
.define _hwint02
.define _hwint03
.define _hwint04
.define _hwint05
.define _hwint06
.define _hwint07
.define _hwint08
.define _hwint09
.define _hwint10
.define _hwint11
.define _hwint12
.define _hwint13
.define _hwint14
.define _hwint15
.define	_restart	! start running a task or process
.define	save		! save the machine state in the proc table
.define	_s_call		! process or task wants to send or receive a message

! Imported functions.

.extern	_cstart
.extern	_main
.extern	_exception
.extern	_interrupt
.extern	_sys_call
.extern	_unhold
.extern	klib_init_prot
.extern	real2prot

! Exported variables.
! Note: when used with a variable the .define does not reserve storage,
! it makes the name externally visible so it may be linked to. 

.define	kernel_ds
.define	begbss
.define	begdata
.define	_sizes

! Imported variables.

.extern kernel_cs
.extern	_gdt
.extern	_code_base
.extern	_data_base
.extern	_held_head
.extern	_k_reenter
.extern	_pc_at
.extern	_proc_ptr
.extern	_protected_mode
.extern	_ps_mca
.extern	_irq_table

	.text
!*===========================================================================*
!*				MINIX					     *
!*===========================================================================*
MINIX:				! this is the entry point for the MINIX kernel
	jmp	over_kernel_ds	! skip over the next few bytes
	.data2	CLICK_SHIFT	! for the monitor: memory granularity
kernel_ds:
	.data2	0x0024		! boot monitor flags:  (later kernel DS)
				!	make stack, will return
over_kernel_ds:

! Set up a C stack frame on the monitor stack.  (The monitor sets cs and ds
! right.  The ss register still references the monitor data segment.)
	push	bp
	mov	bp, sp
	push	si
	push	di
	mov	cx, 4(bp)	! monitor code segment
	test	cx, cx		! nonzero if return possible
	jz	noret
	inc	_mon_return
noret:	mov	_mon_ss, ss	! save stack location for later return
	mov	_mon_sp, sp

! Locate boot parameters, set up kernel segment registers and stack.
	mov	bx, 6(bp)	! boot parameters offset
	mov	dx, 8(bp)	! boot parameters length
	mov	ax, ds		! kernel data
	mov	es, ax
	mov	ss, ax
	mov	sp, #k_stktop	! set sp to point to the top of kernel stack

! Real mode needs to get kernel DS from the code segment.  Protected mode
! needs CS in the jump back to real mode.

  cseg	mov	kernel_cs, cs
  cseg	mov	kernel_ds, ds

! Call C startup code to set up a proper environment to run main().
	push	dx
	push	bx
	push	_mon_ss
	push	cx
	push	ds
	push	cs
	call	_cstart		! cstart(cs, ds, mcs, mds, parmoff, parmlen)
	add	sp, #6*2

	cmp	_protected_mode, #0
	jz	nosw		! ok to switch to protected mode?

	call	klib_init_prot	! initialize klib functions for protected mode
	call	real2prot	! switch to protected mode

	push	#0		! set flags to known good state
	popf			! especially, clear nested task and int enable
nosw:
	jmp	_main		! main()


!*===========================================================================*
!*				interrupt handlers			     *
!*===========================================================================*


!*===========================================================================*
!*				hwint00 - 07				     *
!*===========================================================================*
! Note this is a macro, it looks like a subroutine.
#define hwint_master(irq)	\
	call	save			/* save interrupted process state */;\
	inb	INT_CTLMASK						    ;\
	orb	al, *[1<<irq]						    ;\
	outb	INT_CTLMASK		/* disable the irq		  */;\
	movb	al, *ENABLE						    ;\
	outb	INT_CTL			/* reenable master 8259		  */;\
	sti				/* enable interrupts		  */;\
	mov	ax, *irq						    ;\
	push	ax			/* irq				  */;\
	call	@_irq_table + 2*irq	/* ax = (*irq_table[irq])(irq)	  */;\
	pop	cx							    ;\
	cli				/* disable interrupts		  */;\
	test	ax, ax			/* need to reenable irq?	  */;\
	jz	0f							    ;\
	inb	INT_CTLMASK						    ;\
	andb	al, *~[1<<irq]						    ;\
	outb	INT_CTLMASK		/* enable the irq		  */;\
0:	ret				/* restart (another) process      */

! Each of these entry points is an expansion of the hwint_master macro

_hwint00:		! Interrupt routine for irq 0 (the clock).
	hwint_master(0)


_hwint01:		! Interrupt routine for irq 1 (keyboard)
	hwint_master(1)


_hwint02:		! Interrupt routine for irq 2 (cascade!)
	hwint_master(2)


_hwint03:		! Interrupt routine for irq 3 (second serial)
	hwint_master(3)


_hwint04:		! Interrupt routine for irq 4 (first serial)
	hwint_master(4)


_hwint05:		! Interrupt routine for irq 5 (XT winchester)
	hwint_master(5)


_hwint06:		! Interrupt routine for irq 6 (floppy)
	hwint_master(6)


_hwint07:		! Interrupt routine for irq 7 (printer)
	hwint_master(7)


!*===========================================================================*
!*				hwint08 - 15				     *
!*===========================================================================*
! Note this is a macro, it looks like a subroutine.
#define hwint_slave(irq)	\
	call	save			/* save interrupted process state */;\
	inb	INT2_CTLMASK						    ;\
	orb	al, *[1<<[irq-8]]					    ;\
	outb	INT2_CTLMASK		/* disable the irq		  */;\
	movb	al, *ENABLE						    ;\
	outb	INT_CTL			/* reenable master 8259		  */;\
	jmp	.+2			/* delay			  */;\
	outb	INT2_CTL		/* reenable slave 8259		  */;\
	sti				/* enable interrupts		  */;\
	mov	ax, *irq						    ;\
	push	ax			/* irq				  */;\
	call	@_irq_table + 2*irq	/* eax = (*irq_table[irq])(irq)   */;\
	pop	cx							    ;\
	cli				/* disable interrupts		  */;\
	test	ax, ax			/* need to reenable irq?	  */;\
	jz	0f							    ;\
	inb	INT2_CTLMASK						    ;\
	andb	al, *~[1<<[irq-8]]					    ;\
	outb	INT2_CTLMASK		/* enable the irq		  */;\
0:	ret				/* restart (another) process      */

! Each of these entry points is an expansion of the hwint_slave macro

_hwint08:		! Interrupt routine for irq 8 (realtime clock)
	hwint_slave(8)


_hwint09:		! Interrupt routine for irq 9 (irq 2 redirected)
	hwint_slave(9)


_hwint10:		! Interrupt routine for irq 10
	hwint_slave(10)


_hwint11:		! Interrupt routine for irq 11
	hwint_slave(11)


_hwint12:		! Interrupt routine for irq 12
	hwint_slave(12)


_hwint13:		! Interrupt routine for irq 13 (FPU exception)
	hwint_slave(13)


_hwint14:		! Interrupt routine for irq 14 (AT winchester)
	hwint_slave(14)


_hwint15:		! Interrupt routine for irq 15
	hwint_slave(15)


!*===========================================================================*
!*				save					     *
!*===========================================================================*
save:				! save the machine state in the proc table.

! In protected mode a jump to p_save is patched over the following
! code during initialization.

	cld			! set direction flag to a known value
	push	ds
	push	si
  cseg	mov	ds,kernel_ds
	incb	_k_reenter	! from -1 if not reentering
	jnz	push_current_stack	! stack is already kernel stack

	mov	si,_proc_ptr
	mov	AXREG(si),ax
	mov	BXREG(si),bx
	mov	CXREG(si),cx
	mov	DXREG(si),dx
	pop	SIREG(si)
	mov	DIREG(si),di
	mov	BPREG(si),bp
	mov	ESREG(si),es
	pop	DSREG(si)
	pop	bx		! return adr
	pop	PCREG(si)
	pop	CSREG(si)
	pop	PSWREG(si)
	mov	SPREG(si),sp
	mov	SSREG(si),ss

	mov	dx,ds
	mov	ss,dx
	mov	sp,#k_stktop
	mov	ax,#_restart	! build return address for interrupt handler
	push	ax

stack_switched:
	mov	es,dx
	jmp	(bx)

push_current_stack:
	push	es
	push	bp
	push	di
	push	dx
	push	cx
	push	bx
	push	ax
	mov	bp,sp
	mov	bx,18(bp)	! get the return adr; it becomes junk on stack
	mov	ax,#restart1
	push	ax
	mov	dx,ss
	mov	ds,dx
	jmp	stack_switched


!*===========================================================================*
!*				s_call					     *
!*===========================================================================*
! This is real mode version. Alternate (_p_s_call) will be used in
! protected mode

_s_call:			! System calls are vectored here.
				! Do save routine inline for speed,
				! but do not save ax, bx, cx, dx,
				! since C does not require preservation,
				! and ax returns the result code anyway.
				! Regs bp, si, di get saved by sys_call as
				! well, but it is impractical not to preserve
				! them here, in case context gets switched.
				! Some special-case code in pick_proc()
				! could avoid this.
	cld			! set direction flag to a known value
	push	ds
	push	si
  cseg	mov	ds,kernel_ds
	incb	_k_reenter
	mov	si,_proc_ptr
	pop	SIREG(si)
	mov	DIREG(si),di
	mov	BPREG(si),bp
	mov	ESREG(si),es
	pop	DSREG(si)
	pop	PCREG(si)
	pop	CSREG(si)
	pop	PSWREG(si)
	mov	SPREG(si),sp
	mov	SSREG(si),ss
	mov	dx,ds

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -