source: mainline/kernel/genarch/src/kbd/z8530.c@ fa09449

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since fa09449 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: 5.3 KB
Line 
1/*
2 * Copyright (c) 2001-2004 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 genarch
30 * @{
31 */
32/**
33 * @file
34 * @brief Zilog 8530 serial port / keyboard driver.
35 */
36
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 <cpu.h>
47#include <arch/asm.h>
48#include <arch.h>
49#include <console/chardev.h>
50#include <console/console.h>
51#include <interrupt.h>
52#include <sysinfo/sysinfo.h>
53#include <print.h>
54
55/*
56 * These codes read from z8530 data register are silently ignored.
57 */
58#define IGNORE_CODE 0x7f /* all keys up */
59
60static z8530_t z8530; /**< z8530 device structure. */
61static irq_t z8530_irq; /**< z8530's IRQ. */
62
63static void z8530_suspend(chardev_t *);
64static void z8530_resume(chardev_t *);
65
66static chardev_operations_t ops = {
67 .suspend = z8530_suspend,
68 .resume = z8530_resume,
69 .read = z8530_key_read
70};
71
72/** Initialize keyboard and service interrupts using kernel routine. */
73void z8530_grab(void)
74{
75 ipl_t ipl = interrupts_disable();
76
77 (void) z8530_read_a(&z8530, RR8);
78
79 /*
80 * Clear any pending TX interrupts or we never manage
81 * to set FHC UART interrupt state to idle.
82 */
83 z8530_write_a(&z8530, WR0, WR0_TX_IP_RST);
84
85 /* interrupt on all characters */
86 z8530_write_a(&z8530, WR1, WR1_IARCSC);
87
88 /* 8 bits per character and enable receiver */
89 z8530_write_a(&z8530, WR3, WR3_RX8BITSCH | WR3_RX_ENABLE);
90
91 /* Master Interrupt Enable. */
92 z8530_write_a(&z8530, WR9, WR9_MIE);
93
94 spinlock_lock(&z8530_irq.lock);
95 z8530_irq.notif_cfg.notify = false;
96 spinlock_unlock(&z8530_irq.lock);
97 interrupts_restore(ipl);
98}
99
100/** Resume the former IPC notification behavior. */
101void z8530_release(void)
102{
103 ipl_t ipl = interrupts_disable();
104 spinlock_lock(&z8530_irq.lock);
105 if (z8530_irq.notif_cfg.answerbox)
106 z8530_irq.notif_cfg.notify = true;
107 spinlock_unlock(&z8530_irq.lock);
108 interrupts_restore(ipl);
109}
110
111/** Initialize z8530. */
112void
113z8530_init(devno_t devno, uintptr_t vaddr, inr_t inr, cir_t cir, void *cir_arg)
114{
115 chardev_initialize("z8530_kbd", &kbrd, &ops);
116 stdin = &kbrd;
117
118 z8530.devno = devno;
119 z8530.reg = (uint8_t *) vaddr;
120
121 irq_initialize(&z8530_irq);
122 z8530_irq.devno = devno;
123 z8530_irq.inr = inr;
124 z8530_irq.claim = z8530_claim;
125 z8530_irq.handler = z8530_irq_handler;
126 z8530_irq.cir = cir;
127 z8530_irq.cir_arg = cir_arg;
128 irq_register(&z8530_irq);
129
130 sysinfo_set_item_val("kbd", NULL, true);
131 sysinfo_set_item_val("kbd.type", NULL, KBD_Z8530);
132 sysinfo_set_item_val("kbd.devno", NULL, devno);
133 sysinfo_set_item_val("kbd.inr", NULL, inr);
134 sysinfo_set_item_val("kbd.address.virtual", NULL, vaddr);
135
136 z8530_grab();
137}
138
139/** Process z8530 interrupt.
140 *
141 * @param n Interrupt vector.
142 * @param istate Interrupted state.
143 */
144void z8530_interrupt(void)
145{
146 z8530_poll();
147}
148
149/* Called from getc(). */
150void z8530_resume(chardev_t *d)
151{
152}
153
154/* Called from getc(). */
155void z8530_suspend(chardev_t *d)
156{
157}
158
159char z8530_key_read(chardev_t *d)
160{
161 char ch;
162
163 while(!(ch = active_read_buff_read())) {
164 uint8_t x;
165 while (!(z8530_read_a(&z8530, RR0) & RR0_RCA))
166 ;
167 x = z8530_read_a(&z8530, RR8);
168 if (x != IGNORE_CODE) {
169 if (x & KEY_RELEASE)
170 key_released(x ^ KEY_RELEASE);
171 else
172 active_read_key_pressed(x);
173 }
174 }
175 return ch;
176}
177
178/** Poll for key press and release events.
179 *
180 * This function can be used to implement keyboard polling.
181 */
182void z8530_poll(void)
183{
184 uint8_t x;
185
186 while (z8530_read_a(&z8530, RR0) & RR0_RCA) {
187 x = z8530_read_a(&z8530, RR8);
188 if (x != IGNORE_CODE) {
189 if (x & KEY_RELEASE)
190 key_released(x ^ KEY_RELEASE);
191 else
192 key_pressed(x);
193 }
194 }
195}
196
197irq_ownership_t z8530_claim(void)
198{
199 return (z8530_read_a(&z8530, RR0) & RR0_RCA);
200}
201
202void z8530_irq_handler(irq_t *irq, void *arg, ...)
203{
204 if (irq->notif_cfg.notify && irq->notif_cfg.answerbox)
205 ipc_irq_send_notif(irq);
206 else
207 z8530_interrupt();
208}
209
210/** @}
211 */
Note: See TracBrowser for help on using the repository browser.