mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
bitkeeper revision 1.1093.1.1 (40f68514W0caTBHxeTQAL73i8HXL2A)
console merge
This commit is contained in:
1 parent
4e4436e107
commit
fca9bc6156
4 files changed
+132
-682
No files matched your search
@@ -61,7 +61,6 @@
|
||||
4075806d3fJqqDC1pYYPTZPc575iKg linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/frontend/main.c
|
||||
4075806dibjCcfuXv6CINMhxWTw3jQ linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/frontend/vbd.c
|
||||
3e5a4e65G3e2s0ghPMgiJ-gBTUJ0uQ linux-2.4.26-xen-sparse/arch/xen/drivers/console/Makefile
|
||||
3e5a4e651TH-SXHoufurnWjgl5bfOA linux-2.4.26-xen-sparse/arch/xen/drivers/console/console.c
|
||||
3e5a4e656nfFISThfbyXQOA6HN6YHw linux-2.4.26-xen-sparse/arch/xen/drivers/dom0/Makefile
|
||||
3e5a4e65BXtftInNHUC2PjDfPhdZZA linux-2.4.26-xen-sparse/arch/xen/drivers/dom0/core.c
|
||||
40420a6ebRqDjufoN1WSJvolEW2Wjw linux-2.4.26-xen-sparse/arch/xen/drivers/evtchn/Makefile
|
||||
@@ -195,7 +194,7 @@
|
||||
40f56239y9naBTXe40Pi2J_z3p-d1g linux-2.6.7-xen-sparse/drivers/xen/block/block.h
|
||||
40f56239BVfPsXBiWQitXgDRtOsiqg linux-2.6.7-xen-sparse/drivers/xen/block/vbd.c
|
||||
40f56239fsLjvtD8YBRAWphps4FDjg linux-2.6.7-xen-sparse/drivers/xen/console/Makefile
|
||||
40f56239afE58Oot-9omHGqq4UJ--A linux-2.6.7-xen-sparse/drivers/xen/console/console.c
|
||||
3e5a4e651TH-SXHoufurnWjgl5bfOA linux-2.6.7-xen-sparse/drivers/xen/console/console.c
|
||||
40f56239KYxO0YabhPzCTeUuln-lnA linux-2.6.7-xen-sparse/drivers/xen/evtchn/Makefile
|
||||
40f56239DoibTX6R-ZYd3QTXAB8_TA linux-2.6.7-xen-sparse/drivers/xen/evtchn/evtchn.c
|
||||
40f56239lrg_Ob0BJ8WBFS1zeg2CYw linux-2.6.7-xen-sparse/drivers/xen/net/Kconfig
|
||||
|
||||
@@ -1,625 +0,0 @@
|
||||
/******************************************************************************
|
||||
* console.c
|
||||
*
|
||||
* Virtual console driver.
|
||||
*
|
||||
* Copyright (c) 2002-2004, K A Fraser.
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <asm/evtchn.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/hypervisor.h>
|
||||
#include <asm/hypervisor-ifs/event_channel.h>
|
||||
#include <asm/ctrl_if.h>
|
||||
|
||||
/*
|
||||
* Modes:
|
||||
* 'xencons=off' [XC_OFF]: Console is disabled.
|
||||
* 'xencons=tty' [XC_TTY]: Console attached to '/dev/tty[0-9]+'.
|
||||
* 'xencons=ttyS' [XC_SERIAL]: Console attached to '/dev/ttyS[0-9]+'.
|
||||
* [XC_DEFAULT]: DOM0 -> XC_SERIAL ; all others -> XC_TTY.
|
||||
*
|
||||
* NB. In mode XC_TTY, we create dummy consoles for tty2-63. This suppresses
|
||||
* warnings from standard distro startup scripts.
|
||||
*/
|
||||
static enum { XC_OFF, XC_DEFAULT, XC_TTY, XC_SERIAL } xc_mode = XC_DEFAULT;
|
||||
|
||||
static int __init xencons_setup(char *str)
|
||||
{
|
||||
if ( !strcmp(str, "tty") )
|
||||
xc_mode = XC_TTY;
|
||||
else if ( !strcmp(str, "ttyS") )
|
||||
xc_mode = XC_SERIAL;
|
||||
else if ( !strcmp(str, "off") )
|
||||
xc_mode = XC_OFF;
|
||||
return 1;
|
||||
}
|
||||
__setup("xencons", xencons_setup);
|
||||
|
||||
/* The kernel and user-land drivers share a common transmit buffer. */
|
||||
#define WBUF_SIZE 4096
|
||||
#define WBUF_MASK(_i) ((_i)&(WBUF_SIZE-1))
|
||||
static char wbuf[WBUF_SIZE];
|
||||
static unsigned int wc, wp; /* write_cons, write_prod */
|
||||
|
||||
/* This lock protects accesses to the common transmit buffer. */
|
||||
static spinlock_t xencons_lock = SPIN_LOCK_UNLOCKED;
|
||||
|
||||
/* Common transmit-kick routine. */
|
||||
static void __xencons_tx_flush(void);
|
||||
|
||||
/* This task is used to defer sending console data until there is space. */
|
||||
static void xencons_tx_flush_task_routine(void *data);
|
||||
static struct tq_struct xencons_tx_flush_task = {
|
||||
routine: xencons_tx_flush_task_routine
|
||||
};
|
||||
|
||||
|
||||
/******************** Kernel console driver ********************************/
|
||||
|
||||
static void kcons_write(
|
||||
struct console *c, const char *s, unsigned int count)
|
||||
{
|
||||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&xencons_lock, flags);
|
||||
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
if ( (wp - wc) >= (WBUF_SIZE - 1) )
|
||||
break;
|
||||
if ( (wbuf[WBUF_MASK(wp++)] = s[i]) == '\n' )
|
||||
wbuf[WBUF_MASK(wp++)] = '\r';
|
||||
}
|
||||
|
||||
__xencons_tx_flush();
|
||||
|
||||
spin_unlock_irqrestore(&xencons_lock, flags);
|
||||
}
|
||||
|
||||
static void kcons_write_dom0(
|
||||
struct console *c, const char *s, unsigned int count)
|
||||
{
|
||||
int rc;
|
||||
|
||||
while ( count > 0 )
|
||||
{
|
||||
if ( (rc = HYPERVISOR_console_io(CONSOLEIO_write, count, s)) > 0 )
|
||||
{
|
||||
count -= rc;
|
||||
s += rc;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static kdev_t kcons_device(struct console *c)
|
||||
{
|
||||
return MKDEV(TTY_MAJOR, (xc_mode == XC_SERIAL) ? 64 : 1);
|
||||
}
|
||||
|
||||
static struct console kcons_info = {
|
||||
device: kcons_device,
|
||||
flags: CON_PRINTBUFFER,
|
||||
index: -1
|
||||
};
|
||||
|
||||
void xen_console_init(void)
|
||||
{
|
||||
if ( start_info.flags & SIF_INITDOMAIN )
|
||||
{
|
||||
if ( xc_mode == XC_DEFAULT )
|
||||
xc_mode = XC_SERIAL;
|
||||
kcons_info.write = kcons_write_dom0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( xc_mode == XC_DEFAULT )
|
||||
xc_mode = XC_TTY;
|
||||
kcons_info.write = kcons_write;
|
||||
}
|
||||
|
||||
if ( xc_mode == XC_OFF )
|
||||
return;
|
||||
|
||||
if ( xc_mode == XC_SERIAL )
|
||||
strcpy(kcons_info.name, "ttyS");
|
||||
else
|
||||
strcpy(kcons_info.name, "tty");
|
||||
|
||||
register_console(&kcons_info);
|
||||
}
|
||||
|
||||
|
||||
/*** Useful function for console debugging -- goes straight to Xen. ***/
|
||||
asmlinkage int xprintk(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int printk_len;
|
||||
static char printk_buf[1024];
|
||||
|
||||
/* Emit the output into the temporary buffer */
|
||||
va_start(args, fmt);
|
||||
printk_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
/* Send the processed output directly to Xen. */
|
||||
kcons_write_dom0(NULL, printk_buf, printk_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*** Forcibly flush console data before dying. ***/
|
||||
void xencons_force_flush(void)
|
||||
{
|
||||
ctrl_msg_t msg;
|
||||
int sz;
|
||||
|
||||
/* Emergency console is synchronous, so there's nothing to flush. */
|
||||
if ( start_info.flags & SIF_INITDOMAIN )
|
||||
return;
|
||||
|
||||
/*
|
||||
* We use dangerous control-interface functions that require a quiescent
|
||||
* system and no interrupts. Try to ensure this with a global cli().
|
||||
*/
|
||||
cli();
|
||||
|
||||
/* Spin until console data is flushed through to the domain controller. */
|
||||
while ( (wc != wp) && !ctrl_if_transmitter_empty() )
|
||||
{
|
||||
/* Interrupts are disabled -- we must manually reap responses. */
|
||||
ctrl_if_discard_responses();
|
||||
|
||||
if ( (sz = wp - wc) == 0 )
|
||||
continue;
|
||||
if ( sz > sizeof(msg.msg) )
|
||||
sz = sizeof(msg.msg);
|
||||
if ( sz > (WBUF_SIZE - WBUF_MASK(wc)) )
|
||||
sz = WBUF_SIZE - WBUF_MASK(wc);
|
||||
|
||||
msg.type = CMSG_CONSOLE;
|
||||
msg.subtype = CMSG_CONSOLE_DATA;
|
||||
msg.length = sz;
|
||||
memcpy(msg.msg, &wbuf[WBUF_MASK(wc)], sz);
|
||||
|
||||
if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 )
|
||||
wc += sz;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************** User-space console driver (/dev/console) ************/
|
||||
|
||||
static struct tty_driver xencons_driver;
|
||||
static int xencons_refcount;
|
||||
static struct tty_struct *xencons_table[MAX_NR_CONSOLES];
|
||||
static struct termios *xencons_termios[MAX_NR_CONSOLES];
|
||||
static struct termios *xencons_termios_locked[MAX_NR_CONSOLES];
|
||||
static struct tty_struct *xencons_tty;
|
||||
static int xencons_priv_irq;
|
||||
static char x_char;
|
||||
|
||||
/* Non-privileged receive callback. */
|
||||
static void xencons_rx(ctrl_msg_t *msg, unsigned long id)
|
||||
{
|
||||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&xencons_lock, flags);
|
||||
if ( xencons_tty != NULL )
|
||||
{
|
||||
for ( i = 0; i < msg->length; i++ )
|
||||
tty_insert_flip_char(xencons_tty, msg->msg[i], 0);
|
||||
tty_flip_buffer_push(xencons_tty);
|
||||
}
|
||||
spin_unlock_irqrestore(&xencons_lock, flags);
|
||||
|
||||
msg->length = 0;
|
||||
ctrl_if_send_response(msg);
|
||||
}
|
||||
|
||||
/* Privileged and non-privileged transmit worker. */
|
||||
static void __xencons_tx_flush(void)
|
||||
{
|
||||
int sz, work_done = 0;
|
||||
ctrl_msg_t msg;
|
||||
|
||||
if ( start_info.flags & SIF_INITDOMAIN )
|
||||
{
|
||||
if ( x_char )
|
||||
{
|
||||
kcons_write_dom0(NULL, &x_char, 1);
|
||||
x_char = 0;
|
||||
work_done = 1;
|
||||
}
|
||||
|
||||
while ( wc != wp )
|
||||
{
|
||||
sz = wp - wc;
|
||||
if ( sz > (WBUF_SIZE - WBUF_MASK(wc)) )
|
||||
sz = WBUF_SIZE - WBUF_MASK(wc);
|
||||
kcons_write_dom0(NULL, &wbuf[WBUF_MASK(wc)], sz);
|
||||
wc += sz;
|
||||
work_done = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while ( x_char )
|
||||
{
|
||||
msg.type = CMSG_CONSOLE;
|
||||
msg.subtype = CMSG_CONSOLE_DATA;
|
||||
msg.length = 1;
|
||||
msg.msg[0] = x_char;
|
||||
|
||||
if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 )
|
||||
x_char = 0;
|
||||
else if ( ctrl_if_enqueue_space_callback(&xencons_tx_flush_task) )
|
||||
break;
|
||||
|
||||
work_done = 1;
|
||||
}
|
||||
|
||||
while ( wc != wp )
|
||||
{
|
||||
sz = wp - wc;
|
||||
if ( sz > sizeof(msg.msg) )
|
||||
sz = sizeof(msg.msg);
|
||||
if ( sz > (WBUF_SIZE - WBUF_MASK(wc)) )
|
||||
sz = WBUF_SIZE - WBUF_MASK(wc);
|
||||
|
||||
msg.type = CMSG_CONSOLE;
|
||||
msg.subtype = CMSG_CONSOLE_DATA;
|
||||
msg.length = sz;
|
||||
memcpy(msg.msg, &wbuf[WBUF_MASK(wc)], sz);
|
||||
|
||||
if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 )
|
||||
wc += sz;
|
||||
else if ( ctrl_if_enqueue_space_callback(&xencons_tx_flush_task) )
|
||||
break;
|
||||
|
||||
work_done = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( work_done && (xencons_tty != NULL) )
|
||||
{
|
||||
wake_up_interruptible(&xencons_tty->write_wait);
|
||||
if ( (xencons_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
|
||||
(xencons_tty->ldisc.write_wakeup != NULL) )
|
||||
(xencons_tty->ldisc.write_wakeup)(xencons_tty);
|
||||
}
|
||||
}
|
||||
|
||||
/* Non-privileged transmit kicker. */
|
||||
static void xencons_tx_flush_task_routine(void *data)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&xencons_lock, flags);
|
||||
__xencons_tx_flush();
|
||||
spin_unlock_irqrestore(&xencons_lock, flags);
|
||||
}
|
||||
|
||||
/* Privileged receive callback and transmit kicker. */
|
||||
static void xencons_priv_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
static char rbuf[16];
|
||||
int i, l;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&xencons_lock, flags);
|
||||
|
||||
if ( xencons_tty != NULL )
|
||||
{
|
||||
/* Receive work. */
|
||||
while ( (l = HYPERVISOR_console_io(CONSOLEIO_read, 16, rbuf)) > 0 )
|
||||
for ( i = 0; i < l; i++ )
|
||||
tty_insert_flip_char(xencons_tty, rbuf[i], 0);
|
||||
if ( xencons_tty->flip.count != 0 )
|
||||
tty_flip_buffer_push(xencons_tty);
|
||||
}
|
||||
|
||||
/* Transmit work. */
|
||||
__xencons_tx_flush();
|
||||
|
||||
spin_unlock_irqrestore(&xencons_lock, flags);
|
||||
}
|
||||
|
||||
static int xencons_write_room(struct tty_struct *tty)
|
||||
{
|
||||
return WBUF_SIZE - (wp - wc);
|
||||
}
|
||||
|
||||
static int xencons_chars_in_buffer(struct tty_struct *tty)
|
||||
{
|
||||
return wp - wc;
|
||||
}
|
||||
|
||||
static void xencons_send_xchar(struct tty_struct *tty, char ch)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if ( MINOR(tty->device) != xencons_driver.minor_start )
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&xencons_lock, flags);
|
||||
x_char = ch;
|
||||
__xencons_tx_flush();
|
||||
spin_unlock_irqrestore(&xencons_lock, flags);
|
||||
}
|
||||
|
||||
static void xencons_throttle(struct tty_struct *tty)
|
||||
{
|
||||
if ( MINOR(tty->device) != xencons_driver.minor_start )
|
||||
return;
|
||||
|
||||
if ( I_IXOFF(tty) )
|
||||
xencons_send_xchar(tty, STOP_CHAR(tty));
|
||||
}
|
||||
|
||||
static void xencons_unthrottle(struct tty_struct *tty)
|
||||
{
|
||||
if ( MINOR(tty->device) != xencons_driver.minor_start )
|
||||
return;
|
||||
|
||||
if ( I_IXOFF(tty) )
|
||||
{
|
||||
if ( x_char != 0 )
|
||||
x_char = 0;
|
||||
else
|
||||
xencons_send_xchar(tty, START_CHAR(tty));
|
||||
}
|
||||
}
|
||||
|
||||
static void xencons_flush_buffer(struct tty_struct *tty)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if ( MINOR(tty->device) != xencons_driver.minor_start )
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&xencons_lock, flags);
|
||||
wc = wp = 0;
|
||||
spin_unlock_irqrestore(&xencons_lock, flags);
|
||||
}
|
||||
|
||||
static inline int __xencons_put_char(int ch)
|
||||
{
|
||||
char _ch = (char)ch;
|
||||
if ( (wp - wc) == WBUF_SIZE )
|
||||
return 0;
|
||||
wbuf[WBUF_MASK(wp++)] = _ch;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int xencons_write(struct tty_struct *tty, int from_user,
|
||||
const u_char * buf, int count)
|
||||
{
|
||||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
if ( from_user && verify_area(VERIFY_READ, buf, count) )
|
||||
return -EINVAL;
|
||||
|
||||
if ( MINOR(tty->device) != xencons_driver.minor_start )
|
||||
return count;
|
||||
|
||||
spin_lock_irqsave(&xencons_lock, flags);
|
||||
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
char ch;
|
||||
if ( from_user )
|
||||
__get_user(ch, buf + i);
|
||||
else
|
||||
ch = buf[i];
|
||||
if ( !__xencons_put_char(ch) )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( i != 0 )
|
||||
__xencons_tx_flush();
|
||||
|
||||
spin_unlock_irqrestore(&xencons_lock, flags);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static void xencons_put_char(struct tty_struct *tty, u_char ch)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if ( MINOR(tty->device) != xencons_driver.minor_start )
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&xencons_lock, flags);
|
||||
(void)__xencons_put_char(ch);
|
||||
spin_unlock_irqrestore(&xencons_lock, flags);
|
||||
}
|
||||
|
||||
static void xencons_flush_chars(struct tty_struct *tty)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if ( MINOR(tty->device) != xencons_driver.minor_start )
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&xencons_lock, flags);
|
||||
__xencons_tx_flush();
|
||||
spin_unlock_irqrestore(&xencons_lock, flags);
|
||||
}
|
||||
|
||||
static void xencons_wait_until_sent(struct tty_struct *tty, int timeout)
|
||||
{
|
||||
unsigned long orig_jiffies = jiffies;
|
||||
|
||||
if ( MINOR(tty->device) != xencons_driver.minor_start )
|
||||
return;
|
||||
|
||||
while ( tty->driver.chars_in_buffer(tty) )
|
||||
{
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(1);
|
||||
if ( signal_pending(current) )
|
||||
break;
|
||||
if ( (timeout != 0) && time_after(jiffies, orig_jiffies + timeout) )
|
||||
break;
|
||||
}
|
||||
|
||||
set_current_state(TASK_RUNNING);
|
||||
}
|
||||
|
||||
static int xencons_open(struct tty_struct *tty, struct file *filp)
|
||||
{
|
||||
int line;
|
||||
unsigned long flags;
|
||||
|
||||
if ( MINOR(tty->device) != xencons_driver.minor_start )
|
||||
return 0;
|
||||
|
||||
MOD_INC_USE_COUNT;
|
||||
line = MINOR(tty->device) - tty->driver.minor_start;
|
||||
if ( line != 0 )
|
||||
{
|
||||
MOD_DEC_USE_COUNT;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&xencons_lock, flags);
|
||||
tty->driver_data = NULL;
|
||||
if ( xencons_tty == NULL )
|
||||
xencons_tty = tty;
|
||||
__xencons_tx_flush();
|
||||
spin_unlock_irqrestore(&xencons_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void xencons_close(struct tty_struct *tty, struct file *filp)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if ( MINOR(tty->device) != xencons_driver.minor_start )
|
||||
return;
|
||||
|
||||
if ( tty->count == 1 )
|
||||
{
|
||||
tty->closing = 1;
|
||||
tty_wait_until_sent(tty, 0);
|
||||
if ( tty->driver.flush_buffer != NULL )
|
||||
tty->driver.flush_buffer(tty);
|
||||
if ( tty->ldisc.flush_buffer != NULL )
|
||||
tty->ldisc.flush_buffer(tty);
|
||||
tty->closing = 0;
|
||||
spin_lock_irqsave(&xencons_lock, flags);
|
||||
xencons_tty = NULL;
|
||||
spin_unlock_irqrestore(&xencons_lock, flags);
|
||||
}
|
||||
|
||||
MOD_DEC_USE_COUNT;
|
||||
}
|
||||
|
||||
static int __init xencons_init(void)
|
||||
{
|
||||
memset(&xencons_driver, 0, sizeof(struct tty_driver));
|
||||
xencons_driver.magic = TTY_DRIVER_MAGIC;
|
||||
xencons_driver.major = TTY_MAJOR;
|
||||
xencons_driver.type = TTY_DRIVER_TYPE_SERIAL;
|
||||
xencons_driver.subtype = SERIAL_TYPE_NORMAL;
|
||||
xencons_driver.init_termios = tty_std_termios;
|
||||
xencons_driver.flags =
|
||||
TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_NO_DEVFS;
|
||||
xencons_driver.refcount = &xencons_refcount;
|
||||
xencons_driver.table = xencons_table;
|
||||
xencons_driver.termios = xencons_termios;
|
||||
xencons_driver.termios_locked = xencons_termios_locked;
|
||||
|
||||
if ( xc_mode == XC_OFF )
|
||||
return 0;
|
||||
|
||||
if ( xc_mode == XC_SERIAL )
|
||||
{
|
||||
xencons_driver.name = "ttyS";
|
||||
xencons_driver.minor_start = 64;
|
||||
xencons_driver.num = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
xencons_driver.name = "tty";
|
||||
xencons_driver.minor_start = 1;
|
||||
xencons_driver.num = MAX_NR_CONSOLES;
|
||||
}
|
||||
|
||||
xencons_driver.open = xencons_open;
|
||||
xencons_driver.close = xencons_close;
|
||||
xencons_driver.write = xencons_write;
|
||||
xencons_driver.write_room = xencons_write_room;
|
||||
xencons_driver.put_char = xencons_put_char;
|
||||
xencons_driver.flush_chars = xencons_flush_chars;
|
||||
xencons_driver.chars_in_buffer = xencons_chars_in_buffer;
|
||||
xencons_driver.send_xchar = xencons_send_xchar;
|
||||
xencons_driver.flush_buffer = xencons_flush_buffer;
|
||||
xencons_driver.throttle = xencons_throttle;
|
||||
xencons_driver.unthrottle = xencons_unthrottle;
|
||||
xencons_driver.wait_until_sent = xencons_wait_until_sent;
|
||||
|
||||
if ( tty_register_driver(&xencons_driver) )
|
||||
panic("Couldn't register Xen virtual console driver as %s\n",xencons_driver.name);
|
||||
|
||||
if ( start_info.flags & SIF_INITDOMAIN )
|
||||
{
|
||||
xencons_priv_irq = bind_virq_to_irq(VIRQ_CONSOLE);
|
||||
(void)request_irq(xencons_priv_irq,
|
||||
xencons_priv_interrupt, 0, "console", NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)ctrl_if_register_receiver(CMSG_CONSOLE, xencons_rx, 0);
|
||||
}
|
||||
|
||||
printk("Xen virtual console successfully installed as %s\n",xencons_driver.name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit xencons_fini(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ( (ret = tty_unregister_driver(&xencons_driver)) != 0 )
|
||||
printk(KERN_ERR "Unable to unregister Xen console driver: %d\n", ret);
|
||||
|
||||
if ( start_info.flags & SIF_INITDOMAIN )
|
||||
{
|
||||
free_irq(xencons_priv_irq, NULL);
|
||||
unbind_virq_from_irq(VIRQ_CONSOLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
ctrl_if_unregister_receiver(CMSG_CONSOLE, xencons_rx);
|
||||
}
|
||||
}
|
||||
|
||||
module_init(xencons_init);
|
||||
module_exit(xencons_fini);
|
||||
@@ -102,6 +102,8 @@ for i in `find . -type l`; do rm -f $i; done
|
||||
relative_lndir ${RS}
|
||||
rm -f mkbuildtree
|
||||
|
||||
LINUX_26=${RS}/../linux-2.6.7-xen-sparse
|
||||
|
||||
## There are a whole bunch of special symlinks, mostly for files
|
||||
## which are identical in the i386 and xen-i386 architecture-dependent
|
||||
## subdirectories.
|
||||
@@ -220,3 +222,7 @@ ln -sf ../../i386/lib/usercopy.c
|
||||
cd ../mm
|
||||
ln -sf ../../i386/mm/extable.c
|
||||
ln -sf ../../i386/mm/pageattr.c
|
||||
cd ../drivers/console
|
||||
ln -sf ../../../../${LINUX_26}/drivers/xen/console/console.c
|
||||
#cd ../netif/frontend
|
||||
#ln -sf ../../../../../${LINUX_26}/drivers/xen/net/network.c main.c
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/signal.h>
|
||||
@@ -22,12 +23,12 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <asm-xen/evtchn.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/hypervisor.h>
|
||||
#include <asm/hypervisor-ifs/event_channel.h>
|
||||
#include <asm-xen/evtchn.h>
|
||||
#include <asm-xen/ctrl_if.h>
|
||||
|
||||
/*
|
||||
@@ -63,22 +64,24 @@ static unsigned int wc, wp; /* write_cons, write_prod */
|
||||
/* This lock protects accesses to the common transmit buffer. */
|
||||
static spinlock_t xencons_lock = SPIN_LOCK_UNLOCKED;
|
||||
|
||||
static struct tty_driver *xencons_driver;
|
||||
|
||||
#define NUM_XENCONS 1
|
||||
|
||||
/* Common transmit-kick routine. */
|
||||
static void __xencons_tx_flush(void);
|
||||
|
||||
/* This task is used to defer sending console data until there is space. */
|
||||
static void xencons_tx_flush_task_routine(void *data);
|
||||
#if 0 /* XXXcl tq */
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||
static struct tty_driver *xencons_driver;
|
||||
static DECLARE_WORK(xencons_tx_flush_task,
|
||||
xencons_tx_flush_task_routine,
|
||||
NULL);
|
||||
#else
|
||||
static struct tty_driver xencons_driver;
|
||||
static struct tq_struct xencons_tx_flush_task = {
|
||||
routine: xencons_tx_flush_task_routine
|
||||
};
|
||||
#else
|
||||
static DECLARE_WORK(xencons_tx_flush_task, xencons_tx_flush_task_routine,
|
||||
NULL);
|
||||
#define irqreturn_t void
|
||||
#define IRQ_HANDLED
|
||||
#endif
|
||||
|
||||
|
||||
@@ -112,7 +115,8 @@ static void kcons_write_dom0(
|
||||
|
||||
while ( count > 0 )
|
||||
{
|
||||
if ( (rc = HYPERVISOR_console_io(CONSOLEIO_write, count, (char *)s)) > 0 )
|
||||
if ( (rc = HYPERVISOR_console_io(CONSOLEIO_write,
|
||||
count, (char *)s)) > 0 )
|
||||
{
|
||||
count -= rc;
|
||||
s += rc;
|
||||
@@ -122,11 +126,18 @@ static void kcons_write_dom0(
|
||||
}
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||
static struct tty_driver *kcons_device(struct console *c, int *index)
|
||||
{
|
||||
*index = c->index;
|
||||
return xencons_driver;
|
||||
}
|
||||
#else
|
||||
static kdev_t kcons_device(struct console *c)
|
||||
{
|
||||
return MKDEV(TTY_MAJOR, (xc_mode == XC_SERIAL) ? 64 : 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct console kcons_info = {
|
||||
device: kcons_device,
|
||||
@@ -134,7 +145,13 @@ static struct console kcons_info = {
|
||||
index: -1
|
||||
};
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||
#define __RETCODE 0
|
||||
static int __init xen_console_init(void)
|
||||
#else
|
||||
#define __RETCODE
|
||||
void xen_console_init(void)
|
||||
#endif
|
||||
{
|
||||
if ( start_info.flags & SIF_INITDOMAIN )
|
||||
{
|
||||
@@ -150,7 +167,7 @@ static int __init xen_console_init(void)
|
||||
}
|
||||
|
||||
if ( xc_mode == XC_OFF )
|
||||
return 0;
|
||||
return __RETCODE;
|
||||
|
||||
if ( xc_mode == XC_SERIAL )
|
||||
strcpy(kcons_info.name, "ttyS");
|
||||
@@ -158,10 +175,11 @@ static int __init xen_console_init(void)
|
||||
strcpy(kcons_info.name, "tty");
|
||||
|
||||
register_console(&kcons_info);
|
||||
return 0;
|
||||
return __RETCODE;
|
||||
}
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||
console_initcall(xen_console_init);
|
||||
|
||||
#endif
|
||||
|
||||
/*** Useful function for console debugging -- goes straight to Xen. ***/
|
||||
asmlinkage int xprintk(const char *fmt, ...)
|
||||
@@ -223,6 +241,16 @@ void xencons_force_flush(void)
|
||||
|
||||
/******************** User-space console driver (/dev/console) ************/
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||
#define DRV(_d) (_d)
|
||||
#define TTY_INDEX(_tty) ((_tty)->index)
|
||||
#else
|
||||
static int xencons_refcount;
|
||||
static struct tty_struct *xencons_table[MAX_NR_CONSOLES];
|
||||
#define DRV(_d) (&(_d))
|
||||
#define TTY_INDEX(_tty) (MINOR((_tty)->device) - xencons_driver.minor_start)
|
||||
#endif
|
||||
|
||||
static struct termios *xencons_termios[MAX_NR_CONSOLES];
|
||||
static struct termios *xencons_termios_locked[MAX_NR_CONSOLES];
|
||||
static struct tty_struct *xencons_tty;
|
||||
@@ -284,11 +312,7 @@ static void __xencons_tx_flush(void)
|
||||
|
||||
if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 )
|
||||
x_char = 0;
|
||||
#if 0 /* XXXcl tq */
|
||||
else if ( ctrl_if_enqueue_space_callback(&xencons_tx_flush_task) )
|
||||
#else
|
||||
else if ( ctrl_if_enqueue_space_callback(&xencons_tx_flush_task) )
|
||||
#endif
|
||||
break;
|
||||
|
||||
work_done = 1;
|
||||
@@ -309,11 +333,7 @@ static void __xencons_tx_flush(void)
|
||||
|
||||
if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 )
|
||||
wc += sz;
|
||||
#if 0 /* XXXcl tq */
|
||||
else if ( ctrl_if_enqueue_space_callback(&xencons_tx_flush_task) )
|
||||
#else
|
||||
else if ( ctrl_if_enqueue_space_callback(&xencons_tx_flush_task) )
|
||||
#endif
|
||||
break;
|
||||
|
||||
work_done = 1;
|
||||
@@ -339,7 +359,8 @@ static void xencons_tx_flush_task_routine(void *data)
|
||||
}
|
||||
|
||||
/* Privileged receive callback and transmit kicker. */
|
||||
static irqreturn_t xencons_priv_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
static irqreturn_t xencons_priv_interrupt(int irq, void *dev_id,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
static char rbuf[16];
|
||||
int i, l;
|
||||
@@ -379,6 +400,9 @@ static void xencons_send_xchar(struct tty_struct *tty, char ch)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if ( TTY_INDEX(tty) != 0 )
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&xencons_lock, flags);
|
||||
x_char = ch;
|
||||
__xencons_tx_flush();
|
||||
@@ -387,12 +411,18 @@ static void xencons_send_xchar(struct tty_struct *tty, char ch)
|
||||
|
||||
static void xencons_throttle(struct tty_struct *tty)
|
||||
{
|
||||
if ( TTY_INDEX(tty) != 0 )
|
||||
return;
|
||||
|
||||
if ( I_IXOFF(tty) )
|
||||
xencons_send_xchar(tty, STOP_CHAR(tty));
|
||||
}
|
||||
|
||||
static void xencons_unthrottle(struct tty_struct *tty)
|
||||
{
|
||||
if ( TTY_INDEX(tty) != 0 )
|
||||
return;
|
||||
|
||||
if ( I_IXOFF(tty) )
|
||||
{
|
||||
if ( x_char != 0 )
|
||||
@@ -406,6 +436,9 @@ static void xencons_flush_buffer(struct tty_struct *tty)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if ( TTY_INDEX(tty) != 0 )
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&xencons_lock, flags);
|
||||
wc = wp = 0;
|
||||
spin_unlock_irqrestore(&xencons_lock, flags);
|
||||
@@ -429,6 +462,9 @@ static int xencons_write(struct tty_struct *tty, int from_user,
|
||||
if ( from_user && verify_area(VERIFY_READ, buf, count) )
|
||||
return -EINVAL;
|
||||
|
||||
if ( TTY_INDEX(tty) != 0 )
|
||||
return count;
|
||||
|
||||
spin_lock_irqsave(&xencons_lock, flags);
|
||||
|
||||
for ( i = 0; i < count; i++ )
|
||||
@@ -454,6 +490,9 @@ static void xencons_put_char(struct tty_struct *tty, u_char ch)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if ( TTY_INDEX(tty) != 0 )
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&xencons_lock, flags);
|
||||
(void)__xencons_put_char(ch);
|
||||
spin_unlock_irqrestore(&xencons_lock, flags);
|
||||
@@ -463,6 +502,9 @@ static void xencons_flush_chars(struct tty_struct *tty)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if ( TTY_INDEX(tty) != 0 )
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&xencons_lock, flags);
|
||||
__xencons_tx_flush();
|
||||
spin_unlock_irqrestore(&xencons_lock, flags);
|
||||
@@ -472,7 +514,10 @@ static void xencons_wait_until_sent(struct tty_struct *tty, int timeout)
|
||||
{
|
||||
unsigned long orig_jiffies = jiffies;
|
||||
|
||||
while ( tty->driver->chars_in_buffer(tty) )
|
||||
if ( TTY_INDEX(tty) != 0 )
|
||||
return;
|
||||
|
||||
while ( DRV(tty->driver)->chars_in_buffer(tty) )
|
||||
{
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(1);
|
||||
@@ -487,16 +532,12 @@ static void xencons_wait_until_sent(struct tty_struct *tty, int timeout)
|
||||
|
||||
static int xencons_open(struct tty_struct *tty, struct file *filp)
|
||||
{
|
||||
int line;
|
||||
unsigned long flags;
|
||||
|
||||
MOD_INC_USE_COUNT;
|
||||
line = tty->index;
|
||||
if ( line < 0 || line >= NUM_XENCONS )
|
||||
{
|
||||
MOD_DEC_USE_COUNT;
|
||||
if ( TTY_INDEX(tty) != 0 )
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
MOD_INC_USE_COUNT;
|
||||
|
||||
spin_lock_irqsave(&xencons_lock, flags);
|
||||
tty->driver_data = NULL;
|
||||
@@ -512,12 +553,15 @@ static void xencons_close(struct tty_struct *tty, struct file *filp)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if ( TTY_INDEX(tty) != 0 )
|
||||
return;
|
||||
|
||||
if ( tty->count == 1 )
|
||||
{
|
||||
tty->closing = 1;
|
||||
tty_wait_until_sent(tty, 0);
|
||||
if ( tty->driver->flush_buffer != NULL )
|
||||
tty->driver->flush_buffer(tty);
|
||||
if ( DRV(tty->driver)->flush_buffer != NULL )
|
||||
DRV(tty->driver)->flush_buffer(tty);
|
||||
if ( tty->ldisc.flush_buffer != NULL )
|
||||
tty->ldisc.flush_buffer(tty);
|
||||
tty->closing = 0;
|
||||
@@ -529,6 +573,7 @@ static void xencons_close(struct tty_struct *tty, struct file *filp)
|
||||
MOD_DEC_USE_COUNT;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||
static struct tty_operations xencons_ops = {
|
||||
.open = xencons_open,
|
||||
.close = xencons_close,
|
||||
@@ -543,42 +588,66 @@ static struct tty_operations xencons_ops = {
|
||||
.unthrottle = xencons_unthrottle,
|
||||
.wait_until_sent = xencons_wait_until_sent,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int __init xencons_init(void)
|
||||
{
|
||||
xencons_driver = alloc_tty_driver(NUM_XENCONS); /* XXX */
|
||||
if (!xencons_driver)
|
||||
return -ENOMEM;
|
||||
|
||||
xencons_driver->major = TTY_MAJOR;
|
||||
xencons_driver->type = TTY_DRIVER_TYPE_SERIAL;
|
||||
xencons_driver->subtype = SERIAL_TYPE_NORMAL;
|
||||
xencons_driver->init_termios = tty_std_termios;
|
||||
xencons_driver->flags =
|
||||
TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_NO_DEVFS;
|
||||
xencons_driver->termios = xencons_termios;
|
||||
xencons_driver->termios_locked = xencons_termios_locked;
|
||||
|
||||
if ( xc_mode == XC_OFF )
|
||||
return 0;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||
xencons_driver = alloc_tty_driver((xc_mode == XC_SERIAL) ?
|
||||
1 : MAX_NR_CONSOLES);
|
||||
if ( xencons_driver == NULL )
|
||||
return -ENOMEM;
|
||||
#else
|
||||
memset(&xencons_driver, 0, sizeof(struct tty_driver));
|
||||
xencons_driver.magic = TTY_DRIVER_MAGIC;
|
||||
xencons_driver.refcount = &xencons_refcount;
|
||||
xencons_driver.table = xencons_table;
|
||||
xencons_driver.num = (xc_mode == XC_SERIAL) ? 1 : MAX_NR_CONSOLES;
|
||||
#endif
|
||||
|
||||
DRV(xencons_driver)->major = TTY_MAJOR;
|
||||
DRV(xencons_driver)->type = TTY_DRIVER_TYPE_SERIAL;
|
||||
DRV(xencons_driver)->subtype = SERIAL_TYPE_NORMAL;
|
||||
DRV(xencons_driver)->init_termios = tty_std_termios;
|
||||
DRV(xencons_driver)->flags =
|
||||
TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_NO_DEVFS;
|
||||
DRV(xencons_driver)->termios = xencons_termios;
|
||||
DRV(xencons_driver)->termios_locked = xencons_termios_locked;
|
||||
|
||||
if ( xc_mode == XC_SERIAL )
|
||||
{
|
||||
xencons_driver->name = "ttyS";
|
||||
xencons_driver->minor_start = 64;
|
||||
xencons_driver->num = 1;
|
||||
DRV(xencons_driver)->name = "ttyS";
|
||||
DRV(xencons_driver)->minor_start = 64;
|
||||
}
|
||||
else
|
||||
{
|
||||
xencons_driver->name = "tty";
|
||||
xencons_driver->minor_start = 1;
|
||||
xencons_driver->num = MAX_NR_CONSOLES;
|
||||
DRV(xencons_driver)->name = "tty";
|
||||
DRV(xencons_driver)->minor_start = 1;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||
tty_set_operations(xencons_driver, &xencons_ops);
|
||||
#else
|
||||
xencons_driver.open = xencons_open;
|
||||
xencons_driver.close = xencons_close;
|
||||
xencons_driver.write = xencons_write;
|
||||
xencons_driver.write_room = xencons_write_room;
|
||||
xencons_driver.put_char = xencons_put_char;
|
||||
xencons_driver.flush_chars = xencons_flush_chars;
|
||||
xencons_driver.chars_in_buffer = xencons_chars_in_buffer;
|
||||
xencons_driver.send_xchar = xencons_send_xchar;
|
||||
xencons_driver.flush_buffer = xencons_flush_buffer;
|
||||
xencons_driver.throttle = xencons_throttle;
|
||||
xencons_driver.unthrottle = xencons_unthrottle;
|
||||
xencons_driver.wait_until_sent = xencons_wait_until_sent;
|
||||
#endif
|
||||
|
||||
if ( tty_register_driver(xencons_driver) )
|
||||
panic("Couldn't register Xen virtual console driver as %s\n",xencons_driver->name);
|
||||
if ( tty_register_driver(DRV(xencons_driver)) )
|
||||
panic("Couldn't register Xen virtual console driver as %s\n",
|
||||
DRV(xencons_driver)->name);
|
||||
|
||||
if ( start_info.flags & SIF_INITDOMAIN )
|
||||
{
|
||||
@@ -591,7 +660,8 @@ static int __init xencons_init(void)
|
||||
(void)ctrl_if_register_receiver(CMSG_CONSOLE, xencons_rx, 0);
|
||||
}
|
||||
|
||||
printk("Xen virtual console successfully installed as %s\n",xencons_driver->name);
|
||||
printk("Xen virtual console successfully installed as %s\n",
|
||||
DRV(xencons_driver)->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -600,7 +670,7 @@ static void __exit xencons_fini(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ( (ret = tty_unregister_driver(xencons_driver)) != 0 )
|
||||
if ( (ret = tty_unregister_driver(DRV(xencons_driver))) != 0 )
|
||||
printk(KERN_ERR "Unable to unregister Xen console driver: %d\n", ret);
|
||||
|
||||
if ( start_info.flags & SIF_INITDOMAIN )
|
||||
|
||||