Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 1910 → Rev 1911

/trunk/kernel/genarch/src/kbd/ns16550.c
90,6 → 90,11
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.irq", NULL, 0);
sysinfo_set_item_val("kbd.address.virtual", NULL, (uintptr_t) kbd_virt_address);
ns16550_ier_write(IER_ERBFI); /* enable receiver interrupt */
while (ns16550_lsr_read() & LSR_DATA_READY)
(void) ns16550_rbr_read();
}
 
/** Process ns16550 interrupt.
144,7 → 149,7
{
uint8_t x;
 
while (((x = ns16550_lsr_read() & LSR_DATA_READY))) {
while (ns16550_lsr_read() & LSR_DATA_READY) {
x = ns16550_rbr_read();
if (x != IGNORE_CODE) {
if (x & KEY_RELEASE)
/trunk/kernel/genarch/src/ofw/ebus.c
36,12 → 36,15
*/
 
#include <genarch/ofw/ofw_tree.h>
#include <arch/drivers/pci.h>
#include <arch/memstr.h>
#include <arch/trap/interrupt.h>
#include <func.h>
#include <panic.h>
#include <debug.h>
#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)
{
ofw_tree_property_t *prop;
112,11 → 115,34
/*
* We found the device that functions as an interrupt controller
* for the interrupt. We also found mapping from interrupt to INR.
* What needs to be done now is to verify that this indeed is a PCI
* node.
*/
 
controller = ofw_tree_find_node_by_handle(ofw_tree_lookup("/"), intr_map[i].controller_handle);
if (!controller)
return false;
if (strcmp(ofw_tree_node_name(controller), "pci") != 0) {
/*
* This is not a PCI node.
*/
return false;
}
 
pci_t *pci = controller->device;
if (!pci) {
pci = pci_init(controller);
if (!pci)
return false;
controller->device = pci;
}
pci_enable_interrupt(pci, intr_map[i].controller_inr);
 
*inr = intr_map[i].controller_inr;
*inr |= 0x1f << IGN_SHIFT; /* 0x1f is hardwired IGN */
*inr = intr_map[i].controller_inr;
return true;
}
 
/trunk/kernel/genarch/src/ofw/upa.c
45,7 → 45,7
bool ofw_upa_apply_ranges(ofw_tree_node_t *node, ofw_upa_reg_t *reg, uintptr_t *pa)
{
*pa = reg->addr;
return false;
return true;
}
 
/** @}
/trunk/kernel/arch/sparc64/include/asm.h
324,7 → 324,7
{
uint64_t v;
__asm__ volatile ("ldxa [%1] %2, %0\n" : "=r" (v) : "r" (va), "i" (asi));
__asm__ volatile ("ldxa [%1] %2, %0\n" : "=r" (v) : "r" (va), "i" ((unsigned) asi));
return v;
}
337,7 → 337,7
*/
static inline void asi_u64_write(asi_t asi, uintptr_t va, uint64_t v)
{
__asm__ volatile ("stxa %0, [%1] %2\n" : : "r" (v), "r" (va), "i" (asi) : "memory");
__asm__ volatile ("stxa %0, [%1] %2\n" : : "r" (v), "r" (va), "i" ((unsigned) asi) : "memory");
}
 
/** Flush all valid register windows to memory. */
/trunk/kernel/arch/sparc64/include/trap/interrupt.h
40,6 → 40,14
#include <arch/trap/trap_table.h>
#include <arch/stack.h>
 
/* IMAP register bits */
#define IGN_MASK 0x7c0
#define INO_MASK 0x1f
#define IMAP_V_MASK (1ULL<<31)
 
#define IGN_SHIFT 6
 
 
/* Interrupt ASI registers. */
#define ASI_UDB_INTR_W 0x77
#define ASI_INTR_DISPATCH_STATUS 0x48
/trunk/kernel/arch/sparc64/include/drivers/pci.h
0,0 → 1,70
/*
* Copyright (C) 2006 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup sparc64
* @{
*/
/** @file
*/
 
#ifndef KERN_sparc64_PCI_H_
#define KERN_sparc64_PCI_H_
 
#include <arch/types.h>
#include <genarch/ofw/ofw_tree.h>
#include <arch/arch.h>
#include <arch/asm.h>
 
typedef enum pci_model pci_model_t;
typedef struct pci pci_t;
typedef struct pci_operations pci_operations_t;
 
enum pci_model {
PCI_UNKNOWN,
PCI_SABRE
};
 
struct pci_operations {
void (* enable_interrupt)(pci_t *pci, int inr);
void (* clear_interrupt)(pci_t *pci, int inr);
};
 
struct pci {
pci_model_t model;
pci_operations_t *op;
volatile uint64_t *reg; /**< Registers including interrupt registers. */
};
 
extern pci_t *pci_init(ofw_tree_node_t *node);
extern void pci_enable_interrupt(pci_t *pci, int inr);
extern void pci_clear_interrupt(pci_t *pci, int inr);
 
#endif
 
/** @}
*/
/trunk/kernel/arch/sparc64/include/drivers/ns16550.h
38,10 → 38,18
#include <arch/types.h>
#include <arch/drivers/kbd.h>
 
/* NS16550 registers */
#define RBR_REG 0 /** Receiver Buffer Register. */
#define IER_REG 1 /** Interrupt Enable Register. */
#define IIR_REG 2 /** Interrupt Ident Register (read). */
#define FCR_REG 2 /** FIFO control register (write). */
#define LCR_REG 3 /** Line Control register. */
#define LSR_REG 5 /** Line Status Register. */
 
#define IER_ERBFI 0x01 /** Enable Receive Buffer Full Interrupt. */
 
#define LCR_DLAB 0x80 /** Divisor Latch Access bit. */
 
static inline uint8_t ns16550_rbr_read(void)
{
return kbd_virt_address[RBR_REG];
57,6 → 65,26
kbd_virt_address[IER_REG] = v;
}
 
static inline uint8_t ns16550_iir_read(void)
{
return kbd_virt_address[IIR_REG];
}
 
static inline void ns16550_fcr_write(uint8_t v)
{
kbd_virt_address[FCR_REG] = v;
}
 
static inline uint8_t ns16550_lcr_read(void)
{
return kbd_virt_address[LCR_REG];
}
 
static inline void ns16550_lcr_write(uint8_t v)
{
kbd_virt_address[LCR_REG] = v;
}
 
static inline uint8_t ns16550_lsr_read(void)
{
return kbd_virt_address[LSR_REG];
/trunk/kernel/arch/sparc64/Makefile.inc
100,7 → 100,8
arch/$(ARCH)/src/ddi/ddi.c \
arch/$(ARCH)/src/drivers/tick.c \
arch/$(ARCH)/src/drivers/kbd.c \
arch/$(ARCH)/src/drivers/scr.c
arch/$(ARCH)/src/drivers/scr.c \
arch/$(ARCH)/src/drivers/pci.c
 
ifeq ($(CONFIG_SMP),y)
ARCH_SOURCES += \
/trunk/kernel/arch/sparc64/src/drivers/kbd.c
99,7 → 99,7
uintptr_t pa;
size_t size;
int ino;
int inr;
switch (kbd_type) {
case KBD_Z8530:
108,7 → 108,7
printf("Failed to determine keyboard address.\n");
return;
}
if (!ofw_fhc_map_interrupts(node->parent, ((ofw_fhc_reg_t *) prop->value), interrupts, &ino)) {
if (!ofw_fhc_map_interrupts(node->parent, ((ofw_fhc_reg_t *) prop->value), interrupts, &inr)) {
printf("Failed to determine keyboard interrupts.\n");
return;
}
119,7 → 119,7
printf("Failed to determine keyboard address.\n");
return;
}
if (!ofw_ebus_map_interrupts(node->parent, ((ofw_ebus_reg_t *) prop->value), interrupts, &ino)) {
if (!ofw_ebus_map_interrupts(node->parent, ((ofw_ebus_reg_t *) prop->value), interrupts, &inr)) {
printf("Failed to determine keyboard interrupts.\n");
return;
}
/trunk/kernel/arch/sparc64/src/drivers/pci.c
0,0 → 1,157
/*
* Copyright (C) 2006 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup sparc64
* @{
*/
/**
* @file
* @brief PCI driver.
*/
 
#include <arch/drivers/pci.h>
#include <genarch/ofw/ofw_tree.h>
#include <arch/trap/interrupt.h>
#include <arch/mm/page.h>
#include <mm/slab.h>
#include <arch/types.h>
#include <typedefs.h>
#include <debug.h>
#include <print.h>
#include <func.h>
#include <arch/asm.h>
 
#define PCI_SABRE_REGS_REG 0
 
#define PCI_SABRE_IMAP_BASE 0x200
#define PCI_SABRE_ICLR_BASE 0x300
 
static pci_t *pci_sabre_init(ofw_tree_node_t *node);
static void pci_sabre_enable_interrupt(pci_t *pci, int inr);
static void pci_sabre_clear_interrupt(pci_t *pci, int inr);
 
/** PCI operations for Sabre model. */
static pci_operations_t pci_sabre_ops = {
.enable_interrupt = pci_sabre_enable_interrupt,
.clear_interrupt = pci_sabre_clear_interrupt
};
 
/** Initialize PCI controller (model Sabre). */
pci_t *pci_sabre_init(ofw_tree_node_t *node)
{
pci_t *pci;
ofw_tree_property_t *prop;
 
/*
* Get registers.
*/
prop = ofw_tree_getprop(node, "reg");
if (!prop || !prop->value)
return NULL;
 
ofw_upa_reg_t *reg = prop->value;
count_t regs = prop->size / sizeof(ofw_upa_reg_t);
 
if (regs < PCI_SABRE_REGS_REG + 1)
return NULL;
 
uintptr_t paddr;
if (!ofw_upa_apply_ranges(node->parent, &reg[PCI_SABRE_REGS_REG], &paddr))
return NULL;
 
pci = (pci_t *) malloc(sizeof(pci_t), FRAME_ATOMIC);
if (!pci)
return NULL;
 
pci->model = PCI_SABRE;
pci->op = &pci_sabre_ops;
pci->reg = (uint64_t *) hw_map(paddr, reg[PCI_SABRE_REGS_REG].size);
 
return pci;
}
 
void pci_sabre_enable_interrupt(pci_t *pci, int inr)
{
pci->reg[PCI_SABRE_ICLR_BASE + (inr & INO_MASK)] = 0;
pci->reg[PCI_SABRE_IMAP_BASE + (inr & INO_MASK)] |= IMAP_V_MASK;
}
 
void pci_sabre_clear_interrupt(pci_t *pci, int inr)
{
pci->reg[PCI_SABRE_ICLR_BASE + (inr & INO_MASK)] = 0;
}
 
/** Initialize PCI controller. */
pci_t *pci_init(ofw_tree_node_t *node)
{
ofw_tree_property_t *prop;
 
/*
* First, verify this is a PCI node.
*/
ASSERT(strcmp(ofw_tree_node_name(node), "pci") == 0);
 
/*
* Determine PCI controller model.
*/
prop = ofw_tree_getprop(node, "model");
if (!prop || !prop->value)
return NULL;
if (strcmp(prop->value, "SUNW,sabre") == 0) {
/*
* PCI controller Sabre.
* This model is found on UltraSPARC IIi based machines.
*/
return pci_sabre_init(node);
} else {
/*
* Unsupported model.
*/
printf("Unsupported PCI controller model (%s).\n", prop->value);
}
 
return NULL;
}
 
void pci_enable_interrupt(pci_t *pci, int inr)
{
ASSERT(pci->model);
ASSERT(pci->op && pci->op->enable_interrupt);
pci->op->enable_interrupt(pci, inr);
}
 
void pci_clear_interrupt(pci_t *pci, int inr)
{
ASSERT(pci->model);
ASSERT(pci->op && pci->op->clear_interrupt);
pci->op->clear_interrupt(pci, inr);
}
 
/** @}
*/