mirror of
https://github.com/gbowne1/ClassicOS.git
synced 2025-10-14 05:35:06 -07:00
Made some minor fixes to CMakeLists.tx and working on descriptor tables
This commit is contained in:
@@ -3,6 +3,11 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define MY_DEVICE_VENDOR_ID 0x1234
|
||||
#define MY_DEVICE_DEVICE_ID 0x5678
|
||||
#define MY_DEVICE_CLASS_CODE 0x90AB
|
||||
|
||||
// EISA bus controller base address
|
||||
#define EISA_BASE_ADDRESS 0x0000
|
||||
@@ -46,6 +51,8 @@ void eisa_detect_devices()
|
||||
// This is my device, configure it
|
||||
uint32_t config1 = eisa_read_config_dword(address, 4);
|
||||
uint32_t config2 = eisa_read_config_dword(address, 8);
|
||||
printf("Config1: %u\n", config1);
|
||||
printf("Config2: %u\n", config2);
|
||||
// Do something with the configuration data
|
||||
}
|
||||
}
|
||||
@@ -54,6 +61,44 @@ void eisa_detect_devices()
|
||||
}
|
||||
}
|
||||
|
||||
// Read a double word (32 bits) from an EISA device's configuration space
|
||||
uint32_t eisa_read_config_dword(uint32_t address, uint8_t offset)
|
||||
{
|
||||
// Set the EISA bus controller base address
|
||||
eisa_write(EISA_BASE_ADDRESS, address);
|
||||
|
||||
// Set the EISA bus controller command port to read configuration data
|
||||
eisa_write(EISA_COMMAND_PORT, 0x80 | (offset & 0x03));
|
||||
|
||||
// Read the double word from the EISA bus controller data port
|
||||
uint32_t value = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
value |= (eisa_read(EISA_DATA_PORT) << (i * 8));
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// Read a word (16 bits) from an EISA device's configuration space
|
||||
uint16_t eisa_read_config_word(uint32_t address, uint8_t offset)
|
||||
{
|
||||
// Set the EISA bus controller base address
|
||||
eisa_write(EISA_BASE_ADDRESS, address);
|
||||
|
||||
// Set the EISA bus controller command port to read configuration data
|
||||
eisa_write(EISA_COMMAND_PORT, 0x80 | (offset & 0x03));
|
||||
|
||||
// Read the word from the EISA bus controller data port
|
||||
uint16_t value = 0;
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
value |= (eisa_read(EISA_DATA_PORT) << (i * 8));
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// Read from an EISA device
|
||||
uint8_t eisa_read(uint16_t port)
|
||||
{
|
||||
|
@@ -4,6 +4,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Initialize the EISA bus
|
||||
void eisa_init();
|
||||
@@ -11,6 +12,12 @@ void eisa_init();
|
||||
// Detect and configure EISA devices
|
||||
void eisa_detect_devices();
|
||||
|
||||
// Read a double word (32 bits) from an EISA device's configuration space
|
||||
uint32_t eisa_read_config_dword(uint32_t address, uint8_t offset);
|
||||
|
||||
// Read a word (16 bits) from an EISA device's configuration space
|
||||
uint16_t eisa_read_config_word(uint32_t address, uint8_t offset);
|
||||
|
||||
// Read from an EISA device
|
||||
uint8_t eisa_read(uint16_t port);
|
||||
|
||||
|
@@ -7,41 +7,49 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
// GDT table
|
||||
struct gdt_entry *gdt;
|
||||
|
||||
// GDT constants
|
||||
enum GDT_ACCESS
|
||||
{
|
||||
GDT_ACCESS_PRESENT = 0x80
|
||||
};
|
||||
|
||||
// GDT base and limit constants
|
||||
enum GDT_BASE_LIMIT
|
||||
{
|
||||
GDT_BASE_MIDDLE_SHIFT = 16,
|
||||
GDT_BASE_HIGH_SHIFT = 24,
|
||||
GDT_GRANULARITY_SHIFT = 16,
|
||||
GDT_GRANULARITY_MASK = 0x0F,
|
||||
GDT_ACCESS_MASK = 0xF0,
|
||||
GDT_LIMIT_MASK = 0xFFFF
|
||||
};
|
||||
|
||||
// Initialize a GDT entry
|
||||
void gdt_set_gate(uint32_t num, uint32_t base, uint32_t limit, uint8_t access,
|
||||
uint8_t gran)
|
||||
{
|
||||
gdt[num].base_low = (base & 0xFFFF);
|
||||
gdt[num].base_middle = (base >> 16) & 0xFF;
|
||||
gdt[num].base_high = (base >> 24) & 0xFF;
|
||||
gdt[num].limit_low = (limit & 0xFFFF);
|
||||
gdt[num].granularity = (limit >> 16) & 0x0F;
|
||||
gdt[num].granularity |= gran & 0xF0;
|
||||
gdt[num].base_low = (base & GDT_LIMIT_MASK);
|
||||
gdt[num].base_middle = (base >> GDT_BASE_MIDDLE_SHIFT) & 0xFF;
|
||||
gdt[num].base_high = (base >> GDT_BASE_HIGH_SHIFT) & 0xFF;
|
||||
gdt[num].limit_low = (limit & GDT_LIMIT_MASK);
|
||||
gdt[num].granularity =
|
||||
(limit >> GDT_GRANULARITY_SHIFT) & GDT_GRANULARITY_MASK;
|
||||
gdt[num].granularity |= gran & GDT_ACCESS_MASK;
|
||||
gdt[num].access = access;
|
||||
}
|
||||
|
||||
void gdt_init()
|
||||
{
|
||||
// Set up GDT pointer
|
||||
struct gdt_ptr gp;
|
||||
gp.limit = (sizeof(struct gdt_entry) * 3) - 1;
|
||||
gdt = (struct gdt_entry *)malloc(sizeof(struct gdt_entry) * 3);
|
||||
gp.base = (uint32_t)gdt; // Cast gdt to uint32_t
|
||||
|
||||
// Clear GDT
|
||||
memset(gdt, 0, sizeof(struct gdt_entry) * 3);
|
||||
|
||||
// Set up code segment
|
||||
gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
|
||||
|
||||
// Set up data segment
|
||||
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
|
||||
|
||||
// Load GDT
|
||||
asm volatile("lgdt %0" : : "m"(gp));
|
||||
}
|
||||
|
||||
// Exception handlers
|
||||
@@ -57,13 +65,10 @@ extern void keyboard();
|
||||
extern void device();
|
||||
|
||||
// ISR table
|
||||
void (*isr_table[256])(void);
|
||||
void (*isr_table[256])(void) = {0};
|
||||
|
||||
// Register an ISR
|
||||
void isr_register(uint8_t num, void (*handler)(void))
|
||||
{
|
||||
isr_table[num] = handler;
|
||||
}
|
||||
void isr_register(uint8_t num, void (*handler)(struct isr_regs *regs));
|
||||
|
||||
// ISR handler
|
||||
void isr_handler(struct isr_regs *regs)
|
||||
@@ -80,6 +85,12 @@ void isr_handler(struct isr_regs *regs)
|
||||
// Initialize the ISR
|
||||
void isr_init()
|
||||
{
|
||||
// Initialize ISR table
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
isr_table[i] = NULL;
|
||||
}
|
||||
|
||||
// Register exception handlers
|
||||
isr_register(0, divide_error);
|
||||
isr_register(14, page_fault);
|
||||
|
@@ -3,6 +3,8 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern struct gdt_entry *gdt;
|
||||
|
||||
// GDT entry structure
|
||||
struct gdt_entry
|
||||
{
|
||||
|
@@ -6,11 +6,18 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
enum
|
||||
{
|
||||
GDT_ACCESS_PRESENT = 0x80,
|
||||
BASE_MIDDLE_SHIFT = 16,
|
||||
BYTE_MASK = 0xFF
|
||||
};
|
||||
|
||||
// IDT table
|
||||
struct idt_entry idt[256];
|
||||
|
||||
// IDT pointer
|
||||
struct idt_ptr idtp;
|
||||
const struct idt_ptr idtp = {sizeof(idt) - 1, idt};
|
||||
|
||||
// Exception handlers
|
||||
extern void divide_error_handler();
|
||||
@@ -23,13 +30,16 @@ extern void system_call_handler();
|
||||
extern void timer_handler();
|
||||
extern void keyboard_handler();
|
||||
extern void device_handler();
|
||||
extern void network_handler();
|
||||
extern void disk_handler();
|
||||
extern void serial_port_handler();
|
||||
|
||||
// Initialize an IDT entry
|
||||
void idt_set_gate(uint8_t num, void *base, uint16_t sel, uint8_t flags)
|
||||
{
|
||||
uint32_t base_addr = (uint32_t)base;
|
||||
idt[num].base_lo = base_addr & 0xFFFF;
|
||||
idt[num].base_hi = (base_addr >> 16) & 0xFFFF;
|
||||
idt[num].base_lo = base_addr & BYTE_MASK;
|
||||
idt[num].base_hi = (base_addr >> BASE_MIDDLE_SHIFT) & 0xFFFF;
|
||||
idt[num].sel = sel;
|
||||
idt[num].always0 = 0;
|
||||
idt[num].flags = flags;
|
||||
@@ -38,12 +48,12 @@ void idt_set_gate(uint8_t num, void *base, uint16_t sel, uint8_t flags)
|
||||
// Initialize the IDT
|
||||
void idt_init()
|
||||
{
|
||||
// Set up IDT pointer
|
||||
idtp.limit = sizeof(idt) - 1;
|
||||
idtp.base = &idt[0];
|
||||
|
||||
// Clear IDT
|
||||
memset(&idt, 0, sizeof(idt));
|
||||
#ifdef __STDC_LIB_EXT1__
|
||||
memset_s(idt, 0, sizeof(idt));
|
||||
#else
|
||||
memset(idt, 0, sizeof(idt));
|
||||
#endif
|
||||
|
||||
// Set up exception handlers
|
||||
idt_set_gate(0, divide_error_handler, 0x08, 0x8E);
|
||||
@@ -55,7 +65,9 @@ void idt_init()
|
||||
idt_set_gate(0x80, system_call_handler, 0x08, 0xEE);
|
||||
idt_set_gate(0x20, timer_handler, 0x08, 0x8E);
|
||||
idt_set_gate(0x21, keyboard_handler, 0x08, 0x8E);
|
||||
idt_set_gate(0x30, device_handler, 0x08, 0x8E);
|
||||
idt_set_gate(0x22, network_handler, 0x08, 0x8E);
|
||||
idt_set_gate(0x23, disk_handler, 0x08, 0x8E);
|
||||
idt_set_gate(0x24, serial_port_handler, 0x08, 0x8E);
|
||||
|
||||
// Load IDT
|
||||
__asm__ volatile("lidt %0" : : "m"(idtp));
|
||||
|
@@ -3,6 +3,18 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Structure for storing register values during an ISR
|
||||
struct isr_regs
|
||||
{
|
||||
uint32_t ds; // Data segment selector
|
||||
uint32_t edi, esi, ebp, esp, ebx, edx, ecx,
|
||||
eax; // Pushed by pusha instruction
|
||||
uint32_t int_no,
|
||||
err_code; // Interrupt number and error code (if applicable)
|
||||
uint32_t eip, cs, eflags, useresp,
|
||||
ss; // Pushed by the processor automatically
|
||||
};
|
||||
|
||||
// IDT entry structure
|
||||
struct idt_entry
|
||||
{
|
||||
@@ -22,15 +34,18 @@ struct idt_ptr
|
||||
|
||||
// Exception handlers
|
||||
void divide_error();
|
||||
void page_fault();
|
||||
void general_protection_fault();
|
||||
void page_fault(struct isr_regs *regs);
|
||||
void general_protection_fault(struct isr_regs *regs);
|
||||
void double_fault();
|
||||
|
||||
// Interrupt handlers
|
||||
void system_call();
|
||||
void system_call(struct isr_regs *regs);
|
||||
void timer();
|
||||
void keyboard();
|
||||
void device();
|
||||
void network();
|
||||
void disk();
|
||||
void serial_port();
|
||||
|
||||
// Initialize the IDT
|
||||
void idt_init();
|
||||
|
@@ -2,11 +2,13 @@
|
||||
#include "idt.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#define TIMER_INTERRUPT 0x20
|
||||
#define KEYBOARD_INTERRUPT 0x21
|
||||
#define NETWORK_INTERRUPT 0x22
|
||||
#define DISK_INTERRUPT 0x23
|
||||
#define SERIAL_PORT_INTERRUPT 0x24
|
||||
enum {
|
||||
TIMER_INTERRUPT = 0x20,
|
||||
KEYBOARD_INTERRUPT = 0x21,
|
||||
NETWORK_INTERRUPT = 0x22,
|
||||
DISK_INTERRUPT = 0x23,
|
||||
SERIAL_PORT_INTERRUPT = 0x24
|
||||
};
|
||||
|
||||
// ISR table
|
||||
void (*isr_table[256])(struct isr_regs *regs);
|
||||
@@ -20,27 +22,23 @@ void isr_register(uint8_t num, void (*handler)(struct isr_regs *regs))
|
||||
// ISR handler
|
||||
void isr_handler(struct isr_regs *regs)
|
||||
{
|
||||
if (regs->int_no == 0)
|
||||
{
|
||||
divide_error();
|
||||
}
|
||||
else if (regs->int_no == 13)
|
||||
{
|
||||
general_protection_fault(regs);
|
||||
}
|
||||
else if (regs->int_no == 14)
|
||||
{
|
||||
page_fault(regs);
|
||||
}
|
||||
else
|
||||
{
|
||||
void (*handler)(struct isr_regs *regs);
|
||||
|
||||
handler = isr_table[regs->int_no];
|
||||
if (handler)
|
||||
{
|
||||
handler(regs);
|
||||
}
|
||||
switch (regs->int_no) {
|
||||
case 0:
|
||||
divide_error();
|
||||
break;
|
||||
case 13:
|
||||
general_protection_fault(regs);
|
||||
break;
|
||||
case 14:
|
||||
page_fault(regs);
|
||||
break;
|
||||
default:
|
||||
void (*handler)(struct isr_regs *regs);
|
||||
handler = isr_table[regs->int_no];
|
||||
if (handler) {
|
||||
handler(regs);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +46,7 @@ void isr_handler(struct isr_regs *regs)
|
||||
void divide_error()
|
||||
{
|
||||
printf("Divide by zero error!\n");
|
||||
// Additional actions can be taken as needed
|
||||
}
|
||||
|
||||
void page_fault(struct isr_regs *regs)
|
||||
@@ -55,26 +54,19 @@ void page_fault(struct isr_regs *regs)
|
||||
uint32_t faulting_address;
|
||||
|
||||
// Read the CR2 register to get the faulting address
|
||||
asm volatile("mov %%cr2, %0" : "=r"(faulting_address));
|
||||
__asm__ volatile("mov %%cr2, %0" : "=r"(faulting_address));
|
||||
|
||||
// Print an error message with the faulting address
|
||||
printf("Page fault at 0x%x, virtual address 0x%x\n", regs->eip,
|
||||
faulting_address);
|
||||
|
||||
// Halt the system
|
||||
for (;;)
|
||||
;
|
||||
// Additional actions can be taken as needed
|
||||
}
|
||||
|
||||
void general_protection_fault(struct isr_regs *regs)
|
||||
{
|
||||
// Handle the general protection fault exception
|
||||
printf("General protection fault occurred!\n");
|
||||
// Additional actions can be taken as needed
|
||||
|
||||
// Halt the system
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
|
||||
void double_fault()
|
||||
@@ -89,30 +81,29 @@ void system_call(struct isr_regs *regs)
|
||||
uint32_t syscall_number = regs->eax;
|
||||
|
||||
// Handle different system call numbers
|
||||
switch (syscall_number)
|
||||
{
|
||||
case 1:
|
||||
// Handle open() system call
|
||||
// ...
|
||||
break;
|
||||
case 2:
|
||||
// Handle read() system call
|
||||
// ...
|
||||
break;
|
||||
case 3:
|
||||
// Handle write() system call
|
||||
// ...
|
||||
break;
|
||||
case 4:
|
||||
// Handle close() system call
|
||||
// ...
|
||||
break;
|
||||
switch (syscall_number) {
|
||||
case 1:
|
||||
// Handle open() system call
|
||||
// ...
|
||||
break;
|
||||
case 2:
|
||||
// Handle read() system call
|
||||
// ...
|
||||
break;
|
||||
case 3:
|
||||
// Handle write() system call
|
||||
// ...
|
||||
break;
|
||||
case 4:
|
||||
// Handle close() system call
|
||||
// ...
|
||||
break;
|
||||
// Add more cases for other system calls
|
||||
|
||||
default:
|
||||
// Unknown system call number
|
||||
printf("Unknown system call number: %d\n", syscall_number);
|
||||
break;
|
||||
default:
|
||||
// Unknown system call number
|
||||
printf("Unknown system call number: %d\n", syscall_number);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,31 +120,30 @@ void keyboard()
|
||||
void device()
|
||||
{
|
||||
// Determine the type of device interrupt
|
||||
uint32_t interrupt_type = /* Read the interrupt type from the device */;
|
||||
uint32_t interrupt_type = read_interrupt_type();
|
||||
|
||||
// Call the appropriate interrupt handler
|
||||
switch (interrupt_type)
|
||||
{
|
||||
case TIMER_INTERRUPT:
|
||||
timer();
|
||||
break;
|
||||
case KEYBOARD_INTERRUPT:
|
||||
keyboard();
|
||||
break;
|
||||
case NETWORK_INTERRUPT:
|
||||
network();
|
||||
break;
|
||||
case DISK_INTERRUPT:
|
||||
disk();
|
||||
break;
|
||||
case SERIAL_PORT_INTERRUPT:
|
||||
serial_port();
|
||||
break;
|
||||
switch (interrupt_type) {
|
||||
case TIMER_INTERRUPT:
|
||||
timer();
|
||||
break;
|
||||
case KEYBOARD_INTERRUPT:
|
||||
keyboard();
|
||||
break;
|
||||
case NETWORK_INTERRUPT:
|
||||
network();
|
||||
break;
|
||||
case DISK_INTERRUPT:
|
||||
disk();
|
||||
break;
|
||||
case SERIAL_PORT_INTERRUPT:
|
||||
serial_port();
|
||||
break;
|
||||
// Add more cases for other types of device interrupts
|
||||
|
||||
default:
|
||||
// Unknown interrupt type
|
||||
printf("Unknown device interrupt type: %d\n", interrupt_type);
|
||||
break;
|
||||
default:
|
||||
// Unknown interrupt type
|
||||
printf("Unknown device interrupt type: %d\n", interrupt_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -6,13 +6,13 @@
|
||||
// Structure for storing register values during an ISR
|
||||
struct isr_regs
|
||||
{
|
||||
uint32_t ds; // Data segment selector
|
||||
uint32_t ds; // Data segment selector
|
||||
uint32_t edi, esi, ebp, esp, ebx, edx, ecx,
|
||||
eax; // Pushed by pusha instruction
|
||||
eax; // Pushed by pusha instruction
|
||||
uint32_t int_no,
|
||||
err_code; // Interrupt number and error code (if applicable)
|
||||
uint32_t eip, cs, eflags, useresp,
|
||||
ss; // Pushed by the processor automatically
|
||||
ss; // Pushed by the processor automatically
|
||||
};
|
||||
|
||||
// Register an ISR
|
||||
@@ -21,16 +21,4 @@ void isr_register(uint8_t num, void (*handler)(struct isr_regs *regs));
|
||||
// ISR handler
|
||||
void isr_handler(struct isr_regs *regs);
|
||||
|
||||
// Exception handlers
|
||||
void divide_error();
|
||||
void page_fault();
|
||||
void general_protection_fault();
|
||||
void double_fault();
|
||||
|
||||
// Interrupt handlers
|
||||
void system_call();
|
||||
void timer();
|
||||
void keyboard();
|
||||
void device();
|
||||
|
||||
#endif
|
||||
#endif /* ISR_H */
|
Binary file not shown.
@@ -1,17 +0,0 @@
|
||||
#include "../include/types.h"
|
||||
|
||||
void gdt_set_entry(gdt_entry_t *entry, uint32_t base, uint32_t limit,
|
||||
uint16_t flags)
|
||||
{
|
||||
entry->base = base;
|
||||
entry->limit = limit;
|
||||
entry->flags = flags;
|
||||
}
|
||||
|
||||
void idt_set_entry(idt_entry_t *entry, uint32_t base, uint16_t selector,
|
||||
uint16_t flags)
|
||||
{
|
||||
entry->base = base;
|
||||
entry->selector = selector;
|
||||
entry->flags = flags;
|
||||
}
|
Reference in New Issue
Block a user