mirror of
https://github.com/apache/nuttx.git
synced 2026-06-05 07:12:54 +08:00
Add QEMU interrupt handling (incomplete)
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3339 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
@@ -81,6 +81,42 @@
|
|||||||
#define X86_EFLAGS_VIP (1 << 20) /* Bit 20: Virtual Interrupt Pending (Pentium+) */
|
#define X86_EFLAGS_VIP (1 << 20) /* Bit 20: Virtual Interrupt Pending (Pentium+) */
|
||||||
#define X86_EFLAGS_ID (1 << 21) /* Bit 21: CPUID detection flag (Pentium+) */
|
#define X86_EFLAGS_ID (1 << 21) /* Bit 21: CPUID detection flag (Pentium+) */
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Types
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* GDT data structures
|
||||||
|
*
|
||||||
|
* The Global Descriptor Table or GDT is a data structure used by Intel x86-
|
||||||
|
* family processors starting with the 80286 in order to define the
|
||||||
|
* characteristics of the various memory areas used during program execution,
|
||||||
|
* for example the base address, the size and access privileges like
|
||||||
|
* executability and writability. These memory areas are called segments in
|
||||||
|
* Intel terminology.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This structure defines one segment */
|
||||||
|
|
||||||
|
struct gdt_entry_s
|
||||||
|
{
|
||||||
|
uint16_t lowlimit; /* The lower 16 bits of the limit */
|
||||||
|
uint16_t lowbase; /* The lower 16 bits of the base */
|
||||||
|
uint8_t midbase; /* The next 8 bits of the base */
|
||||||
|
uint8_t access; /* Access flags, determine ring segment can be used in */
|
||||||
|
uint8_t granularity;
|
||||||
|
uint8_t hibase; /* The last 8 bits of the base */
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/* This structure refers to the array of GDT entries, and is in the format
|
||||||
|
* required by the lgdt instruction.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct gdt_ptr_s
|
||||||
|
{
|
||||||
|
uint16_t limit; /* The upper 16 bits of all selector limits */
|
||||||
|
uint32_t base; /* The address of the first gdt_entry_t struct */
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Inline functions
|
* Inline functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|||||||
@@ -48,7 +48,57 @@
|
|||||||
* Definitions
|
* Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define NR_IRQS 0
|
#define ISR0 0
|
||||||
|
#define ISR1 1
|
||||||
|
#define ISR2 2
|
||||||
|
#define ISR3 3
|
||||||
|
#define ISR4 4
|
||||||
|
#define ISR5 5
|
||||||
|
#define ISR6 6
|
||||||
|
#define ISR7 7
|
||||||
|
#define ISR8 8
|
||||||
|
#define ISR9 9
|
||||||
|
#define ISR10 10
|
||||||
|
#define ISR11 11
|
||||||
|
#define ISR12 12
|
||||||
|
#define ISR13 13
|
||||||
|
#define ISR14 14
|
||||||
|
#define ISR15 15
|
||||||
|
#define ISR16 16
|
||||||
|
#define ISR17 17
|
||||||
|
#define ISR18 18
|
||||||
|
#define ISR19 19
|
||||||
|
#define ISR20 20
|
||||||
|
#define ISR21 21
|
||||||
|
#define ISR22 22
|
||||||
|
#define ISR23 23
|
||||||
|
#define ISR24 24
|
||||||
|
#define ISR25 25
|
||||||
|
#define ISR26 26
|
||||||
|
#define ISR27 27
|
||||||
|
#define ISR28 28
|
||||||
|
#define ISR29 29
|
||||||
|
#define ISR30 30
|
||||||
|
#define ISR31 31
|
||||||
|
|
||||||
|
#define IRQ0 32
|
||||||
|
#define IRQ1 33
|
||||||
|
#define IRQ2 34
|
||||||
|
#define IRQ3 35
|
||||||
|
#define IRQ4 36
|
||||||
|
#define IRQ5 37
|
||||||
|
#define IRQ6 38
|
||||||
|
#define IRQ7 39
|
||||||
|
#define IRQ8 40
|
||||||
|
#define IRQ9 41
|
||||||
|
#define IRQ10 42
|
||||||
|
#define IRQ11 43
|
||||||
|
#define IRQ12 44
|
||||||
|
#define IRQ13 45
|
||||||
|
#define IRQ14 46
|
||||||
|
#define IRQ15 47
|
||||||
|
|
||||||
|
#define NR_IRQS 48
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Types
|
* Public Types
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* arch/x86/src/i486/up_assert.c
|
* arch/x86/src/i486/up_assert.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ CMN_CSRCS = up_allocateheap.c up_assert.c up_blocktask.c up_copystate.c \
|
|||||||
|
|
||||||
# Required QEMU files
|
# Required QEMU files
|
||||||
|
|
||||||
CHIP_ASRCS = qemu_saveusercontext.S qemu_fullcontextrestore.S
|
CHIP_ASRCS = qemu_saveusercontext.S qemu_fullcontextrestore.S qemu_vectors.S
|
||||||
CHIP_CSRCS = qemu_idle.c qemu_irq.c qemu_lowputc.c qemu_lowsetup.c \
|
CHIP_CSRCS = qemu_idle.c qemu_irq.c qemu_lowputc.c qemu_lowsetup.c \
|
||||||
qemu_timerisr.c
|
qemu_timerisr.c
|
||||||
|
|
||||||
|
|||||||
+103
-20
@@ -40,20 +40,37 @@
|
|||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* .text
|
* Pre-processor definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* Memory Map: _sbss is the start of the BSS region (see ld.script) _ebss is
|
||||||
|
* the end of the BSS regsion (see ld.script). The idle task stack starts at
|
||||||
|
* the end of BSS and is of size CONFIG_IDLETHREAD_STACKSIZE. The IDLE thread
|
||||||
|
* is the thread that the system boots on and, eventually, becomes the idle,
|
||||||
|
* do nothing task that runs only when there is nothing else to run. The
|
||||||
|
* heap continues from there until the end of memory. See g_heapbase below.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define STACKBASE ((_ebss + 0x1f) & 0xffffffe0)
|
||||||
|
#define IDLE_STACK (STACKBASE+CONFIG_IDLETHREAD_STACKSIZE)
|
||||||
|
#define HEAP_BASE (STACKBASE+CONFIG_IDLETHREAD_STACKSIZE)
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Nasm .text
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_X86_NASM
|
#ifdef CONFIG_X86_NASM
|
||||||
global __start /* Making entry point visible to linker */
|
global __start /* Making entry point visible to linker */
|
||||||
extern os_start /* os_start is defined elsewhere */
|
global _g_heapbase /* The start of the heap */
|
||||||
extern up_lowsetup /* up_lowsetup is defined elsewhere */
|
extern _os_start /* os_start is defined elsewhere */
|
||||||
|
extern _up_lowsetup /* up_lowsetup is defined elsewhere */
|
||||||
|
|
||||||
/* Setting up the Multiboot header - see GRUB docs for details */
|
/* Setting up the Multiboot header - see GRUB docs for details */
|
||||||
|
|
||||||
MODULEALIGN equ 1<<0 /* Align loaded modules on page boundaries */
|
MODULEALIGN equ 1<<0 /* Align loaded modules on page boundaries */
|
||||||
MEMINFO equ 1<<1 /* Provide memory map */
|
MEMINFO equ 1<<1 /* Provide memory map */
|
||||||
FLAGS equ MODULEALIGN | MEMINFO /* This is the Multiboot 'flag' field */
|
FLAGS equ MODULEALIGN | MEMINFO /* This is the Multiboot 'flag' field */
|
||||||
MAGIC equ 0x1BADB002 /* 'magic number' lets bootloader find the header */
|
MAGIC equ 0x1badb002 /* 'magic number' lets bootloader find the header */
|
||||||
CHECKSUM equ -(MAGIC + FLAGS) /* Checksum required */
|
CHECKSUM equ -(MAGIC + FLAGS) /* Checksum required */
|
||||||
|
|
||||||
section .text
|
section .text
|
||||||
@@ -63,63 +80,129 @@ MultiBootHeader:
|
|||||||
dd FLAGS
|
dd FLAGS
|
||||||
dd CHECKSUM
|
dd CHECKSUM
|
||||||
|
|
||||||
/* Reserve initial kernel stack space */
|
|
||||||
|
|
||||||
STACKSIZE equ 0x4000 /* That's 16k */
|
|
||||||
|
|
||||||
__start:
|
__start:
|
||||||
mov esp, stack+STACKSIZE /* Set up the stack */
|
/* Set up the stack */
|
||||||
|
|
||||||
|
mov esp, idle_stack + CONFIG_IDLETHREAD_STACKSIZE
|
||||||
|
|
||||||
|
/* Multiboot setup */
|
||||||
|
|
||||||
push eax /* Pass Multiboot magic number */
|
push eax /* Pass Multiboot magic number */
|
||||||
push ebx /* Pass Multiboot info structure */
|
push ebx /* Pass Multiboot info structure */
|
||||||
|
|
||||||
call up_lowsetup /* Low-level, pre-OS initialization */
|
/* Initialize and start NuttX */
|
||||||
call os_start /* Start NuttX */
|
|
||||||
|
call _up_lowsetup /* Low-level, pre-OS initialization */
|
||||||
|
call _os_start /* Start NuttX */
|
||||||
|
|
||||||
|
/* NuttX will not return */
|
||||||
|
|
||||||
cli
|
cli
|
||||||
hang:
|
hang:
|
||||||
hlt /* Halt machine should NuttX return */
|
hlt /* Halt machine should NuttX return */
|
||||||
jmp hang
|
jmp hang
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* .bss
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* The stack for the IDLE task thread is declared in .bss. NuttX boots and
|
||||||
|
* initializes on the IDLE thread, then at the completion of OS startup, this
|
||||||
|
* thread becomes the thread that executes when there is nothing else to
|
||||||
|
* do in the system (see up_idle()).
|
||||||
|
*/
|
||||||
|
|
||||||
section .bss
|
section .bss
|
||||||
align 4
|
align 4
|
||||||
stack:
|
idle_stack:
|
||||||
resb STACKSIZE /* Reserve 16k stack on a doubleword boundary */
|
resb CONFIG_IDLETHREAD_STACKSIZE
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* .rodata
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
section .rodata
|
||||||
|
|
||||||
|
/* HEAP BASE: _sbss is the start of the BSS region (see ld.script) _ebss is
|
||||||
|
* the end of the BSS region (see ld.script). The heap continues from there
|
||||||
|
* until the end of memory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
align 4
|
||||||
|
g_heapbase:
|
||||||
|
dd _ebss
|
||||||
|
|
||||||
#else /* !CONFIG_X86_NASM (GAS) */
|
#else /* !CONFIG_X86_NASM (GAS) */
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* GAS .text
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
.global __start /* Making entry point visible to linker */
|
.global __start /* Making entry point visible to linker */
|
||||||
.global _os_start /* os_start is defined elsewhere */
|
.global _os_start /* os_start is defined elsewhere */
|
||||||
.global _up_lowsetup /* up_lowsetup is defined elsewhere */
|
.global _up_lowsetup /* up_lowsetup is defined elsewhere */
|
||||||
|
.global _g_heapbase /* The start of the heap */
|
||||||
|
|
||||||
/* Setting up the Multiboot header - see GRUB docs for details */
|
/* Setting up the Multiboot header - see GRUB docs for details */
|
||||||
|
|
||||||
.set ALIGN, 1<<0 /* Align loaded modules on page boundaries */
|
.set ALIGN, 1<<0 /* Align loaded modules on page boundaries */
|
||||||
.set MEMINFO, 1<<1 /* Provide memory map */
|
.set MEMINFO, 1<<1 /* Provide memory map */
|
||||||
.set FLAGS, ALIGN | MEMINFO /* This is the Multiboot 'flag' field */
|
.set FLAGS, ALIGN | MEMINFO /* This is the Multiboot 'flag' field */
|
||||||
.set MAGIC, 0x1BADB002 /* 'magic number' lets bootloader find the header */
|
.set MAGIC, 0x1badb002 /* 'magic number' lets bootloader find the header */
|
||||||
.set CHECKSUM, -(MAGIC + FLAGS) /* Checksum required */
|
.set CHECKSUM, -(MAGIC + FLAGS) /* Checksum required */
|
||||||
|
|
||||||
|
.text
|
||||||
.align 4
|
.align 4
|
||||||
.long MAGIC
|
.long MAGIC
|
||||||
.long FLAGS
|
.long FLAGS
|
||||||
.long CHECKSUM
|
.long CHECKSUM
|
||||||
|
|
||||||
/* Reserve initial kernel stack space */
|
|
||||||
|
|
||||||
.set STACKSIZE, 0x4000 /* That is, 16k */
|
|
||||||
.comm stack, STACKSIZE, 32 /* Reserve 16k stack on a quadword boundary */
|
|
||||||
|
|
||||||
__start:
|
__start:
|
||||||
mov $(stack + STACKSIZE), %esp /* Set up the stack */
|
/* Set up the stack */
|
||||||
|
|
||||||
|
mov $(idle_stack + CONFIG_IDLETHREAD_STACKSIZE), %esp
|
||||||
|
|
||||||
|
/* Multiboot setup */
|
||||||
|
|
||||||
push %eax /* Multiboot magic number */
|
push %eax /* Multiboot magic number */
|
||||||
push %ebx /* Multiboot data structure */
|
push %ebx /* Multiboot data structure */
|
||||||
|
|
||||||
|
/* Initialize and start NuttX */
|
||||||
|
|
||||||
call _up_lowsetup /* Low-level, pre-OS initialization */
|
call _up_lowsetup /* Low-level, pre-OS initialization */
|
||||||
call _os_start /* Start NuttX */
|
call _os_start /* Start NuttX */
|
||||||
|
|
||||||
|
/* NuttX will not return */
|
||||||
|
|
||||||
cli
|
cli
|
||||||
hang:
|
hang:
|
||||||
hlt /* Halt machine should NuttX return */
|
hlt /* Halt machine should NuttX return */
|
||||||
jmp hang
|
jmp hang
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* .bss
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* The stack for the IDLE task thread is declared in .bss. NuttX boots and
|
||||||
|
* initializes on the IDLE thread, then at the completion of OS startup, this
|
||||||
|
* thread becomes the thread that executes when there is nothing else to
|
||||||
|
* do in the system (see up_idle()).
|
||||||
|
*/
|
||||||
|
|
||||||
|
.comm idle_stack, CONFIG_IDLETHREAD_STACKSIZE, 32
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* .rodata
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
.section .rodata, "a"
|
||||||
|
|
||||||
|
/* HEAP BASE: _sbss is the start of the BSS region (see ld.script) _ebss is
|
||||||
|
* the end of the BSS region (see ld.script). The heap continues from there
|
||||||
|
* until the end of memory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
_g_heapbase:
|
||||||
|
.word _ebss
|
||||||
.end
|
.end
|
||||||
#endif /* CONFIG_X86_NASM */
|
#endif /* CONFIG_X86_NASM */
|
||||||
@@ -67,6 +67,14 @@
|
|||||||
|
|
||||||
void up_lowputc(char ch)
|
void up_lowputc(char ch)
|
||||||
{
|
{
|
||||||
|
/* Wait until the BIOS can accept another character (so that the OS will
|
||||||
|
* continue to run.
|
||||||
|
*/
|
||||||
|
|
||||||
|
while ((inb(0x3f8+5) & (1 << 5)) == 0);
|
||||||
|
|
||||||
|
/* Then output the character */
|
||||||
|
|
||||||
outb(ch, 0x3f8);
|
outb(ch, 0x3f8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,57 @@
|
|||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: up_gdtentry
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Set the value of one GDT entry.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void up_gdtentry(struct gdt_entry_s *entry, uint32_t base,
|
||||||
|
uint32_t limit, uint8_t access, uint8_t gran)
|
||||||
|
{
|
||||||
|
entry->lowbase = (base & 0xffff);
|
||||||
|
entry->midbase = (base >> 16) & 0xff;
|
||||||
|
entry->hibase = (base >> 24) & 0xff;
|
||||||
|
|
||||||
|
entry->lowlimit = (limit & 0xffff);
|
||||||
|
entry->granularity = (limit >> 16) & 0x0f;
|
||||||
|
|
||||||
|
entry->granularity |= gran & 0xf0;
|
||||||
|
entry->access = access;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: up_gdtinit
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Initialize the GDT. The Global Descriptor Table or GDT is a data
|
||||||
|
* structure used by Intel x86-family processors starting with the 80286
|
||||||
|
* in order to define the characteristics of the various memory areas used
|
||||||
|
* during program execution, for example the base address, the size and
|
||||||
|
* access privileges like executability and writability. These memory areas
|
||||||
|
* are called segments in Intel terminology.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void up_gdtinit(void)
|
||||||
|
{
|
||||||
|
struct gdt_entry_s gdt_entries[5];
|
||||||
|
struct gdt_ptr_s gdt_ptr;
|
||||||
|
|
||||||
|
up_gdtentry(0, 0, 0, 0, 0); /* Null segment */
|
||||||
|
up_gdtentry(1, 0, 0xffffffff, 0x9a, 0xcf); /* Code segment */
|
||||||
|
up_gdtentry(2, 0, 0xffffffff, 0x92, 0xcf); /* Data segment */
|
||||||
|
up_gdtentry(3, 0, 0xffffffff, 0xfa, 0xcf); /* User mode code segment */
|
||||||
|
up_gdtentry(4, 0, 0xffffffff, 0xf2, 0xcf); /* User mode data segment */
|
||||||
|
|
||||||
|
gdt_ptr.limit = (sizeof(struct gdt_entry_s) * 5) - 1;
|
||||||
|
gdt_ptr.base = (uint32_t)gdt_entries;
|
||||||
|
gdt_flush((uint32_t )&gdt_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|||||||
Executable
+395
@@ -0,0 +1,395 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* arch/x86/src/qemu/qemu_head.S
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||||
|
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||||
|
*
|
||||||
|
* Based on Bran's kernel development tutorials. Rewritten for JamesM's
|
||||||
|
* kernel development tutorials.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
#include <arch/irq.h>
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#define KSEG 0x10
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Nasm .text
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_NASM
|
||||||
|
extern _irq_handler
|
||||||
|
extern _isr_handler
|
||||||
|
|
||||||
|
/* Trace macros, use like trace 'i' to print char to serial port. */
|
||||||
|
|
||||||
|
%macro io_outb 2
|
||||||
|
mov dx, %1 /* param1 = address, param2 = data. */
|
||||||
|
mov al, %2
|
||||||
|
out dx, al
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro trace 1
|
||||||
|
io_outb 0x3f8, %1 /* diagnostic character */
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
/* This macro creates a stub for an ISR which does NOT pass it's own
|
||||||
|
* error code (adds a dummy errcode byte).
|
||||||
|
*/
|
||||||
|
|
||||||
|
%macro ISR_NOERRCODE 1
|
||||||
|
global vector_isr%1
|
||||||
|
vector_isr%1:
|
||||||
|
cli /* Disable interrupts firstly. */
|
||||||
|
push byte 0 /* Push a dummy error code. */
|
||||||
|
push byte %1 /* Push the interrupt number. */
|
||||||
|
jmp isr_common /* Go to our common handler code. */
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
/* This macro creates a stub for an ISR which passes it's own
|
||||||
|
* error code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
%macro ISR_ERRCODE 1
|
||||||
|
global vector_isr%1
|
||||||
|
vector_isr%1:
|
||||||
|
cli /* Disable interrupts. */
|
||||||
|
push byte %1 /* Push the interrupt number */
|
||||||
|
jmp isr_common
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
/* This macro creates a stub for an IRQ - the first parameter is
|
||||||
|
* the IRQ number, the second is the ISR number it is remapped to.
|
||||||
|
*/
|
||||||
|
|
||||||
|
%macro IRQ 2
|
||||||
|
global vector_irq%1
|
||||||
|
vector_irq%1:
|
||||||
|
cli
|
||||||
|
push byte 0
|
||||||
|
push byte %2
|
||||||
|
jmp irq_common
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
/* The following will be the vector address programmed into the IDT */
|
||||||
|
|
||||||
|
ISR_NOERRCODE ISR0
|
||||||
|
ISR_NOERRCODE ISR1
|
||||||
|
ISR_NOERRCODE ISR2
|
||||||
|
ISR_NOERRCODE ISR3
|
||||||
|
ISR_NOERRCODE ISR4
|
||||||
|
ISR_NOERRCODE ISR5
|
||||||
|
ISR_NOERRCODE ISR6
|
||||||
|
ISR_NOERRCODE ISR7
|
||||||
|
ISR_ERRCODE ISR8
|
||||||
|
ISR_NOERRCODE ISR9
|
||||||
|
ISR_ERRCODE ISR10
|
||||||
|
ISR_ERRCODE ISR11
|
||||||
|
ISR_ERRCODE ISR12
|
||||||
|
ISR_ERRCODE ISR13
|
||||||
|
ISR_ERRCODE ISR14
|
||||||
|
ISR_NOERRCODE ISR15
|
||||||
|
ISR_NOERRCODE ISR16
|
||||||
|
ISR_NOERRCODE ISR17
|
||||||
|
ISR_NOERRCODE ISR18
|
||||||
|
ISR_NOERRCODE ISR19
|
||||||
|
ISR_NOERRCODE ISR20
|
||||||
|
ISR_NOERRCODE ISR21
|
||||||
|
ISR_NOERRCODE ISR22
|
||||||
|
ISR_NOERRCODE ISR23
|
||||||
|
ISR_NOERRCODE ISR24
|
||||||
|
ISR_NOERRCODE ISR25
|
||||||
|
ISR_NOERRCODE ISR26
|
||||||
|
ISR_NOERRCODE ISR27
|
||||||
|
ISR_NOERRCODE ISR28
|
||||||
|
ISR_NOERRCODE ISR29
|
||||||
|
ISR_NOERRCODE ISR30
|
||||||
|
ISR_NOERRCODE ISR31
|
||||||
|
IRQ 0, IRQ0
|
||||||
|
IRQ 1, IRQ1
|
||||||
|
IRQ 2, IRQ2
|
||||||
|
IRQ 3, IRQ3
|
||||||
|
IRQ 4, IRQ4
|
||||||
|
IRQ 5, IRQ5
|
||||||
|
IRQ 6, IRQ6
|
||||||
|
IRQ 7, IRQ7
|
||||||
|
IRQ 8, IRQ8
|
||||||
|
IRQ 9, IRQ9
|
||||||
|
IRQ 10, IRQ10
|
||||||
|
IRQ 11, IRQ11
|
||||||
|
IRQ 12, IRQ12
|
||||||
|
IRQ 13, IRQ13
|
||||||
|
IRQ 14, IRQ14
|
||||||
|
IRQ 15, IRQ15
|
||||||
|
|
||||||
|
/* This is our common ISR stub. It saves the processor state, sets up for
|
||||||
|
* kernel mode segments, calls the C-level fault handler, and finally restores
|
||||||
|
* the stack frame.
|
||||||
|
*/
|
||||||
|
|
||||||
|
isr_common:
|
||||||
|
/* trace 'S' */
|
||||||
|
pusha /* Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax */
|
||||||
|
|
||||||
|
mov ax, ds /* Lower 16-bits of eax = ds. */
|
||||||
|
push eax /* Save the data segment descriptor */
|
||||||
|
|
||||||
|
mov ax, KSEG /* Load the kernel data segment descriptor */
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
mov fs, ax
|
||||||
|
mov gs, ax
|
||||||
|
|
||||||
|
call _isr_handler
|
||||||
|
|
||||||
|
pop ebx /* Reload the original data segment descriptor */
|
||||||
|
mov ds, bx
|
||||||
|
mov es, bx
|
||||||
|
mov fs, bx
|
||||||
|
mov gs, bx
|
||||||
|
|
||||||
|
popa /* Pops edi,esi,ebp... */
|
||||||
|
add esp, 8 /* Cleans up the pushed error code and pushed ISR number */
|
||||||
|
sti
|
||||||
|
iret /* Pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP */
|
||||||
|
|
||||||
|
/* This is our common IRQ stub. It saves the processor state, sets up for
|
||||||
|
* kernel mode segments, calls the C-level fault handler, and finally restores
|
||||||
|
* the stack frame.
|
||||||
|
*/
|
||||||
|
|
||||||
|
irq_common:
|
||||||
|
/* trace 'R' */
|
||||||
|
pusha /* Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax */
|
||||||
|
|
||||||
|
mov ax, ds /* Lower 16-bits of eax = ds. */
|
||||||
|
push eax /* Save the data segment descriptor */
|
||||||
|
|
||||||
|
mov ax, KSEG /* Load the kernel data segment descriptor */
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
mov fs, ax
|
||||||
|
mov gs, ax
|
||||||
|
|
||||||
|
call _irq_handler
|
||||||
|
|
||||||
|
pop ebx /* Reload the original data segment descriptor */
|
||||||
|
mov ds, bx
|
||||||
|
mov es, bx
|
||||||
|
mov fs, bx
|
||||||
|
mov gs, bx
|
||||||
|
|
||||||
|
popa /* Pops edi,esi,ebp... */
|
||||||
|
add esp, 8 /* Cleans up the pushed error code and pushed ISR number */
|
||||||
|
sti
|
||||||
|
iret /* Pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP */
|
||||||
|
|
||||||
|
#else /* !CONFIG_X86_NASM (GAS) */
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* GAS .text
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
.globl _irq_handler
|
||||||
|
.globl _isr_handler
|
||||||
|
|
||||||
|
/* Trace macros, use like trace 'i' to print char to serial port. */
|
||||||
|
|
||||||
|
.macro io_outb, addr, data
|
||||||
|
mov dx, $\addr
|
||||||
|
mov al, $\data
|
||||||
|
out dx, al
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro trace, ch
|
||||||
|
io_outb 0x3f8, \ch
|
||||||
|
.endm
|
||||||
|
|
||||||
|
/* This macro creates a stub for an ISR which does NOT pass it's own
|
||||||
|
* error code (adds a dummy errcode byte).
|
||||||
|
*/
|
||||||
|
|
||||||
|
.macro ISR_NOERRCODE, intno
|
||||||
|
.globl vector_isr\intno
|
||||||
|
vector_isr\intno:
|
||||||
|
cli /* Disable interrupts firstly. */
|
||||||
|
push $0 /* Push a dummy error code. */
|
||||||
|
push $\intno /* Push the interrupt number. */
|
||||||
|
jmp isr_common /* Go to the common handler code. */
|
||||||
|
.endm
|
||||||
|
|
||||||
|
/* This macro creates a stub for an ISR which passes it's own
|
||||||
|
* error code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.macro ISR_ERRCODE, intno
|
||||||
|
.globl vector_isr\intno
|
||||||
|
vector_isr\intno:
|
||||||
|
cli /* Disable interrupts firstly. */
|
||||||
|
push $\intno /* Push the interrupt number. */
|
||||||
|
jmp isr_common /* Go to the common handler code. */
|
||||||
|
.endm
|
||||||
|
|
||||||
|
/* This macro creates a stub for an IRQ - the first parameter is
|
||||||
|
* the IRQ number, the second is the ISR number it is remapped to.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.macro IRQ, irqno, intno
|
||||||
|
.globl vector_irq\irqno
|
||||||
|
vector_irq\irqno:
|
||||||
|
cli /* Disable interrupts firstly. */
|
||||||
|
push $0 /* Push a dummy error code. */
|
||||||
|
push $\intno /* Push the interrupt number. */
|
||||||
|
jmp isr_common /* Go to the common handler code. */
|
||||||
|
.endm
|
||||||
|
|
||||||
|
/* The following will be the vector address programmed into the IDT */
|
||||||
|
|
||||||
|
ISR_NOERRCODE ISR0
|
||||||
|
ISR_NOERRCODE ISR1
|
||||||
|
ISR_NOERRCODE ISR2
|
||||||
|
ISR_NOERRCODE ISR3
|
||||||
|
ISR_NOERRCODE ISR4
|
||||||
|
ISR_NOERRCODE ISR5
|
||||||
|
ISR_NOERRCODE ISR6
|
||||||
|
ISR_NOERRCODE ISR7
|
||||||
|
ISR_ERRCODE ISR8
|
||||||
|
ISR_NOERRCODE ISR9
|
||||||
|
ISR_ERRCODE ISR10
|
||||||
|
ISR_ERRCODE ISR11
|
||||||
|
ISR_ERRCODE ISR12
|
||||||
|
ISR_ERRCODE ISR13
|
||||||
|
ISR_ERRCODE ISR14
|
||||||
|
ISR_NOERRCODE ISR15
|
||||||
|
ISR_NOERRCODE ISR16
|
||||||
|
ISR_NOERRCODE ISR17
|
||||||
|
ISR_NOERRCODE ISR18
|
||||||
|
ISR_NOERRCODE ISR19
|
||||||
|
ISR_NOERRCODE ISR20
|
||||||
|
ISR_NOERRCODE ISR21
|
||||||
|
ISR_NOERRCODE ISR22
|
||||||
|
ISR_NOERRCODE ISR23
|
||||||
|
ISR_NOERRCODE ISR24
|
||||||
|
ISR_NOERRCODE ISR25
|
||||||
|
ISR_NOERRCODE ISR26
|
||||||
|
ISR_NOERRCODE ISR27
|
||||||
|
ISR_NOERRCODE ISR28
|
||||||
|
ISR_NOERRCODE ISR29
|
||||||
|
ISR_NOERRCODE ISR30
|
||||||
|
ISR_NOERRCODE ISR31
|
||||||
|
IRQ 0, IRQ0
|
||||||
|
IRQ 1, IRQ1
|
||||||
|
IRQ 2, IRQ2
|
||||||
|
IRQ 3, IRQ3
|
||||||
|
IRQ 4, IRQ4
|
||||||
|
IRQ 5, IRQ5
|
||||||
|
IRQ 6, IRQ6
|
||||||
|
IRQ 7, IRQ7
|
||||||
|
IRQ 8, IRQ8
|
||||||
|
IRQ 9, IRQ9
|
||||||
|
IRQ 10, IRQ10
|
||||||
|
IRQ 11, IRQ11
|
||||||
|
IRQ 12, IRQ12
|
||||||
|
IRQ 13, IRQ13
|
||||||
|
IRQ 14, IRQ14
|
||||||
|
IRQ 15, IRQ15
|
||||||
|
|
||||||
|
/* This is our common ISR stub. It saves the processor state, sets up for
|
||||||
|
* kernel mode segments, calls the C-level fault handler, and finally restores
|
||||||
|
* the stack frame.
|
||||||
|
*/
|
||||||
|
|
||||||
|
isr_common:
|
||||||
|
/* trace 'S' */
|
||||||
|
pusha /* Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax */
|
||||||
|
|
||||||
|
mov %ax, ds /* Lower 16-bits of eax = ds. */
|
||||||
|
pushl %eax /* Save the data segment descriptor */
|
||||||
|
|
||||||
|
mov %ax, KSEG /* Load the kernel data segment descriptor */
|
||||||
|
mov ds, %ax
|
||||||
|
mov es, %ax
|
||||||
|
mov fs, %ax
|
||||||
|
mov gs, %ax
|
||||||
|
|
||||||
|
call _isr_handler
|
||||||
|
|
||||||
|
pop ebx /* Reload the original data segment descriptor */
|
||||||
|
mov ds, %bx
|
||||||
|
mov es, %bx
|
||||||
|
mov fs, %bx
|
||||||
|
mov gs, %bx
|
||||||
|
|
||||||
|
popa /* Pops edi,esi,ebp... */
|
||||||
|
add %esp, 8 /* Cleans up the pushed error code and pushed ISR number */
|
||||||
|
sti
|
||||||
|
iret /* Pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP */
|
||||||
|
|
||||||
|
/* This is our common IRQ stub. It saves the processor state, sets up for
|
||||||
|
* kernel mode segments, calls the C-level fault handler, and finally restores
|
||||||
|
* the stack frame.
|
||||||
|
*/
|
||||||
|
|
||||||
|
irq_common:
|
||||||
|
/* trace 'R' */
|
||||||
|
pusha /* Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax */
|
||||||
|
|
||||||
|
mov %ax, ds /* Lower 16-bits of eax = ds. */
|
||||||
|
push %eax /* Save the data segment descriptor */
|
||||||
|
|
||||||
|
mov %ax, KSEG /* Load the kernel data segment descriptor */
|
||||||
|
mov ds, %ax
|
||||||
|
mov es, %ax
|
||||||
|
mov fs, %ax
|
||||||
|
mov gs, %ax
|
||||||
|
|
||||||
|
call _irq_handler
|
||||||
|
|
||||||
|
pop %ebx /* Reload the original data segment descriptor */
|
||||||
|
mov ds, %bx
|
||||||
|
mov es, %bx
|
||||||
|
mov fs, %bx
|
||||||
|
mov gs, %bx
|
||||||
|
|
||||||
|
popa /* Pops edi,esi,ebp... */
|
||||||
|
add %esp, 8 /* Cleans up the pushed error code and pushed ISR number */
|
||||||
|
sti
|
||||||
|
iret /* Pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP */
|
||||||
|
.end
|
||||||
|
#endif /* CONFIG_X86_NASM */
|
||||||
Reference in New Issue
Block a user