Subversion Repositories HelenOS

Rev

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

Rev 1841 Rev 1842
Line 29... Line 29...
29
/** @addtogroup genarch
29
/** @addtogroup genarch
30
 * @{
30
 * @{
31
 */
31
 */
32
/**
32
/**
33
 * @file
33
 * @file
34
 * @brief   i8042 processor driver.
34
 * @brief   Zilog 8530 serial port / keyboard driver.
35
 *
35
 *
-
 
36
 * Note that this file is derived from the i8042.c.
36
 * It takes care of low-level keyboard functions.
37
 * The i8042 driver could be persuaded to control
-
 
38
 * the z8530 at least in the polling mode.
-
 
39
 * As a result, this file may contain inaccurate
-
 
40
 * and z8530-irrelevant constants, code and comments.
-
 
41
 * Still it miraculously works.
37
 */
42
 */
38
 
43
 
39
#include <genarch/i8042/i8042.h>
44
#include <genarch/kbd/z8530.h>
-
 
45
#include <genarch/kbd/scanc.h>
-
 
46
#include <genarch/kbd/scanc_sun.h>
40
#include <arch/drivers/i8042.h>
47
#include <arch/drivers/z8530.h>
41
#include <arch/interrupt.h>
48
#include <arch/interrupt.h>
42
#include <cpu.h>
49
#include <cpu.h>
43
#include <arch/asm.h>
50
#include <arch/asm.h>
44
#include <arch.h>
51
#include <arch.h>
45
#include <synch/spinlock.h>
52
#include <synch/spinlock.h>
Line 67... Line 74...
67
 *     | | `--------- disable auxiliary device, drives clock line low
74
 *     | | `--------- disable auxiliary device, drives clock line low
68
 *     | `---------- IBM scancode translation 0=AT, 1=PC/XT
75
 *     | `---------- IBM scancode translation 0=AT, 1=PC/XT
69
 *     `----------- reserved, should be 0
76
 *     `----------- reserved, should be 0
70
 */
77
 */
71
 
78
 
72
#define i8042_SET_COMMAND   0x60
79
#define z8530_SET_COMMAND   0x60
73
#define i8042_COMMAND       0x69
80
#define z8530_COMMAND       0x69
74
 
81
 
75
#define i8042_BUFFER_FULL_MASK  0x01
82
#define z8530_BUFFER_FULL_MASK  0x01
76
#define i8042_WAIT_MASK     0x02
83
#define z8530_WAIT_MASK     0x02
77
#define i8042_MOUSE_DATA        0x20
84
#define z8530_MOUSE_DATA        0x20
78
 
85
 
79
#define KEY_RELEASE 0x80
86
#define KEY_RELEASE 0x80
80
 
87
 
81
/**
88
/*
82
 * These codes read from i8042 data register are silently ignored.
89
 * These codes read from z8530 data register are silently ignored.
83
 */
90
 */
84
#define IGNORE_CODE 0x7f
91
#define IGNORE_CODE 0x7f        /* all keys up */
85
 
92
 
86
static void key_released(uint8_t sc);
93
static void key_released(uint8_t sc);
87
static void key_pressed(uint8_t sc);
94
static void key_pressed(uint8_t sc);
88
static char key_read(chardev_t *d);
95
static char key_read(chardev_t *d);
89
 
96
 
Line 97... Line 104...
97
 
104
 
98
SPINLOCK_INITIALIZE(keylock);       /**< keylock protects keyflags and lockflags. */
105
SPINLOCK_INITIALIZE(keylock);       /**< keylock protects keyflags and lockflags. */
99
static volatile int keyflags;       /**< Tracking of multiple keypresses. */
106
static volatile int keyflags;       /**< Tracking of multiple keypresses. */
100
static volatile int lockflags;      /**< Tracking of multiple keys lockings. */
107
static volatile int lockflags;      /**< Tracking of multiple keys lockings. */
101
 
108
 
102
static void i8042_suspend(chardev_t *);
109
static void z8530_suspend(chardev_t *);
103
static void i8042_resume(chardev_t *);
110
static void z8530_resume(chardev_t *);
104
 
111
 
105
static chardev_t kbrd;
112
static chardev_t kbrd;
106
static chardev_operations_t ops = {
113
static chardev_operations_t ops = {
107
    .suspend = i8042_suspend,
114
    .suspend = z8530_suspend,
108
    .resume = i8042_resume,
115
    .resume = z8530_resume,
109
    .read = key_read
116
    .read = key_read
110
};
117
};
111
 
118
 
112
static void i8042_interrupt(int n, istate_t *istate);
119
static void z8530_interrupt(int n, istate_t *istate);
113
static void i8042_wait(void);
120
static void z8530_wait(void);
114
 
121
 
115
static iroutine oldvector;
122
static iroutine oldvector;
116
/** Initialize keyboard and service interrupts using kernel routine */
123
/** Initialize keyboard and service interrupts using kernel routine */
117
void i8042_grab(void)
124
void z8530_grab(void)
118
{
125
{
119
    oldvector = exc_register(VECTOR_KBD, "i8042_interrupt", (iroutine) i8042_interrupt);
126
    oldvector = exc_register(VECTOR_KBD, "z8530_interrupt", (iroutine) z8530_interrupt);
120
    i8042_wait();
127
    z8530_wait();
121
    i8042_command_write(i8042_SET_COMMAND);
128
    z8530_command_write(z8530_SET_COMMAND);
122
    i8042_wait();
129
    z8530_wait();
123
    i8042_data_write(i8042_COMMAND);
130
    z8530_data_write(z8530_COMMAND);
124
    i8042_wait();
131
    z8530_wait();
125
}
132
}
126
/** Resume the former interrupt vector */
133
/** Resume the former interrupt vector */
127
void i8042_release(void)
134
void z8530_release(void)
128
{
135
{
129
    if (oldvector)
136
    if (oldvector)
130
        exc_register(VECTOR_KBD, "user_interrupt", oldvector);
137
        exc_register(VECTOR_KBD, "user_interrupt", oldvector);
131
}
138
}
132
 
139
 
133
/** Initialize i8042. */
140
/** Initialize z8530. */
134
void i8042_init(void)
141
void z8530_init(void)
135
{
142
{
136
    int i;
143
    int i;
137
 
144
 
138
    i8042_grab();
145
    z8530_grab();
139
        /* Prevent user from accidentaly releasing calling i8042_resume
146
        /* Prevent user from accidentaly releasing calling z8530_resume
140
     * and disabling keyboard
147
     * and disabling keyboard
141
     */
148
     */
142
    oldvector = NULL;
149
    oldvector = NULL;
143
 
150
 
144
    trap_virtual_enable_irqs(1<<IRQ_KBD);
151
    trap_virtual_enable_irqs(1<<IRQ_KBD);
145
    chardev_initialize("i8042_kbd", &kbrd, &ops);
152
    chardev_initialize("z8530_kbd", &kbrd, &ops);
146
    stdin = &kbrd;
153
    stdin = &kbrd;
147
 
154
 
148
    /*
155
    /*
149
     * Clear input buffer.
156
     * Clear input buffer.
150
     * Number of iterations is limited to prevent infinite looping.
157
     * Number of iterations is limited to prevent infinite looping.
151
     */
158
     */
152
    for (i = 0; (i8042_status_read() & i8042_BUFFER_FULL_MASK) && i < 100; i++) {
159
    for (i = 0; (z8530_status_read() & z8530_BUFFER_FULL_MASK) && i < 100; i++) {
153
        i8042_data_read();
160
        z8530_data_read();
154
    }  
161
    }  
155
}
162
}
156
 
163
 
157
/** Process i8042 interrupt.
164
/** Process z8530 interrupt.
158
 *
165
 *
159
 * @param n Interrupt vector.
166
 * @param n Interrupt vector.
160
 * @param istate Interrupted state.
167
 * @param istate Interrupted state.
161
 */
168
 */
162
void i8042_interrupt(int n, istate_t *istate)
169
void z8530_interrupt(int n, istate_t *istate)
163
{
170
{
164
    uint8_t x;
171
    uint8_t x;
165
    uint8_t status;
172
    uint8_t status;
166
 
173
 
167
    while (((status=i8042_status_read()) & i8042_BUFFER_FULL_MASK)) {
174
    while (((status=z8530_status_read()) & z8530_BUFFER_FULL_MASK)) {
168
        x = i8042_data_read();
175
        x = z8530_data_read();
169
 
176
 
170
        if ((status & i8042_MOUSE_DATA))
177
        if ((status & z8530_MOUSE_DATA))
171
            continue;
178
            continue;
172
 
179
 
173
        if (x & KEY_RELEASE)
180
        if (x & KEY_RELEASE)
174
            key_released(x ^ KEY_RELEASE);
181
            key_released(x ^ KEY_RELEASE);
175
        else
182
        else
Line 177... Line 184...
177
    }
184
    }
178
    trap_virtual_eoi();
185
    trap_virtual_eoi();
179
}
186
}
180
 
187
 
181
/** Wait until the controller reads its data. */
188
/** Wait until the controller reads its data. */
182
void i8042_wait(void) {
189
void z8530_wait(void) {
183
    while (i8042_status_read() & i8042_WAIT_MASK) {
190
    while (z8530_status_read() & z8530_WAIT_MASK) {
184
        /* wait */
191
        /* wait */
185
    }
192
    }
186
}
193
}
187
 
194
 
188
/** Process release of key.
195
/** Process release of key.
Line 281... Line 288...
281
    }
288
    }
282
    spinlock_unlock(&keylock);
289
    spinlock_unlock(&keylock);
283
}
290
}
284
 
291
 
285
/* Called from getc(). */
292
/* Called from getc(). */
286
void i8042_resume(chardev_t *d)
293
void z8530_resume(chardev_t *d)
287
{
294
{
288
}
295
}
289
 
296
 
290
/* Called from getc(). */
297
/* Called from getc(). */
291
void i8042_suspend(chardev_t *d)
298
void z8530_suspend(chardev_t *d)
292
{
299
{
293
}
300
}
294
 
301
 
295
static uint8_t active_read_buff_read(void)
302
static uint8_t active_read_buff_read(void)
296
{
303
{
Line 385... Line 392...
385
{
392
{
386
    char ch;   
393
    char ch;   
387
 
394
 
388
    while(!(ch = active_read_buff_read())) {
395
    while(!(ch = active_read_buff_read())) {
389
        uint8_t x;
396
        uint8_t x;
390
        while (!(i8042_status_read() & i8042_BUFFER_FULL_MASK))
397
        while (!(z8530_status_read() & z8530_BUFFER_FULL_MASK))
391
            ;
398
            ;
392
        x = i8042_data_read();
399
        x = z8530_data_read();
393
        if (x != IGNORE_CODE) {
400
        if (x != IGNORE_CODE) {
394
            if (x & KEY_RELEASE)
401
            if (x & KEY_RELEASE)
395
                key_released(x ^ KEY_RELEASE);
402
                key_released(x ^ KEY_RELEASE);
396
            else
403
            else
397
                active_read_key_pressed(x);
404
                active_read_key_pressed(x);
Line 402... Line 409...
402
 
409
 
403
/** Poll for key press and release events.
410
/** Poll for key press and release events.
404
 *
411
 *
405
 * This function can be used to implement keyboard polling.
412
 * This function can be used to implement keyboard polling.
406
 */
413
 */
407
void i8042_poll(void)
414
void z8530_poll(void)
408
{
415
{
409
    uint8_t x;
416
    uint8_t x;
410
 
417
 
411
    while (((x = i8042_status_read() & i8042_BUFFER_FULL_MASK))) {
418
    while (((x = z8530_status_read() & z8530_BUFFER_FULL_MASK))) {
412
        x = i8042_data_read();
419
        x = z8530_data_read();
413
        if (x != IGNORE_CODE) {
420
        if (x != IGNORE_CODE) {
414
            if (x & KEY_RELEASE)
421
            if (x & KEY_RELEASE)
415
                key_released(x ^ KEY_RELEASE);
422
                key_released(x ^ KEY_RELEASE);
416
            else
423
            else
417
                key_pressed(x);
424
                key_pressed(x);
Line 419... Line 426...
419
    }
426
    }
420
}
427
}
421
 
428
 
422
/** @}
429
/** @}
423
 */
430
 */
424
 
-