Subversion Repositories HelenOS

Rev

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

Rev 1843 Rev 1848
Line 30... Line 30...
30
 * @{
30
 * @{
31
 */
31
 */
32
/**
32
/**
33
 * @file
33
 * @file
34
 * @brief   Zilog 8530 serial port / keyboard driver.
34
 * @brief   Zilog 8530 serial port / keyboard driver.
35
 *
-
 
36
 * Note that this file is derived from the i8042.c.
-
 
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.
-
 
42
 */
35
 */
43
 
36
 
44
#include <genarch/kbd/z8530.h>
37
#include <genarch/kbd/z8530.h>
45
#include <genarch/kbd/key.h>
38
#include <genarch/kbd/key.h>
46
#include <genarch/kbd/scanc.h>
39
#include <genarch/kbd/scanc.h>
47
#include <genarch/kbd/scanc_sun.h>
40
#include <genarch/kbd/scanc_sun.h>
48
#include <arch/drivers/z8530.h>
41
#include <arch/drivers/z8530.h>
-
 
42
#include <arch/drivers/kbd.h>
49
#include <arch/interrupt.h>
43
#include <arch/interrupt.h>
50
#include <cpu.h>
44
#include <cpu.h>
51
#include <arch/asm.h>
45
#include <arch/asm.h>
52
#include <arch.h>
46
#include <arch.h>
53
#include <typedefs.h>
47
#include <typedefs.h>
54
#include <console/chardev.h>
48
#include <console/chardev.h>
55
#include <console/console.h>
49
#include <console/console.h>
56
#include <interrupt.h>
50
#include <interrupt.h>
57
 
51
 
58
/* Keyboard commands. */
-
 
59
#define KBD_ENABLE  0xf4
-
 
60
#define KBD_DISABLE 0xf5
-
 
61
#define KBD_ACK     0xfa
-
 
62
 
-
 
63
/*
-
 
64
 * 60  Write 8042 Command Byte: next data byte written to port 60h is
-
 
65
 *     placed in 8042 command register. Format:
-
 
66
 *
-
 
67
 *    |7|6|5|4|3|2|1|0|8042 Command Byte
-
 
68
 *     | | | | | | | `---- 1=enable output register full interrupt
-
 
69
 *     | | | | | | `----- should be 0
-
 
70
 *     | | | | | `------ 1=set status register system, 0=clear
-
 
71
 *     | | | | `------- 1=override keyboard inhibit, 0=allow inhibit
-
 
72
 *     | | | `-------- disable keyboard I/O by driving clock line low
-
 
73
 *     | | `--------- disable auxiliary device, drives clock line low
-
 
74
 *     | `---------- IBM scancode translation 0=AT, 1=PC/XT
-
 
75
 *     `----------- reserved, should be 0
-
 
76
 */
-
 
77
 
-
 
78
#define z8530_SET_COMMAND   0x60
-
 
79
#define z8530_COMMAND       0x69
-
 
80
 
-
 
81
#define z8530_BUFFER_FULL_MASK  0x01
-
 
82
#define z8530_WAIT_MASK     0x02
-
 
83
#define z8530_MOUSE_DATA        0x20
-
 
84
 
-
 
85
/*
52
/*
86
 * These codes read from z8530 data register are silently ignored.
53
 * These codes read from z8530 data register are silently ignored.
87
 */
54
 */
88
#define IGNORE_CODE 0x7f        /* all keys up */
55
#define IGNORE_CODE 0x7f        /* all keys up */
89
 
56
 
Line 95... Line 62...
95
    .suspend = z8530_suspend,
62
    .suspend = z8530_suspend,
96
    .resume = z8530_resume,
63
    .resume = z8530_resume,
97
    .read = key_read
64
    .read = key_read
98
};
65
};
99
 
66
 
100
static void z8530_interrupt(int n, istate_t *istate);
67
void z8530_interrupt(int n, istate_t *istate);
101
static void z8530_wait(void);
68
void z8530_wait(void);
102
 
69
 
103
static iroutine oldvector;
-
 
104
/** Initialize keyboard and service interrupts using kernel routine */
70
/** Initialize keyboard and service interrupts using kernel routine */
105
void z8530_grab(void)
71
void z8530_grab(void)
106
{
72
{
107
    oldvector = exc_register(VECTOR_KBD, "z8530_interrupt", (iroutine) z8530_interrupt);
-
 
108
    z8530_wait();
-
 
109
    z8530_command_write(z8530_SET_COMMAND);
-
 
110
    z8530_wait();
-
 
111
    z8530_data_write(z8530_COMMAND);
-
 
112
    z8530_wait();
-
 
113
}
73
}
114
/** Resume the former interrupt vector */
74
/** Resume the former interrupt vector */
115
void z8530_release(void)
75
void z8530_release(void)
116
{
76
{
117
    if (oldvector)
-
 
118
        exc_register(VECTOR_KBD, "user_interrupt", oldvector);
-
 
119
}
77
}
120
 
78
 
-
 
79
#include <print.h>
-
 
80
 
121
/** Initialize z8530. */
81
/** Initialize z8530. */
122
void z8530_init(void)
82
void z8530_init(void)
123
{
83
{
124
    int i;
-
 
125
 
-
 
126
    z8530_grab();
-
 
127
        /* Prevent user from accidentaly releasing calling z8530_resume
-
 
128
     * and disabling keyboard
-
 
129
     */
-
 
130
    oldvector = NULL;
-
 
131
 
-
 
132
    trap_virtual_enable_irqs(1<<IRQ_KBD);
-
 
133
    chardev_initialize("z8530_kbd", &kbrd, &ops);
84
    chardev_initialize("z8530_kbd", &kbrd, &ops);
134
    stdin = &kbrd;
85
    stdin = &kbrd;
135
 
86
 
136
    /*
-
 
137
     * Clear input buffer.
87
    z8530_write_a(WR1, WR1_IARCSC); /* interrupt on all characters */
138
     * Number of iterations is limited to prevent infinite looping.
88
    z8530_write_a(WR2, 12);     /* FIXME: IRQ12 ??? */
139
     */
89
 
140
    for (i = 0; (z8530_status_read() & z8530_BUFFER_FULL_MASK) && i < 100; i++) {
90
    /* 8 bits per character and enable receiver */
141
        z8530_data_read();
91
    z8530_write_a(WR3, WR3_RX8BITSCH | WR3_RX_ENABLE);
142
    }  
92
   
-
 
93
    z8530_write_a(WR9, WR9_MIE);    /* Master Interrupt Enable. */
143
}
94
}
144
 
95
 
145
/** Process z8530 interrupt.
96
/** Process z8530 interrupt.
146
 *
97
 *
147
 * @param n Interrupt vector.
98
 * @param n Interrupt vector.
148
 * @param istate Interrupted state.
99
 * @param istate Interrupted state.
149
 */
100
 */
150
void z8530_interrupt(int n, istate_t *istate)
101
void z8530_interrupt(int n, istate_t *istate)
151
{
102
{
152
    uint8_t x;
-
 
153
    uint8_t status;
-
 
154
 
-
 
155
    while (((status=z8530_status_read()) & z8530_BUFFER_FULL_MASK)) {
-
 
156
        x = z8530_data_read();
-
 
157
 
-
 
158
        if ((status & z8530_MOUSE_DATA))
-
 
159
            continue;
-
 
160
 
-
 
161
        if (x & KEY_RELEASE)
-
 
162
            key_released(x ^ KEY_RELEASE);
-
 
163
        else
-
 
164
            key_pressed(x);
-
 
165
    }
-
 
166
    trap_virtual_eoi();
-
 
167
}
103
}
168
 
104
 
169
/** Wait until the controller reads its data. */
105
/** Wait until the controller reads its data. */
170
void z8530_wait(void) {
106
void z8530_wait(void) {
171
    while (z8530_status_read() & z8530_WAIT_MASK) {
-
 
172
        /* wait */
-
 
173
    }
-
 
174
}
107
}
175
 
108
 
176
/* Called from getc(). */
109
/* Called from getc(). */
177
void z8530_resume(chardev_t *d)
110
void z8530_resume(chardev_t *d)
178
{
111
{
Line 187... Line 120...
187
{
120
{
188
    char ch;   
121
    char ch;   
189
 
122
 
190
    while(!(ch = active_read_buff_read())) {
123
    while(!(ch = active_read_buff_read())) {
191
        uint8_t x;
124
        uint8_t x;
192
        while (!(z8530_status_read() & z8530_BUFFER_FULL_MASK))
125
        while (!(z8530_read_a(RR0) & RR0_RCA))
193
            ;
126
            ;
194
        x = z8530_data_read();
127
        x = z8530_read_a(RR8);
195
        if (x != IGNORE_CODE) {
128
        if (x != IGNORE_CODE) {
196
            if (x & KEY_RELEASE)
129
            if (x & KEY_RELEASE)
197
                key_released(x ^ KEY_RELEASE);
130
                key_released(x ^ KEY_RELEASE);
198
            else
131
            else
199
                active_read_key_pressed(x);
132
                active_read_key_pressed(x);
Line 208... Line 141...
208
 */
141
 */
209
void z8530_poll(void)
142
void z8530_poll(void)
210
{
143
{
211
    uint8_t x;
144
    uint8_t x;
212
 
145
 
213
    while (((x = z8530_status_read() & z8530_BUFFER_FULL_MASK))) {
146
    while (z8530_read_a(RR0) & RR0_RCA) {
214
        x = z8530_data_read();
147
        x = z8530_read_a(RR8);
215
        if (x != IGNORE_CODE) {
148
        if (x != IGNORE_CODE) {
216
            if (x & KEY_RELEASE)
149
            if (x & KEY_RELEASE)
217
                key_released(x ^ KEY_RELEASE);
150
                key_released(x ^ KEY_RELEASE);
218
            else
151
            else
219
                key_pressed(x);
152
                key_pressed(x);