IRQ stuff
This commit is contained in:
parent
ca5a3c3d2f
commit
095d087e1d
@ -110,7 +110,7 @@ extern void isrs_uninstall_handler(size_t isrs);
|
||||
|
||||
/* Interrupt Handlers */
|
||||
extern void irq_install(void);
|
||||
extern void irq_install_handler(size_t irq, irq_handler_chain_t);
|
||||
extern void irq_install_handler(size_t irq, irq_handler_chain_t, char * desc);
|
||||
extern void irq_uninstall_handler(size_t irq);
|
||||
extern int irq_is_handler_free(size_t irq);
|
||||
extern void irq_gates(void);
|
||||
|
@ -85,14 +85,22 @@ void int_enable(void) {
|
||||
|
||||
static void (*irqs[IRQ_CHAIN_SIZE])(void);
|
||||
static irq_handler_chain_t irq_routines[IRQ_CHAIN_SIZE * IRQ_CHAIN_DEPTH] = { NULL };
|
||||
static char * _irq_handler_descriptions[IRQ_CHAIN_SIZE * IRQ_CHAIN_DEPTH] = { NULL };
|
||||
|
||||
void irq_install_handler(size_t irq, irq_handler_chain_t handler) {
|
||||
char * get_irq_handler(int irq, int chain) {
|
||||
if (irq >= IRQ_CHAIN_SIZE) return NULL;
|
||||
if (chain >= IRQ_CHAIN_DEPTH) return NULL;
|
||||
return _irq_handler_descriptions[IRQ_CHAIN_SIZE * chain + irq];
|
||||
}
|
||||
|
||||
void irq_install_handler(size_t irq, irq_handler_chain_t handler, char * desc) {
|
||||
/* Disable interrupts when changing handlers */
|
||||
SYNC_CLI();
|
||||
for (size_t i = 0; i < IRQ_CHAIN_DEPTH; i++) {
|
||||
if (irq_routines[i * IRQ_CHAIN_SIZE + irq])
|
||||
continue;
|
||||
irq_routines[i * IRQ_CHAIN_SIZE + irq] = handler;
|
||||
_irq_handler_descriptions[i * IRQ_CHAIN_SIZE + irq ] = desc;
|
||||
break;
|
||||
}
|
||||
SYNC_STI();
|
||||
|
@ -84,7 +84,7 @@ void relative_time(unsigned long seconds, unsigned long subseconds, unsigned lon
|
||||
void timer_install(void) {
|
||||
debug_print(NOTICE,"Initializing interval timer");
|
||||
boot_time = read_cmos();
|
||||
irq_install_handler(TIMER_IRQ, timer_handler);
|
||||
irq_install_handler(TIMER_IRQ, timer_handler, "pit timer");
|
||||
timer_phase(SUBTICKS_PER_TICK); /* 100Hz */
|
||||
}
|
||||
|
||||
|
@ -238,7 +238,7 @@ static int init(void) {
|
||||
_device.nabmbar = pci_read_field(_device.pci_device, AC97_NABMBAR, 2) & ((uint32_t) -1) << 1;
|
||||
_device.nambar = pci_read_field(_device.pci_device, PCI_BAR0, 4) & ((uint32_t) -1) << 1;
|
||||
_device.irq = pci_read_field(_device.pci_device, PCI_INTERRUPT_LINE, 1);
|
||||
irq_install_handler(_device.irq, irq_handler);
|
||||
irq_install_handler(_device.irq, irq_handler, "ac97");
|
||||
/* Enable all matter of interrupts */
|
||||
outportb(_device.nabmbar + AC97_PO_CR, AC97_X_CR_FEIE | AC97_X_CR_IOCE);
|
||||
|
||||
|
@ -820,8 +820,8 @@ static int ata_initialize(void) {
|
||||
/* Locate ATA device via PCI */
|
||||
pci_scan(&find_ata_pci, -1, &ata_pci);
|
||||
|
||||
irq_install_handler(14, ata_irq_handler);
|
||||
irq_install_handler(15, ata_irq_handler_s);
|
||||
irq_install_handler(14, ata_irq_handler, "ide master");
|
||||
irq_install_handler(15, ata_irq_handler_s, "ide slave");
|
||||
|
||||
atapi_waiter = list_create();
|
||||
|
||||
|
@ -14,6 +14,8 @@
|
||||
|
||||
#include <toaru/list.h>
|
||||
|
||||
#define E1000_LOG_LEVEL NOTICE
|
||||
|
||||
static uint32_t e1000_device_pci = 0x00000000;
|
||||
static int e1000_irq = 0;
|
||||
static uintptr_t mem_base = 0;
|
||||
@ -206,6 +208,8 @@ static void read_mac(void) {
|
||||
|
||||
static int irq_handler(struct regs *r) {
|
||||
|
||||
debug_print(E1000_LOG_LEVEL, "RECEIVED INTERRUPT FROM E1000");
|
||||
|
||||
uint32_t status = read_command(0xc0);
|
||||
|
||||
irq_ack(e1000_irq);
|
||||
@ -216,7 +220,7 @@ static int irq_handler(struct regs *r) {
|
||||
|
||||
if (status & 0x04) {
|
||||
/* Start link */
|
||||
debug_print(NOTICE, "start link");
|
||||
debug_print(E1000_LOG_LEVEL, "start link");
|
||||
} else if (status & 0x10) {
|
||||
/* ?? */
|
||||
} else if (status & ((1 << 6) | (1 << 7))) {
|
||||
@ -249,7 +253,7 @@ static int irq_handler(struct regs *r) {
|
||||
|
||||
static void send_packet(uint8_t* payload, size_t payload_size) {
|
||||
tx_index = read_command(E1000_REG_TXDESCTAIL);
|
||||
debug_print(NOTICE,"sending packet 0x%x, %d desc[%d]", payload, payload_size, tx_index);
|
||||
debug_print(E1000_LOG_LEVEL,"sending packet 0x%x, %d desc[%d]", payload, payload_size, tx_index);
|
||||
|
||||
memcpy(tx_virt[tx_index], payload, payload_size);
|
||||
tx[tx_index].length = payload_size;
|
||||
@ -300,28 +304,52 @@ static void init_tx(void) {
|
||||
|
||||
static void e1000_init(void * data, char * name) {
|
||||
|
||||
debug_print(E1000_LOG_LEVEL, "enabling bus mastering");
|
||||
uint16_t command_reg = pci_read_field(e1000_device_pci, PCI_COMMAND, 2);
|
||||
command_reg |= (1 << 2);
|
||||
command_reg |= (1 << 0);
|
||||
pci_write_field(e1000_device_pci, PCI_COMMAND, 2, command_reg);
|
||||
|
||||
debug_print(NOTICE, "mem base: 0x%x", mem_base);
|
||||
debug_print(E1000_LOG_LEVEL, "mem base: 0x%x", mem_base);
|
||||
|
||||
eeprom_detect();
|
||||
debug_print(NOTICE, "has_eeprom = %d", has_eeprom);
|
||||
debug_print(E1000_LOG_LEVEL, "has_eeprom = %d", has_eeprom);
|
||||
read_mac();
|
||||
|
||||
debug_print(NOTICE, "device mac %2x:%2x:%2x:%2x:%2x:%2x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
|
||||
/* initialize */
|
||||
write_command(E1000_REG_CTRL, (1 << 26));
|
||||
|
||||
/* wait */
|
||||
debug_print(E1000_LOG_LEVEL, "device mac %2x:%2x:%2x:%2x:%2x:%2x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
unsigned long s, ss;
|
||||
|
||||
uint32_t ctrl = read_command(E1000_REG_CTRL);
|
||||
/* reset phy */
|
||||
write_command(E1000_REG_CTRL, ctrl | (0x80000000));
|
||||
read_command(E1000_REG_STATUS);
|
||||
relative_time(0, 10, &s, &ss);
|
||||
sleep_until((process_t *)current_process, s, ss);
|
||||
switch_task(0);
|
||||
debug_print(NOTICE, "back from sleep");
|
||||
|
||||
/* reset mac */
|
||||
write_command(E1000_REG_CTRL, ctrl | (0x04000000));
|
||||
read_command(E1000_REG_STATUS);
|
||||
relative_time(0, 10, &s, &ss);
|
||||
sleep_until((process_t *)current_process, s, ss);
|
||||
switch_task(0);
|
||||
|
||||
/* Reload EEPROM */
|
||||
write_command(E1000_REG_CTRL, ctrl | (0x00002000));
|
||||
read_command(E1000_REG_STATUS);
|
||||
relative_time(0, 20, &s, &ss);
|
||||
sleep_until((process_t *)current_process, s, ss);
|
||||
switch_task(0);
|
||||
|
||||
|
||||
/* initialize */
|
||||
write_command(E1000_REG_CTRL, ctrl | (1 << 26));
|
||||
|
||||
/* wait */
|
||||
relative_time(0, 10, &s, &ss);
|
||||
sleep_until((process_t *)current_process, s, ss);
|
||||
switch_task(0);
|
||||
debug_print(E1000_LOG_LEVEL, "back from sleep");
|
||||
|
||||
uint32_t status = read_command(E1000_REG_CTRL);
|
||||
status |= (1 << 5); /* set auto speed detection */
|
||||
@ -349,10 +377,25 @@ static void e1000_init(void * data, char * name) {
|
||||
net_queue = list_create();
|
||||
rx_wait = list_create();
|
||||
|
||||
uint32_t irq_pin = pci_read_field(e1000_device_pci, 0x3D, 1);
|
||||
debug_print(E1000_LOG_LEVEL, "IRQ pin is 0x%2x", irq_pin);
|
||||
e1000_irq = pci_read_field(e1000_device_pci, PCI_INTERRUPT_LINE, 1);
|
||||
irq_install_handler(e1000_irq, irq_handler);
|
||||
|
||||
debug_print(NOTICE, "Binding interrupt %d", e1000_irq);
|
||||
#define REQ_IRQ 11
|
||||
if (e1000_irq == 255) {
|
||||
debug_print(E1000_LOG_LEVEL, "IRQ line is not set for E1000, trying 11");
|
||||
/* Bad interrupt, need to select one */
|
||||
e1000_irq = REQ_IRQ; /* seems to work okay */
|
||||
pci_write_field(e1000_device_pci, PCI_INTERRUPT_LINE, 1, e1000_irq);
|
||||
e1000_irq = pci_read_field(e1000_device_pci, PCI_INTERRUPT_LINE, 1);
|
||||
if (e1000_irq != REQ_IRQ) {
|
||||
debug_print(E1000_LOG_LEVEL, "irq 10 was rejected?");
|
||||
}
|
||||
}
|
||||
|
||||
irq_install_handler(e1000_irq, irq_handler, "e1000");
|
||||
|
||||
debug_print(E1000_LOG_LEVEL, "Binding interrupt %d", e1000_irq);
|
||||
|
||||
for (int i = 0; i < 128; ++i) {
|
||||
write_command(0x5200 + i * 4, 0);
|
||||
@ -409,7 +452,7 @@ static int init(void) {
|
||||
|
||||
for (int i = 0; i < E1000_NUM_RX_DESC; ++i) {
|
||||
rx_virt[i] = (void*)kvmalloc_p(8192 + 16, (uint32_t *)&rx[i].addr);
|
||||
debug_print(INFO, "rx[%d] 0x%x → 0x%x", i, rx_virt[i], (uint32_t)rx[i].addr);
|
||||
debug_print(E1000_LOG_LEVEL, "rx[%d] 0x%x → 0x%x", i, rx_virt[i], (uint32_t)rx[i].addr);
|
||||
rx[i].status = 0;
|
||||
}
|
||||
|
||||
@ -417,7 +460,7 @@ static int init(void) {
|
||||
|
||||
for (int i = 0; i < E1000_NUM_TX_DESC; ++i) {
|
||||
tx_virt[i] = (void*)kvmalloc_p(8192+16, (uint32_t *)&tx[i].addr);
|
||||
debug_print(INFO, "tx[%d] 0x%x → 0x%x", i, tx_virt[i], (uint32_t)tx[i].addr);
|
||||
debug_print(E1000_LOG_LEVEL, "tx[%d] 0x%x → 0x%x", i, tx_virt[i], (uint32_t)tx[i].addr);
|
||||
tx[i].status = 0;
|
||||
tx[i].cmd = (1 << 0);
|
||||
}
|
||||
|
@ -210,7 +210,7 @@ static void pcnet_init(void * data, char * name) {
|
||||
pcnet_mem_base = pci_read_field(pcnet_device_pci, PCI_BAR1, 4) & 0xFFFFFFF0;
|
||||
|
||||
pcnet_irq = pci_read_field(pcnet_device_pci, PCI_INTERRUPT_LINE, 1);
|
||||
irq_install_handler(pcnet_irq, pcnet_irq_handler);
|
||||
irq_install_handler(pcnet_irq, pcnet_irq_handler, "pcnet");
|
||||
|
||||
debug_print(NOTICE, "irq line: %d", pcnet_irq);
|
||||
debug_print(NOTICE, "io base: 0x%x", pcnet_io_base);
|
||||
|
@ -532,6 +532,34 @@ static uint32_t loader_func(fs_node_t *node, uint32_t offset, uint32_t size, uin
|
||||
return size;
|
||||
}
|
||||
|
||||
extern char * get_irq_handler(int irq, int chain);
|
||||
|
||||
static uint32_t irq_func(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
|
||||
char * buf = malloc(4096);
|
||||
unsigned int soffset = 0;
|
||||
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
soffset += sprintf(&buf[soffset], "irq %d: ", i);
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
char * t = get_irq_handler(i, j);
|
||||
if (!t) break;
|
||||
soffset += sprintf(&buf[soffset], "%s%s", j ? "," : "", t);
|
||||
}
|
||||
soffset += sprintf(&buf[soffset], "\n");
|
||||
}
|
||||
|
||||
size_t _bsize = strlen(buf);
|
||||
if (offset > _bsize) {
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
if (size > _bsize - offset) size = _bsize - offset;
|
||||
|
||||
memcpy(buffer, buf, size);
|
||||
free(buf);
|
||||
return size;
|
||||
}
|
||||
|
||||
static struct procfs_entry std_entries[] = {
|
||||
{-1, "cpuinfo", cpuinfo_func},
|
||||
{-2, "meminfo", meminfo_func},
|
||||
@ -544,6 +572,7 @@ static struct procfs_entry std_entries[] = {
|
||||
{-9, "modules", modules_func},
|
||||
{-10,"filesystems", filesystems_func},
|
||||
{-11,"loader", loader_func},
|
||||
{-12,"irq", irq_func},
|
||||
};
|
||||
|
||||
static struct dirent * readdir_procfs_root(fs_node_t *node, uint32_t index) {
|
||||
|
@ -61,7 +61,7 @@ static int keyboard_install(void) {
|
||||
vfs_mount("/dev/kbd", keyboard_pipe);
|
||||
|
||||
/* Install the interrupt handler */
|
||||
irq_install_handler(KEY_IRQ, keyboard_handler);
|
||||
irq_install_handler(KEY_IRQ, keyboard_handler, "ps2 kbd");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ static int mouse_install(void) {
|
||||
mouse_wait(1);
|
||||
mouse_read();
|
||||
|
||||
irq_install_handler(MOUSE_IRQ, mouse_handler);
|
||||
irq_install_handler(MOUSE_IRQ, mouse_handler, "ps2 mouse");
|
||||
IRQ_RES;
|
||||
|
||||
uint8_t tmp = inportb(0x61);
|
||||
|
@ -304,7 +304,7 @@ int init_rtl(void) {
|
||||
|
||||
rtl_irq = pci_read_field(rtl_device_pci, PCI_INTERRUPT_LINE, 1);
|
||||
debug_print(NOTICE, "Interrupt Line: %x\n", rtl_irq);
|
||||
irq_install_handler(rtl_irq, rtl_irq_handler);
|
||||
irq_install_handler(rtl_irq, rtl_irq_handler, "rtl8139");
|
||||
|
||||
uint32_t rtl_bar0 = pci_read_field(rtl_device_pci, PCI_BAR0, 4);
|
||||
uint32_t rtl_bar1 = pci_read_field(rtl_device_pci, PCI_BAR1, 4);
|
||||
@ -406,7 +406,7 @@ int init_rtl(void) {
|
||||
static int init(void) {
|
||||
pci_scan(&find_rtl, -1, &rtl_device_pci);
|
||||
if (!rtl_device_pci) {
|
||||
debug_print(ERROR, "No RTL 8139 found?");
|
||||
debug_print(NOTICE, "No RTL 8139 found");
|
||||
return 1;
|
||||
}
|
||||
init_rtl();
|
||||
|
@ -149,6 +149,9 @@ static int check_serial(fs_node_t * node) {
|
||||
return selectcheck_fs(*pipe_for_port((int)node->device));
|
||||
}
|
||||
|
||||
static int have_installed_ac = 0;
|
||||
static int have_installed_bd = 0;
|
||||
|
||||
static fs_node_t * serial_device_create(int device) {
|
||||
fs_node_t * fnode = malloc(sizeof(fs_node_t));
|
||||
memset(fnode, 0x00, sizeof(fs_node_t));
|
||||
@ -176,9 +179,15 @@ static fs_node_t * serial_device_create(int device) {
|
||||
serial_enable(device);
|
||||
|
||||
if (device == SERIAL_PORT_A || device == SERIAL_PORT_C) {
|
||||
irq_install_handler(SERIAL_IRQ_AC, serial_handler_ac);
|
||||
if (!have_installed_ac) {
|
||||
irq_install_handler(SERIAL_IRQ_AC, serial_handler_ac, "serial ac");
|
||||
have_installed_ac = 1;
|
||||
}
|
||||
} else {
|
||||
irq_install_handler(SERIAL_IRQ_BD, serial_handler_bd);
|
||||
if (!have_installed_bd) {
|
||||
irq_install_handler(SERIAL_IRQ_BD, serial_handler_bd, "serial bd");
|
||||
have_installed_bd = 1;
|
||||
}
|
||||
}
|
||||
|
||||
*pipe_for_port(device) = make_pipe(128);
|
||||
|
@ -210,7 +210,7 @@ static int vbox_check(void) {
|
||||
}
|
||||
debug_print(WARNING, "(vbox) device IRQ is set to %d", vbox_irq);
|
||||
fprintf(&vb, "irq line is %d\n", vbox_irq);
|
||||
irq_install_handler(vbox_irq, vbox_irq_handler);
|
||||
irq_install_handler(vbox_irq, vbox_irq_handler, "vbox");
|
||||
|
||||
uint32_t vbox_phys = 0;
|
||||
struct vbox_guest_info * packet = (void*)kvmalloc_p(0x1000, &vbox_phys);
|
||||
|
Loading…
x
Reference in New Issue
Block a user