1,5 → 1,5 |
/* |
* Copyright (c) 2007 Michal Kebrt, Petr Stepan |
* Copyright (c) 2009 Vineeth Pillai |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
37,6 → 37,7 |
#include <ipc/irq.h> |
#include <console/chardev.h> |
#include <arch/drivers/qemu.h> |
#include <arch/drivers/pl050.h> |
#include <console/console.h> |
#include <sysinfo/sysinfo.h> |
#include <print.h> |
76,26 → 77,13 |
#define QEMU_ICP_TIMER_IRQ 6 |
|
static qemu_icp_hw_map_t qemu_icp_hw_map; |
static chardev_t console; |
static irq_t qemu_icp_console_irq; |
static irq_t qemu_icp_timer_irq; |
|
static bool hw_map_init_called = false; |
static bool vga_init = false; |
|
static void qemu_icp_kbd_enable(chardev_t *dev); |
static void qemu_icp_kbd_disable(chardev_t *dev); |
static void qemu_icp_write(chardev_t *dev, const char ch); |
static char qemu_icp_do_read(chardev_t *dev); |
void icp_vga_init(void); |
|
static chardev_operations_t qemu_icp_ops = { |
.resume = qemu_icp_kbd_enable, |
.suspend = qemu_icp_kbd_disable, |
.write = qemu_icp_write, |
.read = qemu_icp_do_read, |
}; |
|
/** Initializes the vga |
* |
*/ |
172,107 → 160,16 |
} |
|
|
/** Putchar that works with qemu_icp. |
* |
* @param dev Not used. |
* @param ch Characted to be printed. |
*/ |
static void qemu_icp_write(chardev_t *dev, const char ch) |
{ |
*((char *) qemu_icp_hw_map.videoram) = ch; |
} |
|
/** Enables qemu_icp keyboard (interrupt unmasked). |
* |
* @param dev Not used. |
* |
* Called from getc(). |
*/ |
static void qemu_icp_kbd_enable(chardev_t *dev) |
{ |
qemu_icp_irqc_unmask(QEMU_ICP_KBD_IRQ); |
} |
|
/** Disables qemu_icp keyboard (interrupt masked). |
* |
* @param dev not used |
* |
* Called from getc(). |
*/ |
static void qemu_icp_kbd_disable(chardev_t *dev) |
{ |
qemu_icp_irqc_mask(QEMU_ICP_KBD_IRQ); |
} |
|
/** Read character using polling, assume interrupts disabled. |
* |
* @param dev Not used. |
*/ |
static char qemu_icp_do_read(chardev_t *dev) |
{ |
char ch; |
|
while (1) { |
ch = *((volatile char *) qemu_icp_hw_map.kbd_data); |
if (ch) { |
if (ch == '\r') |
return '\n'; |
if (ch == 0x7f) |
return '\b'; |
return ch; |
} |
} |
} |
|
/** Process keyboard interrupt. |
* |
* @param irq IRQ information. |
* @param arg Not used. |
*/ |
static void qemu_icp_irq_handler(irq_t *irq, void *arg, ...) |
{ |
if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox)) { |
ipc_irq_send_notif(irq); |
} else { |
char ch = 0; |
|
ch = *((char *) qemu_icp_hw_map.kbd_data); |
if (ch == '\r') { |
ch = '\n'; |
} |
if (ch == 0x7f) { |
ch = '\b'; |
} |
chardev_push_character(&console, ch); |
} |
} |
|
static irq_ownership_t qemu_icp_claim(void) |
{ |
return IRQ_ACCEPT; |
} |
|
|
/** Acquire console back for kernel. */ |
void qemu_icp_grab_console(void) |
{ |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&qemu_icp_console_irq.lock); |
qemu_icp_console_irq.notif_cfg.notify = false; |
spinlock_unlock(&qemu_icp_console_irq.lock); |
interrupts_restore(ipl); |
pl050_grab(); |
} |
|
/** Return console to userspace. */ |
void qemu_icp_release_console(void) |
{ |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&qemu_icp_console_irq.lock); |
if (qemu_icp_console_irq.notif_cfg.answerbox) { |
qemu_icp_console_irq.notif_cfg.notify = true; |
} |
spinlock_unlock(&qemu_icp_console_irq.lock); |
interrupts_restore(ipl); |
pl050_release(); |
} |
|
/** Initializes console object representing qemu_icp console. |
281,26 → 178,10 |
*/ |
void qemu_icp_console_init(devno_t devno) |
{ |
chardev_initialize("qemu_icp_console", &console, &qemu_icp_ops); |
stdin = &console; |
stdout = &console; |
|
qemu_icp_irqc_mask(QEMU_ICP_KBD_IRQ); |
irq_initialize(&qemu_icp_console_irq); |
qemu_icp_console_irq.devno = devno; |
qemu_icp_console_irq.inr = QEMU_ICP_KBD_IRQ; |
qemu_icp_console_irq.claim = qemu_icp_claim; |
qemu_icp_console_irq.handler = qemu_icp_irq_handler; |
irq_register(&qemu_icp_console_irq); |
|
*(char *)qemu_icp_hw_map.kbd_ctrl = 0x17; |
|
pl050_init(devno, QEMU_ICP_KBD_IRQ, QEMU_ICP_KBD, qemu_icp_hw_map.kbd_ctrl); |
qemu_icp_irqc_unmask(QEMU_ICP_KBD_IRQ); |
|
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.devno", NULL, devno); |
sysinfo_set_item_val("kbd.inr", NULL, QEMU_ICP_KBD_IRQ); |
sysinfo_set_item_val("kbd.address.virtual", NULL, qemu_icp_hw_map.kbd_data); |
} |
|
/** Starts qemu_icp Real Time Clock device, which asserts regular interrupts. |