Subversion Repositories HelenOS

Rev

Rev 4347 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1410 jermar 1
/*
2071 jermar 2
 * Copyright (c) 2006 Jakub Jermar
1410 jermar 3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 *
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
14
 * - The name of the author may not be used to endorse or promote products
15
 *   derived from this software without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
28
 
4346 svoboda 29
/** @addtogroup sparc64
1702 cejka 30
 * @{
31
 */
32
/** @file
33
 */
34
 
1842 jermar 35
#include <arch/drivers/kbd.h>
1896 jermar 36
#include <genarch/ofw/ofw_tree.h>
4346 svoboda 37
 
38
#ifdef CONFIG_SUN_KBD
39
#include <genarch/kbrd/kbrd.h>
40
#endif
1841 jermar 41
#ifdef CONFIG_Z8530
4346 svoboda 42
#include <genarch/drivers/z8530/z8530.h>
1841 jermar 43
#endif
1844 jermar 44
#ifdef CONFIG_NS16550
4346 svoboda 45
#include <genarch/drivers/ns16550/ns16550.h>
1841 jermar 46
#endif
4346 svoboda 47
 
48
#include <console/console.h>
1920 jermar 49
#include <ddi/irq.h>
1841 jermar 50
#include <arch/mm/page.h>
1410 jermar 51
#include <arch/types.h>
1842 jermar 52
#include <align.h>
4345 svoboda 53
#include <string.h>
1896 jermar 54
#include <print.h>
4344 svoboda 55
#include <sysinfo/sysinfo.h>
1410 jermar 56
 
4346 svoboda 57
#ifdef CONFIG_SUN_KBD
58
 
4348 svoboda 59
#ifdef CONFIG_Z8530
60
 
61
static bool kbd_z8530_init(ofw_tree_node_t *node)
1410 jermar 62
{
4348 svoboda 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;
3674 svoboda 98
    cir_t cir;
99
    void *cir_arg;
4348 svoboda 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;
105
    }
4347 svoboda 106
 
4348 svoboda 107
    /*
108
     * We need to pass aligned address to hw_map().
109
     * However, the physical keyboard address can
110
     * be pretty much unaligned, depending on the
111
     * underlying controller.
112
     */
113
    uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE);
114
    size_t offset = pa - aligned_addr;
1896 jermar 115
 
4348 svoboda 116
    z8530_t *z8530 = (z8530_t *)
117
        (hw_map(aligned_addr, offset + size) + offset);
1896 jermar 118
 
4348 svoboda 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
 
1909 jermar 129
    /*
4348 svoboda 130
     * This is the necessary evil until the userspace drivers are
131
     * entirely self-sufficient.
1909 jermar 132
     */
4348 svoboda 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);
1896 jermar 139
 
4348 svoboda 140
    return true;
141
}
142
 
143
#endif /* CONFIG_Z8530 */
144
 
145
#ifdef CONFIG_NS16550
146
 
147
static bool kbd_ns16550_init(ofw_tree_node_t *node)
148
{
149
    const char *name = ofw_tree_node_name(node);
1896 jermar 150
 
4348 svoboda 151
    if (str_cmp(name, "su") != 0)
152
        return false;
153
 
1909 jermar 154
    /*
155
     * Read 'interrupts' property.
156
     */
4348 svoboda 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
    }
4337 svoboda 162
 
4348 svoboda 163
    uint32_t interrupts = *((uint32_t *) prop->value);
164
 
1909 jermar 165
    /*
166
     * Read 'reg' property.
167
     */
1896 jermar 168
    prop = ofw_tree_getprop(node, "reg");
4348 svoboda 169
    if ((!prop) || (!prop->value)) {
170
        printf("ns16550: Unable to find reg property\n");
171
        return false;
172
    }
1896 jermar 173
 
4348 svoboda 174
    size_t size = ((ofw_ebus_reg_t *) prop->value)->size;
175
 
1896 jermar 176
    uintptr_t pa;
4348 svoboda 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
 
1921 jermar 183
    inr_t inr;
4348 svoboda 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;
1896 jermar 191
    }
192
 
1841 jermar 193
    /*
194
     * We need to pass aligned address to hw_map().
195
     * However, the physical keyboard address can
1896 jermar 196
     * be pretty much unaligned, depending on the
197
     * underlying controller.
1841 jermar 198
     */
4348 svoboda 199
    uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE);
200
    size_t offset = pa - aligned_addr;
4337 svoboda 201
 
4348 svoboda 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
 */
239
void kbd_init(ofw_tree_node_t *node)
240
{
1841 jermar 241
#ifdef CONFIG_Z8530
4348 svoboda 242
    kbd_z8530_init(node);
1841 jermar 243
#endif
4348 svoboda 244
 
1844 jermar 245
#ifdef CONFIG_NS16550
4348 svoboda 246
    kbd_ns16550_init(node);
1841 jermar 247
#endif
1410 jermar 248
}
1702 cejka 249
 
4348 svoboda 250
#endif /* CONFIG_SUN_KBD */
4346 svoboda 251
 
1784 jermar 252
/** @}
1702 cejka 253
 */