Support for grabbing and releasing z8530 keyboard for sparc64.
[helenos.git] / kernel / genarch / src / kbd / z8530.c
blob3508e5c06ccf5834dc6f7057daf7cea9db4ac81d
1 /*
2 * Copyright (C) 2001-2004 Jakub Jermar
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 genarch
30 * @{
32 /**
33 * @file
34 * @brief Zilog 8530 serial port / keyboard driver.
37 #include <genarch/kbd/z8530.h>
38 #include <genarch/kbd/key.h>
39 #include <genarch/kbd/scanc.h>
40 #include <genarch/kbd/scanc_sun.h>
41 #include <arch/drivers/z8530.h>
42 #include <ddi/irq.h>
43 #include <ipc/irq.h>
44 #include <arch/interrupt.h>
45 #include <arch/drivers/kbd.h>
46 #include <arch/drivers/fhc.h>
47 #include <cpu.h>
48 #include <arch/asm.h>
49 #include <arch.h>
50 #include <typedefs.h>
51 #include <console/chardev.h>
52 #include <console/console.h>
53 #include <interrupt.h>
54 #include <sysinfo/sysinfo.h>
55 #include <print.h>
58 * These codes read from z8530 data register are silently ignored.
60 #define IGNORE_CODE 0x7f /* all keys up */
62 static z8530_t z8530; /**< z8530 device structure. */
63 static irq_t z8530_irq; /**< z8530's IRQ. */
65 static ipc_notif_cfg_t saved_notif_cfg;
67 static void z8530_suspend(chardev_t *);
68 static void z8530_resume(chardev_t *);
70 static chardev_operations_t ops = {
71 .suspend = z8530_suspend,
72 .resume = z8530_resume,
73 .read = z8530_key_read
76 /** Initialize keyboard and service interrupts using kernel routine. */
77 void z8530_grab(void)
79 (void) z8530_read_a(&z8530, RR8);
82 * Clear any pending TX interrupts or we never manage
83 * to set FHC UART interrupt state to idle.
85 z8530_write_a(&z8530, WR0, WR0_TX_IP_RST);
87 z8530_write_a(&z8530, WR1, WR1_IARCSC); /* interrupt on all characters */
89 /* 8 bits per character and enable receiver */
90 z8530_write_a(&z8530, WR3, WR3_RX8BITSCH | WR3_RX_ENABLE);
92 z8530_write_a(&z8530, WR9, WR9_MIE); /* Master Interrupt Enable. */
94 if (z8530_irq.notif_cfg.answerbox) {
95 saved_notif_cfg = z8530_irq.notif_cfg;
96 z8530_irq.notif_cfg.answerbox = NULL;
97 z8530_irq.notif_cfg.code = NULL;
98 z8530_irq.notif_cfg.method = 0;
99 z8530_irq.notif_cfg.counter = 0;
103 /** Resume the former IPC notification behavior. */
104 void z8530_release(void)
106 if (saved_notif_cfg.answerbox)
107 z8530_irq.notif_cfg = saved_notif_cfg;
110 /** Initialize z8530. */
111 void z8530_init(devno_t devno, inr_t inr, uintptr_t vaddr)
113 chardev_initialize("z8530_kbd", &kbrd, &ops);
114 stdin = &kbrd;
116 z8530.devno = devno;
117 z8530.reg = (uint8_t *) vaddr;
119 irq_initialize(&z8530_irq);
120 z8530_irq.devno = devno;
121 z8530_irq.inr = inr;
122 z8530_irq.claim = z8530_claim;
123 z8530_irq.handler = z8530_irq_handler;
124 irq_register(&z8530_irq);
126 sysinfo_set_item_val("kbd", NULL, true);
127 sysinfo_set_item_val("kbd.devno", NULL, devno);
128 sysinfo_set_item_val("kbd.inr", NULL, inr);
129 sysinfo_set_item_val("kbd.address.virtual", NULL, vaddr);
131 z8530_grab();
134 /** Process z8530 interrupt.
136 * @param n Interrupt vector.
137 * @param istate Interrupted state.
139 void z8530_interrupt(void)
141 z8530_poll();
144 /* Called from getc(). */
145 void z8530_resume(chardev_t *d)
149 /* Called from getc(). */
150 void z8530_suspend(chardev_t *d)
154 char z8530_key_read(chardev_t *d)
156 char ch;
158 while(!(ch = active_read_buff_read())) {
159 uint8_t x;
160 while (!(z8530_read_a(&z8530, RR0) & RR0_RCA))
162 x = z8530_read_a(&z8530, RR8);
163 if (x != IGNORE_CODE) {
164 if (x & KEY_RELEASE)
165 key_released(x ^ KEY_RELEASE);
166 else
167 active_read_key_pressed(x);
170 return ch;
173 /** Poll for key press and release events.
175 * This function can be used to implement keyboard polling.
177 void z8530_poll(void)
179 uint8_t x;
181 while (z8530_read_a(&z8530, RR0) & RR0_RCA) {
182 x = z8530_read_a(&z8530, RR8);
183 if (x != IGNORE_CODE) {
184 if (x & KEY_RELEASE)
185 key_released(x ^ KEY_RELEASE);
186 else
187 key_pressed(x);
192 irq_ownership_t z8530_claim(void)
194 return (z8530_read_a(&z8530, RR0) & RR0_RCA);
197 void z8530_irq_handler(irq_t *irq, void *arg, ...)
200 * So far, we know we got this interrupt through the FHC.
201 * Since we don't have enough documentation about the FHC
202 * and because the interrupt looks like level sensitive,
203 * we cannot handle it by scheduling one of the level
204 * interrupt traps. Process the interrupt directly.
206 if (irq->notif_cfg.answerbox)
207 ipc_irq_send_notif(irq);
208 else
209 z8530_interrupt();
210 fhc_clear_interrupt(central_fhc, irq->inr);
213 /** @}