Beispiel #1
0
/* We first remap the interrupt controllers, and then we install
*  the appropriate ISRs to the correct entries in the IDT. This
*  is just like installing the exception handlers */
void irq::init()
{
	debug_bochs_printf( "irq_install... " );

    irq_remap();

	int sel = 0x08;

    idt::set_gate(32, (unsigned)irq0, sel, 0x8E);
    idt::set_gate(33, (unsigned)irq1, sel, 0x8E);
    idt::set_gate(34, (unsigned)irq2, sel, 0x8E);
    idt::set_gate(35, (unsigned)irq3, sel, 0x8E);
    idt::set_gate(36, (unsigned)irq4, sel, 0x8E);
    idt::set_gate(37, (unsigned)irq5, sel, 0x8E);
    idt::set_gate(38, (unsigned)irq6, sel, 0x8E);
    idt::set_gate(39, (unsigned)irq7, sel, 0x8E);

    idt::set_gate(40, (unsigned)irq8, sel, 0x8E);
    idt::set_gate(41, (unsigned)irq9, sel, 0x8E);
    idt::set_gate(42, (unsigned)irq10, sel, 0x8E);
    idt::set_gate(43, (unsigned)irq11, sel, 0x8E);
    idt::set_gate(44, (unsigned)irq12, sel, 0x8E);
    idt::set_gate(45, (unsigned)irq13, sel, 0x8E);
    idt::set_gate(46, (unsigned)irq14, sel, 0x8E);
    idt::set_gate(47, (unsigned)irq15, sel, 0x8E);

	debug_bochs_printf( "done\n" );
}
Beispiel #2
0
/* Installs the IDT */
void idt::init()
{
	debug_bochs_printf( "idt::init..." );

	struct idt_ptr idtp =
	{
	    (sizeof s_idt) - 1,
		s_idt
	};

	debug_bochs_printf( "Installing IDT from ptr %x, base = %x\n", &idtp, idtp.base );
    idt_load( &idtp );
}
Beispiel #3
0
/* Each of the IRQ ISRs point to this function, rather than
*  the 'fault_handler' in 'isrs.c'. The IRQ Controllers need
*  to be told when you are done servicing them, so you need
*  to send them an "End of Interrupt" command (0x20). There
*  are two 8259 chips: The first exists at 0x20, the second
*  exists at 0xA0. If the second controller (an IRQ from 8 to
*  15) gets an interrupt, you need to acknowledge the
*  interrupt at BOTH controllers, otherwise, you only send
*  an EOI command to the first controller. If you don't send
*  an EOI, you won't raise any more IRQs */
extern "C" struct cpu_state* irq_handler( struct cpu_state *r )
{
    /* Find out if we have a custom handler to run for this
    *  IRQ, and then finally, run it */
    irq::handler_proc handler = irq_routines[r->int_no - 32];
    if (handler)
    {
        r = handler(r);
    }
	else
	{
		debug_bochs_printf( "No handler registered for IRQ %x\n", r->int_no - 32 );
	}

    /* If the IDT entry that was invoked was greater than 40
    *  (meaning IRQ8 - 15), then we need to send an EOI to
    *  the slave controller */
    if (r->int_no >= 40)
    {
        outportb(0xA0, 0x20);
    }

    /* In either case, we need to send an EOI to the master
    *  interrupt controller too */
    outportb(0x20, 0x20);	

	return r;
}
Beispiel #4
0
void mm::physical::init( const multiboot_info* mbt, uintptr_t kernel_static_end, uintptr_t kernel_dynamic_end, uintptr_t himem_end )
{
	if( !himem_end )
	{
		PANIC( "NO MEMORY FOUND!\n" );
	}
	
	size_t dma_pool_size = (DMA_MEMORY_LIMIT < kernel_dynamic_end) ? DMA_MEMORY_LIMIT : kernel_dynamic_end;	
	size_t default_pool_size = kernel_dynamic_end - dma_pool_size;
	size_t himem_pool_size = himem_end - kernel_dynamic_end;

	size_t dma_pool_pages = dma_pool_size / PAGE_SIZE;
	size_t default_pool_pages = default_pool_size / PAGE_SIZE;
	size_t himem_pool_pages = himem_pool_size / PAGE_SIZE;

	int* dma_pool_bitmap = linear_alloc<int>( dma_pool_pages * sizeof(int), 16, &kernel_static_end );
	int* default_pool_bitmap = linear_alloc<int>( default_pool_pages * sizeof(int), 16, &kernel_static_end );
	int* himem_pool_bitmap = linear_alloc<int>( himem_pool_pages * sizeof(int), 16, &kernel_static_end );

	uintptr_t dma_pool_start = 0;
	uintptr_t default_pool_start = dma_pool_start + dma_pool_size;
	uintptr_t himem_pool_start = default_pool_start + default_pool_size;

	DMAPool.init( dma_pool_start, dma_pool_pages, dma_pool_bitmap );
	DefaultPool.init( default_pool_start, default_pool_pages, default_pool_bitmap );
	HiMemPool.init( himem_pool_start, himem_pool_pages, himem_pool_bitmap );

	debug_bochs_printf( "Physical memory layout:\n" );
	debug_bochs_printf( "  DMA memory     %x-%x\n", DMAPool.base(), DMAPool.limit() );
	debug_bochs_printf( "  Default memory %x-%x\n", DefaultPool.base(), DefaultPool.limit() );
	debug_bochs_printf( "  High memory    %x-%x\n", HiMemPool.base(), HiMemPool.limit() );

	multiboot::iterate_mmap( mbt,
		[](const multiboot_mmap_entry* mmap)
		{
			if( !(mmap->type & MULTIBOOT_MEMORY_AVAILABLE) )
			{
				//console.printf( "Found reserved memory %lx - %lx\n", mmap->addr, mmap->addr + mmap->len );
				reserve_range( mmap->addr, mmap->len );
			}
		}
	);

	// Reserve kernel code + pmem bitmaps (added above to kernel_static_end)
	reserve_range( 0, kernel_static_end );
}
Beispiel #5
0
uintptr_t	mm::physical::alloc_himem(unsigned int pages, unsigned int align)
{
	auto p = HiMemPool.alloc(pages, align);

	if( !p )
		debug_bochs_printf( "mm::physical::alloc_himem: OUT OF MEMORY\n" );

	return p;
}
Beispiel #6
0
/* This is a very repetitive function... it's not hard, it's
*  just annoying. As you can see, we set the first 32 entries
*  in the IDT to the first 32 ISRs. We can't use a for loop
*  for this, because there is no way to get the function names
*  that correspond to that given entry. We set the access
*  flags to 0x8E. This means that the entry is present, is
*  running in ring 0 (kernel level), and has the lower 5 bits
*  set to the required '14', which is represented by 'E' in
*  hex. */
void isr::init()
{
    debug_bochs_printf( "isrs_install... " );

    int sel = 0x08;

    idt::set_gate(0, (unsigned)isr0, sel, 0x8E);
    idt::set_gate(1, (unsigned)isr1, sel, 0x8E);
    idt::set_gate(2, (unsigned)isr2, sel, 0x8E);
    idt::set_gate(3, (unsigned)isr3, sel, 0x8E);
    idt::set_gate(4, (unsigned)isr4, sel, 0x8E);
    idt::set_gate(5, (unsigned)isr5, sel, 0x8E);
    idt::set_gate(6, (unsigned)isr6, sel, 0x8E);
    idt::set_gate(7, (unsigned)isr7, sel, 0x8E);

    idt::set_gate(8, (unsigned)isr8, sel, 0x8E);
    idt::set_gate(9, (unsigned)isr9, sel, 0x8E);
    idt::set_gate(10, (unsigned)isr10, sel, 0x8E);
    idt::set_gate(11, (unsigned)isr11, sel, 0x8E);
    idt::set_gate(12, (unsigned)isr12, sel, 0x8E);
    idt::set_gate(13, (unsigned)isr13, sel, 0x8E);
    idt::set_gate(14, (unsigned)isr14, sel, 0x8E);
    idt::set_gate(15, (unsigned)isr15, sel, 0x8E);

    idt::set_gate(16, (unsigned)isr16, sel, 0x8E);
    idt::set_gate(17, (unsigned)isr17, sel, 0x8E);
    idt::set_gate(18, (unsigned)isr18, sel, 0x8E);
    idt::set_gate(19, (unsigned)isr19, sel, 0x8E);
    idt::set_gate(20, (unsigned)isr20, sel, 0x8E);
    idt::set_gate(21, (unsigned)isr21, sel, 0x8E);
    idt::set_gate(22, (unsigned)isr22, sel, 0x8E);
    idt::set_gate(23, (unsigned)isr23, sel, 0x8E);

    idt::set_gate(24, (unsigned)isr24, sel, 0x8E);
    idt::set_gate(25, (unsigned)isr25, sel, 0x8E);
    idt::set_gate(26, (unsigned)isr26, sel, 0x8E);
    idt::set_gate(27, (unsigned)isr27, sel, 0x8E);
    idt::set_gate(28, (unsigned)isr28, sel, 0x8E);
    idt::set_gate(29, (unsigned)isr29, sel, 0x8E);
    idt::set_gate(30, (unsigned)isr30, sel, 0x8E);
    idt::set_gate(31, (unsigned)isr31, sel, 0x8E);

    debug_bochs_printf( "done\n" );
}
Beispiel #7
0
cpu_state* syscall_handler( cpu_state* s )
{
	switch( (syscall::ID)s->eax )
	{
	case syscall::ID::Yield:
		return scheduler::task_yield( s );
	default:
		debug_bochs_printf( "syscall(%d)\n", s->eax );
		return s;
	}		
}
Beispiel #8
0
/* All of our Exception handling Interrupt Service Routines will
*  point to this function. This will tell us what exception has
*  happened! Right now, we simply halt the system by hitting an
*  endless loop. All ISRs disable interrupts while they are being
*  serviced as a 'locking' mechanism to prevent an IRQ from
*  happening and messing up kernel data structures */
extern "C" void fault_handler(struct cpu_state *r)
{
    if (r->int_no < 32)
    {
        bool handled = false;

        switch( r->int_no )
        {
        case 14: // Page fault
            handled = paging_handle_fault( r, read_cr2() );
            break;
        default:
            debug_bochs_printf( "EXCEPTION!" );
            debug_bochs_printf( " (%x) (err_code = %x)\n", r->int_no, r->err_code );
            debug_bochs_printf( "%s Exception\n", exception_messages[r->int_no] );
            break;
        }

        if( !handled )
        {
            debug_bochs_printf( "\nRegister dump:\n" );

            /*
            unsigned int gs, fs, es, ds;
            unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax;
            unsigned int int_no, err_code;
            unsigned int eip, cs, eflags, useresp, ss;
            */
            debug_bochs_printf( "EAX = %x EBX = %x ECX = %x EDX = %x\n", r->eax, r->ebx, r->ecx, r->edx );
            debug_bochs_printf( "ESP = %x EBP = %x ESI = %x EDI = %x\n", r->esp, r->ebp, r->esi, r->edi );
            debug_bochs_printf( "GS  = %x FS  = %x ES  = %x DS  = %x\n", r->gs, r->fs, r->es, r->ds );
            debug_bochs_printf( "EIP = %x CS  = %x EFLAGS = %x SS = %x\n", r->eip, r->cs, r->eflags, r->ss );

            debug_bochs_printf( "System Halted!\n" );


            for (;;);
        }
    }
}
Beispiel #9
0
/* Installs the keyboard handler into IRQ1 */
void keyboard::init( void )
{
	debug_bochs_printf( "keyboard_install..." );
    irq::install_handler(1, keyboard_handler);
	debug_bochs_printf( "done\n" );
}
Beispiel #10
0
/* Handles the keyboard interrupt */
struct cpu_state* keyboard_handler(struct cpu_state *r)
{
    unsigned char scancode;

    /* Read from the keyboard's data buffer */
    scancode = inportb(0x60);

    /* If the top bit of the byte we read from the keyboard is
    *  set, that means that a key has just been released */
    if (scancode & 0x80)
    {
		scancode &= ~0x80;

        /* You can use this one to see if the user released the
        *  shift, alt, or control keys... */
		if(scancode == 0x2a || scancode == 0x36)
			shift = false;
    }
    else
    {
        /* Here, a key was just pressed. Please note that if you
        *  hold a key down, you will get repeated key press
        *  interrupts. */

		//2a = left shift
		//3a = capslock
		//36 = right shift
		if(scancode == 0x2a || scancode == 0x36)
			shift = true;

        /* Just to show you how this works, we simply translate
        *  the keyboard scancode into an ASCII value, and then
        *  display it to the screen. You can get creative and
        *  use some flags to see if a shift is pressed and use a
        *  different layout, or you can add another 128 entries
        *  to the above layout to correspond to 'shift' being
        *  held. If shift is held using the larger lookup table,
        *  you would add 128 to the scancode when you look for it */
        
		//The LEDs and the lockflags...
		handle_lock_flags(scancode);
		handle_kbdleds();

		
		debug_bochs_printf( "%d", scancode );


		if(kbdus[scancode] != 0)
		{
			if(!shift)
			{
				console.printf( "%c", kbdger[scancode] );
			}
			else
			{
				console.printf( "%c", kbdger_upper[scancode] );
			}
		}
    }

	return r;
}