diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 9fb0b69..a0764de 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -13,7 +13,7 @@ SYS_LOAD_INITRD = 5, SYS_GET_SERVICE = 6, SYS_GET_PROVIDER = 7, - SYS_INTERRUPT = 8, + SYS_SUBSCRIBE_INTERRUPT = 8, } SyscallIds; #endif diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 9fb0b69..a0764de 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -13,7 +13,7 @@ SYS_LOAD_INITRD = 5, SYS_GET_SERVICE = 6, SYS_GET_PROVIDER = 7, - SYS_INTERRUPT = 8, + SYS_SUBSCRIBE_INTERRUPT = 8, } SyscallIds; #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 62206d2..6e973c9 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -26,5 +26,6 @@ extern Service *findService(char *); extern Provider *findProvider(Service *, char *); extern Service *currentService; - +extern void scheduleProvider(Provider *provider, void *data, + uint32_t dataLength, Syscall *respondingTo); #endif diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 9fb0b69..a0764de 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -13,7 +13,7 @@ SYS_LOAD_INITRD = 5, SYS_GET_SERVICE = 6, SYS_GET_PROVIDER = 7, - SYS_INTERRUPT = 8, + SYS_SUBSCRIBE_INTERRUPT = 8, } SyscallIds; #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 62206d2..6e973c9 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -26,5 +26,6 @@ extern Service *findService(char *); extern Provider *findProvider(Service *, char *); extern Service *currentService; - +extern void scheduleProvider(Provider *provider, void *data, + uint32_t dataLength, Syscall *respondingTo); #endif diff --git a/src/kernel/interrupts/interruptDescriptors.asm b/src/kernel/interrupts/interruptDescriptors.asm index ae7c56f..0144759 100644 --- a/src/kernel/interrupts/interruptDescriptors.asm +++ b/src/kernel/interrupts/interruptDescriptors.asm @@ -13,6 +13,8 @@ call onInterrupt pop eax mov cr3, eax + pop eax + pop eax iret %macro interruptHandler 1 diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 9fb0b69..a0764de 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -13,7 +13,7 @@ SYS_LOAD_INITRD = 5, SYS_GET_SERVICE = 6, SYS_GET_PROVIDER = 7, - SYS_INTERRUPT = 8, + SYS_SUBSCRIBE_INTERRUPT = 8, } SyscallIds; #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 62206d2..6e973c9 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -26,5 +26,6 @@ extern Service *findService(char *); extern Provider *findProvider(Service *, char *); extern Service *currentService; - +extern void scheduleProvider(Provider *provider, void *data, + uint32_t dataLength, Syscall *respondingTo); #endif diff --git a/src/kernel/interrupts/interruptDescriptors.asm b/src/kernel/interrupts/interruptDescriptors.asm index ae7c56f..0144759 100644 --- a/src/kernel/interrupts/interruptDescriptors.asm +++ b/src/kernel/interrupts/interruptDescriptors.asm @@ -13,6 +13,8 @@ call onInterrupt pop eax mov cr3, eax + pop eax + pop eax iret %macro interruptHandler 1 diff --git a/src/kernel/interrupts/interrupts.c b/src/kernel/interrupts/interrupts.c index 98c18ba..a185b9a 100644 --- a/src/kernel/interrupts/interrupts.c +++ b/src/kernel/interrupts/interrupts.c @@ -1,6 +1,7 @@ #include "interrupts.h" #include #include +#include #include #define IDT_ENTRY(i) \ @@ -12,17 +13,21 @@ extern GDTEntry newGDT; extern TSS tss; +ListElement *interruptSubscriptions[255]; + __attribute__((section(".sharedFunction"))) __attribute__((aligned(0x10))) IdtEntry idtEntries[256] = {}; void onInterrupt(uint32_t cr3, uint32_t intNo, uint32_t errorCode) { if (intNo > 31) { // an external interrupt was triggered - while (1) + foreach (interruptSubscriptions[intNo], Provider *, provider, + { scheduleProvider(provider, PTR(intNo), 0, NULL); }) ; - } - if (intNo <= 31 && cr3 != 0x500000) { - // a task encountered an exception + } else if (intNo <= 31 && cr3 != 0x500000) { + // a task encountered an exception, end it + // todo: free syscall structure and handle the respondingTo one + // appropriately asm(".intel_syntax noprefix\n" "mov eax, [temporaryESP]\n" "mov esp, eax\n" @@ -34,6 +39,8 @@ extern void *interruptStack; +void setupPic(); + void registerInterrupts() { GDTEntry *currentGdt = &newGDT; currentGdt[5].limit = sizeof(TSS); @@ -57,8 +64,24 @@ .limit = sizeof(idtEntries) - 1, }; asm("lidt %0" ::"m"(pointer)); - asm("mov $0xFF, %%al" ::); - asm("out %%al, $0xA1" ::); - asm("out %%al, $0x21" ::); + setupPic(); asm("sti"); } + +#define outb(port, value) \ + asm("outb %0, %1" : : "a"((uint8_t)value), "Nd"(port)); + +void setupPic() { + // sadly I have to do this here, because the PIC will trigger before the PIC + // driver has a chance to set it up + outb(0x20, 0x11); + outb(0xA0, 0x11); + outb(0xA1, 32); + outb(0x21, 40); + outb(0xA1, 0x04); + outb(0x21, 0x02); + outb(0x21, 0x1); + outb(0xA1, 0x1); + outb(0xA0, 0x20); + outb(0x20, 0x20); +} diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 9fb0b69..a0764de 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -13,7 +13,7 @@ SYS_LOAD_INITRD = 5, SYS_GET_SERVICE = 6, SYS_GET_PROVIDER = 7, - SYS_INTERRUPT = 8, + SYS_SUBSCRIBE_INTERRUPT = 8, } SyscallIds; #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 62206d2..6e973c9 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -26,5 +26,6 @@ extern Service *findService(char *); extern Provider *findProvider(Service *, char *); extern Service *currentService; - +extern void scheduleProvider(Provider *provider, void *data, + uint32_t dataLength, Syscall *respondingTo); #endif diff --git a/src/kernel/interrupts/interruptDescriptors.asm b/src/kernel/interrupts/interruptDescriptors.asm index ae7c56f..0144759 100644 --- a/src/kernel/interrupts/interruptDescriptors.asm +++ b/src/kernel/interrupts/interruptDescriptors.asm @@ -13,6 +13,8 @@ call onInterrupt pop eax mov cr3, eax + pop eax + pop eax iret %macro interruptHandler 1 diff --git a/src/kernel/interrupts/interrupts.c b/src/kernel/interrupts/interrupts.c index 98c18ba..a185b9a 100644 --- a/src/kernel/interrupts/interrupts.c +++ b/src/kernel/interrupts/interrupts.c @@ -1,6 +1,7 @@ #include "interrupts.h" #include #include +#include #include #define IDT_ENTRY(i) \ @@ -12,17 +13,21 @@ extern GDTEntry newGDT; extern TSS tss; +ListElement *interruptSubscriptions[255]; + __attribute__((section(".sharedFunction"))) __attribute__((aligned(0x10))) IdtEntry idtEntries[256] = {}; void onInterrupt(uint32_t cr3, uint32_t intNo, uint32_t errorCode) { if (intNo > 31) { // an external interrupt was triggered - while (1) + foreach (interruptSubscriptions[intNo], Provider *, provider, + { scheduleProvider(provider, PTR(intNo), 0, NULL); }) ; - } - if (intNo <= 31 && cr3 != 0x500000) { - // a task encountered an exception + } else if (intNo <= 31 && cr3 != 0x500000) { + // a task encountered an exception, end it + // todo: free syscall structure and handle the respondingTo one + // appropriately asm(".intel_syntax noprefix\n" "mov eax, [temporaryESP]\n" "mov esp, eax\n" @@ -34,6 +39,8 @@ extern void *interruptStack; +void setupPic(); + void registerInterrupts() { GDTEntry *currentGdt = &newGDT; currentGdt[5].limit = sizeof(TSS); @@ -57,8 +64,24 @@ .limit = sizeof(idtEntries) - 1, }; asm("lidt %0" ::"m"(pointer)); - asm("mov $0xFF, %%al" ::); - asm("out %%al, $0xA1" ::); - asm("out %%al, $0x21" ::); + setupPic(); asm("sti"); } + +#define outb(port, value) \ + asm("outb %0, %1" : : "a"((uint8_t)value), "Nd"(port)); + +void setupPic() { + // sadly I have to do this here, because the PIC will trigger before the PIC + // driver has a chance to set it up + outb(0x20, 0x11); + outb(0xA0, 0x11); + outb(0xA1, 32); + outb(0x21, 40); + outb(0xA1, 0x04); + outb(0x21, 0x02); + outb(0x21, 0x1); + outb(0xA1, 0x1); + outb(0xA0, 0x20); + outb(0x20, 0x20); +} diff --git a/src/kernel/main.c b/src/kernel/main.c index 49b3f59..584518d 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -53,7 +53,7 @@ while (1) { Syscall *call = listPopFirst(&callsToProcess); if (!call) { - asm("hlt"); + asm("sti;hlt"); continue; } if (call->resume) { diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 9fb0b69..a0764de 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -13,7 +13,7 @@ SYS_LOAD_INITRD = 5, SYS_GET_SERVICE = 6, SYS_GET_PROVIDER = 7, - SYS_INTERRUPT = 8, + SYS_SUBSCRIBE_INTERRUPT = 8, } SyscallIds; #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 62206d2..6e973c9 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -26,5 +26,6 @@ extern Service *findService(char *); extern Provider *findProvider(Service *, char *); extern Service *currentService; - +extern void scheduleProvider(Provider *provider, void *data, + uint32_t dataLength, Syscall *respondingTo); #endif diff --git a/src/kernel/interrupts/interruptDescriptors.asm b/src/kernel/interrupts/interruptDescriptors.asm index ae7c56f..0144759 100644 --- a/src/kernel/interrupts/interruptDescriptors.asm +++ b/src/kernel/interrupts/interruptDescriptors.asm @@ -13,6 +13,8 @@ call onInterrupt pop eax mov cr3, eax + pop eax + pop eax iret %macro interruptHandler 1 diff --git a/src/kernel/interrupts/interrupts.c b/src/kernel/interrupts/interrupts.c index 98c18ba..a185b9a 100644 --- a/src/kernel/interrupts/interrupts.c +++ b/src/kernel/interrupts/interrupts.c @@ -1,6 +1,7 @@ #include "interrupts.h" #include #include +#include #include #define IDT_ENTRY(i) \ @@ -12,17 +13,21 @@ extern GDTEntry newGDT; extern TSS tss; +ListElement *interruptSubscriptions[255]; + __attribute__((section(".sharedFunction"))) __attribute__((aligned(0x10))) IdtEntry idtEntries[256] = {}; void onInterrupt(uint32_t cr3, uint32_t intNo, uint32_t errorCode) { if (intNo > 31) { // an external interrupt was triggered - while (1) + foreach (interruptSubscriptions[intNo], Provider *, provider, + { scheduleProvider(provider, PTR(intNo), 0, NULL); }) ; - } - if (intNo <= 31 && cr3 != 0x500000) { - // a task encountered an exception + } else if (intNo <= 31 && cr3 != 0x500000) { + // a task encountered an exception, end it + // todo: free syscall structure and handle the respondingTo one + // appropriately asm(".intel_syntax noprefix\n" "mov eax, [temporaryESP]\n" "mov esp, eax\n" @@ -34,6 +39,8 @@ extern void *interruptStack; +void setupPic(); + void registerInterrupts() { GDTEntry *currentGdt = &newGDT; currentGdt[5].limit = sizeof(TSS); @@ -57,8 +64,24 @@ .limit = sizeof(idtEntries) - 1, }; asm("lidt %0" ::"m"(pointer)); - asm("mov $0xFF, %%al" ::); - asm("out %%al, $0xA1" ::); - asm("out %%al, $0x21" ::); + setupPic(); asm("sti"); } + +#define outb(port, value) \ + asm("outb %0, %1" : : "a"((uint8_t)value), "Nd"(port)); + +void setupPic() { + // sadly I have to do this here, because the PIC will trigger before the PIC + // driver has a chance to set it up + outb(0x20, 0x11); + outb(0xA0, 0x11); + outb(0xA1, 32); + outb(0x21, 40); + outb(0xA1, 0x04); + outb(0x21, 0x02); + outb(0x21, 0x1); + outb(0xA1, 0x1); + outb(0xA0, 0x20); + outb(0x20, 0x20); +} diff --git a/src/kernel/main.c b/src/kernel/main.c index 49b3f59..584518d 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -53,7 +53,7 @@ while (1) { Syscall *call = listPopFirst(&callsToProcess); if (!call) { - asm("hlt"); + asm("sti;hlt"); continue; } if (call->resume) { diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index d13ca0f..130f3ce 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -75,3 +75,23 @@ ; return NULL; } + +void scheduleProvider(Provider *provider, void *data, uint32_t dataLength, + Syscall *respondingTo) { + sharePage(&provider->service->pagingInfo, data, data); + Syscall *runCall = malloc(sizeof(Syscall)); + runCall->function = SYS_RUN; + runCall->esp = malloc(0x1000); + runCall->respondingTo = respondingTo; + runCall->cr3 = + getPhysicalAddressKernel(provider->service->pagingInfo.pageDirectory); + runCall->service = provider->service; + runCall->resume = true; + sharePage(&provider->service->pagingInfo, runCall->esp, runCall->esp); + runCall->esp += 0xFF0; + *(void **)runCall->esp = provider->address; + *(void **)(runCall->esp + 0x4) = &runEnd; + *(void **)(runCall->esp + 0x8) = data; + *(uint32_t *)(runCall->esp + 0xC) = dataLength; + listAdd(&callsToProcess, runCall); +} diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 9fb0b69..a0764de 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -13,7 +13,7 @@ SYS_LOAD_INITRD = 5, SYS_GET_SERVICE = 6, SYS_GET_PROVIDER = 7, - SYS_INTERRUPT = 8, + SYS_SUBSCRIBE_INTERRUPT = 8, } SyscallIds; #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 62206d2..6e973c9 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -26,5 +26,6 @@ extern Service *findService(char *); extern Provider *findProvider(Service *, char *); extern Service *currentService; - +extern void scheduleProvider(Provider *provider, void *data, + uint32_t dataLength, Syscall *respondingTo); #endif diff --git a/src/kernel/interrupts/interruptDescriptors.asm b/src/kernel/interrupts/interruptDescriptors.asm index ae7c56f..0144759 100644 --- a/src/kernel/interrupts/interruptDescriptors.asm +++ b/src/kernel/interrupts/interruptDescriptors.asm @@ -13,6 +13,8 @@ call onInterrupt pop eax mov cr3, eax + pop eax + pop eax iret %macro interruptHandler 1 diff --git a/src/kernel/interrupts/interrupts.c b/src/kernel/interrupts/interrupts.c index 98c18ba..a185b9a 100644 --- a/src/kernel/interrupts/interrupts.c +++ b/src/kernel/interrupts/interrupts.c @@ -1,6 +1,7 @@ #include "interrupts.h" #include #include +#include #include #define IDT_ENTRY(i) \ @@ -12,17 +13,21 @@ extern GDTEntry newGDT; extern TSS tss; +ListElement *interruptSubscriptions[255]; + __attribute__((section(".sharedFunction"))) __attribute__((aligned(0x10))) IdtEntry idtEntries[256] = {}; void onInterrupt(uint32_t cr3, uint32_t intNo, uint32_t errorCode) { if (intNo > 31) { // an external interrupt was triggered - while (1) + foreach (interruptSubscriptions[intNo], Provider *, provider, + { scheduleProvider(provider, PTR(intNo), 0, NULL); }) ; - } - if (intNo <= 31 && cr3 != 0x500000) { - // a task encountered an exception + } else if (intNo <= 31 && cr3 != 0x500000) { + // a task encountered an exception, end it + // todo: free syscall structure and handle the respondingTo one + // appropriately asm(".intel_syntax noprefix\n" "mov eax, [temporaryESP]\n" "mov esp, eax\n" @@ -34,6 +39,8 @@ extern void *interruptStack; +void setupPic(); + void registerInterrupts() { GDTEntry *currentGdt = &newGDT; currentGdt[5].limit = sizeof(TSS); @@ -57,8 +64,24 @@ .limit = sizeof(idtEntries) - 1, }; asm("lidt %0" ::"m"(pointer)); - asm("mov $0xFF, %%al" ::); - asm("out %%al, $0xA1" ::); - asm("out %%al, $0x21" ::); + setupPic(); asm("sti"); } + +#define outb(port, value) \ + asm("outb %0, %1" : : "a"((uint8_t)value), "Nd"(port)); + +void setupPic() { + // sadly I have to do this here, because the PIC will trigger before the PIC + // driver has a chance to set it up + outb(0x20, 0x11); + outb(0xA0, 0x11); + outb(0xA1, 32); + outb(0x21, 40); + outb(0xA1, 0x04); + outb(0x21, 0x02); + outb(0x21, 0x1); + outb(0xA1, 0x1); + outb(0xA0, 0x20); + outb(0x20, 0x20); +} diff --git a/src/kernel/main.c b/src/kernel/main.c index 49b3f59..584518d 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -53,7 +53,7 @@ while (1) { Syscall *call = listPopFirst(&callsToProcess); if (!call) { - asm("hlt"); + asm("sti;hlt"); continue; } if (call->resume) { diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index d13ca0f..130f3ce 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -75,3 +75,23 @@ ; return NULL; } + +void scheduleProvider(Provider *provider, void *data, uint32_t dataLength, + Syscall *respondingTo) { + sharePage(&provider->service->pagingInfo, data, data); + Syscall *runCall = malloc(sizeof(Syscall)); + runCall->function = SYS_RUN; + runCall->esp = malloc(0x1000); + runCall->respondingTo = respondingTo; + runCall->cr3 = + getPhysicalAddressKernel(provider->service->pagingInfo.pageDirectory); + runCall->service = provider->service; + runCall->resume = true; + sharePage(&provider->service->pagingInfo, runCall->esp, runCall->esp); + runCall->esp += 0xFF0; + *(void **)runCall->esp = provider->address; + *(void **)(runCall->esp + 0x4) = &runEnd; + *(void **)(runCall->esp + 0x8) = data; + *(uint32_t *)(runCall->esp + 0xC) = dataLength; + listAdd(&callsToProcess, runCall); +} diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index 8e0a966..8c001be 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -79,22 +79,7 @@ listGet(providerService->providers, call->parameters[1]); void *data = kernelMapPhysical(getPhysicalAddress( service->pagingInfo.pageDirectory, PTR(call->parameters[2]))); - sharePage(&providerService->pagingInfo, data, data); - Syscall *runCall = malloc(sizeof(Syscall)); - runCall->function = SYS_RUN; - runCall->esp = malloc(0x1000); - runCall->respondingTo = call; - runCall->cr3 = - getPhysicalAddressKernel(providerService->pagingInfo.pageDirectory); - runCall->service = providerService; - runCall->resume = true; - sharePage(&providerService->pagingInfo, runCall->esp, runCall->esp); - runCall->esp += 0xFF0; - *(void **)runCall->esp = provider->address; - *(void **)(runCall->esp + 0x4) = &runEnd; - *(void **)(runCall->esp + 0x8) = data; - *(uint32_t *)(runCall->esp + 0xC) = call->parameters[3]; - listAdd(&callsToProcess, runCall); + scheduleProvider(provider, data, call->parameters[3], call); call->avoidReschedule = true; } @@ -179,6 +164,18 @@ ; } +extern ListElement *interruptSubscriptions[255]; + +void handleSubscribeInterruptSyscall(Syscall *call) { + Provider *provider = malloc(sizeof(Provider)); + Service *service = call->service; + char *providerName = "INTERRUPT"; + provider->name = providerName; + provider->address = PTR(call->parameters[1]); + provider->service = call->service; + listAdd(&interruptSubscriptions[call->parameters[0]], provider); +} + void (*syscallHandlers[])(Syscall *) = { 0, (void *)handleInstallSyscall, @@ -188,4 +185,5 @@ (void *)handleLoadFromInitrdSyscall, (void *)handleGetServiceSyscall, (void *)handleGetProviderSyscall, + (void *)handleSubscribeInterruptSyscall, }; diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 9fb0b69..a0764de 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -13,7 +13,7 @@ SYS_LOAD_INITRD = 5, SYS_GET_SERVICE = 6, SYS_GET_PROVIDER = 7, - SYS_INTERRUPT = 8, + SYS_SUBSCRIBE_INTERRUPT = 8, } SyscallIds; #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 62206d2..6e973c9 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -26,5 +26,6 @@ extern Service *findService(char *); extern Provider *findProvider(Service *, char *); extern Service *currentService; - +extern void scheduleProvider(Provider *provider, void *data, + uint32_t dataLength, Syscall *respondingTo); #endif diff --git a/src/kernel/interrupts/interruptDescriptors.asm b/src/kernel/interrupts/interruptDescriptors.asm index ae7c56f..0144759 100644 --- a/src/kernel/interrupts/interruptDescriptors.asm +++ b/src/kernel/interrupts/interruptDescriptors.asm @@ -13,6 +13,8 @@ call onInterrupt pop eax mov cr3, eax + pop eax + pop eax iret %macro interruptHandler 1 diff --git a/src/kernel/interrupts/interrupts.c b/src/kernel/interrupts/interrupts.c index 98c18ba..a185b9a 100644 --- a/src/kernel/interrupts/interrupts.c +++ b/src/kernel/interrupts/interrupts.c @@ -1,6 +1,7 @@ #include "interrupts.h" #include #include +#include #include #define IDT_ENTRY(i) \ @@ -12,17 +13,21 @@ extern GDTEntry newGDT; extern TSS tss; +ListElement *interruptSubscriptions[255]; + __attribute__((section(".sharedFunction"))) __attribute__((aligned(0x10))) IdtEntry idtEntries[256] = {}; void onInterrupt(uint32_t cr3, uint32_t intNo, uint32_t errorCode) { if (intNo > 31) { // an external interrupt was triggered - while (1) + foreach (interruptSubscriptions[intNo], Provider *, provider, + { scheduleProvider(provider, PTR(intNo), 0, NULL); }) ; - } - if (intNo <= 31 && cr3 != 0x500000) { - // a task encountered an exception + } else if (intNo <= 31 && cr3 != 0x500000) { + // a task encountered an exception, end it + // todo: free syscall structure and handle the respondingTo one + // appropriately asm(".intel_syntax noprefix\n" "mov eax, [temporaryESP]\n" "mov esp, eax\n" @@ -34,6 +39,8 @@ extern void *interruptStack; +void setupPic(); + void registerInterrupts() { GDTEntry *currentGdt = &newGDT; currentGdt[5].limit = sizeof(TSS); @@ -57,8 +64,24 @@ .limit = sizeof(idtEntries) - 1, }; asm("lidt %0" ::"m"(pointer)); - asm("mov $0xFF, %%al" ::); - asm("out %%al, $0xA1" ::); - asm("out %%al, $0x21" ::); + setupPic(); asm("sti"); } + +#define outb(port, value) \ + asm("outb %0, %1" : : "a"((uint8_t)value), "Nd"(port)); + +void setupPic() { + // sadly I have to do this here, because the PIC will trigger before the PIC + // driver has a chance to set it up + outb(0x20, 0x11); + outb(0xA0, 0x11); + outb(0xA1, 32); + outb(0x21, 40); + outb(0xA1, 0x04); + outb(0x21, 0x02); + outb(0x21, 0x1); + outb(0xA1, 0x1); + outb(0xA0, 0x20); + outb(0x20, 0x20); +} diff --git a/src/kernel/main.c b/src/kernel/main.c index 49b3f59..584518d 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -53,7 +53,7 @@ while (1) { Syscall *call = listPopFirst(&callsToProcess); if (!call) { - asm("hlt"); + asm("sti;hlt"); continue; } if (call->resume) { diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index d13ca0f..130f3ce 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -75,3 +75,23 @@ ; return NULL; } + +void scheduleProvider(Provider *provider, void *data, uint32_t dataLength, + Syscall *respondingTo) { + sharePage(&provider->service->pagingInfo, data, data); + Syscall *runCall = malloc(sizeof(Syscall)); + runCall->function = SYS_RUN; + runCall->esp = malloc(0x1000); + runCall->respondingTo = respondingTo; + runCall->cr3 = + getPhysicalAddressKernel(provider->service->pagingInfo.pageDirectory); + runCall->service = provider->service; + runCall->resume = true; + sharePage(&provider->service->pagingInfo, runCall->esp, runCall->esp); + runCall->esp += 0xFF0; + *(void **)runCall->esp = provider->address; + *(void **)(runCall->esp + 0x4) = &runEnd; + *(void **)(runCall->esp + 0x8) = data; + *(uint32_t *)(runCall->esp + 0xC) = dataLength; + listAdd(&callsToProcess, runCall); +} diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index 8e0a966..8c001be 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -79,22 +79,7 @@ listGet(providerService->providers, call->parameters[1]); void *data = kernelMapPhysical(getPhysicalAddress( service->pagingInfo.pageDirectory, PTR(call->parameters[2]))); - sharePage(&providerService->pagingInfo, data, data); - Syscall *runCall = malloc(sizeof(Syscall)); - runCall->function = SYS_RUN; - runCall->esp = malloc(0x1000); - runCall->respondingTo = call; - runCall->cr3 = - getPhysicalAddressKernel(providerService->pagingInfo.pageDirectory); - runCall->service = providerService; - runCall->resume = true; - sharePage(&providerService->pagingInfo, runCall->esp, runCall->esp); - runCall->esp += 0xFF0; - *(void **)runCall->esp = provider->address; - *(void **)(runCall->esp + 0x4) = &runEnd; - *(void **)(runCall->esp + 0x8) = data; - *(uint32_t *)(runCall->esp + 0xC) = call->parameters[3]; - listAdd(&callsToProcess, runCall); + scheduleProvider(provider, data, call->parameters[3], call); call->avoidReschedule = true; } @@ -179,6 +164,18 @@ ; } +extern ListElement *interruptSubscriptions[255]; + +void handleSubscribeInterruptSyscall(Syscall *call) { + Provider *provider = malloc(sizeof(Provider)); + Service *service = call->service; + char *providerName = "INTERRUPT"; + provider->name = providerName; + provider->address = PTR(call->parameters[1]); + provider->service = call->service; + listAdd(&interruptSubscriptions[call->parameters[0]], provider); +} + void (*syscallHandlers[])(Syscall *) = { 0, (void *)handleInstallSyscall, @@ -188,4 +185,5 @@ (void *)handleLoadFromInitrdSyscall, (void *)handleGetServiceSyscall, (void *)handleGetProviderSyscall, + (void *)handleSubscribeInterruptSyscall, }; diff --git a/src/userland/loader/main.c b/src/userland/loader/main.c index c3dcdba..d6cb880 100644 --- a/src/userland/loader/main.c +++ b/src/userland/loader/main.c @@ -63,8 +63,6 @@ loadFromInitrd("log"); log("hello world"); log("honey os is alive :)"); - log("doing wrong code..."); - uint32_t x = 1 / 0; - log("something went wrong?"); + loadFromInitrd("pic"); return 0; } diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 9fb0b69..a0764de 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -13,7 +13,7 @@ SYS_LOAD_INITRD = 5, SYS_GET_SERVICE = 6, SYS_GET_PROVIDER = 7, - SYS_INTERRUPT = 8, + SYS_SUBSCRIBE_INTERRUPT = 8, } SyscallIds; #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 62206d2..6e973c9 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -26,5 +26,6 @@ extern Service *findService(char *); extern Provider *findProvider(Service *, char *); extern Service *currentService; - +extern void scheduleProvider(Provider *provider, void *data, + uint32_t dataLength, Syscall *respondingTo); #endif diff --git a/src/kernel/interrupts/interruptDescriptors.asm b/src/kernel/interrupts/interruptDescriptors.asm index ae7c56f..0144759 100644 --- a/src/kernel/interrupts/interruptDescriptors.asm +++ b/src/kernel/interrupts/interruptDescriptors.asm @@ -13,6 +13,8 @@ call onInterrupt pop eax mov cr3, eax + pop eax + pop eax iret %macro interruptHandler 1 diff --git a/src/kernel/interrupts/interrupts.c b/src/kernel/interrupts/interrupts.c index 98c18ba..a185b9a 100644 --- a/src/kernel/interrupts/interrupts.c +++ b/src/kernel/interrupts/interrupts.c @@ -1,6 +1,7 @@ #include "interrupts.h" #include #include +#include #include #define IDT_ENTRY(i) \ @@ -12,17 +13,21 @@ extern GDTEntry newGDT; extern TSS tss; +ListElement *interruptSubscriptions[255]; + __attribute__((section(".sharedFunction"))) __attribute__((aligned(0x10))) IdtEntry idtEntries[256] = {}; void onInterrupt(uint32_t cr3, uint32_t intNo, uint32_t errorCode) { if (intNo > 31) { // an external interrupt was triggered - while (1) + foreach (interruptSubscriptions[intNo], Provider *, provider, + { scheduleProvider(provider, PTR(intNo), 0, NULL); }) ; - } - if (intNo <= 31 && cr3 != 0x500000) { - // a task encountered an exception + } else if (intNo <= 31 && cr3 != 0x500000) { + // a task encountered an exception, end it + // todo: free syscall structure and handle the respondingTo one + // appropriately asm(".intel_syntax noprefix\n" "mov eax, [temporaryESP]\n" "mov esp, eax\n" @@ -34,6 +39,8 @@ extern void *interruptStack; +void setupPic(); + void registerInterrupts() { GDTEntry *currentGdt = &newGDT; currentGdt[5].limit = sizeof(TSS); @@ -57,8 +64,24 @@ .limit = sizeof(idtEntries) - 1, }; asm("lidt %0" ::"m"(pointer)); - asm("mov $0xFF, %%al" ::); - asm("out %%al, $0xA1" ::); - asm("out %%al, $0x21" ::); + setupPic(); asm("sti"); } + +#define outb(port, value) \ + asm("outb %0, %1" : : "a"((uint8_t)value), "Nd"(port)); + +void setupPic() { + // sadly I have to do this here, because the PIC will trigger before the PIC + // driver has a chance to set it up + outb(0x20, 0x11); + outb(0xA0, 0x11); + outb(0xA1, 32); + outb(0x21, 40); + outb(0xA1, 0x04); + outb(0x21, 0x02); + outb(0x21, 0x1); + outb(0xA1, 0x1); + outb(0xA0, 0x20); + outb(0x20, 0x20); +} diff --git a/src/kernel/main.c b/src/kernel/main.c index 49b3f59..584518d 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -53,7 +53,7 @@ while (1) { Syscall *call = listPopFirst(&callsToProcess); if (!call) { - asm("hlt"); + asm("sti;hlt"); continue; } if (call->resume) { diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index d13ca0f..130f3ce 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -75,3 +75,23 @@ ; return NULL; } + +void scheduleProvider(Provider *provider, void *data, uint32_t dataLength, + Syscall *respondingTo) { + sharePage(&provider->service->pagingInfo, data, data); + Syscall *runCall = malloc(sizeof(Syscall)); + runCall->function = SYS_RUN; + runCall->esp = malloc(0x1000); + runCall->respondingTo = respondingTo; + runCall->cr3 = + getPhysicalAddressKernel(provider->service->pagingInfo.pageDirectory); + runCall->service = provider->service; + runCall->resume = true; + sharePage(&provider->service->pagingInfo, runCall->esp, runCall->esp); + runCall->esp += 0xFF0; + *(void **)runCall->esp = provider->address; + *(void **)(runCall->esp + 0x4) = &runEnd; + *(void **)(runCall->esp + 0x8) = data; + *(uint32_t *)(runCall->esp + 0xC) = dataLength; + listAdd(&callsToProcess, runCall); +} diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index 8e0a966..8c001be 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -79,22 +79,7 @@ listGet(providerService->providers, call->parameters[1]); void *data = kernelMapPhysical(getPhysicalAddress( service->pagingInfo.pageDirectory, PTR(call->parameters[2]))); - sharePage(&providerService->pagingInfo, data, data); - Syscall *runCall = malloc(sizeof(Syscall)); - runCall->function = SYS_RUN; - runCall->esp = malloc(0x1000); - runCall->respondingTo = call; - runCall->cr3 = - getPhysicalAddressKernel(providerService->pagingInfo.pageDirectory); - runCall->service = providerService; - runCall->resume = true; - sharePage(&providerService->pagingInfo, runCall->esp, runCall->esp); - runCall->esp += 0xFF0; - *(void **)runCall->esp = provider->address; - *(void **)(runCall->esp + 0x4) = &runEnd; - *(void **)(runCall->esp + 0x8) = data; - *(uint32_t *)(runCall->esp + 0xC) = call->parameters[3]; - listAdd(&callsToProcess, runCall); + scheduleProvider(provider, data, call->parameters[3], call); call->avoidReschedule = true; } @@ -179,6 +164,18 @@ ; } +extern ListElement *interruptSubscriptions[255]; + +void handleSubscribeInterruptSyscall(Syscall *call) { + Provider *provider = malloc(sizeof(Provider)); + Service *service = call->service; + char *providerName = "INTERRUPT"; + provider->name = providerName; + provider->address = PTR(call->parameters[1]); + provider->service = call->service; + listAdd(&interruptSubscriptions[call->parameters[0]], provider); +} + void (*syscallHandlers[])(Syscall *) = { 0, (void *)handleInstallSyscall, @@ -188,4 +185,5 @@ (void *)handleLoadFromInitrdSyscall, (void *)handleGetServiceSyscall, (void *)handleGetProviderSyscall, + (void *)handleSubscribeInterruptSyscall, }; diff --git a/src/userland/loader/main.c b/src/userland/loader/main.c index c3dcdba..d6cb880 100644 --- a/src/userland/loader/main.c +++ b/src/userland/loader/main.c @@ -63,8 +63,6 @@ loadFromInitrd("log"); log("hello world"); log("honey os is alive :)"); - log("doing wrong code..."); - uint32_t x = 1 / 0; - log("something went wrong?"); + loadFromInitrd("pic"); return 0; } diff --git a/src/userland/pic/Makefile b/src/userland/pic/Makefile new file mode 100644 index 0000000..1769890 --- /dev/null +++ b/src/userland/pic/Makefile @@ -0,0 +1,29 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 -e main +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name *.c -or -name *.asm -or -name *.s) +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../../initrd/pic: $(OBJS) + @echo "linking user program 8259 PIC" + @$(LD) $(LD_FLAGS) -o ../../../initrd/pic $(OBJS) + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 9fb0b69..a0764de 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -13,7 +13,7 @@ SYS_LOAD_INITRD = 5, SYS_GET_SERVICE = 6, SYS_GET_PROVIDER = 7, - SYS_INTERRUPT = 8, + SYS_SUBSCRIBE_INTERRUPT = 8, } SyscallIds; #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 62206d2..6e973c9 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -26,5 +26,6 @@ extern Service *findService(char *); extern Provider *findProvider(Service *, char *); extern Service *currentService; - +extern void scheduleProvider(Provider *provider, void *data, + uint32_t dataLength, Syscall *respondingTo); #endif diff --git a/src/kernel/interrupts/interruptDescriptors.asm b/src/kernel/interrupts/interruptDescriptors.asm index ae7c56f..0144759 100644 --- a/src/kernel/interrupts/interruptDescriptors.asm +++ b/src/kernel/interrupts/interruptDescriptors.asm @@ -13,6 +13,8 @@ call onInterrupt pop eax mov cr3, eax + pop eax + pop eax iret %macro interruptHandler 1 diff --git a/src/kernel/interrupts/interrupts.c b/src/kernel/interrupts/interrupts.c index 98c18ba..a185b9a 100644 --- a/src/kernel/interrupts/interrupts.c +++ b/src/kernel/interrupts/interrupts.c @@ -1,6 +1,7 @@ #include "interrupts.h" #include #include +#include #include #define IDT_ENTRY(i) \ @@ -12,17 +13,21 @@ extern GDTEntry newGDT; extern TSS tss; +ListElement *interruptSubscriptions[255]; + __attribute__((section(".sharedFunction"))) __attribute__((aligned(0x10))) IdtEntry idtEntries[256] = {}; void onInterrupt(uint32_t cr3, uint32_t intNo, uint32_t errorCode) { if (intNo > 31) { // an external interrupt was triggered - while (1) + foreach (interruptSubscriptions[intNo], Provider *, provider, + { scheduleProvider(provider, PTR(intNo), 0, NULL); }) ; - } - if (intNo <= 31 && cr3 != 0x500000) { - // a task encountered an exception + } else if (intNo <= 31 && cr3 != 0x500000) { + // a task encountered an exception, end it + // todo: free syscall structure and handle the respondingTo one + // appropriately asm(".intel_syntax noprefix\n" "mov eax, [temporaryESP]\n" "mov esp, eax\n" @@ -34,6 +39,8 @@ extern void *interruptStack; +void setupPic(); + void registerInterrupts() { GDTEntry *currentGdt = &newGDT; currentGdt[5].limit = sizeof(TSS); @@ -57,8 +64,24 @@ .limit = sizeof(idtEntries) - 1, }; asm("lidt %0" ::"m"(pointer)); - asm("mov $0xFF, %%al" ::); - asm("out %%al, $0xA1" ::); - asm("out %%al, $0x21" ::); + setupPic(); asm("sti"); } + +#define outb(port, value) \ + asm("outb %0, %1" : : "a"((uint8_t)value), "Nd"(port)); + +void setupPic() { + // sadly I have to do this here, because the PIC will trigger before the PIC + // driver has a chance to set it up + outb(0x20, 0x11); + outb(0xA0, 0x11); + outb(0xA1, 32); + outb(0x21, 40); + outb(0xA1, 0x04); + outb(0x21, 0x02); + outb(0x21, 0x1); + outb(0xA1, 0x1); + outb(0xA0, 0x20); + outb(0x20, 0x20); +} diff --git a/src/kernel/main.c b/src/kernel/main.c index 49b3f59..584518d 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -53,7 +53,7 @@ while (1) { Syscall *call = listPopFirst(&callsToProcess); if (!call) { - asm("hlt"); + asm("sti;hlt"); continue; } if (call->resume) { diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index d13ca0f..130f3ce 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -75,3 +75,23 @@ ; return NULL; } + +void scheduleProvider(Provider *provider, void *data, uint32_t dataLength, + Syscall *respondingTo) { + sharePage(&provider->service->pagingInfo, data, data); + Syscall *runCall = malloc(sizeof(Syscall)); + runCall->function = SYS_RUN; + runCall->esp = malloc(0x1000); + runCall->respondingTo = respondingTo; + runCall->cr3 = + getPhysicalAddressKernel(provider->service->pagingInfo.pageDirectory); + runCall->service = provider->service; + runCall->resume = true; + sharePage(&provider->service->pagingInfo, runCall->esp, runCall->esp); + runCall->esp += 0xFF0; + *(void **)runCall->esp = provider->address; + *(void **)(runCall->esp + 0x4) = &runEnd; + *(void **)(runCall->esp + 0x8) = data; + *(uint32_t *)(runCall->esp + 0xC) = dataLength; + listAdd(&callsToProcess, runCall); +} diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index 8e0a966..8c001be 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -79,22 +79,7 @@ listGet(providerService->providers, call->parameters[1]); void *data = kernelMapPhysical(getPhysicalAddress( service->pagingInfo.pageDirectory, PTR(call->parameters[2]))); - sharePage(&providerService->pagingInfo, data, data); - Syscall *runCall = malloc(sizeof(Syscall)); - runCall->function = SYS_RUN; - runCall->esp = malloc(0x1000); - runCall->respondingTo = call; - runCall->cr3 = - getPhysicalAddressKernel(providerService->pagingInfo.pageDirectory); - runCall->service = providerService; - runCall->resume = true; - sharePage(&providerService->pagingInfo, runCall->esp, runCall->esp); - runCall->esp += 0xFF0; - *(void **)runCall->esp = provider->address; - *(void **)(runCall->esp + 0x4) = &runEnd; - *(void **)(runCall->esp + 0x8) = data; - *(uint32_t *)(runCall->esp + 0xC) = call->parameters[3]; - listAdd(&callsToProcess, runCall); + scheduleProvider(provider, data, call->parameters[3], call); call->avoidReschedule = true; } @@ -179,6 +164,18 @@ ; } +extern ListElement *interruptSubscriptions[255]; + +void handleSubscribeInterruptSyscall(Syscall *call) { + Provider *provider = malloc(sizeof(Provider)); + Service *service = call->service; + char *providerName = "INTERRUPT"; + provider->name = providerName; + provider->address = PTR(call->parameters[1]); + provider->service = call->service; + listAdd(&interruptSubscriptions[call->parameters[0]], provider); +} + void (*syscallHandlers[])(Syscall *) = { 0, (void *)handleInstallSyscall, @@ -188,4 +185,5 @@ (void *)handleLoadFromInitrdSyscall, (void *)handleGetServiceSyscall, (void *)handleGetProviderSyscall, + (void *)handleSubscribeInterruptSyscall, }; diff --git a/src/userland/loader/main.c b/src/userland/loader/main.c index c3dcdba..d6cb880 100644 --- a/src/userland/loader/main.c +++ b/src/userland/loader/main.c @@ -63,8 +63,6 @@ loadFromInitrd("log"); log("hello world"); log("honey os is alive :)"); - log("doing wrong code..."); - uint32_t x = 1 / 0; - log("something went wrong?"); + loadFromInitrd("pic"); return 0; } diff --git a/src/userland/pic/Makefile b/src/userland/pic/Makefile new file mode 100644 index 0000000..1769890 --- /dev/null +++ b/src/userland/pic/Makefile @@ -0,0 +1,29 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 -e main +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name *.c -or -name *.asm -or -name *.s) +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../../initrd/pic: $(OBJS) + @echo "linking user program 8259 PIC" + @$(LD) $(LD_FLAGS) -o ../../../initrd/pic $(OBJS) + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/userland/pic/main.c b/src/userland/pic/main.c new file mode 100644 index 0000000..e823bfb --- /dev/null +++ b/src/userland/pic/main.c @@ -0,0 +1,96 @@ +#include +#include + +#define PTR(x) ((void *)(uintptr_t)x) +#define U32(x) ((uint32_t)(uintptr_t)x) + +uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, + uint32_t parameter2, uint32_t parameter3) { + uint32_t esp; + asm("push %%eax" ::"a"(&&end)); + asm("mov %%esp, %%eax" : "=a"(esp)); + asm("sysenter\n" + : + : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), + "S"(parameter3), "D"(esp)); +end: + // the 0x1C comes from the number of parameters / local variables do handle + // this function with care or it will break everything + asm("add $0x1C, %%esp\n" + "pop %%ebp\n" + "ret" ::); + // don't go here! ret returns with the correct value + return 0; +} + +void installServiceProvider(char *name, void(provider)(void *, uint32_t)) { + syscall(SYS_REGISTER_FUNCTION, U32(name), U32(provider), 0, 0); +} + +uint32_t strlen(char *string) { + uint32_t size = 0; + while (*string) { + string++; + size++; + } + return size; +} + +uint32_t ioIn(uint16_t port, uint8_t size) { + return syscall(SYS_IO_IN, size, port, 0, 0); +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + syscall(SYS_IO_OUT, size, port, value, 0); +} + +uint32_t getModule(char *name) { + return syscall(SYS_GET_SERVICE, U32(name), strlen(name), 0, 0); +} + +uint32_t getProvider(uint32_t module, char *name) { + return syscall(SYS_GET_PROVIDER, module, U32(name), strlen(name), 0); +} + +void request(uint32_t module, uint32_t function, void *data, uint32_t size) { + syscall(SYS_REQUEST, module, function, U32(data), size); +} + +void log(char *message) { + uint32_t module = getModule("log"); + uint32_t provider = getProvider(module, "log"); + request(module, provider, message, strlen(message)); +} + +#define PIC1 0x20 +#define PIC2 0xA0 + +#define COMMAND_ICW4 0x01 +#define COMMAND_SINGLE 0x02 +#define COMMAND_INTERVAL4 0x04 +#define COMMAND_LEVEL 0x08 +#define COMMAND_INIT 0x10 +#define DATA(x) PIC##x + 1 + +#define COMMAND(x, command) ioOut(1, PIC##x, command); + +#define BOTH(command, ...) \ + command(1, __VA_ARGS__); \ + command(2, __VA_ARGS__); + +void irqMaster(uint32_t intNo) { + ioOut(1, PIC1, 0x20); + ioIn(1, 0x60); + log("irq!"); +} + +void subscribeInterrupt(uint32_t intNo, void *handler) { + syscall(SYS_SUBSCRIBE_INTERRUPT, intNo, U32(handler), 0, 0); +} + +int32_t main() { + log("setting up interrupt handlers for the PIC"); + for (uint32_t i = 32; i < 48; i++) { + subscribeInterrupt(i, irqMaster); + } +}