62 lines
No EOL
1.7 KiB
C
62 lines
No EOL
1.7 KiB
C
|
|
#include <stdint.h>
|
|
#include <kprint.h>
|
|
#include <neobbo.h>
|
|
#include "../sys/acpi.h"
|
|
#include "error.h"
|
|
|
|
#define IOREGSEL 0x0
|
|
#define IOWIN 0x10
|
|
|
|
#define IOAPICID 0x0
|
|
#define IOAPICVER 0x1
|
|
#define IOAPICARB 0x2
|
|
#define IOREDTBL(x) (0x10 + (x * 2)) // 0-23 registers
|
|
|
|
extern uint64_t hhdmoffset;
|
|
|
|
extern madt_t *madt;
|
|
|
|
uint64_t ioapic_address;
|
|
|
|
void ioapic_write_reg(uint8_t reg, uint32_t data){
|
|
/* First we load IOREGSEL with the register we want to access */
|
|
*(uint32_t*)(ioapic_address + IOREGSEL) = (uint8_t) reg;
|
|
|
|
/* Then we write the data to the IOWIN register */
|
|
*(uint32_t*)(ioapic_address + IOWIN) = (uint32_t) data;
|
|
}
|
|
|
|
uint32_t ioapic_read_reg(uint8_t reg){
|
|
*(uint32_t*)(ioapic_address + IOREGSEL) = reg;
|
|
|
|
return *(uint32_t*)(ioapic_address + IOWIN);
|
|
}
|
|
|
|
void write_redir_entry(uint8_t reg, uint64_t data){
|
|
/* First write lower 32-bits of the data to the specified IOREDTBL register */
|
|
ioapic_write_reg(IOREDTBL(reg), (uint32_t)(data & 0xFFFFFFFF));
|
|
|
|
/* Then write the upper 32-bits */
|
|
ioapic_write_reg(IOREDTBL(reg)+1, (uint32_t)(data >> 32));
|
|
}
|
|
|
|
kstatus set_redir_entry(uint8_t pin, uint8_t vector, uint8_t delivery, uint8_t trigger, uint8_t destination_field, uint8_t destination_mode){
|
|
uint64_t data = ((uint64_t)destination_field << 56) | (uint64_t)trigger << 15 | (uint64_t)destination_mode << 11 | (uint64_t)delivery << 8 | vector;
|
|
write_redir_entry(pin, data);
|
|
return KERNEL_STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
void ioapic_init(void){
|
|
|
|
ioapic_t *ioapic = (ioapic_t*) find_ics(0x1);
|
|
|
|
if(!ioapic){
|
|
klog(__func__, "IOAPIC ICS not found\n");
|
|
kkill();
|
|
}
|
|
|
|
ioapic_address = ioapic->ioapic_address + hhdmoffset;
|
|
|
|
} |