Subversion Repositories HelenOS

Rev

Rev 1896 | Go to most recent revision | Show entire file | Regard 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;
-
 
114
 
-
 
115
    i8042_grab();
-
 
116
        /* Prevent user from accidentaly releasing calling i8042_resume
-
 
117
     * and disabling keyboard
-
 
118
     */
-
 
119
    oldvector = NULL;
-
 
120
 
-
 
121
    trap_virtual_enable_irqs(1<<IRQ_KBD);
-
 
122
    chardev_initialize("i8042_kbd", &kbrd, &ops);
-
 
123
    stdin = &kbrd;
128
    return IRQ_ACCEPT;
124
 
-
 
125
    /*
-
 
126
     * Clear input buffer.
-
 
127
     * Number of iterations is limited to prevent infinite looping.
-
 
128
     */
-
 
129
    for (i = 0; (i8042_status_read() & i8042_BUFFER_FULL_MASK) && i < 100; i++) {
-
 
130
        i8042_data_read();
-
 
131
    }  
-
 
132
}
129
}
133
 
130
 
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)
131
static void i8042_irq_handler(irq_t *irq, void *arg, ...)
140
{
132
{
-
 
133
    if (irq->notif_cfg.notify && irq->notif_cfg.answerbox)
-
 
134
        ipc_irq_send_notif(irq);
-
 
135
    else {
141
    uint8_t x;
136
        uint8_t x;
142
    uint8_t status;
137
        uint8_t status;
143
 
138
       
144
    while (((status=i8042_status_read()) & i8042_BUFFER_FULL_MASK)) {
139
        while (((status = i8042_status_read()) & i8042_BUFFER_FULL_MASK)) {
145
        x = i8042_data_read();
140
            x = i8042_data_read();
Line 150... Line 145...
150
        if (x & KEY_RELEASE)
145
            if (x & KEY_RELEASE)
151
            key_released(x ^ KEY_RELEASE);
146
                key_released(x ^ KEY_RELEASE);
152
        else
147
            else
153
            key_pressed(x);
148
                key_pressed(x);
154
    }
149
        }
155
    trap_virtual_eoi();
150
    }
156
}
151
}
157
 
152
 
158
/** Wait until the controller reads its data. */
153
/** Initialize i8042. */
159
void i8042_wait(void) {
154
void i8042_init(devno_t devno, inr_t inr)
-
 
155
{
-
 
156
    chardev_initialize("i8042_kbd", &kbrd, &ops);
-
 
157
    stdin = &kbrd;
-
 
158
   
-
 
159
    irq_initialize(&i8042_irq);
-
 
160
    i8042_irq.devno = devno;
-
 
161
    i8042_irq.inr = inr;
-
 
162
    i8042_irq.claim = i8042_claim;
160
    while (i8042_status_read() & i8042_WAIT_MASK) {
163
    i8042_irq.handler = i8042_irq_handler;
-
 
164
    irq_register(&i8042_irq);
-
 
165
   
-
 
166
    trap_virtual_enable_irqs(1 << inr);
-
 
167
   
-
 
168
    /*
-
 
169
     * Clear input buffer.
-
 
170
     * Number of iterations is limited to prevent infinite looping.
-
 
171
     */
161
        /* wait */
172
    int i;
-
 
173
    for (i = 0; (i8042_status_read() & i8042_BUFFER_FULL_MASK) && i < 100; i++) {
-
 
174
        i8042_data_read();
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
{