Changeset 0b414b5 in mainline


Ignore:
Timestamp:
2006-10-02T21:07:23Z (18 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
233af8c5
Parents:
36db5ac
Message:

Extend the OFW device tree node with a void pointer. The boot loader is
supposed to reset all pointers in all nodes. The kernel uses the pointer
to recognize that a particular device has already been visited and initialized.

Read interrupt mapping from the OFW device tree for FHC devices (z8530) and
EBUS devices (ns16550). In case of FHC devices, remove hardwired values from
the code and use only values read from the tree. FHC initialization is started
when a FHC device wants to map its interrupt. In case of EBUS devices, map
the interrupt to INO. Interrupt enabling in the interrupt controller for that
specific interrupt is not implemented yet.

Files:
10 edited

Legend:

Unmodified
Added
Removed
  • boot/genarch/ofw_tree.c

    r36db5ac r0b414b5  
    9797        current_node->properties = 0;
    9898        current_node->property = NULL;
     99        current_node->device = NULL;
    99100       
    100101        /*
  • boot/genarch/ofw_tree.h

    r36db5ac r0b414b5  
    5050        unsigned properties;                    /**< Number of properties. */
    5151        ofw_tree_property_t *property;
     52       
     53        void *device;                           /**< Member used solely by the kernel. */
    5254};
    5355
  • kernel/arch/sparc64/include/drivers/fhc.h

    r36db5ac r0b414b5  
    3737
    3838#include <arch/types.h>
     39#include <genarch/ofw/ofw_tree.h>
    3940
    40 extern volatile uint32_t *fhc;
     41typedef struct {
     42        volatile uint32_t *uart_imap;
     43} fhc_t;
    4144
    42 extern void fhc_init(void);
    43 extern void fhc_uart_reset(void);
     45extern fhc_t *central_fhc;
     46
     47extern fhc_t *fhc_init(ofw_tree_node_t *node);
     48extern void fhc_enable_interrupt(fhc_t *fhc, int ino);
     49extern void fhc_clear_interrupt(fhc_t *fhc, int ino);
    4450
    4551#endif
  • kernel/arch/sparc64/src/drivers/fhc.c

    r36db5ac r0b414b5  
    4242#include <arch/drivers/fhc.h>
    4343#include <arch/mm/page.h>
     44#include <mm/slab.h>
    4445#include <arch/types.h>
    4546#include <typedefs.h>
    46 
     47#include <genarch/ofw/ofw_tree.h>
    4748#include <genarch/kbd/z8530.h>
    4849
    49 volatile uint32_t *fhc = NULL;
     50fhc_t *central_fhc = NULL;
    5051
    51 #define FHC_UART_ADDR   0x1fff8808000ULL                /* hardcoded for Simics simulation */
     52/**
     53 * I suspect this must be hardcoded in the FHC.
     54 * If it is not, than we can read all IMAP registers
     55 * and get the complete mapping.
     56 */
     57#define FHC_UART_INO    0x39   
    5258
    5359#define FHC_UART_IMAP   0x0
    5460#define FHC_UART_ICLR   0x4
    5561
    56 void fhc_init(void)
     62#define UART_IMAP_REG   4
     63
     64fhc_t *fhc_init(ofw_tree_node_t *node)
    5765{
    58         fhc = (void *) hw_map(FHC_UART_ADDR, PAGE_SIZE);
     66        fhc_t *fhc;
     67        ofw_tree_property_t *prop;
    5968
    60         fhc[FHC_UART_ICLR] = 0;
    61         fhc[FHC_UART_IMAP] = 0x80000000;
     69        prop = ofw_tree_getprop(node, "reg");
     70       
     71        if (!prop || !prop->value)
     72                return NULL;
     73               
     74        count_t regs = prop->size / sizeof(ofw_central_reg_t);
     75        if (regs + 1 < UART_IMAP_REG)
     76                return NULL;
     77
     78        ofw_central_reg_t *reg = &((ofw_central_reg_t *) prop->value)[UART_IMAP_REG];
     79
     80        uintptr_t paddr;
     81        if (!ofw_central_apply_ranges(node->parent, reg, &paddr))
     82                return NULL;
     83
     84        fhc = (fhc_t *) malloc(sizeof(fhc_t), FRAME_ATOMIC);
     85        if (!fhc)
     86                return NULL;
     87
     88        fhc->uart_imap = (uint32_t *) hw_map(paddr, reg->size);
     89       
     90        return fhc;
    6291}
    6392
    64 void fhc_uart_reset(void)
     93void fhc_enable_interrupt(fhc_t *fhc, int ino)
    6594{
    66         fhc[FHC_UART_ICLR] = 0;
     95        switch (ino) {
     96        case FHC_UART_INO:
     97                fhc->uart_imap[FHC_UART_ICLR] = 0x0;
     98                fhc->uart_imap[FHC_UART_IMAP] = 0x80000000;
     99                break;
     100        default:
     101                panic("Unexpected INO (%d)\n", ino);
     102                break;
     103        }
     104}
     105
     106void fhc_clear_interrupt(fhc_t *fhc, int ino)
     107{
     108        ASSERT(fhc->uart_imap);
     109
     110        switch (ino) {
     111        case FHC_UART_INO:
     112                fhc->uart_imap[FHC_UART_ICLR] = 0;
     113                break;
     114        default:
     115                panic("Unexpected INO (%d)\n", ino);
     116                break;
     117        }
    67118}
    68119
  • kernel/arch/sparc64/src/drivers/kbd.c

    r36db5ac r0b414b5  
    6969        name = ofw_tree_node_name(node);
    7070       
     71        /*
     72         * Determine keyboard serial controller type.
     73         */
    7174        if (strcmp(name, "zs") == 0)
    7275                kbd_type = KBD_Z8530;
     
    7982        }
    8083       
     84        /*
     85         * Read 'interrupts' property.
     86         */
     87        uint32_t interrupts;
     88        prop = ofw_tree_getprop(node, "interrupts");
     89        if (!prop || !prop->value)
     90                panic("Can't find \"interrupts\" property.\n");
     91        interrupts = *((uint32_t *) prop->value);
     92
     93        /*
     94         * Read 'reg' property.
     95         */
    8196        prop = ofw_tree_getprop(node, "reg");
    82         if (!prop)
     97        if (!prop || !prop->value)
    8398                panic("Can't find \"reg\" property.\n");
    8499       
    85100        uintptr_t pa;
    86101        size_t size;
     102        int ino;
    87103       
    88104        switch (kbd_type) {
     
    93109                        return;
    94110                }
     111                if (!ofw_fhc_map_interrupts(node->parent, ((ofw_fhc_reg_t *) prop->value), interrupts, &ino)) {
     112                        printf("Failed to determine keyboard interrupts.\n");
     113                        return;
     114                }
    95115                break;
    96116        case KBD_NS16550:
     
    98118                if (!ofw_ebus_apply_ranges(node->parent, ((ofw_ebus_reg_t *) prop->value) , &pa)) {
    99119                        printf("Failed to determine keyboard address.\n");
     120                        return;
     121                }
     122                if (!ofw_ebus_map_interrupts(node->parent, ((ofw_ebus_reg_t *) prop->value), interrupts, &ino)) {
     123                        printf("Failed to determine keyboard interrupts.\n");
    100124                        return;
    101125                }
  • kernel/arch/sparc64/src/trap/interrupt.c

    r36db5ac r0b414b5  
    9797                else
    9898                        ipc_irq_send_notif(0);
    99                 fhc_uart_reset();
     99                fhc_clear_interrupt(central_fhc, data0);
    100100                break;
    101101
  • kernel/genarch/include/ofw/ofw_tree.h

    r36db5ac r0b414b5  
    5050        unsigned properties;                    /**< Number of properties. */
    5151        ofw_tree_property_t *property;
     52       
     53        /**
     54         * Pointer to a structure representing respective device.
     55         * Its semantics is device dependent.
     56         */
     57        void *device;
    5258};
    5359
     
    105111typedef struct ofw_ebus_range ofw_ebus_range_t;
    106112
     113struct ofw_ebus_intr_map {
     114        uint32_t space;
     115        uint32_t addr;
     116        uint32_t intr;
     117        uint32_t controller_handle;
     118        uint32_t controller_ino;
     119} __attribute__ ((packed));
     120typedef struct ofw_ebus_intr_map ofw_ebus_intr_map_t;
     121
     122struct ofw_ebus_intr_mask {
     123        uint32_t space_mask;
     124        uint32_t addr_mask;
     125        uint32_t intr_mask;
     126} __attribute__ ((packed));
     127typedef struct ofw_ebus_intr_mask ofw_ebus_intr_mask_t;
     128
    107129struct ofw_pci_reg {
    108         uint32_t space;                 /* needs to masked to obtain pure space id */
     130        uint32_t space;                 /* needs to be masked to obtain pure space id */
    109131        uint64_t addr;                  /* group phys.mid and phys.lo together */
    110132        uint64_t size;
     
    144166extern bool ofw_pci_reg_absolutize(ofw_tree_node_t *node, ofw_pci_reg_t *reg, ofw_pci_reg_t *out);
    145167
     168extern bool ofw_fhc_map_interrupts(ofw_tree_node_t *node, ofw_fhc_reg_t *reg, uint32_t interrupt, int *ino);
     169extern bool ofw_ebus_map_interrupts(ofw_tree_node_t *node, ofw_ebus_reg_t *reg, uint32_t interrupt, int *ino);
     170
    146171#endif
  • kernel/genarch/src/kbd/z8530.c

    r36db5ac r0b414b5  
    3939#include <genarch/kbd/scanc.h>
    4040#include <genarch/kbd/scanc_sun.h>
    41 #include <arch/drivers/fhc.h>
    4241#include <arch/drivers/z8530.h>
    4342#include <arch/interrupt.h>
     
    107106       
    108107        z8530_write_a(WR9, WR9_MIE);            /* Master Interrupt Enable. */
    109        
    110         /*
    111          * We need to initialize the FireHose Controller,
    112          * to which is this z8530 attached. Otherwise
    113          * interrupts generated by the z8530 would not
    114          * be forwarded to the CPU.
    115          */
    116         fhc_init();
    117108}
    118109
  • kernel/genarch/src/ofw/ebus.c

    r36db5ac r0b414b5  
    4040#include <func.h>
    4141#include <panic.h>
     42#include <debug.h>
    4243#include <macros.h>
    4344
     
    7475}
    7576
     77bool ofw_ebus_map_interrupts(ofw_tree_node_t *node, ofw_ebus_reg_t *reg, uint32_t interrupt, int *ino)
     78{
     79        ofw_tree_property_t *prop;
     80        ofw_tree_node_t *controller;
     81       
     82        prop = ofw_tree_getprop(node, "interrupt-map");
     83        if (!prop || !prop->value)
     84                return false;
     85
     86        ofw_ebus_intr_map_t *intr_map = prop->value;
     87        count_t count = prop->size / sizeof(ofw_ebus_intr_map_t);
     88       
     89        ASSERT(count);
     90       
     91        prop = ofw_tree_getprop(node, "interrupt-map-mask");
     92        if (!prop || !prop->value)
     93                return false;
     94       
     95        ofw_ebus_intr_mask_t *intr_mask = prop->value;
     96       
     97        ASSERT(prop->size == sizeof(ofw_ebus_intr_mask_t));
     98       
     99        uint32_t space = reg->space & intr_mask->space_mask;
     100        uint32_t addr = reg->addr & intr_mask->addr_mask;
     101        uint32_t intr = interrupt & intr_mask->intr_mask;
     102       
     103        int i;
     104        for (i = 0; i < count; i++) {
     105                if ((intr_map[i].space == space) && (intr_map[i].addr == addr)
     106                        && (intr_map[i].intr == intr))
     107                        goto found;
     108        }
     109        return false;
     110
     111found:
     112        /*
     113         * We found the device that functions as an interrupt controller
     114         * for the interrupt. We also found mapping from interrupt to INO.
     115         */
     116
     117        controller = ofw_tree_find_node_by_handle(ofw_tree_lookup("/"), intr_map[i].controller_handle);
     118       
     119        *ino = intr_map[i].controller_ino;
     120        return true;
     121}
     122
    76123/** @}
    77124 */
  • kernel/genarch/src/ofw/fhc.c

    r36db5ac r0b414b5  
    3737
    3838#include <genarch/ofw/ofw_tree.h>
     39#include <arch/drivers/fhc.h>
    3940#include <arch/memstr.h>
    4041#include <func.h>
     
    109110}
    110111
     112bool ofw_fhc_map_interrupts(ofw_tree_node_t *node, ofw_fhc_reg_t *reg, uint32_t interrupt, int *ino)
     113{
     114        fhc_t *fhc = NULL;
     115        if (!node->device) {
     116                fhc = fhc_init(node);
     117                if (!fhc)
     118                        return false;
     119                node->device = fhc;
     120                central_fhc = fhc;
     121        }
     122       
     123        /*
     124         * The interrupt controller for the interrupt is the FHC itself.
     125         */
     126        fhc_enable_interrupt(fhc, interrupt);
     127       
     128        *ino = interrupt;
     129        return true;
     130}
     131
    111132/** @}
    112133 */
Note: See TracChangeset for help on using the changeset viewer.