Index: branches/ErmaC/Enoch/i386/libsaio/bios.s =================================================================== --- branches/ErmaC/Enoch/i386/libsaio/bios.s (revision 2584) +++ branches/ErmaC/Enoch/i386/libsaio/bios.s (revision 2585) @@ -106,6 +106,8 @@ */ LABEL(_bios) enter $0, $0 + pushfl + cli pushal movl 8(%ebp), %edx // address of save area @@ -179,6 +181,7 @@ movl %ebp, O_EBP(%edx) popal + popfl leave ret Index: branches/ErmaC/Enoch/i386/libsaio/biosfn.c =================================================================== --- branches/ErmaC/Enoch/i386/libsaio/biosfn.c (revision 2584) +++ branches/ErmaC/Enoch/i386/libsaio/biosfn.c (revision 2585) @@ -53,12 +53,15 @@ int bgetc(void) { +#if 0 /* Poll for the next character. Most real BIOS do not need this as the INT 16h,AH=0h function will block until one is received. Unfortunately, Apple's EFI CSM will never wake up. This idea is lifted from the grub-a20.patch to GRUB's stage2/asm.S file. */ while(!readKeyboardStatus()); + // Apple's EFI CSM???? Who cares - Zenith432 +#endif bb.intno = 0x16; bb.eax.r.h = 0x00; @@ -85,10 +88,14 @@ int readKeyboardShiftFlags(void) { +#if 0 bb.intno = 0x16; bb.eax.r.h = 0x02; bios(&bb); return bb.eax.r.l; +#else + return *(uint8_t const volatile*) 0x417U; +#endif } @@ -96,6 +103,7 @@ unsigned int time18(void) { +#if 0 union { struct { unsigned int low:16; @@ -112,6 +120,10 @@ time.s.high = bb.ecx.rr; return time.i; +#else + (void) __sync_lock_test_and_set((uint8_t volatile*) 0x470U, (uint8_t) 0U); + return *(uint32_t const volatile*) 0x46CU; +#endif } //#if 0 /* COMMENTED */ @@ -741,6 +753,7 @@ //============================================================================== +#if UNUSED int ebiosEjectMedia(int biosdev) { bb.intno = 0x13; @@ -750,6 +763,7 @@ bios(&bb); return bb.eax.r.h; } +#endif void setCursorPosition(int x, int y, int page) { @@ -977,6 +991,7 @@ } #endif /* EISA_SUPPORT */ +#if UNUSED #define PCI_SIGNATURE 0x20494350 /* "PCI " */ int @@ -997,11 +1012,20 @@ } return -1; } +#endif void sleep(int n) { - unsigned int endtime = (time18() + 18*n); - while (time18() < endtime); + // FIXME: doesn't handle midnight wraparound + unsigned int endtime = (time18() + 18*n); +#ifdef __i386__ + while (time18() < endtime) + { + __asm__ volatile ("rep; nop"); + } +#else + while (time18() < endtime); +#endif } Index: branches/ErmaC/Enoch/i386/boot2/boot.c =================================================================== --- branches/ErmaC/Enoch/i386/boot2/boot.c (revision 2584) +++ branches/ErmaC/Enoch/i386/boot2/boot.c (revision 2585) @@ -77,6 +77,8 @@ bool gScanSingleDrive; bool useGUI; +static int interruptsAvailable = 0; + static bool gUnloadPXEOnExit = false; static char gCacheNameAdler[64 + 256]; @@ -199,6 +201,10 @@ usb_loop(); +#if DEBUG + if (interruptsAvailable) ShowInterruptCounters(); +#endif + // If we were in text mode, switch to graphics mode. // This will draw the boot graphics unless we are in // verbose mode. @@ -224,6 +230,11 @@ // Notify modules that the kernel is about to be started execute_hook("Kernel Start", (void *)kernelEntry, (void *)bootArgs, NULL, NULL); + if (interruptsAvailable) + { + DisableInterrupts(); + } + // Masking out so that Lion doesn't doublefault startprog( kernelEntry, bootArgs ); @@ -233,11 +244,16 @@ // Notify modules that the kernel is about to be started execute_hook("Kernel Start", (void*)kernelEntry, (void*)bootArgsPreLion, NULL, NULL); + if (interruptsAvailable) + { + DisableInterrupts(); + } + startprog( kernelEntry, bootArgsPreLion ); } // Not reached - return 0; + __builtin_unreachable(); } @@ -437,6 +453,13 @@ // Initialize boot-log initBooterLog(); + // Enable interrupts + interruptsAvailable = SetupInterrupts(); + if (interruptsAvailable) + { + EnableInterrupts(); + } + // Initialize boot info structure. initKernBootStruct(); @@ -839,6 +862,11 @@ { nbpUnloadBaseCode(); } + + if (interruptsAvailable) + { + DisableInterrupts(); + } } /*! Index: branches/ErmaC/Enoch/i386/boot2/gui.c =================================================================== --- branches/ErmaC/Enoch/i386/boot2/gui.c (revision 2584) +++ branches/ErmaC/Enoch/i386/boot2/gui.c (revision 2585) @@ -1967,6 +1967,7 @@ // ==================================================================== +#if UNUSED void animateProgressBar() { int y; @@ -1986,6 +1987,7 @@ pixel(buffBar, buffBar->width-1, 0).value = buff; } } +#endif // ==================================================================== @@ -2045,7 +2047,9 @@ } blend(&progressbar, blendInto, p); +#if 0 animateProgressBar(); +#endif free(progressbar.pixels); } Index: branches/ErmaC/Enoch/i386/boot2/options.c =================================================================== --- branches/ErmaC/Enoch/i386/boot2/options.c (revision 2584) +++ branches/ErmaC/Enoch/i386/boot2/options.c (revision 2585) @@ -190,11 +190,24 @@ for ( time = time18(), timeout++; timeout > 0; ) { - if( time18() > lasttime) + int currenttime; + if (lasttime) { - multi--; - lasttime=time18(); - } + currenttime = time18(); + if( currenttime > lasttime) + { + multi -= (currenttime - lasttime); + if (multi < 0) + { + multi = 0; + } + lasttime=currenttime; + } + } + else + { + lasttime = currenttime = time; + } if ( (ch = readKeyboardStatus()) ) break; @@ -207,7 +220,7 @@ break; } - if ( time18() >= time ) + if ( currenttime >= time ) { time += 18; timeout--; @@ -413,7 +426,7 @@ gMenuStart = 0; gMenuEnd = MIN( count, gui.maxdevices ) - 1; - + // If the selected item is not visible, shift the list down. if ( gMenuSelection > gMenuBottom ) @@ -451,38 +464,38 @@ static int updateMenu( int key, void ** paramPtr ) { - int moved = 0; + int moved = 0; - union { - struct { - unsigned int - selectionUp : 1, - selectionDown : 1, - scrollUp : 1, - scrollDown : 1; - } f; - unsigned int w; - } draw = {{0}}; + union { + struct { + unsigned int + selectionUp : 1, + selectionDown : 1, + scrollUp : 1, + scrollDown : 1; + } f; + unsigned int w; + } draw = {{0}}; - if ( gMenuItems == NULL ) + if ( gMenuItems == NULL ) return 0; if( bootArgs->Video.v_display != VGA_TEXT_MODE ) { int res; - + // set navigation keys for horizontal layout as defaults int previous = 0x4B00; // left arrow int subsequent = 0x4D00; // right arrow - int menu = 0x5000; // down arrow - + int menu = 0x5000; // down arrow + if ( gui.layout == VerticalLayout ) { // set navigation keys for vertical layout previous = 0x4800; // up arrow subsequent = 0x5000; // down arrow menu = 0x4B00; // right arrow - } + } if ( key == previous ) { @@ -490,7 +503,7 @@ draw.f.selectionUp = 1; else if ( gMenuTop > 0 ) draw.f.scrollDown = 1; - + } else if ( key == subsequent ) @@ -518,7 +531,7 @@ else { shouldboot = ( res != DO_NOT_BOOT ); - + if ( shouldboot ) gui.menu.draw = false; @@ -528,31 +541,33 @@ gVerboseMode = false; gBootMode = kBootModeNormal; break; - + case BOOT_VERBOSE: gVerboseMode = true; gBootMode = kBootModeNormal; addBootArg(kVerboseModeFlag); break; - + case BOOT_IGNORECACHE: gVerboseMode = false; gBootMode = kBootModeNormal; addBootArg(kIgnoreCachesFlag); break; - + case BOOT_SINGLEUSER: gVerboseMode = true; gBootMode = kBootModeNormal; addBootArg(kSingleUserModeFlag); break; } - + } - - } - - } else { + + } + + } + else + { switch ( key ) { case 0x4800: // Up Arrow @@ -571,31 +586,30 @@ } } - if ( draw.w ) - { - if ( draw.f.scrollUp ) - { - scollPage(0, gMenuRow, 40, gMenuRow + gMenuHeight - 1, 0x07, 1, 1); - gMenuTop++; gMenuBottom++; + if ( draw.w ) + { + if ( draw.f.scrollUp ) + { + scollPage(0, gMenuRow, 40, gMenuRow + gMenuHeight - 1, 0x07, 1, 1); + gMenuTop++; gMenuBottom++; gMenuStart++; gMenuEnd++; - draw.f.selectionDown = 1; - } + draw.f.selectionDown = 1; + } - if ( draw.f.scrollDown ) - { - scollPage(0, gMenuRow, 40, gMenuRow + gMenuHeight - 1, 0x07, 1, -1); - gMenuTop--; gMenuBottom--; - gMenuStart--; gMenuEnd--; - draw.f.selectionUp = 1; - } + if ( draw.f.scrollDown ) + { + scollPage(0, gMenuRow, 40, gMenuRow + gMenuHeight - 1, 0x07, 1, -1); + gMenuTop--; gMenuBottom--; + gMenuStart--; gMenuEnd--; + draw.f.selectionUp = 1; + } - if ( draw.f.selectionUp || draw.f.selectionDown ) - { - + if ( draw.f.selectionUp || draw.f.selectionDown ) + { CursorState cursorState; // Set cursor at current position, and clear inverse video. - + if( bootArgs->Video.v_display == VGA_TEXT_MODE ) { changeCursor( 0, gMenuRow + gMenuSelection - gMenuTop, kCursorTypeHidden, &cursorState ); @@ -610,32 +624,35 @@ gMenuStart--; gMenuEnd--; } - - } else { - gMenuSelection++; - if(( gMenuSelection - ( gui.maxdevices - 1) - gMenuStart) > 0 ) + + } + else { - gMenuStart++; - gMenuEnd++; + gMenuSelection++; + if(( gMenuSelection - ( gui.maxdevices - 1) - gMenuStart) > 0 ) + { + gMenuStart++; + gMenuEnd++; + } } - } - if( bootArgs->Video.v_display == VGA_TEXT_MODE ) - { - moveCursor( 0, gMenuRow + gMenuSelection - gMenuTop ); - printMenuItem( &gMenuItems[gMenuSelection], 1 ); - restoreCursor( &cursorState ); + if( bootArgs->Video.v_display == VGA_TEXT_MODE ) + { + moveCursor( 0, gMenuRow + gMenuSelection - gMenuTop ); + printMenuItem( &gMenuItems[gMenuSelection], 1 ); + restoreCursor( &cursorState ); - } else + } + else + { + drawDeviceList (gMenuStart, gMenuEnd, gMenuSelection); + } + } - drawDeviceList (gMenuStart, gMenuEnd, gMenuSelection); - + *paramPtr = gMenuItems[gMenuSelection].param; + moved = 1; } - *paramPtr = gMenuItems[gMenuSelection].param; - moved = 1; - } - return moved; } @@ -750,7 +767,8 @@ void lspci(void) { - if (bootArgs->Video.v_display == VGA_TEXT_MODE) { + if (bootArgs->Video.v_display == VGA_TEXT_MODE) + { setActiveDisplayPage(1); clearScreenRows(0, 24); setCursorPosition(0, 0, 1); @@ -760,7 +778,8 @@ pause(); - if (bootArgs->Video.v_display == VGA_TEXT_MODE) { + if (bootArgs->Video.v_display == VGA_TEXT_MODE) + { setActiveDisplayPage(0); } } @@ -1156,6 +1175,7 @@ clearScreenRows(kMenuTopRow, kScreenLastRow); changeCursor(0, kMenuTopRow, kCursorTypeUnderline, 0); } + shouldboot = false; gui.menu.draw = false; if (menuItems) { @@ -1200,6 +1220,7 @@ *argP += cnt; *argP[0] = ' '; (*argP)++; + *cntRemainingP -= len; return true; @@ -1243,15 +1264,15 @@ int processBootOptions() { - const char *cp = gBootArgs; - const char *val = 0; - const char *kernel; - int cnt; - int userCnt; - int cntRemaining; - char *argP; - char *configKernelFlags; - char *valueBuffer; + const char *cp = gBootArgs; + const char *val = 0; + const char *kernel; + int cnt; + int userCnt; + int cntRemaining; + char *argP; + char *configKernelFlags; + char *valueBuffer; valueBuffer = malloc(VALUE_SIZE); Index: branches/ErmaC/Enoch/i386/libsa/interrupts.c =================================================================== --- branches/ErmaC/Enoch/i386/libsa/interrupts.c (revision 0) +++ branches/ErmaC/Enoch/i386/libsa/interrupts.c (revision 2585) @@ -0,0 +1,532 @@ +#ifdef __i386__ + +#include "libsa.h" +#include "saio_internal.h" + +#ifdef DEBUG_INTERRUPTS +#define DBG(x...) printf(x) +#else +#define DBG(x...) +#endif + +#define CODE_SEGMENT_SELECTOR 0x28U +#define CODED_EXCEPTION_MASK 0x27D00U +#define IA32_APIC_BASE 27U +#define IA32_APIC_BASE_BSP 0x100U +#define IA32_APIC_BASE_EN 0x800U +#define LAPIC_WANTED_FLAGS (IA32_APIC_BASE_EN | IA32_APIC_BASE_BSP) +#define LAPIC_EOI_OFFSET 0xB0U +#define LAPIC_ISR_OFFSET 0x100U +#define PIC_READ_ISR_COMMAND 11U +#define PIC_EOI_COMMAND 0x20U +#define PIC_PORT0 0 +#define PIC_PORT1 1 + +#define BDA_TICK_COUNT 0x46CU // DWORD +#define BDA_MIDNIGHT_FLAG 0x470U // BYTE +#define BDA_24HR_TURNOVER 0x1800B0U + +enum InterruptSources +{ + IS_Unknown = 0, + IS_APIC = 1, // Covers both LAPIC and IOAPIC + IS_PIC0 = 2, + IS_PIC1 = 3, + IS_Software = 4 +}; + +struct InterruptFrame +{ + uint32_t edx; + uint32_t ecx; + uint32_t eax; + uint32_t index; + uint32_t eip; + uint32_t cs; + uint32_t eflags; +}; + +struct ExceptionFrame +{ + uint32_t edi; + uint32_t esi; + uint32_t ebp; + uint32_t esp; + uint32_t ebx; + uint32_t edx; + uint32_t ecx; + uint32_t eax; + uint32_t index; + uint32_t exception_code; + uint32_t eip; + uint32_t cs; + uint32_t eflags; +}; + +struct InterruptGate +{ + uint16_t offset_0_15; + uint16_t selector; + uint16_t flags; + uint16_t offset_16_31; +}; + +#pragma mark - +#pragma mark Global Data +#pragma mark - + +extern +uint16_t Idtr_prot[]; + +static +uint32_t* counters = NULL; + +static +uint32_t lapic_base = 0U; + +static +uint8_t const PicPorts[2][2] = { { 0x20U, 0x21U }, { 0xA0U, 0xA1U } }; + +#pragma mark - +#pragma mark Assembly Stubs +#pragma mark - + +static +__attribute__((naked, noreturn)) +void InterruptStub(void) +{ + __asm__ volatile ("pushl %%eax\n\t" + "pushl %%ecx\n\t" + "pushl %%edx\n\t" + "pushl %%esp\n\t" + "calll _InterruptHandler\n\t" + "addl $4, %%esp\n\t" + "popl %%edx\n\t" + "popl %%ecx\n\t" + "popl %%eax\n\t" + "addl $4, %%esp\n\t" + "iretl" + :); +} + +static +__attribute__((naked, noreturn)) +void ExceptionWithCodeStub(void) +{ + __asm__ volatile("testl $-57, 8(%%esp)\n\t" + "je 0f\n\t" + "pushal\n\t" + "jmp 1f\n" + "_ExceptionNoCodeStub:\n" + "0:\tsub $4, %%esp\n\t" + "pushal\n\t" + "xorl %%eax, %%eax\n\t" + "xchgl %%eax, 36(%%esp)\n\t" + "movl %%eax, 32(%%esp)\n" + "1:\taddl $20, 12(%%esp)\n\t" + "pushl %%esp\n\t" + "calll _ExceptionHandler\n\t" + "addl $4, %%esp\n\t" + "popal\n\t" + "addl $8, %%esp\n\t" + "iretl" + :); +} + +/* + * Make _ExceptionNoCodeStub accessible to C + */ +static +__attribute__((naked, noreturn, weakref("ExceptionNoCodeStub"))) +void ExceptionNoCodeStubAlias(void); + +static +__attribute__((/* naked, */noinline, regparm(1), section("__INIT,__text"))) +void DispatchBiosVector(uint8_t vector) +{ + __asm__ volatile ("movb %0, 0f + 1\n\t" + "calll __prot_to_real\n\t" + ".code16\n" + "0:\tint $0\n\t" + "calll __real_to_prot\n\t" + ".code32" + : : "r"(vector)); +} + +static +__attribute__((noreturn, noinline, section("__INIT,__text"))) +void DisplayErrorAndStop(void) +{ + __asm__ volatile ("calll __prot_to_real\n\t" + ".code16\n\t" + "movw $2, %%ax\n\t" + "int $0x10\n\t" + "xorw %%ax, %%ax\n\t" + "movw %%ax, %%ds\n\t" + "movw $0x6000, %%si\n\t" + "cld\n" + "0:\tlodsb\n\t" + "testb %%al, %%al\n\t" + "je 1f\n\t" + "movb $0xE, %%ah\n\t" + "movw $0xFF, %%bx\n\t" + "int $0x10\n\t" + "jmp 0b\n" + "1:\thlt\n\t" + "jmp 1b\n\t" + ".code32" + :); + __builtin_unreachable(); +} + +#pragma mark - +#pragma mark Other Inline Assembly +#pragma mark - + +static inline +uint32_t ReadLapic(uint32_t offset) +{ + return *(uint32_t const volatile*) (lapic_base + offset); +} + +static inline +void WriteLapic(uint32_t offset, uint32_t value) +{ + *(uint32_t volatile*) (lapic_base + offset) = value; +} + +static inline +uint8_t ReadPic(int pic, int index) +{ + uint8_t value; + __asm__ volatile ("inb %1, %0" : "=a"(value) : "N"(PicPorts[pic][index])); + return value; +} + +static inline +void WritePic(int pic, int index, uint8_t value) +{ + __asm__ volatile ("outb %0, %1" : : "a"(value), "N"(PicPorts[pic][index])); +} + +#pragma mark - +#pragma mark Main Code +#pragma mark - + +static +int IdentifyInterruptSource(uint8_t vector, uint32_t eip) +{ + if (lapic_base) + { + uint32_t value = ReadLapic(LAPIC_ISR_OFFSET + ((vector & 0xE0U) >> 1)); + if (value & (1U << (vector & 31U))) + return IS_APIC; + } + if (vector >= 8U && vector < 16U) + { + uint8_t value; + WritePic(0, PIC_PORT0, PIC_READ_ISR_COMMAND); + value = ReadPic(0, PIC_PORT0); + if (value & (1U << (vector & 7U))) + return IS_PIC0; + } + if (vector >= 0x70U && vector < 0x78U) + { + uint8_t value; + WritePic(1, PIC_PORT0, PIC_READ_ISR_COMMAND); + value = ReadPic(1, PIC_PORT0); + if (value & (1U << (vector & 7U))) + return IS_PIC1; + } + if (eip) + { + uint8_t const volatile* pInstruction = (uint8_t const volatile*) (eip - 2U); + if ((*pInstruction) == 0xCDU && pInstruction[1] == vector) + return IS_Software; + /* + * There are other software interrupt opcodes + * debug breakpoint 0xCC + * interrupt on overflow 0xCE + * bound instruction 0x62 + * but those all trigger specific vectors, so are handled as exceptions. + */ + } + return IS_Unknown; +} + +static +void SignalEOI(int source) +{ + switch (source) + { + case IS_APIC: + if (lapic_base) + WriteLapic(LAPIC_EOI_OFFSET, 0U); + break; + case IS_PIC1: + WritePic(1, PIC_PORT0, PIC_EOI_COMMAND); + case IS_PIC0: + WritePic(0, PIC_PORT0, PIC_EOI_COMMAND); + default: + break; + } +} + +static +void HandleIRQ(int source, uint8_t vector) +{ + if (source == IS_PIC0 && vector == 8U) + { + uint32_t* pTickCount = (uint32_t*) BDA_TICK_COUNT; + if (++(*pTickCount) == BDA_24HR_TURNOVER) + { + *pTickCount = 0U; + ++(*(uint8_t*)BDA_MIDNIGHT_FLAG); + } + SignalEOI(source); + return; + } + /* + * Default Approach: send to bios + */ + DispatchBiosVector(vector); +} + +static +__attribute__((used)) +void ExceptionHandler(struct ExceptionFrame* pFrame) +{ + uint8_t vector; + int interruptSource; + char* errorString; + + /* + * FIXME: Should check if 0x10000U <= ESP <= 0x1FFFF0 here and switch stacks if not. + */ + if (!pFrame) + { + return; + } + vector = (uint8_t) pFrame->index; + if (counters) + ++counters[vector]; + interruptSource = IdentifyInterruptSource(vector, pFrame->eip); + switch (interruptSource) + { + case IS_APIC: + case IS_PIC0: + case IS_PIC1: + HandleIRQ(interruptSource, vector); + case IS_Software: + return; + default: + break; + } + errorString = (char*) 0x6000U; + switch (vector) + { + case 0U: + strcpy(errorString, "Division By Zero Exception"); + break; + case 1U: + strcpy(errorString, "Debug Exception"); + break; + case 2U: + strcpy(errorString, "NMI Interrupt"); + break; + case 3U: + strcpy(errorString, "Debug Breakpoint"); + break; + case 4U: + strcpy(errorString, "Overflow Exception"); + break; + case 5U: + strcpy(errorString, "BOUND Range Exception"); + break; + case 6U: + strcpy(errorString, "Invalid Opcode Exception"); + break; + case 7U: + strcpy(errorString, "Math Coprocessor Unavailable Exception"); + break; + case 8U: + strcpy(errorString, "Double Fault"); + break; + case 9U: + strcpy(errorString, "Coprocessor Segment Overrun Exception"); + break; + case 10U: + strcpy(errorString, "Invalid TSS Exception"); + break; + case 11U: + strcpy(errorString, "Segment Not Present Exception"); + break; + case 12U: + strcpy(errorString, "Stack-Segment Fault"); + break; + case 13U: + strcpy(errorString, "General Protection Fault"); + break; + case 14U: + strcpy(errorString, "Page Fault"); + break; + case 16U: + strcpy(errorString, "x87 FPU Floating-Point Error"); + break; + case 17U: + strcpy(errorString, "Alignment Check Exception"); + break; + case 18U: + strcpy(errorString, "Machine Check Exception"); + break; + case 19U: + strcpy(errorString, "SIMD Floating-Point Exception"); + break; + case 20U: + strcpy(errorString, "Virtualization Exception"); + break; + default: + sprintf(errorString, "Unknown Exception Vector %d", (int) vector); + break; + } + errorString += strlen(errorString); + + errorString += sprintf(errorString, "\r\nEDI 0x%x, ESI 0x%x, EBP 0x%x, ESP 0x%x", + pFrame->edi, pFrame->esi, pFrame->ebp, pFrame->esp); + errorString += sprintf(errorString, "\r\nEBX 0x%x, EDX 0x%x, ECX 0x%x, EAX 0x%x", + pFrame->ebx, pFrame->edx, pFrame->ecx, pFrame->eax); + errorString += sprintf(errorString, "\r\nException Code 0x%x, EIP 0x%x, CS 0x%x, EFLAGS 0x%x\r\nSystem Halted\r\n", + pFrame->exception_code, pFrame->eip, pFrame->cs, pFrame->eflags); + DisplayErrorAndStop(); +} + +static +__attribute__((used)) +void InterruptHandler(struct InterruptFrame* pFrame) +{ + uint8_t vector; + int interruptSource; + + if (!pFrame) + { + return; + } + vector = (uint8_t) pFrame->index; + if (counters) + ++counters[vector]; + interruptSource = IdentifyInterruptSource(vector, pFrame->eip); + switch (interruptSource) + { + case IS_APIC: + case IS_PIC0: + case IS_PIC1: + HandleIRQ(interruptSource, vector); + default: + break; + } +} + +#if UNUSED +void dumpMasks(void) +{ + int idx; + uint8_t port_val; + uint8_t volatile* apic_index; + uint32_t const volatile* apic_data; + + port_val = ReadPic(0, 1); + DBG("pic0 Masks 0x%x\n", port_val); + port_val = ReadPic(1, 1); + DBG("pic1 Masks 0x%x\n", port_val); + getchar(); + DBG("IOAPIC vectors\n"); + apic_index = (uint8_t volatile*) 0xFEC00000U; + apic_data = (uint32_t const volatile*) 0xFEC00010U; + for (idx = 0; idx != 24; ++idx) + { + uint32_t v1, v2; + *apic_index = (uint8_t) (16U + 2U * (unsigned) idx); + v1 = *apic_data; + if (v1 & 0x10000U) + continue; + *apic_index = (uint8_t) (16U + 2U * (unsigned) idx + 1U); + v2 = *apic_data; + DBG("index %d vector 0x%x%08x\n", idx, v2, v1); + } + getchar(); + if (!lapic_base) + return; + DBG("LAPIC vectors\n"); + for (idx = 0; idx != 7; ++idx) + { + uint32_t offs, v; + if (!idx) + offs = 0x2F0U; + else + offs = 0x320U + 16U * (unsigned) (idx - 1); + v = ReadLapic(offs); + if (v & 0x10000U) + continue; + DBG("index %d vector 0x%x\n", idx, v); + } +} +#endif + +void ShowInterruptCounters(void) +{ + int j; + + if (!counters) + return; + msglog("Interrupt Counters\n"); + for (j = 0; j != 256; ++j) + if (counters[j]) + msglog("counters[%d] == %d\n", j, counters[j]); +} + +int SetupInterrupts(void) +{ + int idx; + uint32_t stub_address; + uint64_t ia32_apic_base; + size_t const total = 2048U + 2048U + 1024U; + uint8_t* workArea = (uint8_t*) malloc(total); + if (!workArea) + { + msglog("%s: Memory Allocation Failed\n", __FUNCTION__); + return 0; + } + counters = (uint32_t*) (workArea + 4096); + bzero(counters, 1024U); + for (idx = 0; idx != 256; ++idx) + { + struct InterruptGate* gate = (struct InterruptGate*) (workArea + idx * sizeof(struct InterruptGate)); + uint8_t* thunk = workArea + 2048 + idx * 8; + gate->offset_0_15 = ((uint32_t) thunk) & 0xFFFFU; + gate->selector = CODE_SEGMENT_SELECTOR; + gate->flags = 0x8E00U; // Interrupt Gate, Present, DPL 0, 32-bit + gate->offset_16_31 = (((uint32_t) thunk) >> 16) & 0xFFFFU; + thunk[0] = 0x6AU; // push byte + thunk[1] = (uint8_t) idx; + thunk[2] = 0xE9U; // jmp rel32 + if (idx >= 32) + stub_address = (uint32_t) &InterruptStub; + else if ((1U << idx) & CODED_EXCEPTION_MASK) + stub_address = (uint32_t) &ExceptionWithCodeStub; + else + stub_address = (uint32_t) &ExceptionNoCodeStubAlias; + *(uint32_t*) (&thunk[3]) = stub_address - (uint32_t) &thunk[7]; + thunk[7] = 0x90U; // nop + } + Idtr_prot[0] = 0x7FFU; + Idtr_prot[1] = ((uint32_t) workArea) & 0xFFFFU; + Idtr_prot[2] = (((uint32_t) workArea) >> 16) & 0xFFFFU; + __asm__ volatile ("lidt %0" : : "m"(Idtr_prot[0])); + __asm__ volatile ("rdmsr" : "=A"(ia32_apic_base) : "c"((uint32_t) IA32_APIC_BASE)); + if ((ia32_apic_base & LAPIC_WANTED_FLAGS) == LAPIC_WANTED_FLAGS && + !((ia32_apic_base >> 32) & 255U)) + lapic_base = ((uint32_t) ia32_apic_base) & ~0xFFFU; + DBG("%s: Work Area 0x%x, lapic_base 0x%x\n", __FUNCTION__, (uint32_t) workArea, lapic_base); + return 1; +} +#endif Index: branches/ErmaC/Enoch/i386/libsa/libsa.h =================================================================== --- branches/ErmaC/Enoch/i386/libsa/libsa.h (revision 2584) +++ branches/ErmaC/Enoch/i386/libsa/libsa.h (revision 2585) @@ -155,4 +155,19 @@ */ extern struct segment_command * getsegbynamefromheader(struct mach_header * mhp, char * segname); +/* + * interrupts.c + */ +#ifdef __i386__ +extern int SetupInterrupts(void); +static inline void EnableInterrupts(void) { __asm__ volatile ("sti"); } +static inline void DisableInterrupts(void) { __asm__ volatile ("cli"); } +extern void ShowInterruptCounters(void); +#else +static inline int SetupInterrupts(void) { return 0; } +static inline void EnableInterrupts(void) { } +static inline void DisableInterrupts(void) { } +static inline void ShowInterruptCounters(void) { } +#endif + #endif /* !__BOOT_LIBSA_H */ Index: branches/ErmaC/Enoch/i386/libsa/Makefile =================================================================== --- branches/ErmaC/Enoch/i386/libsa/Makefile (revision 2584) +++ branches/ErmaC/Enoch/i386/libsa/Makefile (revision 2585) @@ -23,7 +23,7 @@ OBJS = prf.o printf.o zalloc.o \ string.o strtol.o error.o \ - setjmp.o qsort.o efi_tables.o + setjmp.o qsort.o efi_tables.o interrupts.o OBJS := $(addprefix $(OBJROOT)/, $(OBJS)) Index: branches/ErmaC/Enoch/CHANGES =================================================================== --- branches/ErmaC/Enoch/CHANGES (revision 2584) +++ branches/ErmaC/Enoch/CHANGES (revision 2585) @@ -1,3 +1,4 @@ +- Zenith432 : Interrupt Management - Bungo : Added ability to auto-select last booted partition as the boot volume. - Bungo : Added MacOSVerCurrent and MacOSVer2Int function to use instead of macros. - Bungo : Fixed bug in gDarwinBuildVerStr extracting.