Ignore:
Timestamp:
2009-04-21T12:46:26Z (16 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
f2d2c7ba
Parents:
44b7783
Message:

change the way how input devices are wired together according to ticket #44
(also the proposal http://lists.modry.cz/cgi-bin/private/helenos-devel/2009-March/002507.html)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/sparc64/src/drivers/kbd.c

    r44b7783 rc2417bc  
    5555#include <sysinfo/sysinfo.h>
    5656
    57 kbd_type_t kbd_type = KBD_UNKNOWN;
    58 
    5957#ifdef CONFIG_SUN_KBD
    6058
    61 /** Initialize keyboard.
    62  *
    63  * Traverse OpenFirmware device tree in order to find necessary
    64  * info about the keyboard device.
    65  *
    66  * @param node Keyboard device node.
    67  */
    68 void kbd_init(ofw_tree_node_t *node)
     59#ifdef CONFIG_Z8530
     60
     61static bool kbd_z8530_init(ofw_tree_node_t *node)
    6962{
    70         size_t offset;
    71         uintptr_t aligned_addr;
    72         ofw_tree_property_t *prop;
    73         const char *name;
     63        const char *name = ofw_tree_node_name(node);
     64       
     65        if (str_cmp(name, "zs") != 0)
     66                return false;
     67       
     68        /*
     69         * Read 'interrupts' property.
     70         */
     71        ofw_tree_property_t *prop = ofw_tree_getprop(node, "interrupts");
     72        if ((!prop) || (!prop->value)) {
     73                printf("z8530: Unable to find interrupts property\n");
     74                return false;
     75        }
     76       
     77        uint32_t interrupts = *((uint32_t *) prop->value);
     78       
     79        /*
     80         * Read 'reg' property.
     81         */
     82        prop = ofw_tree_getprop(node, "reg");
     83        if ((!prop) || (!prop->value)) {
     84                printf("z8530: Unable to find reg property\n");
     85                return false;
     86        }
     87       
     88        size_t size = ((ofw_fhc_reg_t *) prop->value)->size;
     89       
     90        uintptr_t pa;
     91        if (!ofw_fhc_apply_ranges(node->parent,
     92            ((ofw_fhc_reg_t *) prop->value), &pa)) {
     93                printf("z8530: Failed to determine address\n");
     94                return false;
     95        }
     96       
     97        inr_t inr;
    7498        cir_t cir;
    7599        void *cir_arg;
    76        
    77 #ifdef CONFIG_NS16550
    78         ns16550_t *ns16550;
    79 #endif
    80 #ifdef CONFIG_Z8530
    81         z8530_t *z8530;
    82 #endif
    83        
    84         name = ofw_tree_node_name(node);
    85        
    86         /*
    87          * Determine keyboard serial controller type.
    88          */
    89         if (str_cmp(name, "zs") == 0)
    90                 kbd_type = KBD_Z8530;
    91         else if (str_cmp(name, "su") == 0)
    92                 kbd_type = KBD_NS16550;
    93        
    94         if (kbd_type == KBD_UNKNOWN) {
    95                 printf("Unknown keyboard device.\n");
    96                 return;
    97         }
    98        
    99         /*
    100          * Read 'interrupts' property.
    101          */
    102         uint32_t interrupts;
    103         prop = ofw_tree_getprop(node, "interrupts");
    104         if ((!prop) || (!prop->value))
    105                 panic("Cannot find 'interrupt' property.");
    106         interrupts = *((uint32_t *) prop->value);
    107        
    108         /*
    109          * Read 'reg' property.
    110          */
    111         prop = ofw_tree_getprop(node, "reg");
    112         if ((!prop) || (!prop->value))
    113                 panic("Cannot find 'reg' property.");
    114        
    115         uintptr_t pa;
    116         size_t size;
    117         inr_t inr;
    118        
    119         switch (kbd_type) {
    120         case KBD_Z8530:
    121                 size = ((ofw_fhc_reg_t *) prop->value)->size;
    122                 if (!ofw_fhc_apply_ranges(node->parent,
    123                     ((ofw_fhc_reg_t *) prop->value), &pa)) {
    124                         printf("Failed to determine keyboard address.\n");
    125                         return;
    126                 }
    127                 if (!ofw_fhc_map_interrupt(node->parent,
    128                     ((ofw_fhc_reg_t *) prop->value), interrupts, &inr, &cir,
    129                     &cir_arg)) {
    130                         printf("Failed to determine keyboard interrupt.\n");
    131                         return;
    132                 }
    133                 break;
    134                
    135         case KBD_NS16550:
    136                 size = ((ofw_ebus_reg_t *) prop->value)->size;
    137                 if (!ofw_ebus_apply_ranges(node->parent,
    138                     ((ofw_ebus_reg_t *) prop->value), &pa)) {
    139                         printf("Failed to determine keyboard address.\n");
    140                         return;
    141                 }
    142                 if (!ofw_ebus_map_interrupt(node->parent,
    143                     ((ofw_ebus_reg_t *) prop->value), interrupts, &inr, &cir,
    144                     &cir_arg)) {
    145                         printf("Failed to determine keyboard interrupt.\n");
    146                         return;
    147                 };
    148                 break;
    149         default:
    150                 panic("Unexpected keyboard type.");
     100        if (!ofw_fhc_map_interrupt(node->parent,
     101            ((ofw_fhc_reg_t *) prop->value), interrupts, &inr, &cir,
     102            &cir_arg)) {
     103                printf("z8530: Failed to determine interrupt\n");
     104                return false;
    151105        }
    152106       
     
    157111         * underlying controller.
    158112         */
    159         aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE);
    160         offset = pa - aligned_addr;
    161        
    162         switch (kbd_type) {
     113        uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE);
     114        size_t offset = pa - aligned_addr;
     115       
     116        z8530_t *z8530 = (z8530_t *)
     117            (hw_map(aligned_addr, offset + size) + offset);
     118       
     119        z8530_instance_t *z8530_instance = z8530_init(z8530, inr, cir, cir_arg);
     120        if (z8530_instance) {
     121                kbrd_instance_t *kbrd_instance = kbrd_init();
     122                if (kbrd_instance) {
     123                        indev_t *sink = stdin_wire();
     124                        indev_t *kbrd = kbrd_wire(kbrd_instance, sink);
     125                        z8530_wire(z8530_instance, kbrd);
     126                }
     127        }
     128       
     129        /*
     130         * This is the necessary evil until the userspace drivers are
     131         * entirely self-sufficient.
     132         */
     133        sysinfo_set_item_val("kbd", NULL, true);
     134        sysinfo_set_item_val("kbd.inr", NULL, inr);
     135        sysinfo_set_item_val("kbd.address.kernel", NULL,
     136            (uintptr_t) z8530);
     137        sysinfo_set_item_val("kbd.address.physical", NULL, pa);
     138        sysinfo_set_item_val("kbd.type.z8530", NULL, true);
     139       
     140        return true;
     141}
     142
     143#endif /* CONFIG_Z8530 */
     144
     145#ifdef CONFIG_NS16550
     146
     147static bool kbd_ns16550_init(ofw_tree_node_t *node)
     148{
     149        const char *name = ofw_tree_node_name(node);
     150       
     151        if (str_cmp(name, "su") != 0)
     152                return false;
     153       
     154        /*
     155         * Read 'interrupts' property.
     156         */
     157        ofw_tree_property_t *prop = ofw_tree_getprop(node, "interrupts");
     158        if ((!prop) || (!prop->value)) {
     159                printf("ns16550: Unable to find interrupts property\n");
     160                return false;
     161        }
     162       
     163        uint32_t interrupts = *((uint32_t *) prop->value);
     164       
     165        /*
     166         * Read 'reg' property.
     167         */
     168        prop = ofw_tree_getprop(node, "reg");
     169        if ((!prop) || (!prop->value)) {
     170                printf("ns16550: Unable to find reg property\n");
     171                return false;
     172        }
     173       
     174        size_t size = ((ofw_ebus_reg_t *) prop->value)->size;
     175       
     176        uintptr_t pa;
     177        if (!ofw_ebus_apply_ranges(node->parent,
     178            ((ofw_ebus_reg_t *) prop->value), &pa)) {
     179                printf("ns16550: Failed to determine address\n");
     180                return false;
     181        }
     182       
     183        inr_t inr;
     184        cir_t cir;
     185        void *cir_arg;
     186        if (!ofw_ebus_map_interrupt(node->parent,
     187            ((ofw_ebus_reg_t *) prop->value), interrupts, &inr, &cir,
     188            &cir_arg)) {
     189                printf("ns16550: Failed to determine interrupt\n");
     190                return false;
     191        }
     192       
     193        /*
     194         * We need to pass aligned address to hw_map().
     195         * However, the physical keyboard address can
     196         * be pretty much unaligned, depending on the
     197         * underlying controller.
     198         */
     199        uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE);
     200        size_t offset = pa - aligned_addr;
     201       
     202        ns16550_t *ns16550 = (ns16550_t *)
     203           (hw_map(aligned_addr, offset + size) + offset);
     204       
     205        ns16550_instance_t *ns16550_instance = ns16550_init(ns16550, inr, cir, cir_arg);
     206        if (ns16550_instance) {
     207                kbrd_instance_t *kbrd_instance = kbrd_init();
     208                if (kbrd_instance) {
     209                        indev_t *sink = stdin_wire();
     210                        indev_t *kbrd = kbrd_wire(kbrd_instance, sink);
     211                        ns16550_wire(ns16550_instance, kbrd);
     212                }
     213        }
     214       
     215        /*
     216         * This is the necessary evil until the userspace drivers are
     217         * entirely self-sufficient.
     218         */
     219        sysinfo_set_item_val("kbd", NULL, true);
     220        sysinfo_set_item_val("kbd.inr", NULL, inr);
     221        sysinfo_set_item_val("kbd.address.kernel", NULL,
     222            (uintptr_t) ns16550);
     223        sysinfo_set_item_val("kbd.address.physical", NULL, pa);
     224        sysinfo_set_item_val("kbd.type.ns16550", NULL, true);
     225       
     226        return true;
     227}
     228
     229#endif /* CONFIG_NS16550 */
     230
     231/** Initialize keyboard.
     232 *
     233 * Traverse OpenFirmware device tree in order to find necessary
     234 * info about the keyboard device.
     235 *
     236 * @param node Keyboard device node.
     237 *
     238 */
     239void kbd_init(ofw_tree_node_t *node)
     240{
    163241#ifdef CONFIG_Z8530
    164         case KBD_Z8530:
    165                 z8530 = (z8530_t *)
    166                     (hw_map(aligned_addr, offset + size) + offset);
    167                
    168                 indev_t *kbrdin_z8530 = z8530_init(z8530, inr, cir, cir_arg);
    169                 if (kbrdin_z8530)
    170                         kbrd_init(kbrdin_z8530);
    171                
    172                 /*
    173                  * This is the necessary evil until the userspace drivers are
    174                  * entirely self-sufficient.
    175                  */
    176                 sysinfo_set_item_val("kbd", NULL, true);
    177                 sysinfo_set_item_val("kbd.type", NULL, KBD_Z8530);
    178                 sysinfo_set_item_val("kbd.inr", NULL, inr);
    179                 sysinfo_set_item_val("kbd.address.kernel", NULL,
    180                     (uintptr_t) z8530);
    181                 sysinfo_set_item_val("kbd.address.physical", NULL, pa);
    182                 break;
    183 #endif
     242        kbd_z8530_init(node);
     243#endif
     244       
    184245#ifdef CONFIG_NS16550
    185         case KBD_NS16550:
    186                 ns16550 = (ns16550_t *)
    187                    (hw_map(aligned_addr, offset + size) + offset);
    188                
    189                 indev_t *kbrdin_ns16550 = ns16550_init(ns16550, inr, cir, cir_arg);
    190                 if (kbrdin_ns16550)
    191                         kbrd_init(kbrdin_ns16550);
    192                
    193                 /*
    194                  * This is the necessary evil until the userspace driver is
    195                  * entirely self-sufficient.
    196                  */
    197                 sysinfo_set_item_val("kbd", NULL, true);
    198                 sysinfo_set_item_val("kbd.type", NULL, KBD_NS16550);
    199                 sysinfo_set_item_val("kbd.inr", NULL, inr);
    200                 sysinfo_set_item_val("kbd.address.kernel", NULL,
    201                     (uintptr_t) ns16550);
    202                 sysinfo_set_item_val("kbd.address.physical", NULL, pa);
    203                 break;
    204 #endif
    205         default:
    206                 printf("Kernel is not compiled with the necessary keyboard "
    207                     "driver this machine requires.\n");
    208         }
     246        kbd_ns16550_init(node);
     247#endif
    209248}
    210249
    211 #endif
     250#endif /* CONFIG_SUN_KBD */
    212251
    213252/** @}
Note: See TracChangeset for help on using the changeset viewer.