Subversion Repositories HelenOS

Rev

Rev 3675 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3675 Rev 4377
Line 32... Line 32...
32
/** @file
32
/** @file
33
 */
33
 */
34
 
34
 
35
#include <arch/drivers/kbd.h>
35
#include <arch/drivers/kbd.h>
36
#include <genarch/ofw/ofw_tree.h>
36
#include <genarch/ofw/ofw_tree.h>
-
 
37
 
-
 
38
#ifdef CONFIG_SUN_KBD
-
 
39
#include <genarch/kbrd/kbrd.h>
-
 
40
#endif
37
#ifdef CONFIG_Z8530
41
#ifdef CONFIG_Z8530
38
#include <genarch/kbd/z8530.h>
42
#include <genarch/drivers/z8530/z8530.h>
39
#endif
43
#endif
40
#ifdef CONFIG_NS16550
44
#ifdef CONFIG_NS16550
41
#include <genarch/kbd/ns16550.h>
45
#include <genarch/drivers/ns16550/ns16550.h>
42
#endif
46
#endif
-
 
47
 
43
#include <ddi/device.h>
48
#include <console/console.h>
44
#include <ddi/irq.h>
49
#include <ddi/irq.h>
45
#include <arch/mm/page.h>
50
#include <arch/mm/page.h>
46
#include <arch/types.h>
51
#include <arch/types.h>
47
#include <align.h>
52
#include <align.h>
48
#include <func.h>
53
#include <string.h>
49
#include <print.h>
54
#include <print.h>
-
 
55
#include <sysinfo/sysinfo.h>
50
 
56
 
51
kbd_type_t kbd_type = KBD_UNKNOWN;
57
#ifdef CONFIG_SUN_KBD
52
 
58
 
53
/** Initialize keyboard.
59
#ifdef CONFIG_Z8530
54
 *
60
 
55
 * Traverse OpenFirmware device tree in order to find necessary
-
 
56
 * info about the keyboard device.
-
 
57
 *
-
 
58
 * @param node Keyboard device node.
-
 
59
 */
-
 
60
void kbd_init(ofw_tree_node_t *node)
61
static bool kbd_z8530_init(ofw_tree_node_t *node)
61
{
62
{
62
    size_t offset;
-
 
63
    uintptr_t aligned_addr;
-
 
64
    ofw_tree_property_t *prop;
-
 
65
    const char *name;
63
    const char *name = ofw_tree_node_name(node);
66
    cir_t cir;
-
 
67
    void *cir_arg;
-
 
68
   
64
   
69
    name = ofw_tree_node_name(node);
65
    if (str_cmp(name, "zs") != 0)
-
 
66
        return false;
70
   
67
   
71
    /*
68
    /*
72
     * Determine keyboard serial controller type.
69
     * Read 'interrupts' property.
73
     */
70
     */
74
    if (strcmp(name, "zs") == 0)
-
 
75
        kbd_type = KBD_Z8530;
-
 
76
    else if (strcmp(name, "su") == 0)
71
    ofw_tree_property_t *prop = ofw_tree_getprop(node, "interrupts");
77
        kbd_type = KBD_NS16550;
-
 
78
   
-
 
79
    if (kbd_type == KBD_UNKNOWN) {
72
    if ((!prop) || (!prop->value)) {
80
        printf("Unknown keyboard device.\n");
73
        printf("z8530: Unable to find interrupts property\n");
81
        return;
74
        return false;
82
    }
75
    }
83
   
76
   
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);
77
    uint32_t interrupts = *((uint32_t *) prop->value);
92
 
78
   
93
    /*
79
    /*
94
     * Read 'reg' property.
80
     * Read 'reg' property.
95
     */
81
     */
96
    prop = ofw_tree_getprop(node, "reg");
82
    prop = ofw_tree_getprop(node, "reg");
97
    if (!prop || !prop->value)
83
    if ((!prop) || (!prop->value)) {
98
        panic("Can't find \"reg\" property.\n");
84
        printf("z8530: Unable to find reg property\n");
-
 
85
        return false;
-
 
86
    }
99
   
87
   
100
    uintptr_t pa;
-
 
101
    size_t size;
-
 
102
    inr_t inr;
-
 
103
    devno_t devno = device_assign_devno();
88
    size_t size = ((ofw_fhc_reg_t *) prop->value)->size;
104
   
89
   
105
    switch (kbd_type) {
90
    uintptr_t pa;
106
    case KBD_Z8530:
-
 
107
        size = ((ofw_fhc_reg_t *) prop->value)->size;
-
 
108
        if (!ofw_fhc_apply_ranges(node->parent,
91
    if (!ofw_fhc_apply_ranges(node->parent,
109
            ((ofw_fhc_reg_t *) prop->value), &pa)) {
92
        ((ofw_fhc_reg_t *) prop->value), &pa)) {
110
            printf("Failed to determine keyboard address.\n");
93
        printf("z8530: Failed to determine address\n");
111
            return;
94
        return false;
112
        }
95
    }
-
 
96
   
-
 
97
    inr_t inr;
-
 
98
    cir_t cir;
-
 
99
    void *cir_arg;
113
        if (!ofw_fhc_map_interrupt(node->parent,
100
    if (!ofw_fhc_map_interrupt(node->parent,
114
            ((ofw_fhc_reg_t *) prop->value), interrupts, &inr, &cir,
101
        ((ofw_fhc_reg_t *) prop->value), interrupts, &inr, &cir,
115
            &cir_arg)) {
102
        &cir_arg)) {
116
            printf("Failed to determine keyboard interrupt.\n");
103
        printf("z8530: Failed to determine interrupt\n");
-
 
104
        return false;
-
 
105
    }
-
 
106
   
-
 
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;
-
 
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
 
-
 
147
static 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");
117
            return;
160
        return false;
118
        }
161
    }
119
        break;
-
 
120
       
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");
121
    case KBD_NS16550:
171
        return false;
-
 
172
    }
-
 
173
   
122
        size = ((ofw_ebus_reg_t *) prop->value)->size;
174
    size_t size = ((ofw_ebus_reg_t *) prop->value)->size;
-
 
175
   
-
 
176
    uintptr_t pa;
123
        if (!ofw_ebus_apply_ranges(node->parent,
177
    if (!ofw_ebus_apply_ranges(node->parent,
124
            ((ofw_ebus_reg_t *) prop->value), &pa)) {
178
        ((ofw_ebus_reg_t *) prop->value), &pa)) {
125
            printf("Failed to determine keyboard address.\n");
179
        printf("ns16550: Failed to determine address\n");
126
            return;
180
        return false;
127
        }
181
    }
-
 
182
   
-
 
183
    inr_t inr;
-
 
184
    cir_t cir;
-
 
185
    void *cir_arg;
128
        if (!ofw_ebus_map_interrupt(node->parent,
186
    if (!ofw_ebus_map_interrupt(node->parent,
129
            ((ofw_ebus_reg_t *) prop->value), interrupts, &inr, &cir,
187
        ((ofw_ebus_reg_t *) prop->value), interrupts, &inr, &cir,
130
            &cir_arg)) {
188
        &cir_arg)) {
131
            printf("Failed to determine keyboard interrupt.\n");
189
        printf("ns16550: Failed to determine interrupt\n");
132
            return;
190
        return false;
133
        };
-
 
134
        break;
-
 
135
 
-
 
136
    default:
-
 
137
        panic("Unexpected type.\n");
-
 
138
    }
191
    }
139
   
192
   
140
    /*
193
    /*
141
     * We need to pass aligned address to hw_map().
194
     * We need to pass aligned address to hw_map().
142
     * However, the physical keyboard address can
195
     * However, the physical keyboard address can
143
     * be pretty much unaligned, depending on the
196
     * be pretty much unaligned, depending on the
144
     * underlying controller.
197
     * underlying controller.
145
     */
198
     */
146
    aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE);
199
    uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE);
147
    offset = pa - aligned_addr;
200
    size_t offset = pa - aligned_addr;
148
    uintptr_t vaddr = hw_map(aligned_addr, offset + size) + offset;
-
 
149
 
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();
150
    switch (kbd_type) {
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
{
151
#ifdef CONFIG_Z8530
241
#ifdef CONFIG_Z8530
152
    case KBD_Z8530:
-
 
153
        z8530_init(devno, vaddr, inr, cir, cir_arg);
242
    kbd_z8530_init(node);
154
        break;
-
 
155
#endif
243
#endif
-
 
244
   
156
#ifdef CONFIG_NS16550
245
#ifdef CONFIG_NS16550
157
    case KBD_NS16550:
246
    kbd_ns16550_init(node);
158
        ns16550_init(devno, (ioport_t)vaddr, inr, cir, cir_arg);
-
 
159
        break;
-
 
160
#endif
247
#endif
161
    default:
-
 
162
        printf("Kernel is not compiled with the necessary keyboard "
-
 
163
            "driver this machine requires.\n");
-
 
164
    }
-
 
165
}
248
}
166
 
249
 
-
 
250
#endif /* CONFIG_SUN_KBD */
-
 
251
 
167
/** @}
252
/** @}
168
 */
253
 */