/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, ®[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); |
} |
/** @} |
*/ |