2 * Copyright (C) 2006 Martin Decky
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
35 #include <arch/drivers/cuda.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>
48 #define PACKET_ADB 0x00
49 #define PACKET_CUDA 0x01
51 #define CUDA_POWERDOWN 0x0a
64 static volatile uint8_t *cuda
= NULL
;
65 static irq_t cuda_irq
; /**< Cuda's IRQ. */
67 static char lchars
[0x80] = {
119 '\b', /* Backspace */
121 SPECIAL
, /* Escape */
125 SPECIAL
, /* Caps-Lock */
139 SPECIAL
, /* NumLock */
144 '\n', /* Keypad Enter */
175 SPECIAL
, /* ScrollLock */
182 SPECIAL
, /* Insert */
184 SPECIAL
, /* PageUp */
185 SPECIAL
, /* Delete */
189 SPECIAL
, /* PageDown */
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
;
203 for (i
= 0; i
< count
; i
++)
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
)
231 static chardev_t kbrd
;
232 static chardev_operations_t ops
= {
233 .suspend
= cuda_suspend
,
234 .resume
= cuda_resume
,
239 int cuda_get_scancode(void)
244 receive_packet(&kind
, 4, data
);
246 if ((kind
== PACKET_ADB
) && (data
[0] == 0x40) && (data
[1] == 0x2c))
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
);
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)
273 /** Initialize keyboard and service interrupts using kernel routine */
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
);
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
, ...)
324 cuda
[B
] = cuda
[B
] | TIP
;
325 cuda
[ACR
] = cuda
[ACR
] | SR_OUT
;
327 cuda
[B
] = cuda
[B
] & ~TIP
;
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
;
339 cuda
[B
] = cuda
[B
] | TIP
;
343 void cpu_halt(void) {
344 #ifdef CONFIG_POWEROFF
345 send_packet(PACKET_CUDA
, 1, CUDA_POWERDOWN
);