Initial commit: Schunix as it stands before the SchOS rename
An x86-64 operating system built from xv6, now largely rewritten: SMP, a copy-on-write root filesystem (SchFS), PCI/USB/virtio drivers, a TTF rasteriser, and a Linux-numbered syscall ABI. No history before this point -- the tree was never under version control. This commit exists so the rename that follows has something to undo to.
This commit is contained in:
commit
d0f7acf9eb
275 changed files with 51417 additions and 0 deletions
43
include/irq.h
Normal file
43
include/irq.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#pragma once
|
||||
|
||||
// Hardware interrupt registration.
|
||||
//
|
||||
// Until this existed, trap() was a switch statement listing every interrupt
|
||||
// the kernel knew about, and adding a device meant editing the trap handler.
|
||||
// That is fine while the devices are the four the PC has always had at fixed
|
||||
// pins; it stops being fine the moment a device's IRQ is whatever the BIOS
|
||||
// decided to put in its PCI config space this boot. A driver cannot write
|
||||
// `case T_IRQ0 + IRQ_XHCI:` because there is no such constant -- it only
|
||||
// learns its line at probe time.
|
||||
//
|
||||
// So: a line has a chain of handlers, a driver adds itself to one at probe
|
||||
// time, and enabling the line is a consequence of registering rather than a
|
||||
// separate call somebody can forget.
|
||||
//
|
||||
// Chains matter more than they look. PCI interrupt pins are *shared*: four
|
||||
// INTx lines are routed to a handful of IOAPIC inputs, so two unrelated
|
||||
// devices routinely land on the same one. A handler must therefore check
|
||||
// whether its own device actually raised the interrupt and do nothing if it
|
||||
// did not.
|
||||
|
||||
#define NIRQ 24 // IOAPIC redirection entries on a PC
|
||||
#define NCHAIN 4 // handlers that may share one line
|
||||
|
||||
typedef void (*irq_handler_t)(void *arg);
|
||||
|
||||
// Returns 0, or -1 if the line is out of range, reserved, or full.
|
||||
// Registering enables the line; the last unregister masks it again.
|
||||
//
|
||||
// `level_low` selects PCI's signalling (level-triggered, active low) rather
|
||||
// than ISA's (edge-triggered, active high). Getting this wrong does not fail
|
||||
// cleanly: an edge-configured level interrupt fires once and then wedges,
|
||||
// because the device keeps the line asserted and no further edge ever comes.
|
||||
int irq_register(int irq, irq_handler_t fn, void *arg, const char *name,
|
||||
int level_low);
|
||||
void irq_unregister(int irq, irq_handler_t fn, void *arg);
|
||||
|
||||
// Called from trap() with the IOAPIC pin number, not the vector.
|
||||
void irq_dispatch(int irq);
|
||||
|
||||
void irq_init(void);
|
||||
int irq_info(char *buf, int cap); // /proc/interrupts
|
||||
Loading…
Reference in a new issue