Subversion Repositories HelenOS

Rev

Rev 4632 | Go to most recent revision | Details | Compare with Previous | 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
4634 pillai 56
#define PL050_CAPS_SCAN_CODE   0x58
4629 pillai 57
 
58
static void pl050_suspend(chardev_t *);
59
static void pl050_resume(chardev_t *);
60
 
61
static chardev_operations_t ops = {
62
    .suspend = pl050_suspend,
63
    .resume = pl050_resume,
64
    .read = pl050_key_read
65
};
66
 
67
/** Structure for pl050's IRQ. */
68
static irq_t pl050_kbd_irq;
69
/* static irq_t pl050_mouse_irq; */
70
static uintptr_t    pl050_kbd_pbase;
71
static uintptr_t    pl050_kbd_vbase;
72
 
73
uint8_t pl050_dataread(void)
74
{
75
    return *(uint8_t *)(pl050_kbd_vbase + PL050_DATA);
76
}
77
 
78
uint8_t pl050_statusread(void)
79
{
80
    return *(uint8_t *)(pl050_kbd_vbase + PL050_STAT);
81
}
82
 
83
void pl050_crwrite(uint8_t val)
84
{
85
    *(uint8_t *)pl050_kbd_vbase = val;
86
}
87
 
88
 
89
void pl050_grab(void)
90
{
91
    ipl_t ipl = interrupts_disable();
92
 
93
    spinlock_lock(&pl050_kbd_irq.lock);
94
    pl050_kbd_irq.notif_cfg.notify = false;
95
    spinlock_unlock(&pl050_kbd_irq.lock);
96
 
97
    interrupts_restore(ipl);
98
}
99
 
100
void pl050_release(void)
101
{
102
    ipl_t ipl = interrupts_disable();
103
 
104
    spinlock_lock(&pl050_kbd_irq.lock);
105
    if (pl050_kbd_irq.notif_cfg.answerbox)
106
        pl050_kbd_irq.notif_cfg.notify = true;
107
    spinlock_unlock(&pl050_kbd_irq.lock);
108
 
109
    interrupts_restore(ipl);
110
}
111
 
112
static irq_ownership_t pl050_claim(void)
113
{
114
    return IRQ_ACCEPT;
115
}
116
 
117
static void pl050_irq_handler(irq_t *irq, void *arg, ...)
118
{
119
    static int key_released_flag = 0;
4634 pillai 120
    static int caps_locked = 0;
4629 pillai 121
 
122
    if (irq->notif_cfg.notify && irq->notif_cfg.answerbox)
123
        ipc_irq_send_notif(irq);
124
    else {
125
        uint8_t data;
126
        uint8_t status;
127
 
4634 pillai 128
        while (((status = pl050_statusread()) & PL050_STAT_RXFULL)) {
4629 pillai 129
            data = pl050_dataread();
130
 
131
            if (data == PL050_KEY_RELEASE) {
132
                key_released_flag = 1;
133
            } else {
4632 pillai 134
                if (key_released_flag) {
4634 pillai 135
                    key_released_flag = 0;
136
                    if (data == PL050_CAPS_SCAN_CODE) {
137
                        if (!caps_locked) {
138
                            caps_locked = 1;
139
                        } else {
140
                            caps_locked = 0;
141
                            return;
142
                        }
143
                    }
4629 pillai 144
                    key_released(data);
4634 pillai 145
 
4629 pillai 146
                } else {
4634 pillai 147
                    if (data == PL050_CAPS_SCAN_CODE && caps_locked)
148
                        return;
4629 pillai 149
                    key_pressed(data);
150
                }
151
            }
152
        }
153
    }
154
}
155
 
156
/** Initialize pl050. */
157
void pl050_init(devno_t kbd_devno, inr_t kbd_inr, uintptr_t pbase, uintptr_t vbase)
158
{
159
    uint8_t val = 0;
160
    chardev_initialize("pl050_kbd", &kbrd, &ops);
161
    stdin = &kbrd;
162
 
163
    irq_initialize(&pl050_kbd_irq);
164
    pl050_kbd_irq.devno = kbd_devno;
165
    pl050_kbd_irq.inr = kbd_inr;
166
    pl050_kbd_irq.claim = pl050_claim;
167
    pl050_kbd_irq.handler = pl050_irq_handler;
168
    pl050_kbd_pbase = pbase;
169
    pl050_kbd_vbase = vbase;
170
    irq_register(&pl050_kbd_irq);
4632 pillai 171
    val = PL050_CR_RXINTR | PL050_CR_INTR;
4629 pillai 172
 
173
    pl050_crwrite(val);
174
 
175
    /* reset the data buffer */
176
    pl050_dataread();
177
 
178
    sysinfo_set_item_val("kbd", NULL, true);
179
    sysinfo_set_item_val("kbd.devno", NULL, kbd_devno);
180
    sysinfo_set_item_val("kbd.inr", NULL, kbd_inr);
181
    sysinfo_set_item_val("kbd.pbase", NULL, pl050_kbd_pbase);
182
    sysinfo_set_item_val("kbd.vbase", NULL, vbase);
183
 
184
    pl050_grab();
185
}
186
 
187
/* Called from getc(). */
188
void pl050_resume(chardev_t *d)
189
{
190
}
191
 
192
/* Called from getc(). */
193
void pl050_suspend(chardev_t *d)
194
{
195
}
196
 
197
char pl050_key_read(chardev_t *d)
198
{
199
    char ch;   
4632 pillai 200
    printf("entering key_read\n");
4629 pillai 201
    while(!(ch = active_read_buff_read())) {
202
        uint8_t x;
203
        while (!(pl050_statusread() & PL050_STAT_RXFULL))
204
            ;
205
        x = pl050_dataread();
206
        if (x & KEY_RELEASE)
207
            key_released(x ^ KEY_RELEASE);
208
        else
209
            active_read_key_pressed(x);
210
    }
211
    return ch;
212
}
213
 
214
/** Poll for key press and release events.
215
 *
216
 * This function can be used to implement keyboard polling.
217
 */
218
void pl050_poll(void)
219
{
220
    uint8_t x;
221
 
4632 pillai 222
    printf("entering poll\n");
4629 pillai 223
    while (((x = pl050_statusread() & PL050_STAT_RXFULL))) {
224
        x = pl050_dataread();
225
        if (x & KEY_RELEASE)
226
            key_released(x ^ KEY_RELEASE);
227
        else
228
            key_pressed(x);
229
    }
230
}
231
 
232
/** @}
233
 */