Subversion Repositories HelenOS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4629 pillai 1
/*
2
 * Copyright (c) 2009 Vineeth Pillai
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 arm32  
30
 * @{
31
 */
32
/**
33
 * @file
34
 * @brief   pl050 keyboard/mouse driver.
35
 *
36
 * It takes care of low-level keyboard functions.
37
 */
38
 
39
#include <genarch/kbd/key.h>
40
#include <cpu.h>
41
#include <arch/asm.h>
42
#include <arch.h>
43
#include <arch/drivers/pl050.h>
44
#include <console/console.h>
45
#include <interrupt.h>
46
#include <sysinfo/sysinfo.h>
47
#include <ipc/irq.h>
48
 
49
#include <arch/debug/print.h>
50
#include <genarch/fb/fb.h>
51
#include <genarch/fb/visuals.h>
52
#include <print.h>
53
 
54
#define PL050_KEY_RELEASE 0xF0
55
#define PL050_ESC_KEY   0xE0
56
 
57
static void pl050_suspend(chardev_t *);
58
static void pl050_resume(chardev_t *);
59
 
60
static chardev_operations_t ops = {
61
    .suspend = pl050_suspend,
62
    .resume = pl050_resume,
63
    .read = pl050_key_read
64
};
65
 
66
/** Structure for pl050's IRQ. */
67
static irq_t pl050_kbd_irq;
68
/* static irq_t pl050_mouse_irq; */
69
static uintptr_t    pl050_kbd_pbase;
70
static uintptr_t    pl050_kbd_vbase;
71
 
72
uint8_t pl050_dataread(void)
73
{
74
    return *(uint8_t *)(pl050_kbd_vbase + PL050_DATA);
75
}
76
 
77
uint8_t pl050_statusread(void)
78
{
79
    return *(uint8_t *)(pl050_kbd_vbase + PL050_STAT);
80
}
81
 
82
void pl050_crwrite(uint8_t val)
83
{
84
    *(uint8_t *)pl050_kbd_vbase = val;
85
}
86
 
87
 
88
void pl050_grab(void)
89
{
90
    ipl_t ipl = interrupts_disable();
91
 
92
    spinlock_lock(&pl050_kbd_irq.lock);
93
    pl050_kbd_irq.notif_cfg.notify = false;
94
    spinlock_unlock(&pl050_kbd_irq.lock);
95
 
96
    interrupts_restore(ipl);
97
}
98
 
99
void pl050_release(void)
100
{
101
    ipl_t ipl = interrupts_disable();
102
 
103
    spinlock_lock(&pl050_kbd_irq.lock);
104
    if (pl050_kbd_irq.notif_cfg.answerbox)
105
        pl050_kbd_irq.notif_cfg.notify = true;
106
    spinlock_unlock(&pl050_kbd_irq.lock);
107
 
108
    interrupts_restore(ipl);
109
}
110
 
111
static irq_ownership_t pl050_claim(void)
112
{
113
    return IRQ_ACCEPT;
114
}
115
 
116
static void pl050_irq_handler(irq_t *irq, void *arg, ...)
117
{
118
    static int key_released_flag = 0;
119
    static uint8_t prev_char = 0xFF;
120
 
121
    if (irq->notif_cfg.notify && irq->notif_cfg.answerbox)
122
        ipc_irq_send_notif(irq);
123
    else {
124
        uint8_t data;
125
        uint8_t status;
126
 
127
        if (((status = pl050_statusread()) & PL050_STAT_RXFULL)) {
128
            data = pl050_dataread();
129
 
130
            if (data == PL050_ESC_KEY)
131
                return;
132
 
133
            if (data == PL050_KEY_RELEASE) {
134
                key_released_flag = 1;
135
            } else {
136
                if (key_released_flag && prev_char == data) {
137
                    prev_char = 0xFF;
138
                    key_released(data);
139
                } else {
140
                    key_pressed(data);
141
                    prev_char = data;
142
                }
143
                key_released_flag = 0;
144
            }
145
        }
146
    }
147
}
148
 
149
/** Initialize pl050. */
150
void pl050_init(devno_t kbd_devno, inr_t kbd_inr, uintptr_t pbase, uintptr_t vbase)
151
{
152
    uint8_t val = 0;
153
    chardev_initialize("pl050_kbd", &kbrd, &ops);
154
    stdin = &kbrd;
155
 
156
    irq_initialize(&pl050_kbd_irq);
157
    pl050_kbd_irq.devno = kbd_devno;
158
    pl050_kbd_irq.inr = kbd_inr;
159
    pl050_kbd_irq.claim = pl050_claim;
160
    pl050_kbd_irq.handler = pl050_irq_handler;
161
    pl050_kbd_pbase = pbase;
162
    pl050_kbd_vbase = vbase;
163
    irq_register(&pl050_kbd_irq);
164
    val = PL050_CR_RXINTR | PL050_CR_INTR | PL050_CR_FKMIC;
165
 
166
    pl050_crwrite(val);
167
 
168
    /* reset the data buffer */
169
    pl050_dataread();
170
 
171
    sysinfo_set_item_val("kbd", NULL, true);
172
    sysinfo_set_item_val("kbd.devno", NULL, kbd_devno);
173
    sysinfo_set_item_val("kbd.inr", NULL, kbd_inr);
174
    sysinfo_set_item_val("kbd.pbase", NULL, pl050_kbd_pbase);
175
    sysinfo_set_item_val("kbd.vbase", NULL, vbase);
176
 
177
    pl050_grab();
178
}
179
 
180
/* Called from getc(). */
181
void pl050_resume(chardev_t *d)
182
{
183
}
184
 
185
/* Called from getc(). */
186
void pl050_suspend(chardev_t *d)
187
{
188
}
189
 
190
char pl050_key_read(chardev_t *d)
191
{
192
    char ch;   
193
 
194
    while(!(ch = active_read_buff_read())) {
195
        uint8_t x;
196
        while (!(pl050_statusread() & PL050_STAT_RXFULL))
197
            ;
198
        x = pl050_dataread();
199
        if (x & KEY_RELEASE)
200
            key_released(x ^ KEY_RELEASE);
201
        else
202
            active_read_key_pressed(x);
203
    }
204
    return ch;
205
}
206
 
207
/** Poll for key press and release events.
208
 *
209
 * This function can be used to implement keyboard polling.
210
 */
211
void pl050_poll(void)
212
{
213
    uint8_t x;
214
 
215
    while (((x = pl050_statusread() & PL050_STAT_RXFULL))) {
216
        x = pl050_dataread();
217
        if (x & KEY_RELEASE)
218
            key_released(x ^ KEY_RELEASE);
219
        else
220
            key_pressed(x);
221
    }
222
}
223
 
224
/** @}
225
 */