#include "clib.h"
#include "i386.h"
#include "phmem.h"
#include "systab.h"
#define IS_NULL_DESCRIPTOR(d) ((d).access.system.type == 0)
#define MARK_USED_DESCRIPTOR(d) ((d).access.system.type = 1)
#define MARK_FREE_DESCRIPTOR(d) ((d).access.system.type = 0)
static inline void
lidt (lidt_t *p)
{
asm volatile ("lidt %0" : : "m" (*p));
}
/*
static inline void
sidt (lidt_t *p)
{
asm volatile ("sidt %0" : "=m" (*p) : : "memory");
} */
static inline void
lgdt (lgdt_t *p)
{
asm volatile ("lgdt %0" : : "m" (*p));
}
static inline void
sgdt (lgdt_t *p)
{
asm volatile ("sgdt %0" : "=m"(*p) : : "memory");
}
/*
* gdt :
*
*1 000: NULL
*2 008: VCPI reserved
*3 010: VCPI reserved
*4 018: VCPI reserved
*5 020: 16 bit code (L64K, R+, C-)
*6 028: 16 bit data (64K, W+)
*7 030: 16 bit stub (255, W+)
*8 038: 32 bit kernel data (4G, W+, B+)
*9 040: 32 bit kernel code (4G, R+, C-)
*A 048: temp TSS
*B 050:
*C 058:
*D 060:
*E 068:
*F 070:
*/
descriptor_t *_gdt;
gate_t *_idt;
systable_t gdt_table;
systable_t idt_table;
static descriptor_t gdt[MAX_GDT_DESC];
static gate_t idt[MAX_GDT_DESC];
/*
* [23/09/97] la gdt e la idt vengono ora allocate in modo statico
*/
void systab_setup()
{
lgdt_t gdti;
lidt_t idti;
DEBUG_TRACE;
_gdt = &gdt[0];
memset(_gdt, 0, MAX_GDT_DESC*sizeof(descriptor_t));
// imposta la nuova gdt
sgdt(&gdti);
memcpy(_gdt, (void*) gdti.address, gdti.limit + 1);
gdti.limit = (sizeof(*_gdt) * MAX_GDT_DESC) - 1;
gdti.address = _gdt;
lgdt(&gdti);
// imposta nuova idt
_idt = &idt[0];
idti.limit = (sizeof(*_idt) * MAX_IDT_DESC) - 1;
idti.address = _idt;
lidt(&idti);
gdt_table.table = _gdt;
gdt_table.alloc_start = GDT_ALLOC_START;
gdt_table.alloc_end = MAX_GDT_DESC - 1;
idt_table.table = (descriptor_t*)_idt;
idt_table.alloc_start = 0;
idt_table.alloc_end = MAX_IDT_DESC - 1;
DEBUG_VERBOSE("gdt %xh idt %xh\n", gdti.address, idti.address);
}
int alloc_descriptors(systable_t *t, int num)
{
int nn = num;
int i;
for (i = t->alloc_start; i <= t->alloc_end; i++) {
if (IS_NULL_DESCRIPTOR(t->table[i])) {
if (--nn == 0) {
int j;
for (j = 0; j < num; j++) {
MARK_USED_DESCRIPTOR(t->table[i-j]);
}
return i - j;
}
} else nn = num;
}
return ENOMEM;
}
int alloc_descriptor(systable_t *t)
{
int i;
for (i = t->alloc_start; i <= t->alloc_end; i++) {
if (IS_NULL_DESCRIPTOR(t->table[i])) {
MARK_USED_DESCRIPTOR(t->table[i]);
return i;
};
}
return ENOMEM;
}
int free_descriptors(systable_t *t, int num, int count)
{
int i;
if (num+count > t->alloc_end) return EINVAL;
for (i = 0; i < count; i++) {
MARK_FREE_DESCRIPTOR(t->table[num+i]);
}
return 0;
}
int set_descriptor(systable_t *t, int numd, descriptor_t* d)
{
if (numd < t->alloc_end && d) t->table[numd] = *d;
else return EINVAL;
return 0;
}
int get_descriptor(systable_t *t, int numd, descriptor_t* d)
{
if (numd < t->alloc_end && d) *d = t->table[numd];
else return EINVAL;
return 0;
}