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

📄 tp4_isr.c

📁 小型操作系统,以VC为开发环境,需要boachs调试
💻 C
字号:
/***************************************************************************
**     File name   : tp4_isr.c
**     Author      : x.cheng
**     Create date :
**
**	   Comment:
**        Interrupt manager...
**
**     Revisions:
**     $Log: tp4_isr.c,v $
**     Revision 1.1  2005/08/04 08:32:13  x.cheng
**     add into repositories
**
**
***************************************************************************/
#include "const.h"
#include "type.h"
#include "stdarg.h"

#include "..\..\Inc\i386\system.h"
#include "..\..\Inc\i386\io.h"
#include "..\..\Inc\i386\x86.h"
#include "..\..\Inc\i386\interrupt.h"
#include "..\..\Inc\pmm.h"
#include "..\..\Inc\tui.h"
#include "..\..\Inc\debug.h"

/* debug preprocessor instrument
	#ifdef _DEBUG_ISR__
				
	#endif
***************************/

/************local function prototype**************/
static inline void Tp4EnableIrq( unsigned char ucIrq );
static inline void Tp4DisableIrq( unsigned char ucIrq );
static inline void Tp4MaskAndAckIrq( unsigned char ucIrq );
static inline void Tp4EndOfIrq( unsigned char ucIrq );
static void Tp4UnhandleInterrupt( ts_IrqContext* pstContext );
static inline void Tp4IsrDumpRegisters( ts_IrqContext* pstContext );


/***************global variable*******************/
	//the PIC irq mask
static unsigned short g_uiIrqMask = 0xffff;
	// The PIC irq mask for the master controller.
#define g_ucIrqMasterMask		( ((unsigned char *)&(g_uiIrqMask))[0] )
	// The PIC irq mask for the slave controller.
#define g_ucIrqSlaveMask		( ((unsigned char *)&(g_uiIrqMask))[1] )

	// A table for hardware interrupt handlers only.
static ts_InterruptHandler g_astIrqHandler[ HW_IRQ_NR ] __attribute__ ((aligned(16))) =
{
	[ 0 ... HW_IRQ_NR-1 ] = { .fpIrqHandler = Tp4UnhandleInterrupt  }
};

/****************extern variable*******************/
	// in file tp2_interrupt.asm
//extern void irq_Timer, irq_Keyb, irq_Com2, irq_Com1, irq_Lpt2, irq_Floppy, irq_Lpt1;
//extern void irq_Rtc, irq_PicMaster, irq_Reserved1, irq_Reserved2, irq_Ps2, irq_80x87, irq_IdeChn0, irq_IdeChn1;
//extern void irq_Unhandled;

extern void irq_Timer, irq_Keyb, irq_Com2, irq_Com1, irq_Lpt2, irq_Floppy, irq_Lpt1;
extern void irq_Rtc, irq_PicMaster, irq_Reserved1, irq_Reserved2, irq_Ps2, irq_80x87, irq_IdeChn0, irq_IdeChn1;
extern void irq_Unhandled;


/************************************************************
*************************************************************
**      Function Name:			DefaultInterruptHandler
**      Author:                 x.cheng
**
**      Comment:
**			This is the default interrupt handler. It is invoked
**	  	  every time an interrupt occurs.
**			Send the end of interrupt to the PICs.
**
**      List of parameters:
**			pstContext - The context of the current task after the interrupt.
**
**      Return value:   
**          no
**
**      Revisions:
**
*************************************************************
*************************************************************/
void DefaultInterruptHandler(ts_IrqContext * pstContext)
{
	Tp4MaskAndAckIrq( pstContext->ulIrqNb );

//	Tp4IsrDumpRegisters( pstContext );	
	if ( (pstContext->ulIrqNb-HW_PIC_INTR_START) < HW_IRQ_NR ) {
		g_astIrqHandler[ pstContext->ulIrqNb - HW_PIC_INTR_START ].fpIrqHandler( pstContext );
		//PANIC();
	} else {
		Tp4UnhandleInterrupt( pstContext );
	}

	Tp4EndOfIrq( pstContext->ulIrqNb );
	vDbgDummy();
//	if ( pstContext->ulIrqNb != HWM_TIMER_IRQ0)
//		Tp4IsrDumpRegisters( pstContext );	
//	PANIC();
}

/************************************************************
*************************************************************
**      Function Name:			Tp4IsrInitialize
**      Author:                 x.cheng
**
**      Comment:
**
**
**      List of parameters:
**			no
**
**      Return value:   
**          no
**
**      Revisions:
**
*************************************************************
*************************************************************/
void Tp4IsrInitialize(void)
{
	unsigned int iCnt;

	for (iCnt=0x20; iCnt<0xFF; iCnt++)
		vSetIntrGate(iCnt, &irq_Unhandled);

	vSetIntrGate( HWM_TIMER_IRQ0, &irq_Timer );
	vSetTrapGate( HWM_KEYB_IRQ1, &irq_Keyb );
	
	//vSetTrapGate( , & );
	vSetTrapGate( HWM_COM2_IRQ3, &irq_Com2 );
	vSetTrapGate( HWM_COM1_IRQ4, &irq_Com1 );
	vSetTrapGate( HWM_LPT2_IRQ5, &irq_Lpt2 );
	vSetTrapGate( HWM_FLOPPY_IRQ6, &irq_Floppy );
	vSetTrapGate( HWM_LPT1_IRQ7, &irq_Lpt1 );

	vSetTrapGate( HWM_RTC_IRQ8, &irq_Rtc );
	vSetTrapGate( HWM_PICMASTER_IRQ9, &irq_PicMaster );
	vSetTrapGate( HWM_RESERVED_IRQa, &irq_Reserved1 );
	vSetTrapGate( HWM_RESERVED_IRQb, &irq_Reserved2 );
	vSetTrapGate( HWM_PS2_IRQc, &irq_Ps2 );
	vSetTrapGate( HWM_80x87_IRQd, &irq_80x87 );

	vSetIntrGate( HWM_IDE_CHN0_IRQe, &irq_IdeChn0 );
	vSetIntrGate( HWM_IDE_CHN1_IRQf, &irq_IdeChn1 );
	
}

/************************************************************
*************************************************************
**      Function Name:			Tp4IsrInstallHandler
**      Author:                 x.cheng
**
**      Comment:
**			Install an IRQ handler routine.
**
**			This is valid only for hardware interrupts. You cannot
**		  install a software interrupt handler in this way.
**
**      List of parameters:
**			no
**
**      Return value:   
**          no
**
**      Revisions:
**
*************************************************************
*************************************************************/
void Tp4IsrInstallHandler( unsigned char ucIrq, void *pvHandler )
{
	unsigned long ulFlags;

	if ( (ucIrq - HW_PIC_INTR_START) > HW_IRQ_NR )
		return;

	SaveEflagsAndCli( ulFlags );
	
	g_astIrqHandler[ ucIrq - HW_PIC_INTR_START ].fpIrqHandler = pvHandler;

	RestoreEflags( ulFlags );	//和下面得Tp4EnableIrq的顺序颠倒是不行的!

#ifdef _DEBUG_ISR__
	POSITION();
	vDbgDummy();
#endif
	Tp4EnableIrq( ucIrq );

	return;
}



//----------------------------------------------------------------------------------
//==============================local function======================================
//----------------------------------------------------------------------------------



/************************************************************
*************************************************************
**      Function Name:			Tp4EnableIrq
**      Author:                 x.cheng
**
**      Comment:
**			Enable an IRQ line.
**		  如果要enable从片控制的中断的话,先要enable主片的
**		  irq2.
**
**      List of parameters:
**			ucIrq - The IRQ line to enable.
**
**      Return value:   
**          no
**
**      Revisions:
**
*************************************************************
*************************************************************/
static inline void Tp4EnableIrq( unsigned char ucIrq )
{
	unsigned short uiMask = ~(1 << (ucIrq -= HW_PIC_INTR_START));
	unsigned long ulFlags;

	if ( ucIrq & 0x08 )		// 主片的HWM_SLAVE_IRQ2是控制从片的
		uiMask &= ~0x04;
	SaveEflagsAndCli(ulFlags);

	g_uiIrqMask &= uiMask;

#ifdef _DEBUG_ISR__
	POSITION();
	kprintf("ucIrq= %d, uiMask= %d, g_uiIrqMask= %d\n", ucIrq, uiMask, g_uiIrqMask);
	kprintf("gucIrqSlaveMask= %d, g_ucIrqMasterMask= %d\n", g_ucIrqSlaveMask, g_ucIrqMasterMask);
#endif
	if ( ucIrq & 0x8 ) {				//( ((unsigned char *)&(g_uiIrqMask))[0] )
		vOutPort( PORT_8259A_MINOR+1, g_ucIrqSlaveMask );
	} else {
		vOutPort( PORT_8259A_MAJOR+1, g_ucIrqMasterMask );
	}

	RestoreEflags(ulFlags);
}

/************************************************************
*************************************************************
**      Function Name:			Tp4DisableIrq
**      Author:                 x.cheng
**
**      Comment:
**			Disable an IRQ line.
**
**      List of parameters:
**			ucIrq - The IRQ line to enable.
**
**      Return value:   
**          no
**
**      Revisions:
**
*************************************************************
*************************************************************/
static inline void Tp4DisableIrq( unsigned char ucIrq )
{
	unsigned short uiMask = 1 << (ucIrq -= HW_PIC_INTR_START);
	unsigned long ulFlags;

	SaveEflagsAndCli(ulFlags);

	g_uiIrqMask |= uiMask;
	if ( ucIrq & 0x8 ) {
		vOutPort( PORT_8259A_MINOR+1, g_ucIrqSlaveMask );
	} else {
		vOutPort( PORT_8259A_MAJOR+1, g_ucIrqMasterMask );
	}

	RestoreEflags(ulFlags);

}

/************************************************************
*************************************************************
**      Function Name:			Tp4EndOfIrq
**      Author:                 x.cheng
**
**      Comment:
**			
**
**      List of parameters:
**			ucIrq - The IRQ line to enable.
**
**      Return value:   
**          no
**
**      Revisions:
**
*************************************************************
*************************************************************/
static inline void Tp4EndOfIrq(unsigned char ucIrq)
{
	// Simply re-enable the irq line.
	Tp4EnableIrq( ucIrq );
}

/************************************************************
*************************************************************
**      Function Name:			Tp4MaskAndAckIrq
**      Author:                 x.cheng
**
**      Comment:
**			Acknowledge the irq line.		
**
**      List of parameters:
**			ucIrq - The IRQ line to enable.
**
**      Return value:   
**          no
**
**      Revisions:
**
*************************************************************
*************************************************************/
static inline void Tp4MaskAndAckIrq( unsigned char ucIrq )
{
	unsigned short uiMask = 1 << (ucIrq -= HW_PIC_INTR_START);
	unsigned long ulFlags;

	SaveEflagsAndCli(ulFlags);

	g_uiIrqMask |= uiMask;

#ifdef _DEBUG_ISR__
	POSITION();
	kprintf("\nucIrq= %d, uiMask= %d, g_uiIrqMask= %d\n", ucIrq, uiMask, g_uiIrqMask);
	kprintf("gucIrqSlaveMask= %d, g_ucIrqMasterMask= %d\n", g_ucIrqSlaveMask, g_ucIrqMasterMask);
#endif 

	if ( ucIrq & 0x8)	{
		// Dummy operation (but required).
		(void)ucInPort( PORT_8259A_MINOR+1 );

		// Mask the irq on the slave.
		vOutPort( PORT_8259A_MINOR+1, g_ucIrqSlaveMask );

		// Acknowledge the irq sending a EOI.
		vOutPort( PORT_8259A_MINOR, EOI );
		vOutPort( PORT_8259A_MAJOR, EOI );
	}
	else
	{
		// Dummy operation (but required).
		(void)ucInPort( PORT_8259A_MAJOR+1 );

		// Mask the irq on the master.
		vOutPort( PORT_8259A_MAJOR+1, g_ucIrqMasterMask );

		// Acknowledge the irq sending a EOI.
		vOutPort( PORT_8259A_MAJOR, EOI );
	}

	RestoreEflags(ulFlags);

}

/************************************************************
*************************************************************
**      Function Name:			Tp4UnhandleInterrupt
**      Author:                 x.cheng
**
**      Comment:
**			Manage an unhandled interrupt..		
**
**      List of parameters:
**			ucIrq - The IRQ line to enable.
**
**      Return value:   
**          no
**
**      Revisions:
**
*************************************************************
*************************************************************/
static void Tp4UnhandleInterrupt( ts_IrqContext* pstContext )
{
	kprintf("%s():   unexpected IRQ number %ld!\n", __FUNCTION__, pstContext->ulIrqNb);
}

/************************************************************
*************************************************************
**      Function Name:			Tp4IsrDumpRegisters
**      Author:                 x.cheng
**
**      Comment:
**			Dump the CPU registers.
**
**      List of parameters:
**			pstContext - The context of the current task after an exception.
**
**      Return value:   
**          no
**
**      Revisions:
**
*************************************************************
*************************************************************/
static inline void Tp4IsrDumpRegisters( ts_IrqContext* pstContext )
{
	register unsigned short uiSs;
	register unsigned long ulCr0, ulCr2, ulCr3, ulCr4;
	register unsigned short uiFs, uiGs;

	// Save stack segment register.
	__asm__ __volatile__ ("movw %%ss, %0" : "=&r"(uiSs) : );

	// Save %fs and %gs registers.
	__asm__ __volatile__ ("movw %%fs, %0" : "=m"(uiFs) :);
	__asm__ __volatile__ ("movw %%gs, %0" : "=m"(uiGs) :);

	// Save control registers.
	__asm__ __volatile__ ("movl %%cr0, %0" : "=&r"(ulCr0) : );
	__asm__ __volatile__ ("movl %%cr2, %0" : "=&r"(ulCr2) : );
	__asm__ __volatile__ ("movl %%cr3, %0" : "=&r"(ulCr3) : );
	__asm__ __volatile__ ("movl %%cr2, %0" : "=&r"(ulCr4) : );

	// Dump registers.
	kprintf("\neax = %#010x  ds = %#010x  cr0 = %#010x  esp    = %#010x", pstContext->ulEax, (unsigned short)(pstContext->ulDs), ulCr0, pstContext);
	kprintf("\nebx = %#010x  es = %#010x  cr2 = %#010x  ebp    = %#010x", pstContext->ulEbx, (unsigned short)(pstContext->ulEs), ulCr2, pstContext->ulEbp);
	kprintf("\necx = %#010x  fs = %#010x  cr3 = %#010x  eip    = %#010x", pstContext->ulEcx, (unsigned short)(uiFs), ulCr3, pstContext->ulEip);
	kprintf("\nedx = %#010x  gs = %#010x  cr4 = %#010x  eflags = %#010x", pstContext->ulEdx, (unsigned short)(uiGs), ulCr4, pstContext->ulEflags);
	kprintf("\nesi = %#010x  ss = %#010x  irq = %#010x", pstContext->ulEsi, (unsigned short)(uiSs), pstContext->ulIrqNb);
	kprintf("\nedi = %#010x  cs = %#010x\n", pstContext->ulEdi, (unsigned short)(pstContext->ulCs) );
}

⌨️ 快捷键说明

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