Add mutual exclusion to keyboard grab and release
[helenos.git] / kernel / arch / ppc32 / src / drivers / cuda.c
blob984c205ce6750b28e8d072acfa65bce031f89a3a
1 /*
2 * Copyright (C) 2006 Martin Decky
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
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.
29 /** @addtogroup ppc32
30 * @{
32 /** @file
35 #include <arch/drivers/cuda.h>
36 #include <ddi/irq.h>
37 #include <arch/asm.h>
38 #include <console/console.h>
39 #include <console/chardev.h>
40 #include <arch/drivers/pic.h>
41 #include <sysinfo/sysinfo.h>
42 #include <interrupt.h>
43 #include <stdarg.h>
45 #define CUDA_IRQ 10
46 #define SPECIAL '?'
48 #define PACKET_ADB 0x00
49 #define PACKET_CUDA 0x01
51 #define CUDA_POWERDOWN 0x0a
53 #define RS 0x200
54 #define B (0 * RS)
55 #define A (1 * RS)
56 #define SR (10 * RS)
57 #define ACR (11 * RS)
59 #define SR_OUT 0x10
60 #define TACK 0x10
61 #define TIP 0x20
64 static volatile uint8_t *cuda = NULL;
65 static irq_t cuda_irq; /**< Cuda's IRQ. */
67 static char lchars[0x80] = {
68 'a',
69 's',
70 'd',
71 'f',
72 'h',
73 'g',
74 'z',
75 'x',
76 'c',
77 'v',
78 SPECIAL,
79 'b',
80 'q',
81 'w',
82 'e',
83 'r',
84 'y',
85 't',
86 '1',
87 '2',
88 '3',
89 '4',
90 '6',
91 '5',
92 '=',
93 '9',
94 '7',
95 '-',
96 '8',
97 '0',
98 ']',
99 'o',
100 'u',
101 '[',
102 'i',
103 'p',
104 '\n', /* Enter */
105 'l',
106 'j',
107 '\'',
108 'k',
109 ';',
110 '\\',
111 ',',
112 '/',
113 'n',
114 'm',
115 '.',
116 '\t', /* Tab */
117 ' ',
118 '`',
119 '\b', /* Backspace */
120 SPECIAL,
121 SPECIAL, /* Escape */
122 SPECIAL, /* Ctrl */
123 SPECIAL, /* Alt */
124 SPECIAL, /* Shift */
125 SPECIAL, /* Caps-Lock */
126 SPECIAL, /* RAlt */
127 SPECIAL, /* Left */
128 SPECIAL, /* Right */
129 SPECIAL, /* Down */
130 SPECIAL, /* Up */
131 SPECIAL,
132 SPECIAL,
133 '.', /* Keypad . */
134 SPECIAL,
135 '*', /* Keypad * */
136 SPECIAL,
137 '+', /* Keypad + */
138 SPECIAL,
139 SPECIAL, /* NumLock */
140 SPECIAL,
141 SPECIAL,
142 SPECIAL,
143 '/', /* Keypad / */
144 '\n', /* Keypad Enter */
145 SPECIAL,
146 '-', /* Keypad - */
147 SPECIAL,
148 SPECIAL,
149 SPECIAL,
150 '0', /* Keypad 0 */
151 '1', /* Keypad 1 */
152 '2', /* Keypad 2 */
153 '3', /* Keypad 3 */
154 '4', /* Keypad 4 */
155 '5', /* Keypad 5 */
156 '6', /* Keypad 6 */
157 '7', /* Keypad 7 */
158 SPECIAL,
159 '8', /* Keypad 8 */
160 '9', /* Keypad 9 */
161 SPECIAL,
162 SPECIAL,
163 SPECIAL,
164 SPECIAL, /* F5 */
165 SPECIAL, /* F6 */
166 SPECIAL, /* F7 */
167 SPECIAL, /* F3 */
168 SPECIAL, /* F8 */
169 SPECIAL, /* F9 */
170 SPECIAL,
171 SPECIAL, /* F11 */
172 SPECIAL,
173 SPECIAL, /* F13 */
174 SPECIAL,
175 SPECIAL, /* ScrollLock */
176 SPECIAL,
177 SPECIAL, /* F10 */
178 SPECIAL,
179 SPECIAL, /* F12 */
180 SPECIAL,
181 SPECIAL, /* Pause */
182 SPECIAL, /* Insert */
183 SPECIAL, /* Home */
184 SPECIAL, /* PageUp */
185 SPECIAL, /* Delete */
186 SPECIAL, /* F4 */
187 SPECIAL, /* End */
188 SPECIAL, /* F2 */
189 SPECIAL, /* PageDown */
190 SPECIAL /* F1 */
194 void send_packet(const uint8_t kind, index_t count, ...);
197 static void receive_packet(uint8_t *kind, index_t count, uint8_t data[])
199 cuda[B] = cuda[B] & ~TIP;
200 *kind = cuda[SR];
202 index_t i;
203 for (i = 0; i < count; i++)
204 data[i] = cuda[SR];
206 cuda[B] = cuda[B] | TIP;
210 /* Called from getc(). */
211 static void cuda_resume(chardev_t *d)
216 /* Called from getc(). */
217 static void cuda_suspend(chardev_t *d)
222 static char key_read(chardev_t *d)
224 char ch;
226 ch = 0;
227 return ch;
231 static chardev_t kbrd;
232 static chardev_operations_t ops = {
233 .suspend = cuda_suspend,
234 .resume = cuda_resume,
235 .read = key_read
239 int cuda_get_scancode(void)
241 uint8_t kind;
242 uint8_t data[4];
244 receive_packet(&kind, 4, data);
246 if ((kind == PACKET_ADB) && (data[0] == 0x40) && (data[1] == 0x2c))
247 return data[2];
249 return -1;
252 static void cuda_irq_handler(irq_t *irq, void *arg, ...)
254 if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox))
255 ipc_irq_send_notif(irq);
256 else {
257 int scan_code = cuda_get_scancode();
259 if (scan_code != -1) {
260 uint8_t scancode = (uint8_t) scan_code;
261 if ((scancode & 0x80) != 0x80)
262 chardev_push_character(&kbrd, lchars[scancode & 0x7f]);
267 static irq_ownership_t cuda_claim(void)
269 return IRQ_ACCEPT;
273 /** Initialize keyboard and service interrupts using kernel routine */
274 void cuda_grab(void)
276 ipl_t ipl = interrupts_disable();
277 spinlock_lock(&cuda_irq.lock);
278 cuda_irq.notif_cfg.notify = false;
279 spinlock_unlock(&cuda_irq.lock);
280 interrupts_restore(ipl);
284 /** Resume the former interrupt vector */
285 void cuda_release(void)
287 ipl_t ipl = interrupts_disable();
288 spinlock_lock(&cuda_irq.lock);
289 if (cuda_irq.notif_cfg.answerbox)
290 cuda_irq.notif_cfg.notify = true;
291 spinlock_unlock(&cuda_irq.unlock);
292 interrupts_restore(ipl);
296 void cuda_init(devno_t devno, uintptr_t base, size_t size)
298 cuda = (uint8_t *) hw_map(base, size);
300 chardev_initialize("cuda_kbd", &kbrd, &ops);
301 stdin = &kbrd;
303 irq_initialize(&cuda_irq);
304 cuda_irq.devno = devno;
305 cuda_irq.inr = CUDA_IRQ;
306 cuda_irq.claim = cuda_claim;
307 cuda_irq.handler = cuda_irq_handler;
308 irq_register(&cuda_irq);
310 pic_enable_interrupt(CUDA_IRQ);
312 sysinfo_set_item_val("kbd", NULL, true);
313 sysinfo_set_item_val("kbd.devno", NULL, devno);
314 sysinfo_set_item_val("kbd.inr", NULL, CUDA_IRQ);
315 sysinfo_set_item_val("kbd.address.virtual", NULL, base);
319 void send_packet(const uint8_t kind, index_t count, ...)
321 index_t i;
322 va_list va;
324 cuda[B] = cuda[B] | TIP;
325 cuda[ACR] = cuda[ACR] | SR_OUT;
326 cuda[SR] = kind;
327 cuda[B] = cuda[B] & ~TIP;
329 va_start(va, count);
331 for (i = 0; i < count; i++) {
332 cuda[ACR] = cuda[ACR] | SR_OUT;
333 cuda[SR] = va_arg(va, int);
334 cuda[B] = cuda[B] | TACK;
337 va_end(va);
339 cuda[B] = cuda[B] | TIP;
343 void cpu_halt(void) {
344 #ifdef CONFIG_POWEROFF
345 send_packet(PACKET_CUDA, 1, CUDA_POWERDOWN);
346 #endif
347 asm volatile (
348 "b 0\n"
352 /** @}