Subversion Repositories shark

Rev

Rev 2 | Rev 40 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/* Project:     OSLib
 * Description: The OS Construction Kit
 * Date:                1.6.2000
 * Idea by:             Luca Abeni & Gerardo Lamastra
 *
 * OSLib is an SO project aimed at developing a common, easy-to-use
 * low-level infrastructure for developing OS kernels and Embedded
 * Applications; it partially derives from the HARTIK project but it
 * currently is independently developed.
 *
 * OSLib is distributed under GPL License, and some of its code has
 * been derived from the Linux kernel source; also some important
 * ideas come from studying the DJGPP go32 extender.
 *
 * We acknowledge the Linux Community, Free Software Foundation,
 * D.J. Delorie and all the other developers who believe in the
 * freedom of software and ideas.
 *
 * For legalese, check out the included GPL license.
 */

/*      Exc/IRQ handlers (asm part)     */
/* TODO: Unify the Exc/Int Mechanism... */

#include <ll/i386/sel.h>
#include <ll/i386/linkage.h>
#include <ll/i386/int.h>
#include <ll/i386/defs.h>

.extern SYMBOL_NAME(GDT_base)
.data          

ASMFILE(Exc)

.globl SYMBOL_NAME(ll_irq_table)
.globl SYMBOL_NAME(ll_exc_table)
                
SYMBOL_NAME_LABEL(ll_irq_table) .space  64, 0
SYMBOL_NAME_LABEL(ll_exc_table) .space  64, 65

.text

.extern  SYMBOL_NAME(ll_exc_hook)
.extern  SYMBOL_NAME(ll_FPU_hook)

.globl SYMBOL_NAME(h13_bis)
.globl SYMBOL_NAME(exc7)

/* These are the hardware handlers; they all jump to ll_handler setting */
/* the interrupt number into EAX & save the registers on stack          */
INT(1)
INT(2)
INT(3)
INT(4)
INT(5)
INT(6)
INT(7)
INT(8)
INT(9)
INT(10)
INT(11)
INT(12)
INT(13)
INT(14)
INT(15)

#if 0
/* MPF... If we have an external FPU, it will generate
 * INT 13 instead of EXC 16...
 * We must remap it to EXC 16...
 */
#if 1
SYMBOL_NAME_LABEL(h13_bis)
                        /* Send EOI for 8086 coprocessor trick  */
                        /* Send 0H on Coprocessor port 0F0H     */
                        pushl   %eax    
                        xorb    %al, %al                
                        outb    %al, $0x0F0
                        movb    $0x020, %al
                        outb    %al, $0x0A0
                        outb    %al, $0x020
                        popl    %eax
                        movl    $16, %eax
                        jmp     ll_handler2
#else
SYMBOL_NAME_LABEL(h13_bis)      pushal  
                        /* Send EOI for 8086 coprocessor trick  */
                        /* Send 0H on Coprocessor port 0F0H     */
                        
                        xorb    %al,%al         
                        outb    %al,$0x0F0
                        movb    $0x020,%al
                        outb    %al,$0x0A0
                        outb    %al,$0x020
                        pushl   %ds
                        pushl   %ss
                        pushl   %es
                        pushl   %fs
                        pushl   %gs
                        movw    $(X_FLATDATA_SEL),%ax
                        movw    %ax,%es
                        movw    %ax,%ds
                        movl    $(MATH_EXC),%eax
                        pushl   %eax
                /* LL_ABORT OR EXC_HOOK?? */
/*THIS SURELY WRONG!!!! FIX IT!!!! Gerardo, help me!!! */
                        hlt
/*                      call    SYMBOL_NAME(ll_abort) */
                        addl    $4,%esp
                        popl    %gs
                        popl    %fs
                        popl    %es
                        popl    %ss
                        popl    %ds
                        popal
                        ret
#endif
#endif

/* The ll_handler process the request using the kernel function act_int() */
/* Then sends EOI & schedules any eventual new task!                      */

ll_handler:             
                        /* We do not know what is the DS value  */
                        /* Then we save it & set it correctly   */
                        
                        pushl   %ds
                        pushl   %ss
                        pushl   %es
                        pushl   %fs
                        pushl   %gs              
                        /* But we first transfer to the _act_int  */
                        /* the interrupt number which is required */
                        /* as second argument                     */
                        pushl   %eax
                        movw    $(X_FLATDATA_SEL),%ax
                        movw    %ax,%es
                        mov     %ax,%ds
                        
                        /* Now save the actual context on stack         */
                        /* to pass it to _act_int (C caling convention) */
                        /* CLD is necessary when calling a C function   */
                
                        cld
                        
                        /* The following could be optimized a little... */
                        popl %eax
                        xorl %ebx, %ebx
                        movw %ss, %bx
                        /* We must switch to a ``safe stack'' */
#if 0 
        /*
         * OK, this is the idea: in %esp we have the address of the
         * stack pointer in the APPLICATION address space...
         * We assume that address spaces are implemented through segments...
         * What we have to do is to add the segment base to %esp:
         *      - Load the GDT base in a register
         *      - Add DS * 8 to that value
         *      - Read the corresponding GDT entry (the segment descriptor)
         *      - Compute the base...
         *      It is (*p & 0xFC) | (*(p +1)  & 0x0F) << 16) | *(p + 2)
         */
                        movl SYMBOL_NAME(GDT_base), %edi
                        addl %ebx, %edi
                        xorl %ebx, %ebx
                        movb 7(%edi), %bh
                        movb 4(%edi), %bl
                        shl $16, %ebx
                        movw 2(%edi), %bx
                        /* Is it correct? I think so... Test it!!! */
                        addl %ebx, %esp
                        /* Save EBX for returning to our stack... */
                        movw %ss, %dx
                        movw %ds, %bx
                        movw %bx, %ss
                        pushl %ebx
                        pushl %edx
#endif
                        pushl %eax

                        movl    SYMBOL_NAME(ll_irq_table)(, %eax, 4), %ebx
                        call    *%ebx
                
                        popl    %ebx    /* Store in EBX the Int number  */
#if 0
                        popl    %eax
                        popl    %ecx    /* We must subtract it from ESP...*/
                        subl    %ecx, %esp
                        movw    %ax, %ss
#endif                  
                        /* Send EOI to master & slave (if necessary) PIC */
                        movb    $0x20,%al
                        cmpl    $0x08,%ebx
                        jb      eoi_master
eoi_slave:              movl    $0xA0,%edx
                        outb    %al,%dx
eoi_master:             movl    $0x20,%edx
                        outb    %al,%dx
                        
                        /* Resume the return value of _act_int          */
                        /* & do the context switch if necessary!        */
#ifdef __VIRCSW__
                        movw SYMBOL_NAME(currCtx), %ax
                        cmpw    JmpSel,%ax
                        je      NoPreempt3
                        movw    %ax,JmpSel
                        ljmp    JmpZone 
#endif                  
NoPreempt3:             popl    %gs
                        popl    %fs
                        popl    %es
                        popl    %ss
                        popl    %ds
                        popal
                        iret
                                

EXC(0)
EXC(1)
EXC(2)
EXC(3)
EXC(4)
EXC(5)
EXC(6)
EXC(8)
EXC(9)
EXC(10)
EXC(11)
EXC(12)
EXC(13)
EXC(14)
EXC(15)
EXC(16)

/* OK, this is Exception 7, and it is generated when an ESC or WAIT
 * intruction is reached, and the MP and TS bits are set... Basically,
 * it means that the FPU context must be switched
 */
SYMBOL_NAME_LABEL(exc7) pushal
                        pushl   %ds
                        pushl   %ss
                        pushl   %es
                        pushl   %fs
                        pushl   %gs
                        movw    $(X_FLATDATA_SEL),%ax
                        movw    %ax,%es
                        movw    %ax,%ds
                        cld
                        call    SYMBOL_NAME(ll_FPU_hook)
                        popl    %gs
                        popl    %fs
                        popl    %es
                        popl    %ss
                        popl    %ds
                        popal
                        iret
                        
ll_handler2:            
                        pushl   %eax
                        movw    $(X_FLATDATA_SEL),%ax
                        movw    %ax,%ds
                        movw    %ax,%es


                        /* Again, the following could be optimized... */
/*
    If the Exception raised in a different address space, we have to
    access the task stack from the kernel address space (the linear one...)
*/
                        popl %eax
                        movw %ss, %bx
                        /* We must switch to a ``safe stack'' */
                        movl SYMBOL_NAME(GDT_base), %edi
                        addl %ebx, %edi
                        xorl %ebx, %ebx
                        movb 7(%edi), %bh
                        movb 4(%edi), %bl
                        shl $16, %ebx
                        movw 2(%edi), %bx
                        /* Is it correct? I think so... Test it!!! */
                        addl %ebx, %esp
                        /* Save EBX for returning to our stack... */
                        movw %ss, %dx
                        movw %ds, %bx
                        movw %bx, %ss
                        pushl %ebx
                        pushl %edx
                        pushl %eax
                        call    *SYMBOL_NAME(ll_exc_table)(, %eax, 4)
                        addl    $4,%esp

                        /* Restore the stack pointer!!! */
                        popl %eax
                        popl %ebx
                        movw %ax, %ss
                        subl %ebx, %esp
                        iret