Subversion Repositories HelenOS

Rev

Rev 4629 | 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
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;
4632 pillai 119
    static int caps_count = 0;
4629 pillai 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;
4632 pillai 132
 
133
            if (data == 0x58) {
134
                if (caps_count == 2) {
135
                    caps_count = 0;
136
                    return;
137
                } else if (key_released_flag && !caps_count) {
138
                    key_released_flag = 0;
139
                    return;
140
                }
141
                caps_count++;
142
            }
4629 pillai 143
 
144
            if (data == PL050_KEY_RELEASE) {
145
                key_released_flag = 1;
146
            } else {
4632 pillai 147
                if (key_released_flag) {
4629 pillai 148
                    key_released(data);
149
                } else {
150
                    key_pressed(data);
151
                }
152
                key_released_flag = 0;
153
            }
154
        }
155
    }
156
}
157
 
158
/** Initialize pl050. */
159
void pl050_init(devno_t kbd_devno, inr_t kbd_inr, uintptr_t pbase, uintptr_t vbase)
160
{
161
    uint8_t val = 0;
162
    chardev_initialize("pl050_kbd", &kbrd, &ops);
163
    stdin = &kbrd;
164
 
165
    irq_initialize(&pl050_kbd_irq);
166
    pl050_kbd_irq.devno = kbd_devno;
167
    pl050_kbd_irq.inr = kbd_inr;
168
    pl050_kbd_irq.claim = pl050_claim;
169
    pl050_kbd_irq.handler = pl050_irq_handler;
170
    pl050_kbd_pbase = pbase;
171
    pl050_kbd_vbase = vbase;
172
    irq_register(&pl050_kbd_irq);
4632 pillai 173
    val = PL050_CR_RXINTR | PL050_CR_INTR;
4629 pillai 174
 
175
    pl050_crwrite(val);
176
 
177
    /* reset the data buffer */
178
    pl050_dataread();
179
 
180
    sysinfo_set_item_val("kbd", NULL, true);
181
    sysinfo_set_item_val("kbd.devno", NULL, kbd_devno);
182
    sysinfo_set_item_val("kbd.inr", NULL, kbd_inr);
183
    sysinfo_set_item_val("kbd.pbase", NULL, pl050_kbd_pbase);
184
    sysinfo_set_item_val("kbd.vbase", NULL, vbase);
185
 
186
    pl050_grab();
187
}
188
 
189
/* Called from getc(). */
190
void pl050_resume(chardev_t *d)
191
{
192
}
193
 
194
/* Called from getc(). */
195
void pl050_suspend(chardev_t *d)
196
{
197
}
198
 
199
char pl050_key_read(chardev_t *d)
200
{
201
    char ch;   
4632 pillai 202
    printf("entering key_read\n");
4629 pillai 203
    while(!(ch = active_read_buff_read())) {
204
        uint8_t x;
205
        while (!(pl050_statusread() & PL050_STAT_RXFULL))
206
            ;
207
        x = pl050_dataread();
208
        if (x & KEY_RELEASE)
209
            key_released(x ^ KEY_RELEASE);
210
        else
211
            active_read_key_pressed(x);
212
    }
213
    return ch;
214
}
215
 
216
/** Poll for key press and release events.
217
 *
218
 * This function can be used to implement keyboard polling.
219
 */
220
void pl050_poll(void)
221
{
222
    uint8_t x;
223
 
4632 pillai 224
    printf("entering poll\n");
4629 pillai 225
    while (((x = pl050_statusread() & PL050_STAT_RXFULL))) {
226
        x = pl050_dataread();
227
        if (x & KEY_RELEASE)
228
            key_released(x ^ KEY_RELEASE);
229
        else
230
            key_pressed(x);
231
    }
232
}
233
 
234
/** @}
235
 */