[GOOD] BUILD 0.1.0.450 DATE 8/29/2011 AT 10:30 AM
==================================================== + Changed 'align 0x4' line above multiboot header in loader.asm to 'align 4' + Removed -e option for echo in build.sh + Modified build.sh for linux + Fixed triple fault when enabling paging + Fixed page faults at memory manager initialization + Fixed 'mem' console function + Added more info about page fault at crash screen + Added Panic() macro + Added verbose mode for memory manager [ BAD] BUILD 0.1.0.390 DATE 8/27/2011 AT 10:54 PM ==================================================== + Added stdlib routines, separated in different files + Rewritten physical memory manager + Added virtual mem manager + Added memory allocation/freeing + Added memory library + Added temporary allocation (at end of kernel), until paging is started - Removed functionality from debug console function 'mem' - Removed system.h, the one remaining function now in stdio.h
This commit is contained in:
		
							
								
								
									
										23
									
								
								Kernel/hal/cpu/gdt-asm.asm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								Kernel/hal/cpu/gdt-asm.asm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
; GLOBAL DESCRIPTOR TABLE
 | 
			
		||||
; 
 | 
			
		||||
; 
 | 
			
		||||
 | 
			
		||||
bits 32
 | 
			
		||||
; !!!  GDT  !!!
 | 
			
		||||
; This will set up our new segment registers. We need to do
 | 
			
		||||
; something special in order to set CS. We do what is called a
 | 
			
		||||
; far jump. A jump that includes a segment as well as an offset.
 | 
			
		||||
 | 
			
		||||
global GdtFlush     ; Allows the C code to link to this
 | 
			
		||||
extern gp            ; Says that 'gp' is in another file
 | 
			
		||||
GdtFlush:
 | 
			
		||||
    lgdt [gp]        ; Load the GDT with our 'gp' which is a special pointer
 | 
			
		||||
    mov ax, 0x10      ; 0x10 is the offset in the GDT to our data segment
 | 
			
		||||
    mov ds, ax
 | 
			
		||||
    mov es, ax
 | 
			
		||||
    mov fs, ax
 | 
			
		||||
    mov gs, ax
 | 
			
		||||
    mov ss, ax
 | 
			
		||||
    jmp 0x08:flush2   ; 0x08 is the offset to our code segment: Far jump!
 | 
			
		||||
flush2:
 | 
			
		||||
    ret               ; Returns back to the C code!
 | 
			
		||||
							
								
								
									
										74
									
								
								Kernel/hal/cpu/gdt.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								Kernel/hal/cpu/gdt.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
			
		||||
/******************************************************************
 | 
			
		||||
 *    gdt.c  -  GLOBAL DESCRIPTOR TABLE                           *
 | 
			
		||||
 *      Contains function prototypes for setting up the GDT       *
 | 
			
		||||
 ******************************************************************/
 | 
			
		||||
#define MAX_DESCRIPTORS 5
 | 
			
		||||
#include "gdt.h"
 | 
			
		||||
 | 
			
		||||
/* Our GDT, with 3 entries, and finally our special GDT pointer */
 | 
			
		||||
struct GdtEntry gdt[MAX_DESCRIPTORS];
 | 
			
		||||
struct GdtPointer gp;
 | 
			
		||||
 | 
			
		||||
		
 | 
			
		||||
/* Setup a descriptor in the Global Descriptor Table */
 | 
			
		||||
void GdtSetGate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran)
 | 
			
		||||
{
 | 
			
		||||
    /* Sanity check */
 | 
			
		||||
    if (num >= MAX_DESCRIPTORS) return;
 | 
			
		||||
    
 | 
			
		||||
    /* Setup the descriptor base address */
 | 
			
		||||
    gdt[num].base_low = (base & 0xFFFF);
 | 
			
		||||
    gdt[num].base_middle = (base >> 16) & 0xFF;
 | 
			
		||||
    gdt[num].base_high = (base >> 24) & 0xFF;
 | 
			
		||||
 | 
			
		||||
    /* Setup the descriptor limits */
 | 
			
		||||
    gdt[num].limit_low = (limit & 0xFFFF);
 | 
			
		||||
    gdt[num].granularity = ((limit >> 16) & 0x0F);
 | 
			
		||||
 | 
			
		||||
    /* Finally, set up the granularity and access flags */
 | 
			
		||||
    gdt[num].granularity |= (gran & 0xF0);
 | 
			
		||||
    gdt[num].access = access;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct GdtEntry* GdtGetGate(int num)
 | 
			
		||||
{
 | 
			
		||||
      if (num>MAX_DESCRIPTORS) return 0;
 | 
			
		||||
      return &gdt[num];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Should be called by main. This will setup the special GDT
 | 
			
		||||
*  pointer, set up the first 3 entries in our GDT, and then
 | 
			
		||||
*  finally call gdt_flush() in our assembler file in order
 | 
			
		||||
*  to tell the processor where the new GDT is and update the
 | 
			
		||||
*  new segment registers */
 | 
			
		||||
void GdtInstall()
 | 
			
		||||
{
 | 
			
		||||
    /* Setup the GDT pointer and limit */
 | 
			
		||||
    gp.limit = (sizeof(struct GdtEntry) * 3) - 1;
 | 
			
		||||
    gp.base = (unsigned int)&gdt;
 | 
			
		||||
 | 
			
		||||
    /* Our NULL descriptor */
 | 
			
		||||
    GdtSetGate(0, 0, 0, 0, 0);
 | 
			
		||||
 | 
			
		||||
    /* The second entry is our Code Segment. The base address
 | 
			
		||||
    *  is 0, the limit is 4GBytes, it uses 4KByte granularity,
 | 
			
		||||
    *  uses 32-bit opcodes, and is a Code Segment descriptor.
 | 
			
		||||
    *  Please check the table above in the tutorial in order
 | 
			
		||||
    *  to see exactly what each value means */
 | 
			
		||||
    GdtSetGate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
 | 
			
		||||
 | 
			
		||||
    /* The third entry is our Data Segment. It's EXACTLY the
 | 
			
		||||
    *  same as our code segment, but the descriptor type in
 | 
			
		||||
    *  this entry's access byte says it's a Data Segment */
 | 
			
		||||
    GdtSetGate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
 | 
			
		||||
 | 
			
		||||
    /* User mode Code segment*/
 | 
			
		||||
    GdtSetGate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF);
 | 
			
		||||
    
 | 
			
		||||
    /* User mode data segment*/
 | 
			
		||||
    GdtSetGate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF);
 | 
			
		||||
 | 
			
		||||
    /* Flush out the old GDT and install the new changes! */
 | 
			
		||||
    GdtFlush();
 | 
			
		||||
}
 | 
			
		||||
		
 | 
			
		||||
							
								
								
									
										38
									
								
								Kernel/hal/cpu/gdt.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								Kernel/hal/cpu/gdt.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
/******************************************************************
 | 
			
		||||
 *    gdt.h  -  GLOBAL DESCRIPTOR TABLE                           *
 | 
			
		||||
 *      Contains structures and function declarations for GDT     *
 | 
			
		||||
 ******************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef __GDT_H
 | 
			
		||||
#define __GDT_H
 | 
			
		||||
 | 
			
		||||
/* Defines a GDT entry. We say packed, because it prevents the
 | 
			
		||||
*  compiler from doing things that it thinks is best: Prevent
 | 
			
		||||
*  compiler "optimization" by packing */
 | 
			
		||||
struct GdtEntry
 | 
			
		||||
{
 | 
			
		||||
    unsigned short limit_low;
 | 
			
		||||
    unsigned short base_low;
 | 
			
		||||
    unsigned char base_middle;
 | 
			
		||||
    unsigned char access;
 | 
			
		||||
    unsigned char granularity;
 | 
			
		||||
    unsigned char base_high;
 | 
			
		||||
} __attribute__((packed));
 | 
			
		||||
 | 
			
		||||
/* Special pointer which includes the limit: The max bytes
 | 
			
		||||
*  taken up by the GDT, minus 1. Again, this NEEDS to be packed */
 | 
			
		||||
struct GdtPointer
 | 
			
		||||
{
 | 
			
		||||
    unsigned short limit;
 | 
			
		||||
    unsigned int base;
 | 
			
		||||
} __attribute__((packed));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* This will be a function in start.asm. We use this to properly
 | 
			
		||||
*  reload the new segment registers */
 | 
			
		||||
extern void GdtInstall();
 | 
			
		||||
extern void GdtFlush();
 | 
			
		||||
extern void GdtSetGate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran);
 | 
			
		||||
extern struct GdtEntry* GdtGetGate(int num);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										9
									
								
								Kernel/hal/cpu/idt-asm.asm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								Kernel/hal/cpu/idt-asm.asm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
bits 32
 | 
			
		||||
 | 
			
		||||
; !!!  IDT  !!!
 | 
			
		||||
; Loads the IDT defined in '_idtp'
 | 
			
		||||
global IdtLoad
 | 
			
		||||
extern idtp
 | 
			
		||||
IdtLoad:
 | 
			
		||||
      lidt [idtp]
 | 
			
		||||
      ret
 | 
			
		||||
							
								
								
									
										45
									
								
								Kernel/hal/cpu/idt.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								Kernel/hal/cpu/idt.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
/******************************************************************
 | 
			
		||||
 *    idt.h  -  INTERRUPT DESCRIPTOR TABLE                        *
 | 
			
		||||
 *      Contains structures and function declarations for IDT     *
 | 
			
		||||
 ******************************************************************/
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include "idt.h"
 | 
			
		||||
 | 
			
		||||
extern void IdtLoad();
 | 
			
		||||
/* Declare an IDT of 256 entries.  */
 | 
			
		||||
struct IdtEntry idt[256];
 | 
			
		||||
struct IdtPointer idtp;
 | 
			
		||||
 | 
			
		||||
/* Use this function to set an entry in the IDT. Alot simpler
 | 
			
		||||
*  than twiddling with the GDT ;) */
 | 
			
		||||
void IdtSetGate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags)
 | 
			
		||||
{
 | 
			
		||||
    /* The interrupt routine's base address */
 | 
			
		||||
    idt[num].base_lo = (base & 0xFFFF);
 | 
			
		||||
    idt[num].base_hi = (base >> 16) & 0xFFFF;
 | 
			
		||||
 | 
			
		||||
    /* The segment or 'selector' that this IDT entry will use
 | 
			
		||||
    *  is set here, along with any access flags */
 | 
			
		||||
    idt[num].sel = sel;
 | 
			
		||||
    idt[num].always0 = 0;
 | 
			
		||||
    idt[num].flags = flags;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct IdtEntry* IdtGetGate(unsigned char num)
 | 
			
		||||
{
 | 
			
		||||
      return &idt[num];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Installs the IDT */
 | 
			
		||||
void IdtInstall()
 | 
			
		||||
{
 | 
			
		||||
    /* Sets the special IDT pointer up, just like in 'gdt.c' */
 | 
			
		||||
    idtp.limit = (sizeof (struct IdtEntry) * 256) - 1;
 | 
			
		||||
    idtp.base = (unsigned int)&idt;
 | 
			
		||||
 | 
			
		||||
    /* Clear out the entire IDT, initializing it to zeros */
 | 
			
		||||
    memset (&idt, 0, sizeof(struct IdtEntry) * 256);
 | 
			
		||||
 | 
			
		||||
    /* Points the processor's internal register to the new IDT */
 | 
			
		||||
    IdtLoad();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								Kernel/hal/cpu/idt.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								Kernel/hal/cpu/idt.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
/******************************************************************
 | 
			
		||||
 *    idt.h  -  INTERRUPT DESCRIPTOR TABLE                        *
 | 
			
		||||
 *      Contains structures and function declarations for IDT     *
 | 
			
		||||
 ******************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef __IDT_H
 | 
			
		||||
#define __IDT_H
 | 
			
		||||
 | 
			
		||||
/* Defines an IDT entry */
 | 
			
		||||
struct IdtEntry
 | 
			
		||||
{
 | 
			
		||||
    unsigned short base_lo;
 | 
			
		||||
    unsigned short sel;
 | 
			
		||||
    unsigned char always0;
 | 
			
		||||
    unsigned char flags;
 | 
			
		||||
    unsigned short base_hi;
 | 
			
		||||
} __attribute__((packed));
 | 
			
		||||
 | 
			
		||||
struct IdtPointer
 | 
			
		||||
{
 | 
			
		||||
    unsigned short limit;
 | 
			
		||||
    unsigned int base;
 | 
			
		||||
} __attribute__((packed));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* This exists in 'start.asm', and is used to load our IDT */
 | 
			
		||||
extern void IdtSetGate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags);
 | 
			
		||||
extern struct IdtEntry* IdtGetGate(unsigned char num);
 | 
			
		||||
extern void IdtInstall();
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										159
									
								
								Kernel/hal/cpu/irq-asm.asm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								Kernel/hal/cpu/irq-asm.asm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,159 @@
 | 
			
		||||
bits 32
 | 
			
		||||
 | 
			
		||||
; !!!  IRQ !!!
 | 
			
		||||
global Irq_0
 | 
			
		||||
global Irq_1
 | 
			
		||||
global Irq_2
 | 
			
		||||
global Irq_3
 | 
			
		||||
global Irq_4
 | 
			
		||||
global Irq_5
 | 
			
		||||
global Irq_6
 | 
			
		||||
global Irq_7
 | 
			
		||||
global Irq_8
 | 
			
		||||
global Irq_9
 | 
			
		||||
global Irq_10
 | 
			
		||||
global Irq_11
 | 
			
		||||
global Irq_12
 | 
			
		||||
global Irq_13
 | 
			
		||||
global Irq_14
 | 
			
		||||
global Irq_15
 | 
			
		||||
 | 
			
		||||
; 32: IRQ0
 | 
			
		||||
Irq_0:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 32; Note that these don't push an error code on the stack:
 | 
			
		||||
                   ; We need to push a dummy error code
 | 
			
		||||
      jmp irq_common_stub
 | 
			
		||||
 | 
			
		||||
; 33: IRQ1
 | 
			
		||||
Irq_1:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 33
 | 
			
		||||
      jmp irq_common_stub
 | 
			
		||||
 | 
			
		||||
; 34: IRQ2
 | 
			
		||||
Irq_2:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 34
 | 
			
		||||
      jmp irq_common_stub
 | 
			
		||||
      
 | 
			
		||||
; 35: IRQ3
 | 
			
		||||
Irq_3:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 35
 | 
			
		||||
      jmp irq_common_stub
 | 
			
		||||
 | 
			
		||||
; 36: IRQ4
 | 
			
		||||
Irq_4:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 36
 | 
			
		||||
      jmp irq_common_stub
 | 
			
		||||
 | 
			
		||||
; 37: IRQ5
 | 
			
		||||
Irq_5:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 37
 | 
			
		||||
      jmp irq_common_stub
 | 
			
		||||
 | 
			
		||||
; 38: IRQ6
 | 
			
		||||
Irq_6:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 38
 | 
			
		||||
      jmp irq_common_stub
 | 
			
		||||
      
 | 
			
		||||
; 39: IRQ7
 | 
			
		||||
Irq_7:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 39
 | 
			
		||||
      jmp irq_common_stub
 | 
			
		||||
 | 
			
		||||
; 40: IRQ8
 | 
			
		||||
Irq_8:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 40
 | 
			
		||||
      jmp irq_common_stub      
 | 
			
		||||
; 41: IRQ9
 | 
			
		||||
Irq_9:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 41
 | 
			
		||||
      jmp irq_common_stub
 | 
			
		||||
 | 
			
		||||
; 42: IRQ10
 | 
			
		||||
Irq_10:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 42
 | 
			
		||||
      jmp irq_common_stub
 | 
			
		||||
      
 | 
			
		||||
; 43: IRQ11
 | 
			
		||||
Irq_11:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 43
 | 
			
		||||
      jmp irq_common_stub
 | 
			
		||||
 | 
			
		||||
; 44: IRQ12
 | 
			
		||||
Irq_12:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 44
 | 
			
		||||
      jmp irq_common_stub
 | 
			
		||||
      
 | 
			
		||||
; 45: IRQ13
 | 
			
		||||
Irq_13:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 45
 | 
			
		||||
      jmp irq_common_stub
 | 
			
		||||
 | 
			
		||||
; 46: IRQ14
 | 
			
		||||
Irq_14:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 46
 | 
			
		||||
      jmp irq_common_stub
 | 
			
		||||
      
 | 
			
		||||
; 47: IRQ15
 | 
			
		||||
Irq_15:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 47
 | 
			
		||||
      jmp irq_common_stub
 | 
			
		||||
 | 
			
		||||
extern IrqHandler
 | 
			
		||||
 | 
			
		||||
; This is a stub that we have created for IRQ based ISRs. This calls
 | 
			
		||||
; 'Irq__handler' in our C code. We need to create this in an 'irq.c'
 | 
			
		||||
irq_common_stub:
 | 
			
		||||
      pusha
 | 
			
		||||
      push ds
 | 
			
		||||
      push es
 | 
			
		||||
      push fs
 | 
			
		||||
      push gs
 | 
			
		||||
      mov ax, 0x10
 | 
			
		||||
      mov ds, ax
 | 
			
		||||
      mov es, ax
 | 
			
		||||
      mov fs, ax
 | 
			
		||||
      mov gs, ax
 | 
			
		||||
      mov eax, esp
 | 
			
		||||
      push eax
 | 
			
		||||
      mov eax, IrqHandler
 | 
			
		||||
      call eax
 | 
			
		||||
      pop eax
 | 
			
		||||
      pop gs
 | 
			
		||||
      pop fs
 | 
			
		||||
      pop es
 | 
			
		||||
      pop ds
 | 
			
		||||
      popa
 | 
			
		||||
      add esp, 8
 | 
			
		||||
      iret
 | 
			
		||||
							
								
								
									
										91
									
								
								Kernel/hal/cpu/irq.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								Kernel/hal/cpu/irq.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include "pic.h"
 | 
			
		||||
#include "irq.h"
 | 
			
		||||
#include "idt.h"
 | 
			
		||||
 | 
			
		||||
/* These are own ISRs that point to our special IRQ handler
 | 
			
		||||
*  instead of the regular 'fault_handler' function */
 | 
			
		||||
extern void Irq_0();
 | 
			
		||||
extern void Irq_1();
 | 
			
		||||
extern void Irq_2();
 | 
			
		||||
extern void Irq_3();
 | 
			
		||||
extern void Irq_4();
 | 
			
		||||
extern void Irq_5();
 | 
			
		||||
extern void Irq_6();
 | 
			
		||||
extern void Irq_7();
 | 
			
		||||
extern void Irq_8();
 | 
			
		||||
extern void Irq_9();
 | 
			
		||||
extern void Irq_10();
 | 
			
		||||
extern void Irq_11();
 | 
			
		||||
extern void Irq_12();
 | 
			
		||||
extern void Irq_13();
 | 
			
		||||
extern void Irq_14();
 | 
			
		||||
extern void Irq_15();
 | 
			
		||||
 | 
			
		||||
/* This array is actually an array of function pointers. We use
 | 
			
		||||
*  this to handle custom IRQ handlers for a given IRQ */
 | 
			
		||||
void *IrqRoutines[16] =
 | 
			
		||||
{
 | 
			
		||||
    0, 0, 0, 0, 0, 0, 0, 0,
 | 
			
		||||
    0, 0, 0, 0, 0, 0, 0, 0
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* This installs a custom IRQ handler for the given IRQ */
 | 
			
		||||
void IrqInstallHandler (int irq, void (*handler)(_RegsStack32 *r))
 | 
			
		||||
{
 | 
			
		||||
      IrqRoutines[irq] = handler;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void IrqUninstallHandler (int irq)
 | 
			
		||||
{
 | 
			
		||||
      IrqRoutines[irq] = 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 IrqInstall()
 | 
			
		||||
{
 | 
			
		||||
      PicRemap(32,40);
 | 
			
		||||
      
 | 
			
		||||
      IdtSetGate(32, (unsigned)Irq_0, 0x08, 0x8E);
 | 
			
		||||
      IdtSetGate(33, (unsigned)Irq_1, 0x08, 0x8E);
 | 
			
		||||
      IdtSetGate(34, (unsigned)Irq_2, 0x08, 0x8E);
 | 
			
		||||
      IdtSetGate(35, (unsigned)Irq_3, 0x08, 0x8E);
 | 
			
		||||
      IdtSetGate(36, (unsigned)Irq_4, 0x08, 0x8E);
 | 
			
		||||
      IdtSetGate(37, (unsigned)Irq_5, 0x08, 0x8E);
 | 
			
		||||
      IdtSetGate(38, (unsigned)Irq_6, 0x08, 0x8E);
 | 
			
		||||
      IdtSetGate(39, (unsigned)Irq_7, 0x08, 0x8E);
 | 
			
		||||
      IdtSetGate(40, (unsigned)Irq_8, 0x08, 0x8E);
 | 
			
		||||
      IdtSetGate(41, (unsigned)Irq_9, 0x08, 0x8E);
 | 
			
		||||
      IdtSetGate(42, (unsigned)Irq_10, 0x08, 0x8E);
 | 
			
		||||
      IdtSetGate(43, (unsigned)Irq_11, 0x08, 0x8E);
 | 
			
		||||
      IdtSetGate(44, (unsigned)Irq_12, 0x08, 0x8E);
 | 
			
		||||
      IdtSetGate(45, (unsigned)Irq_13, 0x08, 0x8E);
 | 
			
		||||
      IdtSetGate(46, (unsigned)Irq_14, 0x08, 0x8E);
 | 
			
		||||
      IdtSetGate(47, (unsigned)Irq_15, 0x08, 0x8E);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Default IRQ handler, launches other handler if installed.
 | 
			
		||||
// Also sends end-of-interrupt messages to PIC
 | 
			
		||||
void IrqHandler (_RegsStack32 *r)
 | 
			
		||||
{
 | 
			
		||||
	/* This is a blank function pointer */
 | 
			
		||||
      void (*handler)(_RegsStack32 *r);
 | 
			
		||||
      
 | 
			
		||||
    /* Find out if we have a custom handler to run for this
 | 
			
		||||
    *  IRQ, and then finally, run it */
 | 
			
		||||
      handler = IrqRoutines[r->int_no - 32];
 | 
			
		||||
      if (handler) handler(r);
 | 
			
		||||
      
 | 
			
		||||
    /* 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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								Kernel/hal/cpu/irq.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								Kernel/hal/cpu/irq.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
#ifndef __IRQ_H
 | 
			
		||||
#define __IRQ_H
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
extern void IrqInstallHandler (int irq, void (*handler)(_RegsStack32 *r));
 | 
			
		||||
extern void IrqUninstallHandler (int irq);
 | 
			
		||||
extern void IrqInstall();
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										217
									
								
								Kernel/hal/cpu/isrs-asm.asm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										217
									
								
								Kernel/hal/cpu/isrs-asm.asm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,217 @@
 | 
			
		||||
bits 32
 | 
			
		||||
 | 
			
		||||
; !!!  ISRs  !!!
 | 
			
		||||
global isr_exception_0
 | 
			
		||||
global isr_exception_1
 | 
			
		||||
global isr_exception_2
 | 
			
		||||
global isr_exception_3
 | 
			
		||||
global isr_exception_4
 | 
			
		||||
global isr_exception_5
 | 
			
		||||
global isr_exception_6
 | 
			
		||||
global isr_exception_7
 | 
			
		||||
global isr_exception_8
 | 
			
		||||
global isr_exception_9
 | 
			
		||||
global isr_exception_10
 | 
			
		||||
global isr_exception_11
 | 
			
		||||
global isr_exception_12
 | 
			
		||||
global isr_exception_13
 | 
			
		||||
global isr_exception_14
 | 
			
		||||
global isr_exception_15
 | 
			
		||||
global isr_exception_16
 | 
			
		||||
global isr_exception_17
 | 
			
		||||
global isr_exception_18
 | 
			
		||||
global isr_exception_19
 | 
			
		||||
global isr_exception_20
 | 
			
		||||
global isr_exception_21
 | 
			
		||||
global isr_exception_22
 | 
			
		||||
global isr_exception_23
 | 
			
		||||
global isr_exception_24
 | 
			
		||||
global isr_exception_25
 | 
			
		||||
global isr_exception_26
 | 
			
		||||
global isr_exception_27
 | 
			
		||||
global isr_exception_28
 | 
			
		||||
global isr_exception_29
 | 
			
		||||
global isr_exception_30
 | 
			
		||||
global isr_exception_31
 | 
			
		||||
 | 
			
		||||
isr_exception_0:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0; A normal ISR stub that pops a dummy error code to keep a
 | 
			
		||||
                   ; uniform stack frame
 | 
			
		||||
      push byte 0
 | 
			
		||||
      jmp isr_common_stub
 | 
			
		||||
isr_exception_1:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 1
 | 
			
		||||
      jmp isr_common_stub
 | 
			
		||||
isr_exception_2:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 2
 | 
			
		||||
      jmp isr_common_stub
 | 
			
		||||
isr_exception_3:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 3
 | 
			
		||||
      jmp isr_common_stub
 | 
			
		||||
isr_exception_4:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 4
 | 
			
		||||
      jmp isr_common_stub
 | 
			
		||||
isr_exception_5:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 5
 | 
			
		||||
      jmp isr_common_stub
 | 
			
		||||
isr_exception_6:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 6
 | 
			
		||||
      jmp isr_common_stub
 | 
			
		||||
isr_exception_7:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 7
 | 
			
		||||
      jmp isr_common_stub
 | 
			
		||||
isr_exception_8:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 8
 | 
			
		||||
      jmp isr_common_stub
 | 
			
		||||
isr_exception_9:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 9
 | 
			
		||||
      jmp isr_common_stub      
 | 
			
		||||
isr_exception_10:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 10
 | 
			
		||||
      jmp isr_common_stub
 | 
			
		||||
isr_exception_11:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 11
 | 
			
		||||
      jmp isr_common_stub
 | 
			
		||||
isr_exception_12:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 12
 | 
			
		||||
      jmp isr_common_stub
 | 
			
		||||
isr_exception_13:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 13
 | 
			
		||||
      jmp isr_common_stub
 | 
			
		||||
isr_exception_14:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 14
 | 
			
		||||
      jmp isr_common_stub
 | 
			
		||||
isr_exception_15:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 15
 | 
			
		||||
      jmp isr_common_stub
 | 
			
		||||
isr_exception_16:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 16
 | 
			
		||||
      jmp isr_common_stub
 | 
			
		||||
isr_exception_17:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 17
 | 
			
		||||
      jmp isr_common_stub      
 | 
			
		||||
isr_exception_18:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 18
 | 
			
		||||
      jmp isr_common_stub      
 | 
			
		||||
isr_exception_19:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 19
 | 
			
		||||
      jmp isr_common_stub      
 | 
			
		||||
isr_exception_20:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 20
 | 
			
		||||
      jmp isr_common_stub      
 | 
			
		||||
isr_exception_21:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 21
 | 
			
		||||
      jmp isr_common_stub      
 | 
			
		||||
isr_exception_22:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 22
 | 
			
		||||
      jmp isr_common_stub      
 | 
			
		||||
isr_exception_23:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 23
 | 
			
		||||
      jmp isr_common_stub      
 | 
			
		||||
isr_exception_24:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 24
 | 
			
		||||
      jmp isr_common_stub      
 | 
			
		||||
isr_exception_25:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 25
 | 
			
		||||
      jmp isr_common_stub      
 | 
			
		||||
isr_exception_26:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 26
 | 
			
		||||
      jmp isr_common_stub      
 | 
			
		||||
isr_exception_27:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 27
 | 
			
		||||
      jmp isr_common_stub      
 | 
			
		||||
isr_exception_28:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 28
 | 
			
		||||
      jmp isr_common_stub      
 | 
			
		||||
isr_exception_29:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 29
 | 
			
		||||
      jmp isr_common_stub      
 | 
			
		||||
isr_exception_30:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 30
 | 
			
		||||
      jmp isr_common_stub      
 | 
			
		||||
isr_exception_31:
 | 
			
		||||
      cli
 | 
			
		||||
      push byte 0
 | 
			
		||||
      push byte 31
 | 
			
		||||
      jmp isr_common_stub      
 | 
			
		||||
            
 | 
			
		||||
extern IsrsFaultHandler
 | 
			
		||||
 | 
			
		||||
isr_common_stub:
 | 
			
		||||
    pusha
 | 
			
		||||
    push ds
 | 
			
		||||
    push es
 | 
			
		||||
    push fs
 | 
			
		||||
    push gs
 | 
			
		||||
    mov ax, 0x10   ; Load the Kernel Data Segment descriptor!
 | 
			
		||||
    mov ds, ax
 | 
			
		||||
    mov es, ax
 | 
			
		||||
    mov fs, ax
 | 
			
		||||
    mov gs, ax
 | 
			
		||||
    mov eax, esp   ; Push us the stack
 | 
			
		||||
    push eax
 | 
			
		||||
    mov eax, IsrsFaultHandler
 | 
			
		||||
    call eax       ; A special call, preserves the 'eip' register
 | 
			
		||||
    pop eax
 | 
			
		||||
    pop gs
 | 
			
		||||
    pop fs
 | 
			
		||||
    pop es
 | 
			
		||||
    pop ds
 | 
			
		||||
    popa
 | 
			
		||||
    add esp, 8     ; Cleans up the pushed error code and pushed ISR number
 | 
			
		||||
    iret           ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP!
 | 
			
		||||
							
								
								
									
										114
									
								
								Kernel/hal/cpu/isrs.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								Kernel/hal/cpu/isrs.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,114 @@
 | 
			
		||||
#include <debugio.h>
 | 
			
		||||
 | 
			
		||||
#include "isrs.h"
 | 
			
		||||
#include "idt.h"
 | 
			
		||||
 | 
			
		||||
// Assembly coded
 | 
			
		||||
extern void isr_exception_0();
 | 
			
		||||
extern void isr_exception_1();
 | 
			
		||||
extern void isr_exception_2();
 | 
			
		||||
extern void isr_exception_3();
 | 
			
		||||
extern void isr_exception_4();
 | 
			
		||||
extern void isr_exception_5();
 | 
			
		||||
extern void isr_exception_6();
 | 
			
		||||
extern void isr_exception_7();
 | 
			
		||||
extern void isr_exception_8();
 | 
			
		||||
extern void isr_exception_9();
 | 
			
		||||
extern void isr_exception_10();
 | 
			
		||||
extern void isr_exception_11();
 | 
			
		||||
extern void isr_exception_12();
 | 
			
		||||
extern void isr_exception_13();
 | 
			
		||||
extern void isr_exception_14();
 | 
			
		||||
extern void isr_exception_15();
 | 
			
		||||
extern void isr_exception_16();
 | 
			
		||||
extern void isr_exception_17();
 | 
			
		||||
extern void isr_exception_18();
 | 
			
		||||
extern void isr_exception_19();
 | 
			
		||||
extern void isr_exception_20();
 | 
			
		||||
extern void isr_exception_21();
 | 
			
		||||
extern void isr_exception_22();
 | 
			
		||||
extern void isr_exception_23();
 | 
			
		||||
extern void isr_exception_24();
 | 
			
		||||
extern void isr_exception_25();
 | 
			
		||||
extern void isr_exception_26();
 | 
			
		||||
extern void isr_exception_27();
 | 
			
		||||
extern void isr_exception_28();
 | 
			
		||||
extern void isr_exception_29();
 | 
			
		||||
extern void isr_exception_30();
 | 
			
		||||
extern void isr_exception_31();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void* IdtFaultHandlers[32] = {
 | 
			
		||||
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 | 
			
		||||
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
void IsrsInstall()
 | 
			
		||||
{
 | 
			
		||||
	IdtSetGate(0, (unsigned)isr_exception_0, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(1, (unsigned)isr_exception_1, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(2, (unsigned)isr_exception_2, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(3, (unsigned)isr_exception_3, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(4, (unsigned)isr_exception_4, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(5, (unsigned)isr_exception_5, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(6, (unsigned)isr_exception_6, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(7, (unsigned)isr_exception_7, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(8, (unsigned)isr_exception_8, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(9, (unsigned)isr_exception_9, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(10, (unsigned)isr_exception_10, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(11, (unsigned)isr_exception_11, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(12, (unsigned)isr_exception_12, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(13, (unsigned)isr_exception_13, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(14, (unsigned)isr_exception_14, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(15, (unsigned)isr_exception_15, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(16, (unsigned)isr_exception_16, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(17, (unsigned)isr_exception_17, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(18, (unsigned)isr_exception_18, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(19, (unsigned)isr_exception_19, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(20, (unsigned)isr_exception_20, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(21, (unsigned)isr_exception_21, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(22, (unsigned)isr_exception_22, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(23, (unsigned)isr_exception_23, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(24, (unsigned)isr_exception_24, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(25, (unsigned)isr_exception_25, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(26, (unsigned)isr_exception_26, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(27, (unsigned)isr_exception_27, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(28, (unsigned)isr_exception_28, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(29, (unsigned)isr_exception_29, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(30, (unsigned)isr_exception_30, 0x08, 0x8E);
 | 
			
		||||
	IdtSetGate(31, (unsigned)isr_exception_31, 0x08, 0x8E);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void IsrsInstallHandler(int interr, void (*function)(_RegsStack32 *r))
 | 
			
		||||
{
 | 
			
		||||
	if (interr < 32) IdtFaultHandlers[interr] = function;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void IsrsUninstallHandler(int interr)
 | 
			
		||||
{
 | 
			
		||||
	if (interr < 32) IdtFaultHandlers[interr] = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
extern void CrashMessage(_RegsStack32 *r);
 | 
			
		||||
// Default fault handler; calls other handlers, or displays error message.
 | 
			
		||||
void IsrsFaultHandler(_RegsStack32 *r)
 | 
			
		||||
{
 | 
			
		||||
	/* Is this a fault whose number is from 0 to 31? */
 | 
			
		||||
	if (r->int_no < 32)
 | 
			
		||||
	{
 | 
			
		||||
		void (*func)(_RegsStack32 *r);
 | 
			
		||||
		func = IdtFaultHandlers[r->int_no];
 | 
			
		||||
		
 | 
			
		||||
		// Halt system if unhandled
 | 
			
		||||
		if (!func) {
 | 
			
		||||
			CrashMessage(r);
 | 
			
		||||
			asm ("cli");
 | 
			
		||||
			asm ("hlt");
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		else (*func)(r);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								Kernel/hal/cpu/isrs.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								Kernel/hal/cpu/isrs.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
#ifndef __ISRS_H_
 | 
			
		||||
#define __ISRS_H_
 | 
			
		||||
 | 
			
		||||
#include <types.h>
 | 
			
		||||
 | 
			
		||||
extern void IsrsInstall();
 | 
			
		||||
extern void IsrsInstallHandler(int interr, void (*function)(_RegsStack32 *r));
 | 
			
		||||
extern void IsrsUninstallHandler(int interr);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										23
									
								
								Kernel/hal/cpu/pic.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								Kernel/hal/cpu/pic.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include "pic.h"
 | 
			
		||||
 | 
			
		||||
void PicRemap(int pic1, int pic2)
 | 
			
		||||
{
 | 
			
		||||
      // Send ICW1
 | 
			
		||||
      outportb(0x20, 0x11);
 | 
			
		||||
      outportb(0xA0, 0x11);
 | 
			
		||||
      
 | 
			
		||||
      // send ICW2
 | 
			
		||||
      outportb(0x21, pic1); // remap pics
 | 
			
		||||
      outportb(0xA1, pic2);
 | 
			
		||||
      
 | 
			
		||||
      // send ICW3
 | 
			
		||||
      outportb(0x21, 4);
 | 
			
		||||
      outportb(0xA1, 2);
 | 
			
		||||
      
 | 
			
		||||
      // Send ICW4
 | 
			
		||||
      outportb(0x21, 0x01);
 | 
			
		||||
      outportb(0xA1, 0x01);
 | 
			
		||||
      
 | 
			
		||||
      outportb(0x21, 0x00);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										6
									
								
								Kernel/hal/cpu/pic.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								Kernel/hal/cpu/pic.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
#ifndef _PIC_H
 | 
			
		||||
#define _PIC_H
 | 
			
		||||
 | 
			
		||||
extern void PicRemap(int pic1, int pic2);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
		Reference in New Issue
	
	Block a user