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

📄 irq_asm.s

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 S
字号:
/* irq.c * *  This file contains the implementation of the function described in irq.h * *  CopyRight (C) 1998 valette@crf.canon.fr * *  The license and distribution terms for this file may be *  found in found in the file LICENSE in this distribution or at *  http://www.rtems.com/license/LICENSE. * *  $Id: irq_asm.S,v 1.1.8.1 2003/09/04 18:44:05 joel Exp $ */#include "asm.h"	#include <irq_asm.h>	       BEGIN_CODE	SYM (_ISR_Handler):	       /*        *  Before this was point is reached the vectors unique        *  entry point did the following:        *        *     1. saved scratch registers registers eax edx ecx"        *     2. put the vector number in ecx.        *        * BEGINNING OF ESTABLISH SEGMENTS        *        *  WARNING: If an interrupt can occur when the segments are        *           not correct, then this is where we should establish        *           the segments.  In addition to establishing the        *           segments, it may be necessary to establish a stack        *           in the current data area on the outermost interrupt.        *        *  NOTE:  If the previous values of the segment registers are        *         pushed, do not forget to adjust SAVED_REGS.        *        *  NOTE:  Make sure the exit code which restores these        *         when this type of code is needed.        */       /***** ESTABLISH SEGMENTS CODE GOES HERE  ******/       /*        * END OF ESTABLISH SEGMENTS        */        /*         *  Now switch stacks if necessary         */	movw	  SYM (i8259s_cache), ax # move current i8259 interrupt mask in ax	pushl	  eax			      # push it on the stack	/*	 * compute the new PIC mask:	 *	 * <new mask> = <old mask> | irq_mask_or_tbl[<intr number aka ecx>]	 */	movw	  SYM (irq_mask_or_tbl) (,ecx,2), dx	orw	  dx, ax	/*	 * Install new computed value on the i8259 and update cache	 * accordingly	 */	movw      ax, SYM (i8259s_cache)	outb	  $PIC_MASTER_IMR_IO_PORT	movb	  ah, al	outb	  $PIC_SLAVE_IMR_IO_PORT	/*	 * acknowledge the interrupt	 *	 */	movb	$PIC_EOI, al        cmpl    $7, ecx	jbe	.master	outb    $PIC_SLAVE_COMMAND_IO_PORT.master:        outb    $PIC_MASTER_COMMAND_IO_PORT	.check_stack_switch:	pushl	  ebp        movl      esp, ebp                  # ebp = previous stack pointer        cmpl      $0, SYM (_ISR_Nest_level) # is this the outermost interrupt?        jne       nested                    # No, then continue        movl      SYM (_CPU_Interrupt_stack_high), esp        /*         *  We want to insure that the old stack pointer is on the         *  stack we will be on at the end of the ISR when we restore it.         *  By saving it on every interrupt, all we have to do is pop it         *  near the end of every interrupt.         */nested:        incl      SYM (_ISR_Nest_level)     # one nest level deeper        incl      SYM (_Thread_Dispatch_disable_level) # disable multitasking	/*	 * re-enable interrupts at processor level as the current	 * interrupt source is now masked via i8259	 */	sti	        /*	 *  ECX is preloaded with the vector number but it is a scratch register	 *  so we must save it again.	 */	        pushl     ecx                       # push vector number        mov       SYM (current_irq) (,ecx,4),eax                                            # eax = Users handler        call      *eax                      # invoke user ISR	/*	 * disable interrupts_again	 */	cli        popl       ecx                       # ecx = vector number	/*	 * restore stack	 */	movl	  ebp, esp	popl	  ebp	/*	 * restore the original i8259 masks	 */	popl	  eax	movw      ax, SYM (i8259s_cache)	outb	  $PIC_MASTER_IMR_IO_PORT	movb	  ah, al	outb	  $PIC_SLAVE_IMR_IO_PORT		        decl      SYM (_ISR_Nest_level)     # one less ISR nest level                                            # If interrupts are nested,                                            #   then dispatching is disabled        decl      SYM (_Thread_Dispatch_disable_level)                                            # unnest multitasking                                            # Is dispatch disabled        jne       .exit                     # Yes, then exit        cmpl      $0, SYM (_Context_Switch_necessary)                                            # Is task switch necessary?        jne	  .schedule		    # Yes, then call the scheduler        cmpl      $0, SYM (_ISR_Signals_to_thread_executing)                                            # signals sent to Run_thread                                            #   while in interrupt handler?        je        .exit                     # No, exit	.bframe:        movl      $0, SYM (_ISR_Signals_to_thread_executing)	/*	 * This code is the less critical path. In order to have a single	 * Thread Context, we take the same frame than the one pushed on 	 * exceptions. This makes sense because Signal is a software 	 * exception.	 */	popl	edx	popl	ecx	popl	eax	pushl	$0	# fake fault code	pushl	$0	# fake exception number	pusha	pushl	esp	call	_ThreadProcessSignalsFromIrq	addl	$4, esp	popa	addl	$8, esp	iret			.schedule:	/*	 * the scratch registers have already been saved and we are already	 * back on the thread system stack. So we can call _Thread_Displatch 	 * directly	 */	call _Thread_Dispatch	/*	 * fall through exit to restore complete contex (scratch registers	 * eip, CS, Flags).	 */.exit:       /*        * BEGINNING OF DE-ESTABLISH SEGMENTS        *        *  NOTE:  Make sure there is code here if code is added to        *         load the segment registers.        *        */       /******* DE-ESTABLISH SEGMENTS CODE GOES HERE ********/       /*        * END OF DE-ESTABLISH SEGMENTS        */	popl	edx	popl	ecx	popl	eax	iret				#define DISTINCT_INTERRUPT_ENTRY(_vector) \        .p2align 4                         ; \        PUBLIC (rtems_irq_prologue_ ## _vector ) ; \SYM (rtems_irq_prologue_ ## _vector ):             \        pushl	eax		; \	pushl	ecx		; \	pushl	edx		; \	movl	$ _vector, ecx  ; \        jmp   SYM (_ISR_Handler) ;DISTINCT_INTERRUPT_ENTRY(0)DISTINCT_INTERRUPT_ENTRY(1)DISTINCT_INTERRUPT_ENTRY(2)DISTINCT_INTERRUPT_ENTRY(3)DISTINCT_INTERRUPT_ENTRY(4)DISTINCT_INTERRUPT_ENTRY(5)DISTINCT_INTERRUPT_ENTRY(6)DISTINCT_INTERRUPT_ENTRY(7)DISTINCT_INTERRUPT_ENTRY(8)DISTINCT_INTERRUPT_ENTRY(9)DISTINCT_INTERRUPT_ENTRY(10)DISTINCT_INTERRUPT_ENTRY(11)DISTINCT_INTERRUPT_ENTRY(12)DISTINCT_INTERRUPT_ENTRY(13)DISTINCT_INTERRUPT_ENTRY(14)DISTINCT_INTERRUPT_ENTRY(15)		/*	 * routine used to initialize the IDT by default	 */		PUBLIC (default_raw_idt_handler)PUBLIC (raw_idt_notify)		SYM (default_raw_idt_handler):	pusha	cld	call	raw_idt_notify	popa	iret	END_CODEEND

⌨️ 快捷键说明

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