source: mainline/kernel/arch/sparc64/src/drivers/kbd.c@ 84afc7b

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 84afc7b was 84afc7b, checked in by Martin Decky <martin@…>, 16 years ago

as kernel little brother drivers are not needed anymore, the device numbers do not have to be correlated between kernel and uspace in any way
introduce new syscall sys_device_assign_devno() for generating system-wide unique device numbers for uspace

  • Property mode set to 100644
File size: 5.7 KB
Line 
1/*
2 * Copyright (c) 2006 Jakub 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
29/** @addtogroup sparc64
30 * @{
31 */
32/** @file
33 */
34
35#include <arch/drivers/kbd.h>
36#include <genarch/ofw/ofw_tree.h>
37
38#ifdef CONFIG_SUN_KBD
39#include <genarch/kbrd/kbrd.h>
40#endif
41#ifdef CONFIG_Z8530
42#include <genarch/drivers/z8530/z8530.h>
43#endif
44#ifdef CONFIG_NS16550
45#include <genarch/drivers/ns16550/ns16550.h>
46#endif
47
48#include <console/console.h>
49#include <ddi/irq.h>
50#include <arch/mm/page.h>
51#include <arch/types.h>
52#include <align.h>
53#include <string.h>
54#include <print.h>
55#include <sysinfo/sysinfo.h>
56
57kbd_type_t kbd_type = KBD_UNKNOWN;
58
59#ifdef CONFIG_SUN_KBD
60
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 */
68void kbd_init(ofw_tree_node_t *node)
69{
70 size_t offset;
71 uintptr_t aligned_addr;
72 ofw_tree_property_t *prop;
73 const char *name;
74 cir_t cir;
75 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 (strcmp(name, "zs") == 0)
90 kbd_type = KBD_Z8530;
91 else if (strcmp(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.");
151 }
152
153 /*
154 * We need to pass aligned address to hw_map().
155 * However, the physical keyboard address can
156 * be pretty much unaligned, depending on the
157 * underlying controller.
158 */
159 aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE);
160 offset = pa - aligned_addr;
161
162 switch (kbd_type) {
163#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);
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
184#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);
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 }
209}
210
211#endif
212
213/** @}
214 */
Note: See TracBrowser for help on using the repository browser.