www.pudn.com > COS0.0.1.rar > idt.c


/*
 idt.c - code to set up idt
  
 Author:        Paul Barker
 Part of:       COS
 Created:       15/04/04
 Last Modified: 06/10/04

 Copyright (C) 2004 Paul Barker
    
    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., 675 Mass Ave, Cambridge, MA 02139, USA.

                     (See file "Copying")

	Some code has been included from GeekOS, see "COPYING-GEEKOS"
*/

#include 

#include 
#include 
#include 
#include 
#include 
#include 

// the default IDT is 2k in size

// imports from int.s
extern char g_entryPointTableStart, g_entryPointTableEnd;
extern int g_handlerSizeNoErr, g_handlerSizeErr;

// interrupts must be disabled when calling this
void low_install_handler(idt_entry_t* desc, u32_t addr)
{
	desc->ig.offsetLow = addr & 0xffff;
	desc->ig.segmentSelector = KERNEL_CS;
	desc->ig.reserved = 0;
	desc->ig.signature = 0x70; // == 01110000b
	desc->ig.dpl = 0;
	desc->ig.present = 1;
	desc->ig.offsetHigh = addr >> 16;
}

// initialise the idt
void idt_init()
{
	TRACE(("idt_init()\n"));
	word_t limitAndBase[3];
	count_t i = 0;
	idt_entry_t* the_idt = (idt_entry_t*) (sysinfo->interrupts->idt);

	// Blank out the IDT page before we start
	memset((ptr_t)the_idt, 0, 4096);

	u32_t addr = (ulong_t) &g_entryPointTableStart;
	// load dummy interrupt handlers
	while (i < IDT_NENTRIES)
	{
		low_install_handler(&(the_idt[i++]), addr);
		addr += g_handlerSizeNoErr;
	}

	addr = (u32_t)the_idt;
	
	// Cruft together a 16 bit limit and 32 bit base address
	// to load into the IDTR.
	limitAndBase[0] = IDT_NENTRIES << 3;
	limitAndBase[1] = addr & 0xffff;
	limitAndBase[2] = addr >> 16;

	// Install the new table in the IDTR.
	lidtr(limitAndBase);
	
	TRACE(("idt_init() done\n"));
}

// public function to install an interrupt handler,
//  interrupts must be disabled?
void install_handler(u8_t i, interrupt_handler_t hand)
{
	TRACE(("Installing handler for int %d,\n", i));
	TRACE(("\tat 0x%x\n", hand));
	sysinfo->interrupts->handlers[i] = hand;
}