diff options
author | Alex AUVOLAT <alex.auvolat@ens.fr> | 2014-03-28 09:10:23 +0100 |
---|---|---|
committer | Alex AUVOLAT <alex.auvolat@ens.fr> | 2014-03-28 09:10:23 +0100 |
commit | bb55beef914e7488350ad1d0419d4bc60ad63c99 (patch) | |
tree | b1cfe0e5c76cbca16e7e3c16e108c23e366a2902 /sos-code-article3/hwcore | |
download | SOS-bb55beef914e7488350ad1d0419d4bc60ad63c99.tar.gz SOS-bb55beef914e7488350ad1d0419d4bc60ad63c99.zip |
Import code for article1, 2, 3, 4
Diffstat (limited to 'sos-code-article3/hwcore')
-rw-r--r-- | sos-code-article3/hwcore/exception.c | 92 | ||||
-rw-r--r-- | sos-code-article3/hwcore/exception.h | 80 | ||||
-rw-r--r-- | sos-code-article3/hwcore/exception_wrappers.S | 197 | ||||
-rw-r--r-- | sos-code-article3/hwcore/gdt.c | 150 | ||||
-rw-r--r-- | sos-code-article3/hwcore/gdt.h | 41 | ||||
-rw-r--r-- | sos-code-article3/hwcore/i8254.c | 80 | ||||
-rw-r--r-- | sos-code-article3/hwcore/i8254.h | 36 | ||||
-rw-r--r-- | sos-code-article3/hwcore/i8259.c | 80 | ||||
-rw-r--r-- | sos-code-article3/hwcore/i8259.h | 41 | ||||
-rw-r--r-- | sos-code-article3/hwcore/idt.c | 160 | ||||
-rw-r--r-- | sos-code-article3/hwcore/idt.h | 85 | ||||
-rw-r--r-- | sos-code-article3/hwcore/ioports.h | 47 | ||||
-rw-r--r-- | sos-code-article3/hwcore/irq.c | 91 | ||||
-rw-r--r-- | sos-code-article3/hwcore/irq.h | 74 | ||||
-rw-r--r-- | sos-code-article3/hwcore/irq_wrappers.S | 173 | ||||
-rw-r--r-- | sos-code-article3/hwcore/segment.h | 59 |
16 files changed, 1486 insertions, 0 deletions
diff --git a/sos-code-article3/hwcore/exception.c b/sos-code-article3/hwcore/exception.c new file mode 100644 index 0000000..9ab5aff --- /dev/null +++ b/sos-code-article3/hwcore/exception.c @@ -0,0 +1,92 @@ +/* Copyright (C) 2004 David Decotigny + Copyright (C) 1999 Free Software Foundation, Inc. + + 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. +*/ +#include "idt.h" +#include "irq.h" + +#include "exception.h" + +/* array of exception wrappers, defined in exception_wrappers.S */ +extern sos_vaddr_t sos_exception_wrapper_array[SOS_EXCEPT_NUM]; + +/* arrays of exception handlers, shared with exception_wrappers.S */ +sos_exception_handler_t sos_exception_handler_array[SOS_EXCEPT_NUM] = + { NULL, }; + +sos_ret_t sos_exceptions_setup(void) +{ + /* We inidicate that the double fault exception handler is defined, + and give its address. this handler is a do-nothing handler (see + exception_wrappers.S), and it can NOT be overriden by the + functions below */ + return sos_idt_set_handler(SOS_EXCEPT_BASE + SOS_EXCEPT_DOUBLE_FAULT, + (sos_vaddr_t) sos_exception_wrapper_array[SOS_EXCEPT_DOUBLE_FAULT], + 0 /* CPL0 routine */); +} + + +sos_ret_t sos_exception_set_routine(int exception_number, + sos_exception_handler_t routine) +{ + sos_ret_t retval; + sos_ui32_t flags; + + if ((exception_number < 0) || (exception_number >= SOS_EXCEPT_NUM)) + return -SOS_EINVAL; + + /* Double fault not supported */ + if (exception_number == SOS_EXCEPT_DOUBLE_FAULT) + return -SOS_ENOSUP; + + sos_disable_IRQs(flags); + + retval = SOS_OK; + + /* Set the exception routine to be called by the exception wrapper */ + sos_exception_handler_array[exception_number] = routine; + + /* If the exception is to be enabled, update the IDT with the exception + wrapper */ + if (routine != NULL) + retval + = sos_idt_set_handler(SOS_EXCEPT_BASE + exception_number, + (sos_vaddr_t) sos_exception_wrapper_array[exception_number], + 0 /* CPL0 routine */); + else /* Disable the IDT entry */ + retval + = sos_idt_set_handler(SOS_EXCEPT_BASE + exception_number, + (sos_vaddr_t)NULL /* No routine => disable IDTE */, + 0 /* don't care */); + + sos_restore_IRQs(flags); + return retval; +} + + +sos_exception_handler_t sos_exception_get_routine(int exception_number) +{ + if ((exception_number < 0) || (exception_number >= SOS_EXCEPT_NUM)) + return NULL; + + /* Double fault not supported */ + if (exception_number == SOS_EXCEPT_DOUBLE_FAULT) + return NULL; + + /* Expected to be atomic */ + return sos_exception_handler_array[exception_number]; +} diff --git a/sos-code-article3/hwcore/exception.h b/sos-code-article3/hwcore/exception.h new file mode 100644 index 0000000..7e52fe5 --- /dev/null +++ b/sos-code-article3/hwcore/exception.h @@ -0,0 +1,80 @@ +/* Copyright (C) 2004 David Decotigny + Copyright (C) 1999 Free Software Foundation, Inc. + + 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. +*/ +#ifndef _SOS_HWEXCEPT_H_ +#define _SOS_HWEXCEPT_H_ + +/** + * @file exception.c + * + * Hardware exception routines management. + */ + +#ifndef ASM_SOURCE +# include <sos/errno.h> +#endif + +/** + * Standard Intel x86 exceptions. + * + * @see Intel x86 doc vol 3, section 5.12. + */ +#define SOS_EXCEPT_DIVIDE_ERROR 0 // No error code +#define SOS_EXCEPT_DEBUG 1 // No error code +#define SOS_EXCEPT_NMI_INTERRUPT 2 // No error code +#define SOS_EXCEPT_BREAKPOINT 3 // No error code +#define SOS_EXCEPT_OVERFLOW 4 // No error code +#define SOS_EXCEPT_BOUND_RANGE_EXCEDEED 5 // No error code +#define SOS_EXCEPT_INVALID_OPCODE 6 // No error code +#define SOS_EXCEPT_DEVICE_NOT_AVAILABLE 7 // No error code +#define SOS_EXCEPT_DOUBLE_FAULT 8 // Yes (Zero) +#define SOS_EXCEPT_COPROCESSOR_SEGMENT_OVERRUN 9 // No error code +#define SOS_EXCEPT_INVALID_TSS 10 // Yes +#define SOS_EXCEPT_SEGMENT_NOT_PRESENT 11 // Yes +#define SOS_EXCEPT_STACK_SEGMENT_FAULT 12 // Yes +#define SOS_EXCEPT_GENERAL_PROTECTION 13 // Yes +#define SOS_EXCEPT_PAGE_FAULT 14 // Yes +#define SOS_EXCEPT_INTEL_RESERVED_1 15 // No +#define SOS_EXCEPT_FLOATING_POINT_ERROR 16 // No +#define SOS_EXCEPT_ALIGNEMENT_CHECK 17 // Yes (Zero) +#define SOS_EXCEPT_MACHINE_CHECK 18 // No +#define SOS_EXCEPT_INTEL_RESERVED_2 19 // No +#define SOS_EXCEPT_INTEL_RESERVED_3 20 // No +#define SOS_EXCEPT_INTEL_RESERVED_4 21 // No +#define SOS_EXCEPT_INTEL_RESERVED_5 22 // No +#define SOS_EXCEPT_INTEL_RESERVED_6 23 // No +#define SOS_EXCEPT_INTEL_RESERVED_7 24 // No +#define SOS_EXCEPT_INTEL_RESERVED_8 25 // No +#define SOS_EXCEPT_INTEL_RESERVED_9 26 // No +#define SOS_EXCEPT_INTEL_RESERVED_10 27 // No +#define SOS_EXCEPT_INTEL_RESERVED_11 28 // No +#define SOS_EXCEPT_INTEL_RESERVED_12 29 // No +#define SOS_EXCEPT_INTEL_RESERVED_13 30 // No +#define SOS_EXCEPT_INTEL_RESERVED_14 31 // No + +#ifndef ASM_SOURCE + +typedef void (*sos_exception_handler_t)(int exception_number); + +sos_ret_t sos_exceptions_setup(void); +sos_ret_t sos_exception_set_routine(int exception_number, + sos_exception_handler_t routine); +sos_exception_handler_t sos_exception_get_routine(int exception_number); +#endif /* ! ASM_SOURCE */ + +#endif /* _SOS_HWEXCEPT_H_ */ diff --git a/sos-code-article3/hwcore/exception_wrappers.S b/sos-code-article3/hwcore/exception_wrappers.S new file mode 100644 index 0000000..2f7665c --- /dev/null +++ b/sos-code-article3/hwcore/exception_wrappers.S @@ -0,0 +1,197 @@ +/* Copyright (C) 2004 The KOS Team + Copyright (C) 1999 Free Software Foundation, Inc. + + 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. +*/ +#include "exception.h" + +.file "exception_wrappers.S" + +.text + +/* The address of the table of handlers (defined in exception.c) */ +.extern sos_exception_handler_array + +/* The address of the table of wrappers (defined below, and shared + with exception.c */ +.globl sos_exception_wrapper_array + + +/** + * For exceptions with/without error code, refer to Intel x86 doc vol 3, + * section 5.12 + */ + +/* These wrappers are for exceptions without error code */ +.irp id, \ + SOS_EXCEPT_DIVIDE_ERROR, \ + SOS_EXCEPT_DEBUG, \ + SOS_EXCEPT_NMI_INTERRUPT, \ + SOS_EXCEPT_BREAKPOINT, \ + SOS_EXCEPT_OVERFLOW, \ + SOS_EXCEPT_BOUND_RANGE_EXCEDEED, \ + SOS_EXCEPT_INVALID_OPCODE, \ + SOS_EXCEPT_DEVICE_NOT_AVAILABLE, \ + SOS_EXCEPT_COPROCESSOR_SEGMENT_OVERRUN, \ + SOS_EXCEPT_INTEL_RESERVED_1, \ + SOS_EXCEPT_FLOATING_POINT_ERROR, \ + SOS_EXCEPT_MACHINE_CHECK, \ + SOS_EXCEPT_INTEL_RESERVED_2, \ + SOS_EXCEPT_INTEL_RESERVED_3, \ + SOS_EXCEPT_INTEL_RESERVED_4, \ + SOS_EXCEPT_INTEL_RESERVED_5, \ + SOS_EXCEPT_INTEL_RESERVED_6, \ + SOS_EXCEPT_INTEL_RESERVED_7, \ + SOS_EXCEPT_INTEL_RESERVED_8, \ + SOS_EXCEPT_INTEL_RESERVED_9, \ + SOS_EXCEPT_INTEL_RESERVED_10, \ + SOS_EXCEPT_INTEL_RESERVED_11, \ + SOS_EXCEPT_INTEL_RESERVED_12, \ + SOS_EXCEPT_INTEL_RESERVED_13, \ + SOS_EXCEPT_INTEL_RESERVED_14 + + .p2align 2, 0x90 + sos_exception_wrapper_\id: + .type sos_exception_wrapper_\id,@function + + /* Fake error code */ + pushl $0 + /* Backup the context */ + pushl %ebp + movl %esp, %ebp + + pushl %edi + pushl %esi + pushl %edx + pushl %ecx + pushl %ebx + pushl %eax + subl $2,%esp + pushw %ss + pushw %ds + pushw %es + pushw %fs + pushw %gs + + /* Call the handler with exception number as + * argument */ + pushl $\id + leal sos_exception_handler_array,%edi + call *\id*4(%edi) + addl $4, %esp + + /* Restore the context */ + popw %gs + popw %fs + popw %es + popw %ds + popw %ss + addl $2,%esp + popl %eax + popl %ebx + popl %ecx + popl %edx + popl %esi + popl %edi + + popl %ebp + /* Remove fake error code */ + addl $4, %esp + iret +.endr + + /* These wrappers are for exceptions with error code */ +.irp id, \ + SOS_EXCEPT_INVALID_TSS, \ + SOS_EXCEPT_SEGMENT_NOT_PRESENT, \ + SOS_EXCEPT_STACK_SEGMENT_FAULT, \ + SOS_EXCEPT_GENERAL_PROTECTION, \ + SOS_EXCEPT_PAGE_FAULT, \ + SOS_EXCEPT_ALIGNEMENT_CHECK + + .p2align 2, 0x90 + sos_exception_wrapper_\id: + .type sos_exception_wrapper_\id,@function + + /* ret eflags */ + /* ret cs */ + /* ret eip */ + /* Error code */ + + /* Backup the context */ + pushl %ebp + movl %esp, %ebp + + pushl %edi + pushl %esi + pushl %edx + pushl %ecx + pushl %ebx + pushl %eax + subl $2,%esp + pushw %ss + pushw %ds + pushw %es + pushw %fs + pushw %gs + + /* Call the handler with exception number as + * argument */ + pushl $\id + leal sos_exception_handler_array,%edi + call *\id*4(%edi) + addl $4, %esp + + /* Restore the context */ + popw %gs + popw %fs + popw %es + popw %ds + popw %ss + addl $2,%esp + popl %eax + popl %ebx + popl %ecx + popl %edx + popl %esi + popl %edi + popl %ebp + + /* Error code isn't compatible with iretd */ + addl $4, %esp + + iret +.endr + + +/* Double fault handler not supported. We must define it since we + define an entry for it in the sos_exception_wrapper_array. */ +.irp id, SOS_EXCEPT_DOUBLE_FAULT +.p2align 2, 0x90 +sos_exception_wrapper_\id: +.type sos_exception_wrapper_\id,@function +1: hlt + jmp 1b /* Machine halting */ +.endr + +/* Build the sos_irq_wrapper_array, shared with interrupt.c */ +.section ".rodata" +.p2align 5, 0x0 +sos_exception_wrapper_array: + .irp id, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, \ + 16,17,18,19,20,21,22,23,24,25,26,27,29,30,31 + .long (sos_exception_wrapper_\id) + .endr diff --git a/sos-code-article3/hwcore/gdt.c b/sos-code-article3/hwcore/gdt.c new file mode 100644 index 0000000..7945c8c --- /dev/null +++ b/sos-code-article3/hwcore/gdt.c @@ -0,0 +1,150 @@ +/* Copyright (C) 2004 David Decotigny + Copyright (C) 1999 Free Software Foundation, Inc. + + 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. +*/ +#include "segment.h" + +#include "gdt.h" + + +/** + * The sructure of a segment descriptor. + * + * @see Intel x86 doc, Vol 3, section 3.4.3, figure 3-8. For segment + * types, see section 3.5 + */ +struct x86_segment_descriptor +{ + /* Lowest dword */ + sos_ui16_t limit_15_0; /* Segment limit, bits 15..0 */ + sos_ui16_t base_paged_addr_15_0; /* Base address, bits 15..0 */ + + /* Highest dword */ + sos_ui8_t base_paged_addr_23_16; /* Base address bits 23..16 */ + sos_ui8_t segment_type:4; /* Section 3.4.3.1 (code/data) + and 3.5 (system) of Intel x86 vol 3 */ + sos_ui8_t descriptor_type:1; /* 0=system, 1=Code/Data */ + sos_ui8_t dpl:2; + sos_ui8_t present:1; + + sos_ui8_t limit_19_16:4; /* Segment limit, bits 19..16 */ + sos_ui8_t custom:1; + sos_ui8_t zero:1; + sos_ui8_t op_size:1; /* 0=16bits instructions, 1=32bits */ + sos_ui8_t granularity:1; /* 0=limit in bytes, 1=limit in pages */ + + sos_ui8_t base_paged_addr_31_24; /* Base address bits 31..24 */ +} __attribute__ ((packed, aligned (8))); + + +/** + * The GDT register, which stores the address and size of the + * GDT. + * + * @see Intel x86 doc vol 3, section 2.4, figure 2-4; and section + * 3.5.1 + */ +struct x86_gdt_register { + /* The maximum GDT offset allowed to access an entry in the GDT */ + sos_ui16_t limit; + + /* This is not exactly a "virtual" address, ie an adddress such as + those of instructions and data; this is a "linear" address, ie an + address in the paged memory. However, in SOS we configure the + segmented memory as a "flat" space: the 0-4GB segment-based (ie + "virtual") addresses directly map to the 0-4GB paged memory (ie + "linear"), so that the "linear" addresses are numerically equal + to the "virtual" addresses: this base_addr will thus be the same + as the address of the gdt array */ + sos_ui32_t base_addr; +} __attribute__((packed, aligned(8))); + + +/** + * Helper macro that builds a Segment descriptor for the virtual + * 0..4GB addresses to be mapped to the linear 0..4GB linear + * addresses. + */ +#define BUILD_GDTE(descr_privilege_level,is_code) \ + ((struct x86_segment_descriptor) { \ + .limit_15_0= 0xffff, \ + .base_paged_addr_15_0= 0, \ + .base_paged_addr_23_16= 0, \ + .segment_type= ((is_code)?0xb:0x3), \ + /* With descriptor_type (below) = 1 (code/data), \ + * see Figure 3-1 of section 3.4.3.1 in Intel \ + * x86 vol 3: \ + * - Code (bit 3 = 1): \ + * bit 0: 1=Accessed \ + * bit 1: 1=Readable \ + * bit 2: 0=Non-Conforming \ + * - Data (bit 3 = 0): \ + * bit 0: 1=Accessed \ + * bit 1: 1=Writable \ + * bit 2: 0=Expand up (stack-related) \ + * For Conforming/non conforming segments, see \ + * Intel x86 Vol 3 section 4.8.1.1 \ + */ \ + .descriptor_type= 1, /* 1=Code/Data */ \ + .dpl= ((descr_privilege_level) & 0x3), \ + .present= 1, \ + .limit_19_16= 0xf, \ + .custom= 0, \ + .op_size= 1, /* 32 bits instr/data */ \ + .granularity= 1 /* limit is in 4kB Pages */ \ + }) + + +/** The actual GDT */ +static struct x86_segment_descriptor gdt[] = { + [SOS_SEG_NULL] = (struct x86_segment_descriptor){ 0, }, + [SOS_SEG_KCODE] = BUILD_GDTE(0, 1), + [SOS_SEG_KDATA] = BUILD_GDTE(0, 0), +}; + +sos_ret_t sos_gdt_setup(void) +{ + struct x86_gdt_register gdtr; + + /* Address of the GDT */ + gdtr.base_addr = (sos_ui32_t) gdt; + + /* The limit is the maximum offset in bytes from the base address of + the GDT */ + gdtr.limit = sizeof(gdt) - 1; + + /* Commit the GDT into the CPU, and update the segment + registers. The CS register may only be updated with a long jump + to an absolute address in the given segment (see Intel x86 doc + vol 3, section 4.8.1). */ + asm volatile ("lgdt %0 \n\ + ljmp %1,$1f \n\ + 1: \n\ + movw %2, %%ax \n\ + movw %%ax, %%ss \n\ + movw %%ax, %%ds \n\ + movw %%ax, %%es \n\ + movw %%ax, %%fs \n\ + movw %%ax, %%gs" + : + :"m"(gdtr), + "i"(SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KCODE)), + "i"(SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KDATA)) + :"memory","eax"); + + return SOS_OK; +} diff --git a/sos-code-article3/hwcore/gdt.h b/sos-code-article3/hwcore/gdt.h new file mode 100644 index 0000000..b7e3f4c --- /dev/null +++ b/sos-code-article3/hwcore/gdt.h @@ -0,0 +1,41 @@ +/* Copyright (C) 2004 David Decotigny + Copyright (C) 1999 Free Software Foundation, Inc. + + 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. +*/ +#ifndef _SOS_GDT_H_ +#define _SOS_GDT_H_ + +/** + * @file gdt.h + * + * The routines that manage the GDT, the table that maps the virtual + * addresses (data/instructions, segment-relative), to "linear" + * addresses (ie paged-memory). In SOS/x86, we use a "flat" virtual + * space, ie the virtual and linear spaces are equivalent. + * + * @see Intel x86 doc vol 3, chapter 3 + */ + +#include <sos/errno.h> + +/** + * Configure the virtual space as a direct mapping to the linear + * address space (ie "flat" virtual space). + */ +sos_ret_t sos_gdt_setup(void); + +#endif /* _SOS_GDT_H_ */ diff --git a/sos-code-article3/hwcore/i8254.c b/sos-code-article3/hwcore/i8254.c new file mode 100644 index 0000000..5fbb156 --- /dev/null +++ b/sos-code-article3/hwcore/i8254.c @@ -0,0 +1,80 @@ +/* Copyright (C) 2004 The KOS Team + Copyright (C) 1999 Free Software Foundation, Inc. + + 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. +*/ +#include <hwcore/ioports.h> + +#include "i8254.h" + +/** 82c54 clock frequency */ +#define I8254_MAX_FREQ 1193180 + +/* Ports to communicate with the 82c54 */ +#define I8254_TIMER0 0x40 +#define I8254_TIMER1 0x41 +#define I8254_TIMER2 0x42 +#define I8254_CONTROL 0x43 + +/** + * Configure the first timer of the 82c54 chip as a rate generator, + * which will raise an IRQ0 on a regular periodic basis, as given by + * the freq parameter. Second (RAM refresh) and third (speaker) timers + * are left unchanged. Maximum frequency is that of the 8254 clock, ie + * 1193180 Hz. + * + * Ahhh PC systems are nice toys: this maximum "strange" frequency + * equals that of the NTSC clock (14.31818 MHz) divided by 12. In + * turn, the famous 4.77 MHz cpu clock frequency of the first IBM PC + * is this same NTSC frequency divided by 3. Why the NTSC frequency as + * a base "standard" ? Because the 14.31818 MHz quartz were cheap at + * that time, and because it allows to simply drive altogether the + * cpu, the "time of day" timer, and the video signal generators. + */ +sos_ret_t sos_i8254_set_frequency(unsigned int freq) +{ + unsigned int nb_tick; + + if (freq <= 0) + return -SOS_EINVAL; + + /* Compute counter value */ + nb_tick = I8254_MAX_FREQ / freq; + + /* Counter must be between 1 and 65536 */ + if (nb_tick > 65536) + return -SOS_EINVAL; + if (nb_tick <= 0) + return -SOS_EINVAL; + + /* The i8254 interprets 0 to mean counter == 65536, because 65536 + cannot be coded on 16bits */ + if (nb_tick == 65536) + nb_tick = 0; + + /* We want to configure timer0, we want to send both LSB+MSB to set + timer0 freq (-> 0x30), and we configure timer0 in mode 2, ie as a + rate generator (-> 0x4) ==> 0x34 */ + outb(0x34, I8254_CONTROL); + + /* Send LSB of counter first */ + outb((nb_tick & 0xFF), I8254_TIMER0); + + /* Send MSB of counter */ + outb((nb_tick >> 8) & 0xFF, I8254_TIMER0); + + return SOS_OK; +} diff --git a/sos-code-article3/hwcore/i8254.h b/sos-code-article3/hwcore/i8254.h new file mode 100644 index 0000000..4838ff4 --- /dev/null +++ b/sos-code-article3/hwcore/i8254.h @@ -0,0 +1,36 @@ +/* Copyright (C) 2004 David Decotigny + Copyright (C) 1999 Free Software Foundation, Inc. + + 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. +*/ +#ifndef _SOS_i8259_H_ +#define _SOS_i8259_H_ + +#include <sos/errno.h> + +/** + * @file i8254.h PC programmable timer + * + * Programmable timer routines. See the Intel 82C54 datasheet (on kos + * website). + * + * @see i82C54 datasheet on Kos website. + */ + +/** Change timer interrupt (IRQ 0) frequency */ +sos_ret_t sos_i8254_set_frequency(unsigned int freq); + +#endif /* _SOS_i8259_H_ */ diff --git a/sos-code-article3/hwcore/i8259.c b/sos-code-article3/hwcore/i8259.c new file mode 100644 index 0000000..8391c07 --- /dev/null +++ b/sos-code-article3/hwcore/i8259.c @@ -0,0 +1,80 @@ +/* Copyright (C) 2004 The KOS Team + Copyright (C) 1999 Free Software Foundation, Inc. + + 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. +*/ +#include "ioports.h" + +#include "i8259.h" + +#define PIC_MASTER 0x20 +#define PIC_SLAVE 0xa0 + +/** Setup the 8259 PIC */ +sos_ret_t sos_i8259_setup(void) +{ + /* Send ICW1: 8086 mode + NOT Single ctrl + call address + interval=8 */ + outb(0x11, PIC_MASTER); + outb(0x11, PIC_SLAVE); + + /* Send ICW2: ctrl base address */ + outb(0x20, PIC_MASTER+1); + outb(0x28, PIC_SLAVE+1); + + /* Send ICW3 master: mask where slaves are connected */ + outb(0x4, PIC_MASTER+1); + /* Send ICW3 slave: index where the slave is connected on master */ + outb(0x2, PIC_SLAVE+1); + + /* Send ICW4: 8086 mode, fully nested, not buffered, no implicit EOI */ + outb(0x1, PIC_MASTER+1); + outb(0x1, PIC_SLAVE+1); + + /* Send OCW1: + * Closing all IRQs : waiting for a correct handler The only IRQ + * enabled is the cascade (that's why we use 0xFB for the master) */ + outb(0xFB, PIC_MASTER+1); + outb(0xFF, PIC_SLAVE+1); + + return SOS_OK; +} + + +sos_ret_t sos_i8259_enable_irq_line(int numirq) +{ + if(numirq < 8) + /* irq on master PIC */ + outb((inb(PIC_MASTER+1) & ~(1 << numirq)), PIC_MASTER+1); + else + /* irq on slave PIC */ + outb((inb(PIC_SLAVE+1) & ~(1 << (numirq-8))), PIC_SLAVE+1); + + return SOS_OK; +} + + +sos_ret_t sos_i8259_disable_irq_line(int numirq) +{ + if(numirq < 8) + /* irq on master PIC */ + outb((inb(PIC_MASTER+1) | (1 << numirq)), PIC_MASTER+1); + else + /* irq on slave PIC */ + outb((inb(PIC_SLAVE+1) | (1 << (numirq-8))), PIC_SLAVE+1); + + return SOS_OK; +} diff --git a/sos-code-article3/hwcore/i8259.h b/sos-code-article3/hwcore/i8259.h new file mode 100644 index 0000000..c1771dd --- /dev/null +++ b/sos-code-article3/hwcore/i8259.h @@ -0,0 +1,41 @@ +/* Copyright (C) 2004 David Decotigny + Copyright (C) 1999 Free Software Foundation, Inc. + + 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. +*/ +#ifndef _SOS_i8259_H_ +#define _SOS_i8259_H_ + +#include <sos/errno.h> + +/** + * @file i8259.h PIC + * + * PIC Management routines. See the Intel 8259A datasheet (on kos + * website), page 9+. Should be not be used directly: only interrupt.c + * should use this. + * + * @see i8259A datasheet on Kos website. + */ + +/** Setup PIC and Disable all IRQ lines */ +sos_ret_t sos_i8259_setup(void); + +sos_ret_t sos_i8259_enable_irq_line(int numirq); + +sos_ret_t sos_i8259_disable_irq_line(int numirq); + +#endif /* _SOS_i8259_H_ */ diff --git a/sos-code-article3/hwcore/idt.c b/sos-code-article3/hwcore/idt.c new file mode 100644 index 0000000..51e3a9d --- /dev/null +++ b/sos-code-article3/hwcore/idt.c @@ -0,0 +1,160 @@ +/* Copyright (C) 2004 David Decotigny + Copyright (C) 1999 Free Software Foundation, Inc. + + 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. +*/ +#include "segment.h" + +#include "idt.h" + +/** + * An entry in the IDT, or "IDTE" in the following, ie a reference to + * a interrupt/trap routine or a task gate to handle the sw/hw + * interrupts and exceptions. + * + * @see figure 5-2, intel x86 doc, vol 3 + */ +struct x86_idt_entry +{ + /* Low dword */ + sos_ui16_t offset_low; /* 15..0, offset of the routine in the segment */ + sos_ui16_t seg_sel; /* 31..16, the ID of the segment */ + + /* High dword */ + sos_ui8_t reserved:5; /* 4..0 */ + sos_ui8_t flags:3; /* 7..5 */ + sos_ui8_t type:3; /* 10..8 (interrupt gate, trap gate...) */ + sos_ui8_t op_size:1; /* 11 (0=16bits instructions, 1=32bits instr.) */ + sos_ui8_t zero:1; /* 12 */ + sos_ui8_t dpl:2; /* 14..13 */ + sos_ui8_t present:1; /* 15 */ + sos_ui16_t offset_high; /* 31..16 */ +} __attribute__((packed)); + + +/** + * The IDT register, which stores the address and size of the + * IDT. + * + * @see Intel x86 doc vol 3, section 2.4, figure 2-4 + */ +struct x86_idt_register +{ + /* The maximum GDT offset allowed to access an entry in the GDT */ + sos_ui16_t limit; + + /* This is not exactly a "virtual" address, ie an adddress such as + those of instructions and data; this is a "linear" address, ie an + address in the paged memory. However, in SOS we configure the + segmented memory as a "flat" space: the 0-4GB segment-based (ie + "virtual") addresses directly map to the 0-4GB paged memory (ie + "linear"), so that the "linear" addresses are numerically equal + to the "virtual" addresses: this base_addr will thus be the same + as the address of the gdt array */ + sos_ui32_t base_addr; +} __attribute__((packed, aligned (8))); + + +static struct x86_idt_entry idt[SOS_IDTE_NUM]; + +sos_ret_t sos_idt_setup() +{ + struct x86_idt_register idtr; + int i; + + for (i = 0 ; + i < SOS_IDTE_NUM ; + i++) + { + struct x86_idt_entry *idte = idt + i; + + /* Setup an empty IDTE interrupt gate, see figure 5-2 in Intel + x86 doc, vol 3 */ + idte->seg_sel = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KCODE); + idte->reserved = 0; + idte->flags = 0; + idte->type = 0x6; /* Interrupt gate (110b) */ + idte->op_size = 1; /* 32bits instructions */ + idte->zero = 0; + + /* Disable this IDT entry for the moment */ + sos_idt_set_handler(i, (sos_vaddr_t)NULL, 0/* Don't care */); + } + + /* + * Setup the IDT register, see Intel x86 doc vol 3, section 5.8. + */ + + /* Address of the IDT */ + idtr.base_addr = (sos_ui32_t) idt; + + /* The limit is the maximum offset in bytes from the base address of + the IDT */ + idtr.limit = sizeof(idt) - 1; + + /* Commit the IDT into the CPU */ + asm volatile ("lidt %0\n"::"m"(idtr):"memory"); + + return SOS_OK; +} + + +sos_ret_t sos_idt_set_handler(int index, + sos_vaddr_t handler_address, + int lowest_priviledge /* 0..3 */) +{ + struct x86_idt_entry *idte; + + if ((index < 0) || (index >= SOS_IDTE_NUM)) + return -SOS_EINVAL; + if ((lowest_priviledge < 0) || (lowest_priviledge > 3)) + return -SOS_EINVAL; + + idte = idt + index; + if (handler_address != (sos_vaddr_t)NULL) + { + idte->offset_low = handler_address & 0xffff; + idte->offset_high = (handler_address >> 16) & 0xffff; + idte->dpl = lowest_priviledge; + idte->present = 1; /* Yes, there is a handler */ + } + else /* Disable this IDT entry */ + { + idte->offset_low = 0; + idte->offset_high = 0; + idte->dpl = 0; + idte->present = 0; /* No, there is no handler */ + } + + return SOS_OK; +} + + +sos_ret_t sos_idt_get_handler(int index, + sos_vaddr_t *handler_address, + int *lowest_priviledge) +{ + if ((index < 0) || (index >= SOS_IDTE_NUM)) + return -SOS_EINVAL; + + if (handler_address != NULL) + *handler_address = idt[index].offset_low + | (idt[index].offset_high << 16); + if (lowest_priviledge != NULL) + *lowest_priviledge = idt[index].dpl; + + return SOS_OK; +} diff --git a/sos-code-article3/hwcore/idt.h b/sos-code-article3/hwcore/idt.h new file mode 100644 index 0000000..7afe364 --- /dev/null +++ b/sos-code-article3/hwcore/idt.h @@ -0,0 +1,85 @@ +/* Copyright (C) 2004 David Decotigny + Copyright (C) 1999 Free Software Foundation, Inc. + + 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. +*/ +#ifndef _SOS_IDT_H_ +#define _SOS_IDT_H_ + +/** + * @file idt.h + * + * Manage the x86 Interrupt Descriptor Table, the table which maps the + * hardware interrupt lines, hardware exceptions, and software + * interrupts, to software routines. We only define "interrupt gate" + * IDT entries. Don't use it directly; refer instead to interrupt.c, + * exceptions.c and syscall.c. + * + * @see Intel x86 doc, Vol 3, chapter 5 + */ + +#include <sos/errno.h> +#include <sos/types.h> + +/* Mapping of the CPU exceptions in the IDT (imposed by Intel + standards) */ +#define SOS_EXCEPT_BASE 0 +#define SOS_EXCEPT_NUM 32 +#define SOS_EXCEPT_MAX (SOS_HWEXCEPT_BASE + SOS_HWEXCEPT_NUM - 1) + +/* Mapping of the IRQ lines in the IDT */ +#define SOS_IRQ_BASE 32 +#define SOS_IRQ_NUM 16 +#define SOS_IRQ_MAX (SOS_IRQ_BASE + SOS_IRQ_NUM - 1) + +/** + * Number of IDT entries. + * + * @note Must be large enough to map the hw interrupts, the exceptions + * (=> total is 48 entries), and the syscall(s). Since our syscall + * will be 0x42, it must be >= 0x43. Intel doc limits this to 256 + * entries, we use this limit. + */ +#define SOS_IDTE_NUM 256 /* 0x100 */ + +/** Initialization routine: all the IDT entries (or "IDTE") are marked + "not present". */ +sos_ret_t sos_idt_setup(void); + +/** + * Enable the IDT entry if handler_address != NULL, with the given + * lowest_priviledge.\ Disable the IDT entry when handler_address == + * NULL (the lowest_priviledge parameter is then ignored). Intel doc + * says that there must not be more than 256 entries. + * + * @note IRQ Unsafe + */ +sos_ret_t sos_idt_set_handler(int index, + sos_vaddr_t handler_address, + int lowest_priviledge /* 0..3 */); + + +/** + * @note IRQ Unsafe + * + * @return the handler address and DPL in the 2nd and 3rd + * parameters + */ +sos_ret_t sos_idt_get_handler(int index, + sos_vaddr_t *handler_address, + int *lowest_priviledge); + +#endif /* _SOS_IDT_H_ */ diff --git a/sos-code-article3/hwcore/ioports.h b/sos-code-article3/hwcore/ioports.h new file mode 100644 index 0000000..443acb7 --- /dev/null +++ b/sos-code-article3/hwcore/ioports.h @@ -0,0 +1,47 @@ +/* Copyright (C) 2004 All GPL'ed OS + Copyright (C) 1999 Free Software Foundation, Inc. + + 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. +*/ +#ifndef _SOS_IOPORTS_H_ +#define _SOS_IOPORTS_H_ + +/** + * @ioports.h + * + * Intel-specific I/O space access routines. + */ + +/* This macro allows to write to an I/O port */ +#define outb(value, port) \ + __asm__ volatile ( \ + "outb %b0,%w1" \ + ::"a" (value),"Nd" (port) \ + ) \ + +// read one byte from port +#define inb(port) \ +({ \ + unsigned char _v; \ + __asm__ volatile ( \ + "inb %w1,%0" \ + :"=a" (_v) \ + :"Nd" (port) \ + ); \ + _v; \ +}) + +#endif /* _SOS_IOPORTS_H_ */ diff --git a/sos-code-article3/hwcore/irq.c b/sos-code-article3/hwcore/irq.c new file mode 100644 index 0000000..6ec3371 --- /dev/null +++ b/sos-code-article3/hwcore/irq.c @@ -0,0 +1,91 @@ +/* Copyright (C) 2004 David Decotigny + Copyright (C) 1999 Free Software Foundation, Inc. + + 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. +*/ +#include "idt.h" +#include "i8259.h" + +#include "irq.h" + +/* array of IRQ wrappers, defined in irq_wrappers.S */ +extern sos_vaddr_t sos_irq_wrapper_array[SOS_IRQ_NUM]; + +/* arrays of IRQ handlers, shared with irq_wrappers.S */ +sos_irq_handler_t sos_irq_handler_array[SOS_IRQ_NUM] = { NULL, }; + + +sos_ret_t sos_irq_setup(void) +{ + return sos_i8259_setup(); +} + + +sos_ret_t sos_irq_set_routine(int irq_level, + sos_irq_handler_t routine) +{ + sos_ret_t retval; + sos_ui32_t flags; + + if ((irq_level < 0) || (irq_level >= SOS_IRQ_NUM)) + return -SOS_EINVAL; + + sos_disable_IRQs(flags); + + retval = SOS_OK; + + /* Set the irq routine to be called by the IRQ wrapper */ + sos_irq_handler_array[irq_level] = routine; + + /* If the irq is to be enabled, update the IDT with the IRQ + wrapper */ + if (routine != NULL) + { + retval + = sos_idt_set_handler(SOS_IRQ_BASE + irq_level, + (sos_vaddr_t) sos_irq_wrapper_array[irq_level], + 0 /* CPL0 routine */); + /* A problem occured */ + if (retval != SOS_OK) + sos_irq_handler_array[irq_level] = NULL; + } + else /* Disable this idt entry */ + { + retval + = sos_idt_set_handler(SOS_IRQ_BASE + irq_level, + (sos_vaddr_t)NULL /* Disable IDTE */, + 0 /* Don't care */); + } + + /* Update the PIC only if an IRQ handler has been set */ + if (sos_irq_handler_array[irq_level] != NULL) + sos_i8259_enable_irq_line(irq_level); + else + sos_i8259_disable_irq_line(irq_level); + + sos_restore_IRQs(flags); + return retval; +} + + +sos_irq_handler_t sos_irq_get_routine(int irq_level) +{ + if ((irq_level < 0) || (irq_level >= SOS_IRQ_NUM)) + return NULL; + + /* Expected to be atomic */ + return sos_irq_handler_array[irq_level]; +} diff --git a/sos-code-article3/hwcore/irq.h b/sos-code-article3/hwcore/irq.h new file mode 100644 index 0000000..5b39230 --- /dev/null +++ b/sos-code-article3/hwcore/irq.h @@ -0,0 +1,74 @@ +/* Copyright (C) 2004 David Decotigny + Copyright (C) 1999 Free Software Foundation, Inc. + + 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. +*/ +#ifndef _SOS_HWINTR_H_ +#define _SOS_HWINTR_H_ + +/** + * @file irq.c + * + * Hardware interrupts routines management. + */ + +#include <sos/errno.h> + +#define sos_save_flags(flags) \ + asm volatile("pushfl ; popl %0":"=g"(flags)::"memory") +#define sos_restore_flags(flags) \ + asm volatile("push %0; popfl"::"g"(flags):"memory") + +#define sos_disable_IRQs(flags) \ + ({ sos_save_flags(flags); asm("cli\n"); }) +#define sos_restore_IRQs(flags) \ + sos_restore_flags(flags) + +/* Usual IRQ levels */ +#define SOS_IRQ_TIMER 0 +#define SOS_IRQ_KEYBOARD 1 +#define SOS_IRQ_SLAVE_PIC 2 +#define SOS_IRQ_COM2 3 +#define SOS_IRQ_COM1 4 +#define SOS_IRQ_LPT2 5 +#define SOS_IRQ_FLOPPY 6 +#define SOS_IRQ_LPT1 7 +#define SOS_IRQ_8_NOT_DEFINED 8 +#define SOS_IRQ_RESERVED_1 9 +#define SOS_IRQ_RESERVED_2 10 +#define SOS_IRQ_RESERVED_3 11 +#define SOS_IRQ_RESERVED_4 12 +#define SOS_IRQ_COPROCESSOR 13 +#define SOS_IRQ_HARDDISK 14 +#define SOS_IRQ_RESERVED_5 15 + +typedef void (*sos_irq_handler_t)(int irq_level); + +/** Setup the PIC */ +sos_ret_t sos_irq_setup(void); + +/** + * If the routine is not NULL, the IDT is setup to call an IRQ + * wrapper upon interrupt, which in turn will call the routine, and + * the PIC is programmed to raise an irq.\ If the routine is + * NULL, we disable the irq line. + */ +sos_ret_t sos_irq_set_routine(int irq_level, + sos_irq_handler_t routine); + +sos_irq_handler_t sos_irq_get_routine(int irq_level); + +#endif /* _SOS_HWINTR_H_ */ diff --git a/sos-code-article3/hwcore/irq_wrappers.S b/sos-code-article3/hwcore/irq_wrappers.S new file mode 100644 index 0000000..cf3355d --- /dev/null +++ b/sos-code-article3/hwcore/irq_wrappers.S @@ -0,0 +1,173 @@ +/* Copyright (C) 2004 The KOS Team + Copyright (C) 1999 Free Software Foundation, Inc. + + 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. +*/ +#define ASM_SOURCE 1 + +.file "irq_wrappers.S" + +.text + +/* The address of the table of handlers (defined in irq.c) */ +.extern sos_irq_handler_array + +/* The address of the table of wrappers (defined below, and shared + with irq.c */ +.globl sos_irq_wrapper_array + + +/* These pre-handlers are for IRQ (Master PIC) */ +.irp id, 0,1,2,3,4,5,6,7 + + .p2align 2, 0x90 + + sos_irq_wrapper_\id: + .type sos_irq_wrapper_\id,@function + + /* + * Backup the CPU context + */ + + /* Fake error code */ + pushl $0 + + /* Backup the actual context */ + pushl %ebp + movl %esp, %ebp + + pushl %edi + pushl %esi + pushl %edx + pushl %ecx + pushl %ebx + pushl %eax + subl $2,%esp + pushw %ss + pushw %ds + pushw %es + pushw %fs + pushw %gs + + /* Send EOI to PIC. See Intel 8259 datasheet + available on Kos website */ + movb $0x20, %al + outb %al, $0x20 + + /* + * Call the handler with IRQ number as argument + */ + pushl $\id + leal sos_irq_handler_array,%edi + call *\id*4(%edi) + addl $4, %esp + + /* Restore the context */ + popw %gs + popw %fs + popw %es + popw %ds + popw %ss + addl $2,%esp + popl %eax + popl %ebx + popl %ecx + popl %edx + popl %esi + popl %edi + popl %ebp + + /* Remove fake error code */ + addl $4, %esp + + iret + .endr + + +/* These pre-handlers are for IRQ (Slave PIC) */ +.irp id, 8,9,10,11,12,13,14,15 + + .p2align 2, 0x90 + + sos_irq_wrapper_\id: + .type sos_irq_wrapper_\id,@function + + /* + * Backup the CPU context + */ + + /* Fake error code */ + pushl $0 + + /* Backup the actual context */ + pushl %ebp + movl %esp, %ebp + + pushl %edi + pushl %esi + pushl %edx + pushl %ecx + pushl %ebx + pushl %eax + subl $2,%esp + pushw %ss + pushw %ds + pushw %es + pushw %fs + pushw %gs + + /* Send EOI to PIC. See Intel 8259 datasheet + available on Kos website */ + movb $0x20, %al + outb %al, $0xa0 + outb %al, $0x20 + + /* + * Call the handler with IRQ number as argument + */ + pushl $\id + leal sos_irq_handler_array,%edi + call *\id*4(%edi) + addl $4, %esp + + /* Restore the context */ + popw %gs + popw %fs + popw %es + popw %ds + popw %ss + addl $2,%esp + popl %eax + popl %ebx + popl %ecx + popl %edx + popl %esi + popl %edi + popl %ebp + + /* Remove fake error code */ + addl $4, %esp + + iret + .endr + +/* Build the sos_irq_wrapper_array, shared with irq.c */ +.section ".rodata" +.p2align 5, 0x0 +sos_irq_wrapper_array: + .irp id, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 + .long (sos_irq_wrapper_\id) + .endr diff --git a/sos-code-article3/hwcore/segment.h b/sos-code-article3/hwcore/segment.h new file mode 100644 index 0000000..37bdf5e --- /dev/null +++ b/sos-code-article3/hwcore/segment.h @@ -0,0 +1,59 @@ +/* Copyright (C) 2004 The SOS Team + Copyright (C) 1999 Free Software Foundation, Inc. + + 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. +*/ +#ifndef _SOS_HWSEGS_H_ +#define _SOS_HWSEGS_H_ + +/** + * @file segments.h + * + * Global and local (GDT/LDT) segment descriptor definition and + * structure. These segments map virtual addresses (ie + * data/instruction addresses, relative to these segment descriptors) + * to linear addresses (ie addresses in the paged-memory space). + * + * @see Intel x86 doc, vol 3 chapter 3. + */ + +#include <sos/types.h> + +/* + * Global segment selectors (GDT) for SOS/x86. + * + * @see gdt.h + */ +#define SOS_SEG_NULL 0 /* NULL segment, unused by the procesor */ +#define SOS_SEG_KCODE 1 /* Kernel code segment */ +#define SOS_SEG_KDATA 2 /* Kernel data segment */ + + +/** + * Helper macro that builds a segment register's value + */ +#define SOS_BUILD_SEGMENT_REG_VALUE(desc_privilege,in_ldt,seg_index) \ + ( (((desc_privilege) & 0x3) << 0) \ + | (((in_ldt)?1:0) << 2) \ + | ((seg_index) << 3) ) + + +/* + * Local segment selectors (LDT) for SOS/x86 + */ +/* None */ + +#endif /* _SOS_HWSEGS_H_ */ |