source: mainline/kernel/arch/sparc64/src/drivers/kbd.c@ 8d2760f

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8d2760f was 8d2760f, checked in by Jakub Jermar <jakub@…>, 17 years ago

Add additional members to the irq_t structure so that an interrupt-driven driver
does not need to know how to clear the level interrupt. The z8530 was modified
in this way and is much more generic. The ns16550 driver has also been modified,
but awaits testing. The sparc64 interrupt mapping and dispatch code is now using
the new info and calls the clear-interrupt-routine itself.

  • Property mode set to 100644
File size: 4.5 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#ifdef CONFIG_Z8530
38#include <genarch/kbd/z8530.h>
39#endif
40#ifdef CONFIG_NS16550
41#include <genarch/kbd/ns16550.h>
42#endif
43#include <ddi/device.h>
44#include <ddi/irq.h>
45#include <arch/mm/page.h>
46#include <arch/types.h>
47#include <align.h>
48#include <func.h>
49#include <print.h>
50
51kbd_type_t kbd_type = KBD_UNKNOWN;
52
53/** Initialize keyboard.
54 *
55 * Traverse OpenFirmware device tree in order to find necessary
56 * info about the keyboard device.
57 *
58 * @param node Keyboard device node.
59 */
60void kbd_init(ofw_tree_node_t *node)
61{
62 size_t offset;
63 uintptr_t aligned_addr;
64 ofw_tree_property_t *prop;
65 const char *name;
66 cir_t cir;
67 void *cir_arg;
68
69 name = ofw_tree_node_name(node);
70
71 /*
72 * Determine keyboard serial controller type.
73 */
74 if (strcmp(name, "zs") == 0)
75 kbd_type = KBD_Z8530;
76 else if (strcmp(name, "su") == 0)
77 kbd_type = KBD_NS16550;
78
79 if (kbd_type == KBD_UNKNOWN) {
80 printf("Unknown keyboard device.\n");
81 return;
82 }
83
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);
92
93 /*
94 * Read 'reg' property.
95 */
96 prop = ofw_tree_getprop(node, "reg");
97 if (!prop || !prop->value)
98 panic("Can't find \"reg\" property.\n");
99
100 uintptr_t pa;
101 size_t size;
102 inr_t inr;
103 devno_t devno = device_assign_devno();
104
105 switch (kbd_type) {
106 case KBD_Z8530:
107 size = ((ofw_fhc_reg_t *) prop->value)->size;
108 if (!ofw_fhc_apply_ranges(node->parent,
109 ((ofw_fhc_reg_t *) prop->value), &pa)) {
110 printf("Failed to determine keyboard address.\n");
111 return;
112 }
113 if (!ofw_fhc_map_interrupt(node->parent,
114 ((ofw_fhc_reg_t *) prop->value), interrupts, &inr, &cir,
115 &cir_arg)) {
116 printf("Failed to determine keyboard interrupt.\n");
117 return;
118 }
119 break;
120
121 case KBD_NS16550:
122 size = ((ofw_ebus_reg_t *) prop->value)->size;
123 if (!ofw_ebus_apply_ranges(node->parent,
124 ((ofw_ebus_reg_t *) prop->value), &pa)) {
125 printf("Failed to determine keyboard address.\n");
126 return;
127 }
128 if (!ofw_ebus_map_interrupt(node->parent,
129 ((ofw_ebus_reg_t *) prop->value), interrupts, &inr, &cir,
130 &cir_arg)) {
131 printf("Failed to determine keyboard interrupt.\n");
132 return;
133 };
134 break;
135
136 default:
137 panic("Unexpected type.\n");
138 }
139
140 /*
141 * We need to pass aligned address to hw_map().
142 * However, the physical keyboard address can
143 * be pretty much unaligned, depending on the
144 * underlying controller.
145 */
146 aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE);
147 offset = pa - aligned_addr;
148 uintptr_t vaddr = hw_map(aligned_addr, offset + size) + offset;
149
150 switch (kbd_type) {
151#ifdef CONFIG_Z8530
152 case KBD_Z8530:
153 z8530_init(devno, vaddr, inr, cir, cir_arg);
154 break;
155#endif
156#ifdef CONFIG_NS16550
157 case KBD_NS16550:
158 ns16550_init(devno, (ioport_t)vaddr, inr, cir, cir_arg);
159 break;
160#endif
161 default:
162 printf("Kernel is not compiled with the necessary keyboard "
163 "driver this machine requires.\n");
164 }
165}
166
167/** @}
168 */
Note: See TracBrowser for help on using the repository browser.