Subversion Repositories HelenOS

Rev

Rev 4347 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4347 Rev 4348
Line 52... Line 52...
52
#include <align.h>
52
#include <align.h>
53
#include <string.h>
53
#include <string.h>
54
#include <print.h>
54
#include <print.h>
55
#include <sysinfo/sysinfo.h>
55
#include <sysinfo/sysinfo.h>
56
 
56
 
57
kbd_type_t kbd_type = KBD_UNKNOWN;
-
 
58
 
-
 
59
#ifdef CONFIG_SUN_KBD
57
#ifdef CONFIG_SUN_KBD
60
 
58
 
61
/** Initialize keyboard.
59
#ifdef CONFIG_Z8530
62
 *
60
 
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)
61
static bool kbd_z8530_init(ofw_tree_node_t *node)
69
{
62
{
-
 
63
    const char *name = ofw_tree_node_name(node);
-
 
64
   
-
 
65
    if (str_cmp(name, "zs") != 0)
70
    size_t offset;
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
   
71
    uintptr_t aligned_addr;
90
    uintptr_t pa;
-
 
91
    if (!ofw_fhc_apply_ranges(node->parent,
72
    ofw_tree_property_t *prop;
92
        ((ofw_fhc_reg_t *) prop->value), &pa)) {
-
 
93
        printf("z8530: Failed to determine address\n");
73
    const char *name;
94
        return false;
-
 
95
    }
-
 
96
   
-
 
97
    inr_t inr;
74
    cir_t cir;
98
    cir_t cir;
75
    void *cir_arg;
99
    void *cir_arg;
-
 
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
    }
76
   
106
   
-
 
107
    /*
-
 
108
     * We need to pass aligned address to hw_map().
-
 
109
     * However, the physical keyboard address can
77
#ifdef CONFIG_NS16550
110
     * be pretty much unaligned, depending on the
78
    ns16550_t *ns16550;
111
     * underlying controller.
79
#endif
112
     */
-
 
113
    uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE);
80
#ifdef CONFIG_Z8530
114
    size_t offset = pa - aligned_addr;
-
 
115
   
81
    z8530_t *z8530;
116
    z8530_t *z8530 = (z8530_t *)
82
#endif
117
        (hw_map(aligned_addr, offset + size) + offset);
83
   
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);
84
    name = ofw_tree_node_name(node);
125
            z8530_wire(z8530_instance, kbrd);
-
 
126
        }
-
 
127
    }
85
   
128
   
86
    /*
129
    /*
-
 
130
     * This is the necessary evil until the userspace drivers are
87
     * Determine keyboard serial controller type.
131
     * entirely self-sufficient.
88
     */
132
     */
89
    if (strcmp(name, "zs") == 0)
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,
90
        kbd_type = KBD_Z8530;
136
        (uintptr_t) z8530);
91
    else if (strcmp(name, "su") == 0)
137
    sysinfo_set_item_val("kbd.address.physical", NULL, pa);
92
        kbd_type = KBD_NS16550;
138
    sysinfo_set_item_val("kbd.type.z8530", NULL, true);
93
   
139
   
-
 
140
    return true;
-
 
141
}
-
 
142
 
-
 
143
#endif /* CONFIG_Z8530 */
-
 
144
 
94
    if (kbd_type == KBD_UNKNOWN) {
145
#ifdef CONFIG_NS16550
-
 
146
 
95
        printf("Unknown keyboard device.\n");
147
static bool kbd_ns16550_init(ofw_tree_node_t *node)
96
        return;
148
{
-
 
149
    const char *name = ofw_tree_node_name(node);
97
    }
150
   
-
 
151
    if (str_cmp(name, "su") != 0)
-
 
152
        return false;
98
   
153
   
99
    /*
154
    /*
100
     * Read 'interrupts' property.
155
     * Read 'interrupts' property.
101
     */
156
     */
102
    uint32_t interrupts;
-
 
103
    prop = ofw_tree_getprop(node, "interrupts");
157
    ofw_tree_property_t *prop = ofw_tree_getprop(node, "interrupts");
104
    if ((!prop) || (!prop->value))
158
    if ((!prop) || (!prop->value)) {
105
        panic("Cannot find 'interrupt' property.");
159
        printf("ns16550: Unable to find interrupts property\n");
-
 
160
        return false;
-
 
161
    }
-
 
162
   
106
    interrupts = *((uint32_t *) prop->value);
163
    uint32_t interrupts = *((uint32_t *) prop->value);
107
   
164
   
108
    /*
165
    /*
109
     * Read 'reg' property.
166
     * Read 'reg' property.
110
     */
167
     */
111
    prop = ofw_tree_getprop(node, "reg");
168
    prop = ofw_tree_getprop(node, "reg");
112
    if ((!prop) || (!prop->value))
169
    if ((!prop) || (!prop->value)) {
113
        panic("Cannot find 'reg' property.");
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;
114
   
175
   
115
    uintptr_t pa;
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");
116
    size_t size;
180
        return false;
117
    inr_t inr;
181
    }
118
   
182
   
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;
183
    inr_t inr;
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;
184
    cir_t cir;
132
        }
-
 
133
        break;
185
    void *cir_arg;
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,
186
    if (!ofw_ebus_map_interrupt(node->parent,
143
            ((ofw_ebus_reg_t *) prop->value), interrupts, &inr, &cir,
187
        ((ofw_ebus_reg_t *) prop->value), interrupts, &inr, &cir,
144
            &cir_arg)) {
188
        &cir_arg)) {
145
            printf("Failed to determine keyboard interrupt.\n");
189
        printf("ns16550: Failed to determine interrupt\n");
146
            return;
190
        return false;
147
        };
-
 
148
        break;
-
 
149
    default:
-
 
150
        panic("Unexpected keyboard type.");
-
 
151
    }
191
    }
152
   
192
   
153
    /*
193
    /*
154
     * We need to pass aligned address to hw_map().
194
     * We need to pass aligned address to hw_map().
155
     * However, the physical keyboard address can
195
     * However, the physical keyboard address can
156
     * be pretty much unaligned, depending on the
196
     * be pretty much unaligned, depending on the
157
     * underlying controller.
197
     * underlying controller.
158
     */
198
     */
159
    aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE);
199
    uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE);
160
    offset = pa - aligned_addr;
200
    size_t offset = pa - aligned_addr;
161
   
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();
162
    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
{
163
#ifdef CONFIG_Z8530
241
#ifdef CONFIG_Z8530
164
    case KBD_Z8530:
-
 
165
        z8530 = (z8530_t *) hw_map(aligned_addr, offset + size) +
-
 
166
            offset;
-
 
167
       
-
 
168
        indev_t *kbrdin_z8530 = z8530_init(z8530, inr, cir, cir_arg);
-
 
169
        if (kbrdin_z8530)
-
 
170
            kbrd_init(kbrdin_z8530);
242
    kbd_z8530_init(node);
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
243
#endif
-
 
244
   
184
#ifdef CONFIG_NS16550
245
#ifdef CONFIG_NS16550
185
    case KBD_NS16550:
-
 
186
        ns16550 = (ns16550_t *) hw_map(aligned_addr, offset + size) +
-
 
187
            offset;
-
 
188
       
-
 
189
        indev_t *kbrdin_ns16550 = ns16550_init(ns16550, inr, cir, cir_arg);
-
 
190
        if (kbrdin_ns16550)
-
 
191
            kbrd_init(kbrdin_ns16550);
246
    kbd_ns16550_init(node);
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
247
#endif
205
    default:
-
 
206
        printf("Kernel is not compiled with the necessary keyboard "
-
 
207
            "driver this machine requires.\n");
-
 
208
    }
-
 
209
}
248
}
210
 
249
 
211
#endif
250
#endif /* CONFIG_SUN_KBD */
212
 
251
 
213
/** @}
252
/** @}
214
 */
253
 */