Subversion Repositories HelenOS

Rev

Rev 1921 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1921 Rev 1931
1
/*
1
/*
2
 * Copyright (C) 2001-2006 Jakub Jermar
2
 * Copyright (C) 2001-2006 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:
8
 *
8
 *
9
 * - Redistributions of source code must retain the above copyright
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
13
 *   documentation and/or other materials provided with the distribution.
14
 * - The name of the author may not be used to endorse or promote products
14
 * - The name of the author may not be used to endorse or promote products
15
 *   derived from this software without specific prior written permission.
15
 *   derived from this software without specific prior written permission.
16
 *
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
27
 */
28
 
28
 
29
/** @addtogroup genarch
29
/** @addtogroup genarch
30
 * @{
30
 * @{
31
 */
31
 */
32
/**
32
/**
33
 * @file
33
 * @file
34
 * @brief   NS 16550 serial port / keyboard driver.
34
 * @brief   NS 16550 serial port / keyboard driver.
35
 */
35
 */
36
 
36
 
37
#include <genarch/kbd/ns16550.h>
37
#include <genarch/kbd/ns16550.h>
38
#include <genarch/kbd/key.h>
38
#include <genarch/kbd/key.h>
39
#include <genarch/kbd/scanc.h>
39
#include <genarch/kbd/scanc.h>
40
#include <genarch/kbd/scanc_sun.h>
40
#include <genarch/kbd/scanc_sun.h>
-
 
41
#include <arch/drivers/kbd.h>
41
#include <arch/drivers/ns16550.h>
42
#include <arch/drivers/ns16550.h>
42
#include <ddi/irq.h>
43
#include <ddi/irq.h>
43
#include <arch/interrupt.h>
44
#include <ipc/irq.h>
44
#include <cpu.h>
45
#include <cpu.h>
45
#include <arch/asm.h>
46
#include <arch/asm.h>
46
#include <arch.h>
47
#include <arch.h>
47
#include <typedefs.h>
48
#include <typedefs.h>
48
#include <console/chardev.h>
49
#include <console/chardev.h>
49
#include <console/console.h>
50
#include <console/console.h>
50
#include <interrupt.h>
51
#include <interrupt.h>
-
 
52
#include <arch/interrupt.h>
51
#include <sysinfo/sysinfo.h>
53
#include <sysinfo/sysinfo.h>
-
 
54
#include <synch/spinlock.h>
52
 
55
 
53
#define LSR_DATA_READY  0x01
56
#define LSR_DATA_READY  0x01
54
 
57
 
55
/** Structure representing the ns16550. */
58
/** Structure representing the ns16550. */
56
static ns16550_t ns16550;
59
static ns16550_t ns16550;
57
 
60
 
58
/** Structure for ns16550's IRQ. */
61
/** Structure for ns16550's IRQ. */
59
static irq_t ns16550_irq;
62
static irq_t ns16550_irq;
60
 
63
 
-
 
64
static ipc_notif_cfg_t saved_notif_cfg;
-
 
65
 
61
/*
66
/*
62
 * These codes read from ns16550 data register are silently ignored.
67
 * These codes read from ns16550 data register are silently ignored.
63
 */
68
 */
64
#define IGNORE_CODE 0x7f        /* all keys up */
69
#define IGNORE_CODE 0x7f        /* all keys up */
65
 
70
 
66
static void ns16550_suspend(chardev_t *);
71
static void ns16550_suspend(chardev_t *);
67
static void ns16550_resume(chardev_t *);
72
static void ns16550_resume(chardev_t *);
68
 
73
 
69
static chardev_operations_t ops = {
74
static chardev_operations_t ops = {
70
    .suspend = ns16550_suspend,
75
    .suspend = ns16550_suspend,
71
    .resume = ns16550_resume,
76
    .resume = ns16550_resume,
72
    .read = ns16550_key_read
77
    .read = ns16550_key_read
73
};
78
};
74
 
79
 
75
void ns16550_interrupt(int n, istate_t *istate);
-
 
76
void ns16550_wait(void);
80
void ns16550_interrupt(void);
77
 
81
 
78
/** Initialize keyboard and service interrupts using kernel routine */
82
/** Initialize keyboard and service interrupts using kernel routine */
79
void ns16550_grab(void)
83
void ns16550_grab(void)
80
{
84
{
-
 
85
    ns16550_ier_write(&ns16550, IER_ERBFI);     /* enable receiver interrupt */
-
 
86
   
-
 
87
    while (ns16550_lsr_read(&ns16550) & LSR_DATA_READY)
-
 
88
        (void) ns16550_rbr_read(&ns16550);
-
 
89
 
-
 
90
    if (ns16550_irq.notif_cfg.answerbox) {
-
 
91
        saved_notif_cfg = ns16550_irq.notif_cfg;
-
 
92
        ns16550_irq.notif_cfg.answerbox = NULL;
-
 
93
        ns16550_irq.notif_cfg.code = NULL;
-
 
94
        ns16550_irq.notif_cfg.method = 0;
-
 
95
        ns16550_irq.notif_cfg.counter = 0;
81
    /* TODO */
96
    }
82
}
97
}
83
 
98
 
84
/** Resume the former interrupt vector */
99
/** Resume the former interrupt vector */
85
void ns16550_release(void)
100
void ns16550_release(void)
86
{
101
{
87
    /* TODO */
102
    if (saved_notif_cfg.answerbox)
-
 
103
        ns16550_irq.notif_cfg = saved_notif_cfg;
88
}
104
}
89
 
105
 
90
/** Initialize ns16550.
106
/** Initialize ns16550.
91
 *
107
 *
92
 * @param devno Device number.
108
 * @param devno Device number.
93
 * @param inr Interrupt number.
109
 * @param inr Interrupt number.
94
 * @param vaddr Virtual address of device's registers.
110
 * @param vaddr Virtual address of device's registers.
95
 */
111
 */
96
void ns16550_init(devno_t devno, inr_t inr, uintptr_t vaddr)
112
void ns16550_init(devno_t devno, inr_t inr, uintptr_t vaddr)
97
{
113
{
98
    ns16550_grab();
-
 
99
    chardev_initialize("ns16550_kbd", &kbrd, &ops);
114
    chardev_initialize("ns16550_kbd", &kbrd, &ops);
100
    stdin = &kbrd;
115
    stdin = &kbrd;
101
   
116
   
102
    ns16550.devno = devno;
117
    ns16550.devno = devno;
103
    ns16550.reg = (uint8_t *) vaddr;
118
    ns16550.reg = (uint8_t *) vaddr;
104
   
119
   
105
    irq_initialize(&ns16550_irq);
120
    irq_initialize(&ns16550_irq);
106
    ns16550_irq.devno = devno;
121
    ns16550_irq.devno = devno;
107
    ns16550_irq.inr = inr;
122
    ns16550_irq.inr = inr;
108
    ns16550_irq.claim = ns16550_claim;
123
    ns16550_irq.claim = ns16550_claim;
109
    ns16550_irq.handler = ns16550_irq_handler;
124
    ns16550_irq.handler = ns16550_irq_handler;
110
    irq_register(&ns16550_irq);
125
    irq_register(&ns16550_irq);
111
   
126
   
112
    sysinfo_set_item_val("kbd", NULL, true);
127
    sysinfo_set_item_val("kbd", NULL, true);
-
 
128
    sysinfo_set_item_val("kbd.type", NULL, KBD_NS16550);
113
    sysinfo_set_item_val("kbd.devno", NULL, devno);
129
    sysinfo_set_item_val("kbd.devno", NULL, devno);
114
    sysinfo_set_item_val("kbd.inr", NULL, inr);
130
    sysinfo_set_item_val("kbd.inr", NULL, inr);
115
    sysinfo_set_item_val("kbd.address.virtual", NULL, vaddr);
131
    sysinfo_set_item_val("kbd.address.virtual", NULL, vaddr);
116
   
132
   
117
    ns16550_ier_write(&ns16550, IER_ERBFI);     /* enable receiver interrupt */
-
 
118
   
-
 
119
    while (ns16550_lsr_read(&ns16550) & LSR_DATA_READY)
-
 
120
        (void) ns16550_rbr_read(&ns16550);
133
    ns16550_grab();
121
}
-
 
122
 
-
 
123
/** Process ns16550 interrupt.
-
 
124
 *
-
 
125
 * @param n Interrupt vector.
-
 
126
 * @param istate Interrupted state.
-
 
127
 */
-
 
128
void ns16550_interrupt(int n, istate_t *istate)
-
 
129
{
-
 
130
    /* TODO */
-
 
131
}
134
}
132
 
135
 
133
/** Wait until the controller reads its data. */
136
/** Process ns16550 interrupt. */
134
void ns16550_wait(void)
137
void ns16550_interrupt(void)
135
{
138
{
-
 
139
    /* TODO
-
 
140
     *
-
 
141
     * ns16550 works in the polled mode so far.
-
 
142
     */
136
}
143
}
137
 
144
 
138
/* Called from getc(). */
145
/* Called from getc(). */
139
void ns16550_resume(chardev_t *d)
146
void ns16550_resume(chardev_t *d)
140
{
147
{
141
}
148
}
142
 
149
 
143
/* Called from getc(). */
150
/* Called from getc(). */
144
void ns16550_suspend(chardev_t *d)
151
void ns16550_suspend(chardev_t *d)
145
{
152
{
146
}
153
}
147
 
154
 
148
char ns16550_key_read(chardev_t *d)
155
char ns16550_key_read(chardev_t *d)
149
{
156
{
150
    char ch;   
157
    char ch;   
151
 
158
 
152
    while(!(ch = active_read_buff_read())) {
159
    while(!(ch = active_read_buff_read())) {
153
        uint8_t x;
160
        uint8_t x;
154
        while (!(ns16550_lsr_read(&ns16550) & LSR_DATA_READY))
161
        while (!(ns16550_lsr_read(&ns16550) & LSR_DATA_READY))
155
            ;
162
            ;
156
        x = ns16550_rbr_read(&ns16550);
163
        x = ns16550_rbr_read(&ns16550);
157
        if (x != IGNORE_CODE) {
164
        if (x != IGNORE_CODE) {
158
            if (x & KEY_RELEASE)
165
            if (x & KEY_RELEASE)
159
                key_released(x ^ KEY_RELEASE);
166
                key_released(x ^ KEY_RELEASE);
160
            else
167
            else
161
                active_read_key_pressed(x);
168
                active_read_key_pressed(x);
162
        }
169
        }
163
    }
170
    }
164
    return ch;
171
    return ch;
165
}
172
}
166
 
173
 
167
/** Poll for key press and release events.
174
/** Poll for key press and release events.
168
 *
175
 *
169
 * This function can be used to implement keyboard polling.
176
 * This function can be used to implement keyboard polling.
170
 */
177
 */
171
void ns16550_poll(void)
178
void ns16550_poll(void)
172
{
179
{
173
    uint8_t x;
180
    ipl_t ipl;
-
 
181
 
-
 
182
    ipl = interrupts_disable();
-
 
183
    spinlock_lock(&ns16550_irq.lock);
-
 
184
 
-
 
185
    if (ns16550_lsr_read(&ns16550) & LSR_DATA_READY) {
-
 
186
        if (ns16550_irq.notif_cfg.answerbox) {
-
 
187
            /*
-
 
188
             * Send IPC notification.
-
 
189
             */
-
 
190
            ipc_irq_send_notif(&ns16550_irq);
-
 
191
            spinlock_unlock(&ns16550_irq.lock);
-
 
192
            interrupts_restore(ipl);
-
 
193
            return;
-
 
194
        }
-
 
195
    }
-
 
196
 
-
 
197
    spinlock_unlock(&ns16550_irq.lock);
-
 
198
    interrupts_restore(ipl);
174
 
199
 
175
    while (ns16550_lsr_read(&ns16550) & LSR_DATA_READY) {
200
    while (ns16550_lsr_read(&ns16550) & LSR_DATA_READY) {
-
 
201
        uint8_t x;
-
 
202
       
176
        x = ns16550_rbr_read(&ns16550);
203
        x = ns16550_rbr_read(&ns16550);
177
        if (x != IGNORE_CODE) {
204
        if (x != IGNORE_CODE) {
178
            if (x & KEY_RELEASE)
205
            if (x & KEY_RELEASE)
179
                key_released(x ^ KEY_RELEASE);
206
                key_released(x ^ KEY_RELEASE);
180
            else
207
            else
181
                key_pressed(x);
208
                key_pressed(x);
182
        }
209
        }
183
    }
210
    }
184
}
211
}
185
 
212
 
186
irq_ownership_t ns16550_claim(void)
213
irq_ownership_t ns16550_claim(void)
187
{
214
{
188
    /* TODO */
-
 
189
    return IRQ_ACCEPT;
215
    return (ns16550_lsr_read(&ns16550) & LSR_DATA_READY);
190
}
216
}
191
 
217
 
192
void ns16550_irq_handler(irq_t *irq, void *arg, ...)
218
void ns16550_irq_handler(irq_t *irq, void *arg, ...)
193
{
219
{
194
    panic("Not yet implemented.\n");
220
    panic("Not yet implemented, ns16550 works in polled mode.\n");
195
}
221
}
196
 
222
 
197
/** @}
223
/** @}
198
 */
224
 */
199
 
225