207 lines
4.8 KiB
C
207 lines
4.8 KiB
C
/*
|
|
* ---------- header ----------------------------------------------------------
|
|
*
|
|
* project kaneton
|
|
*
|
|
* license kaneton
|
|
*
|
|
* file /home/mycure/kane...hine/architecture/ia32/educational/idt.c
|
|
*
|
|
* created renaud voltz [sun feb 12 02:02:19 2006]
|
|
* updated julien quintard [mon apr 11 13:44:56 2011]
|
|
*/
|
|
|
|
/*
|
|
* ---------- information -----------------------------------------------------
|
|
*
|
|
* this file provides functionalities for managing the IDT - Interrupt
|
|
* Descriptor Table.
|
|
*
|
|
* for more information regarding the handlers triggered through the IDT,
|
|
* please have a look at the handler.c file.
|
|
*/
|
|
|
|
/*
|
|
* ---------- includes --------------------------------------------------------
|
|
*/
|
|
|
|
#include <kaneton.h>
|
|
|
|
/*
|
|
* ---------- externs ---------------------------------------------------------
|
|
*/
|
|
|
|
/*
|
|
* the segment manager which contains the current IDT.
|
|
*/
|
|
|
|
extern m_segment _segment;
|
|
|
|
/*
|
|
* ---------- functions -------------------------------------------------------
|
|
*/
|
|
|
|
/* FIXME[complete if necessary] */
|
|
|
|
t_error architecture_idt_dump(void)
|
|
{
|
|
t_uint16 i;
|
|
|
|
module_call(console, message,
|
|
'#', "IDT: table(0x%08x) size(%u)\n",
|
|
_segment.machine.idt.table,
|
|
_segment.machine.idt.size);
|
|
|
|
for (i = 0; i < _segment.machine.idt.size; i++)
|
|
{
|
|
t_privilege privilege;
|
|
t_paddr offset;
|
|
char* type;
|
|
char flag;
|
|
|
|
if (!(_segment.machine.idt.table[i] & ARCHITECTURE_IDTE_PRESENT))
|
|
continue;
|
|
|
|
offset = ARCHITECTURE_IDTE_OFFSET_GET(_segment.machine.idt.table[i]);
|
|
|
|
privilege = ARCHITECTURE_IDTE_DPL_GET(_segment.machine.idt.table[i]);
|
|
|
|
if (_segment.machine.idt.table[i] & ARCHITECTURE_GDTE_32BIT)
|
|
flag = 's';
|
|
else
|
|
flag = '.';
|
|
|
|
if ((_segment.machine.idt.table[i] & ARCHITECTURE_IDTE_TRAP) == ARCHITECTURE_IDTE_TRAP)
|
|
type = "trap";
|
|
else if ((_segment.machine.idt.table[i] & ARCHITECTURE_IDTE_INTERRUPT) == ARCHITECTURE_IDTE_INTERRUPT)
|
|
type = "interrupt";
|
|
else
|
|
type = "task";
|
|
|
|
module_call(console, message,
|
|
'#', " %u: offset(0x%08x) type(%s) "
|
|
"privilege(%u) flags(%c)\n",
|
|
i, offset, type, privilege, flag);
|
|
}
|
|
|
|
MACHINE_LEAVE();
|
|
}
|
|
|
|
t_error architecture_idt_import(as_idt* idt)
|
|
{
|
|
as_idtr idtr;
|
|
|
|
if (idt == NULL)
|
|
MACHINE_ESCAPE("the 'idt' argument is null");
|
|
|
|
idtr.base = (t_paddr)idt->table;
|
|
idtr.limit = idt->size * sizeof (at_idte);
|
|
|
|
ARCHITECTURE_LIDT(idtr);
|
|
|
|
memcpy(&_segment.machine.idt, idt, sizeof (as_idt));
|
|
|
|
MACHINE_LEAVE();
|
|
}
|
|
|
|
t_error architecture_idt_export(as_idt* idt)
|
|
{
|
|
as_idtr idtr;
|
|
at_idte* source;
|
|
at_idte* dest;
|
|
|
|
if (idt == NULL)
|
|
MACHINE_ESCAPE("the 'idt' argument is null");
|
|
|
|
ARCHITECTURE_SIDT(idtr);
|
|
|
|
source = (at_idte*)idtr.base;
|
|
dest = idt->table;
|
|
|
|
memcpy(dest, source, idtr.limit);
|
|
|
|
idt->size = idtr.limit / sizeof (at_idte);
|
|
|
|
MACHINE_LEAVE();
|
|
}
|
|
|
|
t_error architecture_idt_insert(t_uint16 index,
|
|
t_paddr offset,
|
|
t_flags flags)
|
|
{
|
|
if (index >= _segment.machine.idt.size)
|
|
MACHINE_ESCAPE("out-of-bound insertion");
|
|
|
|
if (_segment.machine.idt.table[index] & ARCHITECTURE_IDTE_PRESENT)
|
|
MACHINE_ESCAPE("the IDT entry to update is already in use");
|
|
|
|
_segment.machine.idt.table[index] =
|
|
ARCHITECTURE_IDTE_INTERRUPT |
|
|
ARCHITECTURE_IDTE_PRESENT |
|
|
ARCHITECTURE_IDTE_OFFSET_SET(offset) |
|
|
ARCHITECTURE_IDTE_32BIT |
|
|
flags;
|
|
|
|
MACHINE_LEAVE();
|
|
}
|
|
|
|
t_error architecture_idt_reserve(t_paddr base,
|
|
t_flags flags,
|
|
t_uint16* index)
|
|
{
|
|
t_uint16 i;
|
|
|
|
if (index == NULL)
|
|
MACHINE_ESCAPE("the 'index' argument is null");
|
|
|
|
*index = 0;
|
|
|
|
for (i = 0; i < _segment.machine.idt.size; i++)
|
|
if (!(_segment.machine.idt.table[i] & ARCHITECTURE_IDTE_PRESENT))
|
|
{
|
|
*index = i;
|
|
|
|
break;
|
|
}
|
|
|
|
if (architecture_idt_insert(*index, base, flags) != ERROR_OK)
|
|
MACHINE_ESCAPE("unable to insert the segment in the IDT");
|
|
|
|
MACHINE_LEAVE();
|
|
}
|
|
|
|
t_error architecture_idt_delete(t_uint16 index)
|
|
{
|
|
if (index >= _segment.machine.idt.size)
|
|
MACHINE_ESCAPE("out-of-bound insertion");
|
|
|
|
if (!(_segment.machine.idt.table[index] & ARCHITECTURE_IDTE_PRESENT))
|
|
MACHINE_ESCAPE("the IDT entry to delete is not present");
|
|
|
|
memset(&_segment.machine.idt.table[index], 0x0, sizeof (at_idte));
|
|
|
|
MACHINE_LEAVE();
|
|
}
|
|
|
|
t_error architecture_idt_build(t_paddr base,
|
|
t_psize size,
|
|
as_idt* idt)
|
|
{
|
|
if (idt == NULL)
|
|
MACHINE_ESCAPE("the 'idt' argument is null");
|
|
|
|
if (size > (ARCHITECTURE_IDT_SIZE * sizeof (at_idte)))
|
|
MACHINE_ESCAPE("the given size is too large as exceeding the IDT's "
|
|
"theoretically maximum capacity");
|
|
|
|
if (base % sizeof (at_idte))
|
|
base += sizeof (at_idte) - (base % sizeof (at_idte));
|
|
|
|
idt->table = (at_idte*)base;
|
|
idt->size = size / sizeof (at_idte);
|
|
|
|
memset(idt->table, 0x0, idt->size * sizeof (at_idte));
|
|
|
|
MACHINE_LEAVE();
|
|
}
|