intel8259interruptcontroller.cc

来自「Murphy 大俠 GPL 的 C++/x86 RTOS, 支持 MMU, 用戶」· CC 代码 · 共 166 行

CC
166
字号
// File: Intel8259InterruptController.cc

/*
 * Copyright (c) 1998-1999 Murphy Cheng-Che Chen <murphychen@mail2000.com.tw>
 *
 *  This program 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 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
*/

/*
 1999/03/10: Created by Murphy Cheng-Che Chen
 1999/03/12: Murphy
	void Intel8259InterruptController::AcknowledgeIRQ(unsigned char nIRQ);
	Not only put 8259-related stuffs here, but also processor-related
		interrupt mechanism stuffs here.

*/



#include "Intel8259InterruptController.h"
#include "IO.h"
#include "proc_reg.h"
#include "LibC/assert/assert.h"



extern struct gate_init_entry *trap_inittab;



void Intel8259InterruptController::Initialize()
{
	/////////////////////// Initialize 8259-1. //////////////////////////

	// Init command 1: cascade and require 4th init BYTE
	outb_p(0x20, 0x11);

	// Init command 2: switch IRQ's to int 20h
	outb_p(0x21, 0x20);

	// Init command 3: slave controller on IRQ 2
	outb_p(0x21, 0x04);

	// Init command 4: normal EOI, nonbuffered, 80x86
	outb_p(0x21, 0x01);

	/////////////////////// Initialize 8259-2. //////////////////////////

	// Init command 1: cascade and require 4th init BYTE
	outb_p(0xA0, 0x11);

	// Init command 2: switch IRQ's to int 28h
	outb_p(0xA1, 0x28);

	// Init command 3: slave controller on IRQ 2
	outb_p(0xA1, 0x02);

	// Init command 4: normal EOI, nonbuffered, 80x86
	outb_p(0xA1, 0x01);

	// Acknowledge any bogus interrupts by setting the End Of Interrupt bit.
	outb_p(0x20, 0x20);
	outb_p(0xA0, 0x20);

	///////// Initialize the interrupt descriptor table for 386+ ///////
	m_IDT.Init();
	m_IDT.GateInit((struct gate_init_entry*)&trap_inittab);

	// Create a pseudo-descriptor describing the IDT.
	struct pseudo_descriptor pdesc;
	pdesc.limit = m_IDT.GetLimit();
	pdesc.linear_base = (DWORD)m_IDT.GetBase();

	// Load the IDT.
	set_idt(&pdesc);
}



void Intel8259InterruptController::EnableAll()
{
	outb(0x21, 0);
	outb(0xA1, 0);
}



void Intel8259InterruptController::DisableAll()
{
	outb(0x21, 0xFF);
	outb(0xA1, 0xFF);
}



// Enable the interrupt request nIRQ by clearing the appropriate bit in 8259.
void Intel8259InterruptController::EnableIRQ(unsigned char nIRQ)
{
	unsigned int flags;

	assert(nIRQ < 16);
	flags = get_eflags();
	cli();

	if (nIRQ < 8)
		outb(0x21, inb(0x21) & ~(1 << nIRQ));
	else {
		// Enable the cascade line on the master.
		outb(0x21, inb(0x21) & ~(1 << 2));

		nIRQ -= 8;
		outb(0xA1, inb(0xA1) & ~(1 << nIRQ));
	}

	set_eflags(flags);
}



// Disable the interrupt request nIRQ by setting the appropriate bit in 8259.
void Intel8259InterruptController::DisableIRQ(unsigned char nIRQ)
{
	unsigned int flags;

	assert(nIRQ < 16);
	flags = get_eflags();
	cli();

	if (nIRQ < 8)
		outb(0x21, inb(0x21) | (1 << nIRQ));
	else {
		nIRQ -= 8;
		outb(0xA1, inb(0xA1) | (1 << nIRQ));
	}

	set_eflags(flags);
}



void Intel8259InterruptController::AcknowledgeIRQ(unsigned char nIRQ)
{
	outb(0x20, 0x20);
	if ((nIRQ) >= 8)
		outb(0xA0, 0x20);
}


void Intel8259InterruptController::HookIRQ(WORD nIRQ, void *pEntryFunction)
{
	m_IDT.SetIDT(nIRQ, (DWORD)pEntryFunction, ACC_PL_K | ACC_INTR_GATE);
}

⌨️ 快捷键说明

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