Subversion Repositories HelenOS

Rev

Rev 4343 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4343 Rev 4344
Line 1... Line 1...
1
/*
1
/*
2
 * Copyright (c) 2001-2004 Jakub Jermar
2
 * Copyright (c) 2009 Jakub Jermar
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:
Line 39... Line 39...
39
#include <genarch/kbd/i8042.h>
39
#include <genarch/kbd/i8042.h>
40
#include <arch/drivers/kbd.h>
40
#include <arch/drivers/kbd.h>
41
#include <genarch/kbd/key.h>
41
#include <genarch/kbd/key.h>
42
#include <genarch/kbd/scanc.h>
42
#include <genarch/kbd/scanc.h>
43
#include <genarch/kbd/scanc_pc.h>
43
#include <genarch/kbd/scanc_pc.h>
44
#include <arch/drivers/i8042.h>
44
#include <genarch/drivers/legacy/ia32/io.h>
45
#include <cpu.h>
45
#include <cpu.h>
46
#include <arch/asm.h>
46
#include <arch/asm.h>
47
#include <arch.h>
47
#include <arch.h>
48
#include <console/chardev.h>
48
#include <console/chardev.h>
49
#include <console/console.h>
49
#include <console/console.h>
50
#include <interrupt.h>
50
#include <interrupt.h>
51
#include <sysinfo/sysinfo.h>
-
 
52
#include <ipc/irq.h>
-
 
53
 
51
 
54
/* Keyboard commands. */
52
/* Keyboard commands. */
55
#define KBD_ENABLE  0xf4
53
#define KBD_ENABLE  0xf4
56
#define KBD_DISABLE 0xf5
54
#define KBD_DISABLE 0xf5
57
#define KBD_ACK     0xfa
55
#define KBD_ACK     0xfa
Line 73... Line 71...
73
 
71
 
74
#define i8042_SET_COMMAND   0x60
72
#define i8042_SET_COMMAND   0x60
75
#define i8042_COMMAND       0x69
73
#define i8042_COMMAND       0x69
76
 
74
 
77
#define i8042_BUFFER_FULL_MASK  0x01
75
#define i8042_BUFFER_FULL_MASK  0x01
78
#define i8042_WAIT_MASK         0x02
76
#define i8042_WAIT_MASK     0x02
79
#define i8042_MOUSE_DATA        0x20
77
#define i8042_MOUSE_DATA    0x20
80
 
78
 
81
static void i8042_suspend(chardev_t *);
79
static void i8042_suspend(chardev_t *);
82
static void i8042_resume(chardev_t *);
80
static void i8042_resume(chardev_t *);
83
 
81
 
84
static chardev_operations_t ops = {
82
static chardev_operations_t ops = {
85
    .suspend = i8042_suspend,
83
    .suspend = i8042_suspend,
86
    .resume = i8042_resume,
84
    .resume = i8042_resume,
87
    .read = i8042_key_read
-
 
88
};
85
};
89
 
86
 
90
/** Structure for i8042's IRQ. */
-
 
91
static irq_t i8042_kbd_irq;
-
 
92
static irq_t i8042_mouse_irq;
87
static irq_ownership_t i8042_claim(irq_t *irq)
93
 
-
 
94
void i8042_grab(void)
-
 
95
{
88
{
96
    ipl_t ipl = interrupts_disable();
-
 
97
   
-
 
98
    spinlock_lock(&i8042_kbd_irq.lock);
-
 
99
    i8042_kbd_irq.notif_cfg.notify = false;
89
    i8042_instance_t *i8042_instance = irq->instance;
100
    spinlock_unlock(&i8042_kbd_irq.lock);
-
 
101
   
-
 
102
    spinlock_lock(&i8042_mouse_irq.lock);
-
 
103
    i8042_mouse_irq.notif_cfg.notify = false;
90
    i8042_t *dev = i8042_instance->i8042;
104
    spinlock_unlock(&i8042_mouse_irq.lock);
91
    if (pio_read_8(&dev->status) & i8042_BUFFER_FULL_MASK)
105
   
-
 
106
    interrupts_restore(ipl);
92
        return IRQ_ACCEPT;
107
}
-
 
108
 
-
 
109
void i8042_release(void)
-
 
110
{
-
 
111
    ipl_t ipl = interrupts_disable();
-
 
112
   
-
 
113
    spinlock_lock(&i8042_kbd_irq.lock);
-
 
114
    if (i8042_kbd_irq.notif_cfg.answerbox)
-
 
115
        i8042_kbd_irq.notif_cfg.notify = true;
-
 
116
    spinlock_unlock(&i8042_kbd_irq.lock);
-
 
117
   
-
 
118
    spinlock_lock(&i8042_mouse_irq.lock);
-
 
119
    if (i8042_mouse_irq.notif_cfg.answerbox)
-
 
120
        i8042_mouse_irq.notif_cfg.notify = true;
-
 
121
    spinlock_unlock(&i8042_mouse_irq.lock);
-
 
122
   
93
    else
123
    interrupts_restore(ipl);
-
 
124
}
-
 
125
 
-
 
126
static irq_ownership_t i8042_claim(void *instance)
-
 
127
{
-
 
128
    return IRQ_ACCEPT;
94
        return IRQ_DECLINE;
129
}
95
}
130
 
96
 
131
static void i8042_irq_handler(irq_t *irq)
97
static void i8042_irq_handler(irq_t *irq)
132
{
98
{
133
    if (irq->notif_cfg.notify && irq->notif_cfg.answerbox)
99
    i8042_instance_t *instance = irq->instance;
134
        ipc_irq_send_notif(irq);
100
    i8042_t *dev = instance->i8042;
135
    else {
101
 
136
        uint8_t data;
102
    uint8_t data;
137
        uint8_t status;
103
    uint8_t status;
138
       
104
       
139
        while (((status = i8042_status_read()) & i8042_BUFFER_FULL_MASK)) {
105
    if (((status = pio_read_8(&dev->status)) & i8042_BUFFER_FULL_MASK)) {
140
            data = i8042_data_read();
106
        data = pio_read_8(&dev->data);
141
           
107
           
142
            if ((status & i8042_MOUSE_DATA))
108
        if ((status & i8042_MOUSE_DATA))
143
                continue;
109
            return;
144
 
110
 
145
            if (data & KEY_RELEASE)
111
        if (data & KEY_RELEASE)
146
                key_released(data ^ KEY_RELEASE);
112
            key_released(data ^ KEY_RELEASE);
147
            else
113
        else
148
                key_pressed(data);
114
            key_pressed(data);
149
        }
-
 
150
    }
115
    }
151
}
116
}
152
 
117
 
153
/** Initialize i8042. */
118
/** Initialize i8042. */
-
 
119
bool
154
void i8042_init(devno_t kbd_devno, inr_t kbd_inr, devno_t mouse_devno, inr_t mouse_inr)
120
i8042_init(i8042_t *dev, devno_t devno, inr_t inr)
155
{
121
{
-
 
122
    i8042_instance_t *instance;
-
 
123
 
156
    chardev_initialize("i8042_kbd", &kbrd, &ops);
124
    chardev_initialize("i8042_kbd", &kbrd, &ops);
157
    stdin = &kbrd;
125
    stdin = &kbrd;
158
   
126
   
159
    irq_initialize(&i8042_kbd_irq);
127
    instance = malloc(sizeof(i8042_instance_t), FRAME_ATOMIC);
160
    i8042_kbd_irq.devno = kbd_devno;
128
    if (!instance)
161
    i8042_kbd_irq.inr = kbd_inr;
129
        return false;
-
 
130
   
162
    i8042_kbd_irq.claim = i8042_claim;
131
    instance->devno = devno;
163
    i8042_kbd_irq.handler = i8042_irq_handler;
-
 
164
    irq_register(&i8042_kbd_irq);
132
    instance->i8042 = dev;
165
   
133
   
166
    irq_initialize(&i8042_mouse_irq);
134
    irq_initialize(&instance->irq);
167
    i8042_mouse_irq.devno = mouse_devno;
135
    instance->irq.devno = devno;
168
    i8042_mouse_irq.inr = mouse_inr;
136
    instance->irq.inr = inr;
169
    i8042_mouse_irq.claim = i8042_claim;
137
    instance->irq.claim = i8042_claim;
170
    i8042_mouse_irq.handler = i8042_irq_handler;
138
    instance->irq.handler = i8042_irq_handler;
-
 
139
    instance->irq.instance = instance;
171
    irq_register(&i8042_mouse_irq);
140
    irq_register(&instance->irq);
172
   
141
   
173
    trap_virtual_enable_irqs(1 << kbd_inr);
142
    trap_virtual_enable_irqs(1 << inr);
174
    trap_virtual_enable_irqs(1 << mouse_inr);
-
 
175
   
143
   
176
    /*
144
    /*
177
     * Clear input buffer.
145
     * Clear input buffer.
178
     * Number of iterations is limited to prevent infinite looping.
-
 
179
     */
146
     */
180
    int i;
-
 
181
    for (i = 0; (i8042_status_read() & i8042_BUFFER_FULL_MASK) && i < 100; i++) {
147
    while (pio_read_8(&dev->status) & i8042_BUFFER_FULL_MASK)
182
        i8042_data_read();
148
        (void) pio_read_8(&dev->data);
183
    }
-
 
184
   
-
 
185
    sysinfo_set_item_val("kbd", NULL, true);
-
 
186
    sysinfo_set_item_val("kbd.devno", NULL, kbd_devno);
-
 
187
    sysinfo_set_item_val("kbd.inr", NULL, kbd_inr);
-
 
188
#ifdef KBD_LEGACY
-
 
189
    sysinfo_set_item_val("kbd.type", NULL, KBD_LEGACY);
-
 
190
#endif
-
 
191
    sysinfo_set_item_val("mouse", NULL, true);
-
 
192
    sysinfo_set_item_val("mouse.devno", NULL, mouse_devno);
-
 
193
    sysinfo_set_item_val("mouse.inr", NULL, mouse_inr);
-
 
194
   
149
   
195
    i8042_grab();
150
    return true;
196
}
151
}
197
 
152
 
198
/* Called from getc(). */
153
/* Called from getc(). */
199
void i8042_resume(chardev_t *d)
154
void i8042_resume(chardev_t *d)
200
{
155
{
Line 203... Line 158...
203
/* Called from getc(). */
158
/* Called from getc(). */
204
void i8042_suspend(chardev_t *d)
159
void i8042_suspend(chardev_t *d)
205
{
160
{
206
}
161
}
207
 
162
 
208
char i8042_key_read(chardev_t *d)
-
 
209
{
-
 
210
    char ch;
-
 
211
   
-
 
212
    while (!(ch = active_read_buff_read())) {
-
 
213
        uint8_t x;
-
 
214
       
-
 
215
        while (!(i8042_status_read() & i8042_BUFFER_FULL_MASK));
-
 
216
       
-
 
217
        x = i8042_data_read();
-
 
218
        if (x & KEY_RELEASE)
-
 
219
            key_released(x ^ KEY_RELEASE);
-
 
220
        else
-
 
221
            active_read_key_pressed(x);
-
 
222
    }
-
 
223
    return ch;
-
 
224
}
-
 
225
 
-
 
226
/** Poll for key press and release events.
-
 
227
 *
-
 
228
 * This function can be used to implement keyboard polling.
-
 
229
 */
-
 
230
void i8042_poll(void)
-
 
231
{
-
 
232
    uint8_t x;
-
 
233
   
-
 
234
    while (((x = i8042_status_read() & i8042_BUFFER_FULL_MASK))) {
-
 
235
        x = i8042_data_read();
-
 
236
        if (x & KEY_RELEASE)
-
 
237
            key_released(x ^ KEY_RELEASE);
-
 
238
        else
-
 
239
            key_pressed(x);
-
 
240
    }
-
 
241
}
-
 
242
 
-
 
243
/** @}
163
/** @}
244
 */
164
 */