Subversion Repositories HelenOS

Rev

Rev 4632 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4632 Rev 4634
1
/*
1
/*
2
 * Copyright (c) 2009 Vineeth Pillai
2
 * Copyright (c) 2009 Vineeth Pillai
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
7
 * are met:
7
 * are met:
8
 *
8
 *
9
 * - Redistributions of source code must retain the above copyright
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
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
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.
15
 *   derived from this software without specific prior written permission.
16
 *
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
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
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
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
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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
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.
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
27
 */
28
 
28
 
29
/** @addtogroup arm32  
29
/** @addtogroup arm32  
30
 * @{
30
 * @{
31
 */
31
 */
32
/**
32
/**
33
 * @file
33
 * @file
34
 * @brief   pl050 keyboard/mouse driver.
34
 * @brief   pl050 keyboard/mouse driver.
35
 *
35
 *
36
 * It takes care of low-level keyboard functions.
36
 * It takes care of low-level keyboard functions.
37
 */
37
 */
38
 
38
 
39
#include <genarch/kbd/key.h>
39
#include <genarch/kbd/key.h>
40
#include <cpu.h>
40
#include <cpu.h>
41
#include <arch/asm.h>
41
#include <arch/asm.h>
42
#include <arch.h>
42
#include <arch.h>
43
#include <arch/drivers/pl050.h>
43
#include <arch/drivers/pl050.h>
44
#include <console/console.h>
44
#include <console/console.h>
45
#include <interrupt.h>
45
#include <interrupt.h>
46
#include <sysinfo/sysinfo.h>
46
#include <sysinfo/sysinfo.h>
47
#include <ipc/irq.h>
47
#include <ipc/irq.h>
48
 
48
 
49
#include <arch/debug/print.h>
49
#include <arch/debug/print.h>
50
#include <genarch/fb/fb.h>
50
#include <genarch/fb/fb.h>
51
#include <genarch/fb/visuals.h>
51
#include <genarch/fb/visuals.h>
52
#include <print.h>
52
#include <print.h>
53
 
53
 
54
#define PL050_KEY_RELEASE 0xF0
54
#define PL050_KEY_RELEASE 0xF0
55
#define PL050_ESC_KEY   0xE0
55
#define PL050_ESC_KEY   0xE0
-
 
56
#define PL050_CAPS_SCAN_CODE   0x58
56
 
57
 
57
static void pl050_suspend(chardev_t *);
58
static void pl050_suspend(chardev_t *);
58
static void pl050_resume(chardev_t *);
59
static void pl050_resume(chardev_t *);
59
 
60
 
60
static chardev_operations_t ops = {
61
static chardev_operations_t ops = {
61
    .suspend = pl050_suspend,
62
    .suspend = pl050_suspend,
62
    .resume = pl050_resume,
63
    .resume = pl050_resume,
63
    .read = pl050_key_read
64
    .read = pl050_key_read
64
};
65
};
65
 
66
 
66
/** Structure for pl050's IRQ. */
67
/** Structure for pl050's IRQ. */
67
static irq_t pl050_kbd_irq;
68
static irq_t pl050_kbd_irq;
68
/* static irq_t pl050_mouse_irq; */
69
/* static irq_t pl050_mouse_irq; */
69
static uintptr_t    pl050_kbd_pbase;
70
static uintptr_t    pl050_kbd_pbase;
70
static uintptr_t    pl050_kbd_vbase;
71
static uintptr_t    pl050_kbd_vbase;
71
 
72
 
72
uint8_t pl050_dataread(void)
73
uint8_t pl050_dataread(void)
73
{
74
{
74
    return *(uint8_t *)(pl050_kbd_vbase + PL050_DATA);
75
    return *(uint8_t *)(pl050_kbd_vbase + PL050_DATA);
75
}
76
}
76
 
77
 
77
uint8_t pl050_statusread(void)
78
uint8_t pl050_statusread(void)
78
{
79
{
79
    return *(uint8_t *)(pl050_kbd_vbase + PL050_STAT);
80
    return *(uint8_t *)(pl050_kbd_vbase + PL050_STAT);
80
}
81
}
81
 
82
 
82
void pl050_crwrite(uint8_t val)
83
void pl050_crwrite(uint8_t val)
83
{
84
{
84
    *(uint8_t *)pl050_kbd_vbase = val;
85
    *(uint8_t *)pl050_kbd_vbase = val;
85
}
86
}
86
   
87
   
87
   
88
   
88
void pl050_grab(void)
89
void pl050_grab(void)
89
{
90
{
90
    ipl_t ipl = interrupts_disable();
91
    ipl_t ipl = interrupts_disable();
91
   
92
   
92
    spinlock_lock(&pl050_kbd_irq.lock);
93
    spinlock_lock(&pl050_kbd_irq.lock);
93
    pl050_kbd_irq.notif_cfg.notify = false;
94
    pl050_kbd_irq.notif_cfg.notify = false;
94
    spinlock_unlock(&pl050_kbd_irq.lock);
95
    spinlock_unlock(&pl050_kbd_irq.lock);
95
   
96
   
96
    interrupts_restore(ipl);
97
    interrupts_restore(ipl);
97
}
98
}
98
 
99
 
99
void pl050_release(void)
100
void pl050_release(void)
100
{
101
{
101
    ipl_t ipl = interrupts_disable();
102
    ipl_t ipl = interrupts_disable();
102
   
103
   
103
    spinlock_lock(&pl050_kbd_irq.lock);
104
    spinlock_lock(&pl050_kbd_irq.lock);
104
    if (pl050_kbd_irq.notif_cfg.answerbox)
105
    if (pl050_kbd_irq.notif_cfg.answerbox)
105
        pl050_kbd_irq.notif_cfg.notify = true;
106
        pl050_kbd_irq.notif_cfg.notify = true;
106
    spinlock_unlock(&pl050_kbd_irq.lock);
107
    spinlock_unlock(&pl050_kbd_irq.lock);
107
   
108
   
108
    interrupts_restore(ipl);
109
    interrupts_restore(ipl);
109
}
110
}
110
 
111
 
111
static irq_ownership_t pl050_claim(void)
112
static irq_ownership_t pl050_claim(void)
112
{
113
{
113
    return IRQ_ACCEPT;
114
    return IRQ_ACCEPT;
114
}
115
}
115
 
116
 
116
static void pl050_irq_handler(irq_t *irq, void *arg, ...)
117
static void pl050_irq_handler(irq_t *irq, void *arg, ...)
117
{
118
{
118
    static int key_released_flag = 0;
119
    static int key_released_flag = 0;
119
    static int caps_count = 0;
120
    static int caps_locked = 0;
120
 
121
 
121
    if (irq->notif_cfg.notify && irq->notif_cfg.answerbox)
122
    if (irq->notif_cfg.notify && irq->notif_cfg.answerbox)
122
        ipc_irq_send_notif(irq);
123
        ipc_irq_send_notif(irq);
123
    else {
124
    else {
124
        uint8_t data;
125
        uint8_t data;
125
        uint8_t status;
126
        uint8_t status;
126
       
127
       
127
        if (((status = pl050_statusread()) & PL050_STAT_RXFULL)) {
128
        while (((status = pl050_statusread()) & PL050_STAT_RXFULL)) {
128
            data = pl050_dataread();
129
            data = pl050_dataread();
129
 
130
 
130
            if (data == PL050_ESC_KEY)
-
 
131
                return;
-
 
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
            }
-
 
143
           
-
 
144
            if (data == PL050_KEY_RELEASE) {
131
            if (data == PL050_KEY_RELEASE) {
145
                key_released_flag = 1;
132
                key_released_flag = 1;
146
            } else {
133
            } else {
147
                if (key_released_flag) {
134
                if (key_released_flag) {
-
 
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
                    }
148
                    key_released(data);
144
                    key_released(data);
-
 
145
                       
149
                } else {
146
                } else {
-
 
147
                    if (data == PL050_CAPS_SCAN_CODE && caps_locked)
-
 
148
                        return;
150
                    key_pressed(data);
149
                    key_pressed(data);
151
                }
150
                }
152
                key_released_flag = 0;
-
 
153
            }
151
            }
154
        }
152
        }
155
    }
153
    }
156
}
154
}
157
 
155
 
158
/** Initialize pl050. */
156
/** Initialize pl050. */
159
void pl050_init(devno_t kbd_devno, inr_t kbd_inr, uintptr_t pbase, uintptr_t vbase)
157
void pl050_init(devno_t kbd_devno, inr_t kbd_inr, uintptr_t pbase, uintptr_t vbase)
160
{
158
{
161
    uint8_t val = 0;
159
    uint8_t val = 0;
162
    chardev_initialize("pl050_kbd", &kbrd, &ops);
160
    chardev_initialize("pl050_kbd", &kbrd, &ops);
163
    stdin = &kbrd;
161
    stdin = &kbrd;
164
   
162
   
165
    irq_initialize(&pl050_kbd_irq);
163
    irq_initialize(&pl050_kbd_irq);
166
    pl050_kbd_irq.devno = kbd_devno;
164
    pl050_kbd_irq.devno = kbd_devno;
167
    pl050_kbd_irq.inr = kbd_inr;
165
    pl050_kbd_irq.inr = kbd_inr;
168
    pl050_kbd_irq.claim = pl050_claim;
166
    pl050_kbd_irq.claim = pl050_claim;
169
    pl050_kbd_irq.handler = pl050_irq_handler;
167
    pl050_kbd_irq.handler = pl050_irq_handler;
170
    pl050_kbd_pbase = pbase;
168
    pl050_kbd_pbase = pbase;
171
    pl050_kbd_vbase = vbase;
169
    pl050_kbd_vbase = vbase;
172
    irq_register(&pl050_kbd_irq);
170
    irq_register(&pl050_kbd_irq);
173
    val = PL050_CR_RXINTR | PL050_CR_INTR;
171
    val = PL050_CR_RXINTR | PL050_CR_INTR;
174
 
172
 
175
    pl050_crwrite(val);
173
    pl050_crwrite(val);
176
 
174
 
177
    /* reset the data buffer */
175
    /* reset the data buffer */
178
    pl050_dataread();
176
    pl050_dataread();
179
   
177
   
180
    sysinfo_set_item_val("kbd", NULL, true);
178
    sysinfo_set_item_val("kbd", NULL, true);
181
    sysinfo_set_item_val("kbd.devno", NULL, kbd_devno);
179
    sysinfo_set_item_val("kbd.devno", NULL, kbd_devno);
182
    sysinfo_set_item_val("kbd.inr", NULL, kbd_inr);
180
    sysinfo_set_item_val("kbd.inr", NULL, kbd_inr);
183
    sysinfo_set_item_val("kbd.pbase", NULL, pl050_kbd_pbase);
181
    sysinfo_set_item_val("kbd.pbase", NULL, pl050_kbd_pbase);
184
    sysinfo_set_item_val("kbd.vbase", NULL, vbase);
182
    sysinfo_set_item_val("kbd.vbase", NULL, vbase);
185
   
183
   
186
    pl050_grab();
184
    pl050_grab();
187
}
185
}
188
 
186
 
189
/* Called from getc(). */
187
/* Called from getc(). */
190
void pl050_resume(chardev_t *d)
188
void pl050_resume(chardev_t *d)
191
{
189
{
192
}
190
}
193
 
191
 
194
/* Called from getc(). */
192
/* Called from getc(). */
195
void pl050_suspend(chardev_t *d)
193
void pl050_suspend(chardev_t *d)
196
{
194
{
197
}
195
}
198
 
196
 
199
char pl050_key_read(chardev_t *d)
197
char pl050_key_read(chardev_t *d)
200
{
198
{
201
    char ch;   
199
    char ch;   
202
    printf("entering key_read\n");
200
    printf("entering key_read\n");
203
    while(!(ch = active_read_buff_read())) {
201
    while(!(ch = active_read_buff_read())) {
204
        uint8_t x;
202
        uint8_t x;
205
        while (!(pl050_statusread() & PL050_STAT_RXFULL))
203
        while (!(pl050_statusread() & PL050_STAT_RXFULL))
206
            ;
204
            ;
207
        x = pl050_dataread();
205
        x = pl050_dataread();
208
        if (x & KEY_RELEASE)
206
        if (x & KEY_RELEASE)
209
            key_released(x ^ KEY_RELEASE);
207
            key_released(x ^ KEY_RELEASE);
210
        else
208
        else
211
            active_read_key_pressed(x);
209
            active_read_key_pressed(x);
212
    }
210
    }
213
    return ch;
211
    return ch;
214
}
212
}
215
 
213
 
216
/** Poll for key press and release events.
214
/** Poll for key press and release events.
217
 *
215
 *
218
 * This function can be used to implement keyboard polling.
216
 * This function can be used to implement keyboard polling.
219
 */
217
 */
220
void pl050_poll(void)
218
void pl050_poll(void)
221
{
219
{
222
    uint8_t x;
220
    uint8_t x;
223
 
221
 
224
    printf("entering poll\n");
222
    printf("entering poll\n");
225
    while (((x = pl050_statusread() & PL050_STAT_RXFULL))) {
223
    while (((x = pl050_statusread() & PL050_STAT_RXFULL))) {
226
        x = pl050_dataread();
224
        x = pl050_dataread();
227
        if (x & KEY_RELEASE)
225
        if (x & KEY_RELEASE)
228
            key_released(x ^ KEY_RELEASE);
226
            key_released(x ^ KEY_RELEASE);
229
        else
227
        else
230
            key_pressed(x);
228
            key_pressed(x);
231
    }
229
    }
232
}
230
}
233
 
231
 
234
/** @}
232
/** @}
235
 */
233
 */
236
 
234