IRQ stuff

This commit is contained in:
K. Lange 2018-07-21 16:02:39 +09:00
parent ca5a3c3d2f
commit 095d087e1d
13 changed files with 118 additions and 29 deletions

View File

@ -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);

View File

@ -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();

View File

@ -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 */
}

View File

@ -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);

View File

@ -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();

View File

@ -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);
}

View File

@ -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);

View File

@ -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) {

View File

@ -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;
}

View File

@ -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);

View File

@ -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();

View File

@ -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);

View File

@ -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);