Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4628 → Rev 4629

/branches/arm/kernel/arch/arm32/src/drivers/qemu.c
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.