/branches/sparc/kernel/genarch/src/kbd/ns16550.c |
---|
38,8 → 38,8 |
#include <genarch/kbd/key.h> |
#include <genarch/kbd/scanc.h> |
#include <genarch/kbd/scanc_sun.h> |
#include <arch/drivers/kbd.h> |
#ifndef ia64 |
#include <arch/drivers/kbd.h> |
#include <arch/drivers/ns16550.h> |
#endif |
#include <ddi/irq.h> |
107,11 → 107,14 |
/** Initialize ns16550. |
* |
* @param devno Device number. |
* @param inr Interrupt number. |
* @param vaddr Virtual address of device's registers. |
* @param devno Device number. |
* @param port Virtual/IO address of device's registers. |
* @param inr Interrupt number. |
* @param cir Clear interrupt function. |
* @param cir_arg First argument to cir. |
*/ |
void ns16550_init(devno_t devno, inr_t inr, ioport_t port) |
void |
ns16550_init(devno_t devno, ioport_t port, inr_t inr, cir_t cir, void *cir_arg) |
{ |
chardev_initialize("ns16550_kbd", &kbrd, &ops); |
stdin = &kbrd; |
124,18 → 127,31 |
ns16550_irq.inr = inr; |
ns16550_irq.claim = ns16550_claim; |
ns16550_irq.handler = ns16550_irq_handler; |
ns16550_irq.cir = cir; |
ns16550_irq.cir_arg = cir_arg; |
irq_register(&ns16550_irq); |
while ((ns16550_lsr_read(&ns16550) & LSR_DATA_READY)) |
ns16550_rbr_read(&ns16550); |
sysinfo_set_item_val("kbd", NULL, true); |
#ifndef ia64 |
sysinfo_set_item_val("kbd.type", NULL, KBD_NS16550); |
#endif |
sysinfo_set_item_val("kbd.devno", NULL, devno); |
sysinfo_set_item_val("kbd.inr", NULL, inr); |
sysinfo_set_item_val("kbd.address.virtual", NULL, port); |
sysinfo_set_item_val("kbd.port", NULL, port); |
#ifdef CONFIG_NS16550_INTERRUPT_DRIVEN |
/* Enable interrupts */ |
ns16550_ier_write(&ns16550, IER_ERBFI); |
ns16550_mcr_write(&ns16550, MCR_OUT2); |
#endif |
#ifdef ia64 |
uint8_t c; |
// This switches rbr & ier to mode when accept baudrate constant |
c = ns16550_lcr_read(&ns16550); |
ns16550_lcr_write(&ns16550, 0x80 | c); |
ns16550_rbr_write(&ns16550, 0x0c); |
149,10 → 165,7 |
/** Process ns16550 interrupt. */ |
void ns16550_interrupt(void) |
{ |
/* TODO |
* |
* ns16550 works in the polled mode so far. |
*/ |
ns16550_poll(); |
} |
/* Called from getc(). */ |
201,6 → 214,7 |
*/ |
void ns16550_poll(void) |
{ |
#ifndef CONFIG_NS16550_INTERRUPT_DRIVEN |
ipl_t ipl; |
ipl = interrupts_disable(); |
220,6 → 234,7 |
spinlock_unlock(&ns16550_irq.lock); |
interrupts_restore(ipl); |
#endif |
while (ns16550_lsr_read(&ns16550) & LSR_DATA_READY) { |
uint8_t x; |
251,7 → 266,10 |
void ns16550_irq_handler(irq_t *irq, void *arg, ...) |
{ |
panic("Not yet implemented, ns16550 works in polled mode.\n"); |
if (irq->notif_cfg.notify && irq->notif_cfg.answerbox) |
ipc_irq_send_notif(irq); |
else |
ns16550_interrupt(); |
} |
/** @} |
/branches/sparc/kernel/genarch/src/kbd/i8042.c |
---|
37,6 → 37,9 |
*/ |
#include <genarch/kbd/i8042.h> |
#ifdef ia64 |
#include <arch/drivers/kbd.h> |
#endif |
#include <genarch/kbd/key.h> |
#include <genarch/kbd/scanc.h> |
#include <genarch/kbd/scanc_pc.h> |
184,7 → 187,9 |
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.devno", NULL, kbd_devno); |
sysinfo_set_item_val("kbd.inr", NULL, kbd_inr); |
#ifdef KBD_LEGACY |
sysinfo_set_item_val("kbd.type", NULL, KBD_LEGACY); |
#endif |
sysinfo_set_item_val("mouse", NULL, true); |
sysinfo_set_item_val("mouse.devno", NULL, mouse_devno); |
sysinfo_set_item_val("mouse.inr", NULL, mouse_inr); |
/branches/sparc/kernel/genarch/src/kbd/z8530.c |
---|
43,7 → 43,6 |
#include <ipc/irq.h> |
#include <arch/interrupt.h> |
#include <arch/drivers/kbd.h> |
#include <arch/drivers/fhc.h> |
#include <cpu.h> |
#include <arch/asm.h> |
#include <arch.h> |
83,12 → 82,14 |
*/ |
z8530_write_a(&z8530, WR0, WR0_TX_IP_RST); |
z8530_write_a(&z8530, WR1, WR1_IARCSC); /* interrupt on all characters */ |
/* interrupt on all characters */ |
z8530_write_a(&z8530, WR1, WR1_IARCSC); |
/* 8 bits per character and enable receiver */ |
z8530_write_a(&z8530, WR3, WR3_RX8BITSCH | WR3_RX_ENABLE); |
z8530_write_a(&z8530, WR9, WR9_MIE); /* Master Interrupt Enable. */ |
/* Master Interrupt Enable. */ |
z8530_write_a(&z8530, WR9, WR9_MIE); |
spinlock_lock(&z8530_irq.lock); |
z8530_irq.notif_cfg.notify = false; |
108,7 → 109,8 |
} |
/** Initialize z8530. */ |
void z8530_init(devno_t devno, inr_t inr, uintptr_t vaddr) |
void |
z8530_init(devno_t devno, uintptr_t vaddr, inr_t inr, cir_t cir, void *cir_arg) |
{ |
chardev_initialize("z8530_kbd", &kbrd, &ops); |
stdin = &kbrd; |
121,6 → 123,8 |
z8530_irq.inr = inr; |
z8530_irq.claim = z8530_claim; |
z8530_irq.handler = z8530_irq_handler; |
z8530_irq.cir = cir; |
z8530_irq.cir_arg = cir_arg; |
irq_register(&z8530_irq); |
sysinfo_set_item_val("kbd", NULL, true); |
197,18 → 201,10 |
void z8530_irq_handler(irq_t *irq, void *arg, ...) |
{ |
/* |
* So far, we know we got this interrupt through the FHC. |
* Since we don't have enough documentation about the FHC |
* and because the interrupt looks like level sensitive, |
* we cannot handle it by scheduling one of the level |
* interrupt traps. Process the interrupt directly. |
*/ |
if (irq->notif_cfg.notify && irq->notif_cfg.answerbox) |
ipc_irq_send_notif(irq); |
else |
z8530_interrupt(); |
fhc_clear_interrupt(central_fhc, irq->inr); |
} |
/** @} |
/branches/sparc/kernel/genarch/src/ofw/ebus.c |
---|
44,7 → 44,8 |
#include <macros.h> |
/** Apply EBUS ranges to EBUS register. */ |
bool ofw_ebus_apply_ranges(ofw_tree_node_t *node, ofw_ebus_reg_t *reg, uintptr_t *pa) |
bool |
ofw_ebus_apply_ranges(ofw_tree_node_t *node, ofw_ebus_reg_t *reg, uintptr_t *pa) |
{ |
ofw_tree_property_t *prop; |
ofw_ebus_range_t *range; |
62,11 → 63,13 |
for (i = 0; i < ranges; i++) { |
if (reg->space != range[i].child_space) |
continue; |
if (overlaps(reg->addr, reg->size, range[i].child_base, range[i].size)) { |
if (overlaps(reg->addr, reg->size, range[i].child_base, |
range[i].size)) { |
ofw_pci_reg_t pci_reg; |
pci_reg.space = range[i].parent_space; |
pci_reg.addr = range[i].parent_base + (reg->addr - range[i].child_base); |
pci_reg.addr = range[i].parent_base + |
(reg->addr - range[i].child_base); |
pci_reg.size = reg->size; |
return ofw_pci_apply_ranges(node->parent, &pci_reg, pa); |
76,7 → 79,9 |
return false; |
} |
bool ofw_ebus_map_interrupt(ofw_tree_node_t *node, ofw_ebus_reg_t *reg, uint32_t interrupt, int *inr) |
bool |
ofw_ebus_map_interrupt(ofw_tree_node_t *node, ofw_ebus_reg_t *reg, |
uint32_t interrupt, int *inr, cir_t *cir, void **cir_arg) |
{ |
ofw_tree_property_t *prop; |
ofw_tree_node_t *controller; |
104,8 → 109,8 |
unsigned int i; |
for (i = 0; i < count; i++) { |
if ((intr_map[i].space == space) && (intr_map[i].addr == addr) |
&& (intr_map[i].intr == intr)) |
if ((intr_map[i].space == space) && |
(intr_map[i].addr == addr) && (intr_map[i].intr == intr)) |
goto found; |
} |
return false; |
113,10 → 118,12 |
found: |
/* |
* We found the device that functions as an interrupt controller |
* for the interrupt. We also found partial mapping from interrupt to INO. |
* for the interrupt. We also found partial mapping from interrupt to |
* INO. |
*/ |
controller = ofw_tree_find_node_by_handle(ofw_tree_lookup("/"), intr_map[i].controller_handle); |
controller = ofw_tree_find_node_by_handle(ofw_tree_lookup("/"), |
intr_map[i].controller_handle); |
if (!controller) |
return false; |
130,7 → 137,8 |
/* |
* Let the PCI do the next step in mapping the interrupt. |
*/ |
if (!ofw_pci_map_interrupt(controller, NULL, intr_map[i].controller_ino, inr)) |
if (!ofw_pci_map_interrupt(controller, NULL, intr_map[i].controller_ino, |
inr, cir, cir_arg)) |
return false; |
return true; |
/branches/sparc/kernel/genarch/src/ofw/fhc.c |
---|
109,7 → 109,9 |
return false; |
} |
bool ofw_fhc_map_interrupt(ofw_tree_node_t *node, ofw_fhc_reg_t *reg, uint32_t interrupt, int *inr) |
bool |
ofw_fhc_map_interrupt(ofw_tree_node_t *node, ofw_fhc_reg_t *reg, |
uint32_t interrupt, int *inr, cir_t *cir, void **cir_arg) |
{ |
fhc_t *fhc = NULL; |
if (!node->device) { |
126,6 → 128,8 |
fhc_enable_interrupt(fhc, interrupt); |
*inr = interrupt; |
*cir = fhc_clear_interrupt; |
*cir_arg = fhc; |
return true; |
} |
/branches/sparc/kernel/genarch/src/ofw/pci.c |
---|
49,7 → 49,8 |
#define PCI_IGN 0x1f |
bool ofw_pci_apply_ranges(ofw_tree_node_t *node, ofw_pci_reg_t *reg, uintptr_t *pa) |
bool |
ofw_pci_apply_ranges(ofw_tree_node_t *node, ofw_pci_reg_t *reg, uintptr_t *pa) |
{ |
ofw_tree_property_t *prop; |
ofw_pci_range_t *range; |
68,10 → 69,13 |
unsigned int i; |
for (i = 0; i < ranges; i++) { |
if ((reg->space & PCI_SPACE_MASK) != (range[i].space & PCI_SPACE_MASK)) |
if ((reg->space & PCI_SPACE_MASK) != |
(range[i].space & PCI_SPACE_MASK)) |
continue; |
if (overlaps(reg->addr, reg->size, range[i].child_base, range[i].size)) { |
*pa = range[i].parent_base + (reg->addr - range[i].child_base); |
if (overlaps(reg->addr, reg->size, range[i].child_base, |
range[i].size)) { |
*pa = range[i].parent_base + |
(reg->addr - range[i].child_base); |
return true; |
} |
} |
79,7 → 83,9 |
return false; |
} |
bool ofw_pci_reg_absolutize(ofw_tree_node_t *node, ofw_pci_reg_t *reg, ofw_pci_reg_t *out) |
bool |
ofw_pci_reg_absolutize(ofw_tree_node_t *node, ofw_pci_reg_t *reg, |
ofw_pci_reg_t *out) |
{ |
if (reg->space & PCI_ABS_MASK) { |
/* already absolute */ |
103,7 → 109,8 |
unsigned int i; |
for (i = 0; i < assigned_addresses; i++) { |
if ((assigned_address[i].space & PCI_REG_MASK) == (reg->space & PCI_REG_MASK)) { |
if ((assigned_address[i].space & PCI_REG_MASK) == |
(reg->space & PCI_REG_MASK)) { |
out->space = assigned_address[i].space; |
out->addr = reg->addr + assigned_address[i].addr; |
out->size = reg->size; |
119,7 → 126,9 |
* So far, we only know how to map interrupts of non-PCI devices connected |
* to a PCI bridge. |
*/ |
bool ofw_pci_map_interrupt(ofw_tree_node_t *node, ofw_pci_reg_t *reg, int ino, int *inr) |
bool |
ofw_pci_map_interrupt(ofw_tree_node_t *node, ofw_pci_reg_t *reg, int ino, |
int *inr, cir_t *cir, void **cir_arg) |
{ |
pci_t *pci = node->device; |
if (!pci) { |
132,6 → 141,8 |
pci_enable_interrupt(pci, ino); |
*inr = (PCI_IGN << IGN_SHIFT) | ino; |
*cir = pci_clear_interrupt; |
*cir_arg = pci; |
return true; |
} |