Subversion Repositories HelenOS

Rev

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

Rev 1896 Rev 1956
Line 39... Line 39...
39
#include <genarch/kbd/i8042.h>
39
#include <genarch/kbd/i8042.h>
40
#include <genarch/kbd/key.h>
40
#include <genarch/kbd/key.h>
41
#include <genarch/kbd/scanc.h>
41
#include <genarch/kbd/scanc.h>
42
#include <genarch/kbd/scanc_pc.h>
42
#include <genarch/kbd/scanc_pc.h>
43
#include <arch/drivers/i8042.h>
43
#include <arch/drivers/i8042.h>
44
#include <arch/interrupt.h>
-
 
45
#include <cpu.h>
44
#include <cpu.h>
46
#include <arch/asm.h>
45
#include <arch/asm.h>
47
#include <arch.h>
46
#include <arch.h>
48
#include <typedefs.h>
47
#include <typedefs.h>
49
#include <console/chardev.h>
48
#include <console/chardev.h>
50
#include <console/console.h>
49
#include <console/console.h>
51
#include <interrupt.h>
50
#include <interrupt.h>
-
 
51
#include <sysinfo/sysinfo.h>
-
 
52
#include <ddi/irq.h>
52
 
53
 
53
/* Keyboard commands. */
54
/* Keyboard commands. */
54
#define KBD_ENABLE  0xf4
55
#define KBD_ENABLE  0xf4
55
#define KBD_DISABLE 0xf5
56
#define KBD_DISABLE 0xf5
56
#define KBD_ACK     0xfa
57
#define KBD_ACK     0xfa
Line 84... Line 85...
84
    .suspend = i8042_suspend,
85
    .suspend = i8042_suspend,
85
    .resume = i8042_resume,
86
    .resume = i8042_resume,
86
    .read = i8042_key_read
87
    .read = i8042_key_read
87
};
88
};
88
 
89
 
-
 
90
/** Structure for i8042's IRQ. */
-
 
91
static irq_t i8042_irq;
-
 
92
 
89
static void i8042_interrupt(int n, istate_t *istate);
93
/** Wait until the controller reads its data. */
90
static void i8042_wait(void);
94
static void i8042_wait(void) {
-
 
95
    while (i8042_status_read() & i8042_WAIT_MASK) {
-
 
96
        /* wait */
-
 
97
    }
-
 
98
}
91
 
99
 
92
static iroutine oldvector;
-
 
93
/** Initialize keyboard and service interrupts using kernel routine */
-
 
94
void i8042_grab(void)
100
void i8042_grab(void)
95
{
101
{
96
    oldvector = exc_register(VECTOR_KBD, "i8042_interrupt", (iroutine) i8042_interrupt);
102
    ipl_t ipl = interrupts_disable();
-
 
103
   
97
    i8042_wait();
104
    i8042_wait();
98
    i8042_command_write(i8042_SET_COMMAND);
105
    i8042_command_write(i8042_SET_COMMAND);
99
    i8042_wait();
106
    i8042_wait();
100
    i8042_data_write(i8042_COMMAND);
107
    i8042_data_write(i8042_COMMAND);
101
    i8042_wait();
108
    i8042_wait();
-
 
109
 
-
 
110
    spinlock_lock(&i8042_irq.lock);
-
 
111
    i8042_irq.notif_cfg.notify = false;
-
 
112
    spinlock_unlock(&i8042_irq.lock);
-
 
113
    interrupts_restore(ipl);
102
}
114
}
103
/** Resume the former interrupt vector */
-
 
-
 
115
 
104
void i8042_release(void)
116
void i8042_release(void)
105
{
117
{
-
 
118
    ipl_t ipl = interrupts_disable();
-
 
119
    spinlock_lock(&i8042_irq.lock);
106
    if (oldvector)
120
    if (i8042_irq.notif_cfg.answerbox)
107
        exc_register(VECTOR_KBD, "user_interrupt", oldvector);
121
        i8042_irq.notif_cfg.notify = true;
-
 
122
    spinlock_unlock(&i8042_irq.lock);
-
 
123
    interrupts_restore(ipl);
108
}
124
}
109
 
125
 
110
/** Initialize i8042. */
-
 
111
void i8042_init(void)
126
static irq_ownership_t i8042_claim(void)
112
{
127
{
113
    int i;
128
    return IRQ_ACCEPT;
-
 
129
}
114
 
130
 
-
 
131
static void i8042_irq_handler(irq_t *irq, void *arg, ...)
-
 
132
{
-
 
133
    if (irq->notif_cfg.notify && irq->notif_cfg.answerbox)
-
 
134
        ipc_irq_send_notif(irq);
-
 
135
    else {
-
 
136
        uint8_t x;
115
    i8042_grab();
137
        uint8_t status;
-
 
138
       
116
        /* Prevent user from accidentaly releasing calling i8042_resume
139
        while (((status = i8042_status_read()) & i8042_BUFFER_FULL_MASK)) {
117
     * and disabling keyboard
140
            x = i8042_data_read();
-
 
141
           
-
 
142
            if ((status & i8042_MOUSE_DATA))
-
 
143
                continue;
118
     */
144
           
-
 
145
            if (x & KEY_RELEASE)
-
 
146
                key_released(x ^ KEY_RELEASE);
-
 
147
            else
119
    oldvector = NULL;
148
                key_pressed(x);
-
 
149
        }
-
 
150
    }
-
 
151
}
120
 
152
 
-
 
153
/** Initialize i8042. */
121
    trap_virtual_enable_irqs(1<<IRQ_KBD);
154
void i8042_init(devno_t devno, inr_t inr)
-
 
155
{
122
    chardev_initialize("i8042_kbd", &kbrd, &ops);
156
    chardev_initialize("i8042_kbd", &kbrd, &ops);
123
    stdin = &kbrd;
157
    stdin = &kbrd;
124
 
158
   
-
 
159
    irq_initialize(&i8042_irq);
-
 
160
    i8042_irq.devno = devno;
-
 
161
    i8042_irq.inr = inr;
-
 
162
    i8042_irq.claim = i8042_claim;
-
 
163
    i8042_irq.handler = i8042_irq_handler;
-
 
164
    irq_register(&i8042_irq);
-
 
165
   
-
 
166
    trap_virtual_enable_irqs(1 << inr);
-
 
167
   
125
    /*
168
    /*
126
     * Clear input buffer.
169
     * Clear input buffer.
127
     * Number of iterations is limited to prevent infinite looping.
170
     * Number of iterations is limited to prevent infinite looping.
128
     */
171
     */
-
 
172
    int i;
129
    for (i = 0; (i8042_status_read() & i8042_BUFFER_FULL_MASK) && i < 100; i++) {
173
    for (i = 0; (i8042_status_read() & i8042_BUFFER_FULL_MASK) && i < 100; i++) {
130
        i8042_data_read();
174
        i8042_data_read();
131
    }  
-
 
132
}
-
 
133
 
-
 
134
/** Process i8042 interrupt.
-
 
135
 *
-
 
136
 * @param n Interrupt vector.
-
 
137
 * @param istate Interrupted state.
-
 
138
 */
-
 
139
void i8042_interrupt(int n, istate_t *istate)
-
 
140
{
-
 
141
    uint8_t x;
-
 
142
    uint8_t status;
-
 
143
 
-
 
144
    while (((status=i8042_status_read()) & i8042_BUFFER_FULL_MASK)) {
-
 
145
        x = i8042_data_read();
-
 
146
 
-
 
147
        if ((status & i8042_MOUSE_DATA))
-
 
148
            continue;
-
 
149
 
-
 
150
        if (x & KEY_RELEASE)
-
 
151
            key_released(x ^ KEY_RELEASE);
-
 
152
        else
-
 
153
            key_pressed(x);
-
 
154
    }
-
 
155
    trap_virtual_eoi();
-
 
156
}
-
 
157
 
-
 
158
/** Wait until the controller reads its data. */
-
 
159
void i8042_wait(void) {
-
 
160
    while (i8042_status_read() & i8042_WAIT_MASK) {
-
 
161
        /* wait */
-
 
162
    }
175
    }
-
 
176
   
-
 
177
    sysinfo_set_item_val("kbd", NULL, true);
-
 
178
    sysinfo_set_item_val("kbd.devno", NULL, devno);
-
 
179
    sysinfo_set_item_val("kbd.inr", NULL, inr);
-
 
180
   
-
 
181
    i8042_grab();
163
}
182
}
164
 
183
 
165
/* Called from getc(). */
184
/* Called from getc(). */
166
void i8042_resume(chardev_t *d)
185
void i8042_resume(chardev_t *d)
167
{
186
{