Subversion Repositories HelenOS

Rev

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

Rev 4628 Rev 4629
Line 1... Line 1...
1
/*
1
/*
2
 * Copyright (c) 2007 Michal Kebrt, Petr Stepan
2
 * Copyright (c) 2009 Vineeth Pillai
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:
Line 35... Line 35...
35
 
35
 
36
#include <interrupt.h>
36
#include <interrupt.h>
37
#include <ipc/irq.h>
37
#include <ipc/irq.h>
38
#include <console/chardev.h>
38
#include <console/chardev.h>
39
#include <arch/drivers/qemu.h>
39
#include <arch/drivers/qemu.h>
-
 
40
#include <arch/drivers/pl050.h>
40
#include <console/console.h>
41
#include <console/console.h>
41
#include <sysinfo/sysinfo.h>
42
#include <sysinfo/sysinfo.h>
42
#include <print.h>
43
#include <print.h>
43
#include <ddi/device.h>
44
#include <ddi/device.h>
44
#include <mm/page.h>
45
#include <mm/page.h>
Line 74... Line 75...
74
/* IRQs */
75
/* IRQs */
75
#define QEMU_ICP_KBD_IRQ        3
76
#define QEMU_ICP_KBD_IRQ        3
76
#define QEMU_ICP_TIMER_IRQ      6
77
#define QEMU_ICP_TIMER_IRQ      6
77
 
78
 
78
static qemu_icp_hw_map_t qemu_icp_hw_map;
79
static qemu_icp_hw_map_t qemu_icp_hw_map;
79
static chardev_t console;
-
 
80
static irq_t qemu_icp_console_irq;
-
 
81
static irq_t qemu_icp_timer_irq;
80
static irq_t qemu_icp_timer_irq;
82
 
81
 
83
static bool hw_map_init_called = false;
82
static bool hw_map_init_called = false;
84
static bool vga_init = false;
83
static bool vga_init = false;
85
 
84
 
86
static void qemu_icp_kbd_enable(chardev_t *dev);
-
 
87
static void qemu_icp_kbd_disable(chardev_t *dev);
-
 
88
static void qemu_icp_write(chardev_t *dev, const char ch);
-
 
89
static char qemu_icp_do_read(chardev_t *dev);
-
 
90
void icp_vga_init(void);
85
void icp_vga_init(void);
91
 
86
 
92
static chardev_operations_t qemu_icp_ops = {
-
 
93
    .resume = qemu_icp_kbd_enable,
-
 
94
    .suspend = qemu_icp_kbd_disable,
-
 
95
    .write = qemu_icp_write,
-
 
96
    .read = qemu_icp_do_read,
-
 
97
};
-
 
98
 
-
 
99
/** Initializes the vga
87
/** Initializes the vga
100
 *
88
 *
101
 */
89
 */
102
void icp_vga_init(void)
90
void icp_vga_init(void)
103
{
91
{
Line 170... Line 158...
170
 
158
 
171
    hw_map_init_called = true;
159
    hw_map_init_called = true;
172
}
160
}
173
 
161
 
174
 
162
 
175
/** Putchar that works with qemu_icp.
-
 
176
 *
-
 
177
 * @param dev Not used.
-
 
178
 * @param ch Characted to be printed.
-
 
179
 */
-
 
180
static void qemu_icp_write(chardev_t *dev, const char ch)
-
 
181
{
-
 
182
    *((char *) qemu_icp_hw_map.videoram) = ch;
-
 
183
}
-
 
184
 
-
 
185
/** Enables qemu_icp keyboard (interrupt unmasked).
-
 
186
 *
-
 
187
 * @param dev Not used.
-
 
188
 *
-
 
189
 * Called from getc().
-
 
190
 */
-
 
191
static void qemu_icp_kbd_enable(chardev_t *dev)
-
 
192
{
-
 
193
    qemu_icp_irqc_unmask(QEMU_ICP_KBD_IRQ);
-
 
194
}
-
 
195
 
-
 
196
/** Disables qemu_icp keyboard (interrupt masked).
-
 
197
 *
-
 
198
 * @param dev not used
-
 
199
 *
-
 
200
 * Called from getc().
-
 
201
 */
-
 
202
static void qemu_icp_kbd_disable(chardev_t *dev)
-
 
203
{
-
 
204
    qemu_icp_irqc_mask(QEMU_ICP_KBD_IRQ);
-
 
205
}
-
 
206
 
-
 
207
/** Read character using polling, assume interrupts disabled.
-
 
208
 *
-
 
209
 *  @param dev Not used.
-
 
210
 */
-
 
211
static char qemu_icp_do_read(chardev_t *dev)
-
 
212
{
-
 
213
    char ch;
-
 
214
 
-
 
215
    while (1) {
-
 
216
        ch = *((volatile char *) qemu_icp_hw_map.kbd_data);
-
 
217
        if (ch) {
-
 
218
            if (ch == '\r')
-
 
219
                return '\n';
-
 
220
            if (ch == 0x7f)
-
 
221
                return '\b';
-
 
222
            return ch;
-
 
223
        }
-
 
224
    }
-
 
225
}
-
 
226
 
-
 
227
/** Process keyboard interrupt.
-
 
228
 *  
-
 
229
 *  @param irq IRQ information.
-
 
230
 *  @param arg Not used.
-
 
231
 */
-
 
232
static void qemu_icp_irq_handler(irq_t *irq, void *arg, ...)
-
 
233
{
-
 
234
    if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox)) {
-
 
235
        ipc_irq_send_notif(irq);
-
 
236
    } else {
-
 
237
        char ch = 0;
-
 
238
       
-
 
239
        ch = *((char *) qemu_icp_hw_map.kbd_data);
-
 
240
        if (ch == '\r') {
-
 
241
            ch = '\n';
-
 
242
        }
-
 
243
        if (ch == 0x7f) {
-
 
244
            ch = '\b';
-
 
245
        }
-
 
246
        chardev_push_character(&console, ch);
-
 
247
    }
-
 
248
}
-
 
249
 
-
 
250
static irq_ownership_t qemu_icp_claim(void)
-
 
251
{
-
 
252
    return IRQ_ACCEPT;
-
 
253
}
-
 
254
 
-
 
255
 
-
 
256
/** Acquire console back for kernel. */
163
/** Acquire console back for kernel. */
257
void qemu_icp_grab_console(void)
164
void qemu_icp_grab_console(void)
258
{
165
{
259
    ipl_t ipl = interrupts_disable();
-
 
260
    spinlock_lock(&qemu_icp_console_irq.lock);
-
 
261
    qemu_icp_console_irq.notif_cfg.notify = false;
-
 
262
    spinlock_unlock(&qemu_icp_console_irq.lock);
-
 
263
    interrupts_restore(ipl);
166
    pl050_grab();
264
}
167
}
265
 
168
 
266
/** Return console to userspace. */
169
/** Return console to userspace. */
267
void qemu_icp_release_console(void)
170
void qemu_icp_release_console(void)
268
{
171
{
269
    ipl_t ipl = interrupts_disable();
-
 
270
    spinlock_lock(&qemu_icp_console_irq.lock);
-
 
271
    if (qemu_icp_console_irq.notif_cfg.answerbox) {
-
 
272
        qemu_icp_console_irq.notif_cfg.notify = true;
-
 
273
    }
-
 
274
    spinlock_unlock(&qemu_icp_console_irq.lock);
-
 
275
    interrupts_restore(ipl);
172
    pl050_release();
276
}
173
}
277
 
174
 
278
/** Initializes console object representing qemu_icp console.
175
/** Initializes console object representing qemu_icp console.
279
 *
176
 *
280
 *  @param devno device number.
177
 *  @param devno device number.
281
 */
178
 */
282
void qemu_icp_console_init(devno_t devno)
179
void qemu_icp_console_init(devno_t devno)
283
{
180
{
284
    chardev_initialize("qemu_icp_console", &console, &qemu_icp_ops);
-
 
285
    stdin = &console;
-
 
286
    stdout = &console;
-
 
287
   
181
   
288
    qemu_icp_irqc_mask(QEMU_ICP_KBD_IRQ);
182
    qemu_icp_irqc_mask(QEMU_ICP_KBD_IRQ);
289
    irq_initialize(&qemu_icp_console_irq);
-
 
290
    qemu_icp_console_irq.devno = devno;
-
 
291
    qemu_icp_console_irq.inr = QEMU_ICP_KBD_IRQ;
-
 
292
    qemu_icp_console_irq.claim = qemu_icp_claim;
-
 
293
    qemu_icp_console_irq.handler = qemu_icp_irq_handler;
183
    pl050_init(devno, QEMU_ICP_KBD_IRQ, QEMU_ICP_KBD, qemu_icp_hw_map.kbd_ctrl);
294
    irq_register(&qemu_icp_console_irq);
-
 
295
 
-
 
296
    *(char *)qemu_icp_hw_map.kbd_ctrl = 0x17;
-
 
297
   
-
 
298
    qemu_icp_irqc_unmask(QEMU_ICP_KBD_IRQ);
184
    qemu_icp_irqc_unmask(QEMU_ICP_KBD_IRQ);
299
   
-
 
300
    sysinfo_set_item_val("kbd", NULL, true);
-
 
301
    sysinfo_set_item_val("kbd.devno", NULL, devno);
-
 
302
    sysinfo_set_item_val("kbd.inr", NULL, QEMU_ICP_KBD_IRQ);
-
 
303
    sysinfo_set_item_val("kbd.address.virtual", NULL, qemu_icp_hw_map.kbd_data);
-
 
304
}
185
}
305
 
186
 
306
/** Starts qemu_icp Real Time Clock device, which asserts regular interrupts.
187
/** Starts qemu_icp Real Time Clock device, which asserts regular interrupts.
307
 *
188
 *
308
 * @param frequency Interrupts frequency (0 disables RTC).
189
 * @param frequency Interrupts frequency (0 disables RTC).