Hi.
Implemented xen hpsimsieral input routine.
To use this CONFIG_XEN_CONSOLE_INPUT should be defined.
NOTE:
The modification of xen_do_IRQ() is a temporal work around.
I think ns16550 driver also have similar problem on IA-64.
diff -r 0255f48b757f -r 7f581d389113 xen/arch/ia64/xen/domain.c
--- a/xen/arch/ia64/xen/domain.c Sun Dec 4 20:12:00 2005 +0100
+++ b/xen/arch/ia64/xen/domain.c Wed Dec 14 21:00:58 2005 +0900
@@ -961,7 +961,6 @@
#ifdef CLONE_DOMAIN0
if (d == dom0)
#endif
- serial_input_init();
if (d == dom0) {
VCPU(v, delivery_mask[0]) = -1L;
VCPU(v, delivery_mask[1]) = -1L;
diff -r 0255f48b757f -r 7f581d389113 xen/arch/ia64/xen/hpsimserial.c
--- a/xen/arch/ia64/xen/hpsimserial.c Sun Dec 4 20:12:00 2005 +0100
+++ b/xen/arch/ia64/xen/hpsimserial.c Wed Dec 14 21:00:58 2005 +0900
@@ -3,21 +3,158 @@
*
* Copyright (C) 2004 Hewlett-Packard Co
* Dan Magenheimer <dan.magenheimer@xxxxxx>
+ * Copyright (C) 2005 VA Linux Systema Japan K.K.
+ * Isaku Yamahata <yamahata at valinux.co.jp>
*/
#include <linux/config.h>
#include <xen/sched.h>
#include <xen/serial.h>
+#include <xen/irq.h>
+#include <asm/linux/asm/hw_irq.h>
+
#include "hpsim_ssc.h"
-static void hp_ski_putc(struct serial_port *port, char c)
+static struct hpsimserial {
+ int is_saved;
+ unsigned char save;
+
+ int irq;
+ struct irqaction irqaction;
+} hpsimserial;
+
+static char opt_hpsimserial[30] = "";
+string_param("hpsimserial", opt_hpsimserial);
+
+// return value
+// 0: there is no char left.
+// !0: there is char to be get.
+static int
+hp_ski_peek(struct hpsimserial* uart)
+{
+ if (!uart->is_saved) {
+ uart->save = ia64_ssc(0, 0, 0, 0, SSC_GETCHAR);
+ if (uart->save) {
+ uart->is_saved = 1;
+ }
+ }
+ return uart->is_saved;
+}
+
+static void
+hp_ski_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
+{
+ struct serial_port *port = dev_id;
+ struct hpsimserial *uart = port->uart;
+
+ while (hp_ski_peek(uart)) {
+ serial_rx_interrupt(port, regs);
+ }
+}
+
+static void
+hp_ski_init_preirq(struct serial_port *port)
+{
+ // nothing
+}
+
+static void
+hp_ski_init_postirq(struct serial_port *port)
+{
+ int rc;
+ struct hpsimserial* uart = port->uart;
+
+ uart->irqaction.handler = hp_ski_interrupt;
+ uart->irqaction.name = "hpsimserial";
+ uart->irqaction.dev_id = port;
+ if (uart->irq == 0) {
+ uart->irq = assign_irq_vector(AUTO_ASSIGN);
+ if (uart->irq < 0) {
+ panic("%s: out of interrupt vectors!\n", __func__);
+ }
+ }
+
+ printk("hpsimserial: irq = %d 0x%x\n", uart->irq, uart->irq);
+ rc = setup_irq(uart->irq, &uart->irqaction);
+ if (rc) {
+ printk("ERROR: Failed to allocate hpsimserial IRQ %d 0x%x\n",
+ uart->irq, uart->irq);
+ } else {
+ port->rx = serial_rx;
+#define KEYBOARD_INTR 3 /* must match with simulator! */
+ ia64_ssc(KEYBOARD_INTR, uart->irq, 0, 0, SSC_CONNECT_INTERRUPT);
+ }
+}
+
+static void
+hp_ski_endboot(struct serial_port* port)
+{
+ // nothing
+}
+
+static int
+hp_ski_tx_empty()
+{
+ return 1;
+}
+
+// return value
+// 0: no char left
+// !0: success to read char
+static int
+hp_ski_getc(struct serial_port *port, char *pc)
+{
+ struct hpsimserial* uart = port->uart;
+
+ if (!uart->is_saved) {
+ uart->save = ia64_ssc(0, 0, 0, 0, SSC_GETCHAR);
+ if (!uart->save) {
+ return 0;
+ }
+ }
+
+ *pc = uart->save;
+ uart->is_saved = 0;
+ return 1;
+}
+
+static void
+hp_ski_putc(struct serial_port *port, char c)
{
ia64_ssc(c,0,0,0,SSC_PUTCHAR);
}
-static struct uart_driver hp_ski = { .putc = hp_ski_putc };
+static struct uart_driver hp_ski = {
+ .init_preirq = hp_ski_init_preirq,
+ .init_postirq = hp_ski_init_postirq,
+ .endboot = hp_ski_endboot,
+ .tx_empty = hp_ski_tx_empty,
+ .putc = hp_ski_putc,
+ .getc = hp_ski_getc
+};
-void hpsim_serial_init(void)
+static void
+hp_ski_parse_config(struct hpsimserial* uart, const char* conf)
{
- serial_register_uart(0, &hp_ski, 0);
+ if (conf == NULL || *conf == '\0') {
+ return;
+ }
+ uart->irq = simple_strtoul(conf, &conf, 0);
}
+
+void
+hpsim_serial_init(void)
+{
+ hpsimserial.is_saved = 0;
+ hp_ski_parse_config(&hpsimserial, opt_hpsimserial);
+ serial_register_uart(0, &hp_ski, &hpsimserial);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
diff -r 0255f48b757f -r 7f581d389113 xen/arch/ia64/xen/irq.c
--- a/xen/arch/ia64/xen/irq.c Sun Dec 4 20:12:00 2005 +0100
+++ b/xen/arch/ia64/xen/irq.c Wed Dec 14 21:00:58 2005 +0900
@@ -1479,25 +1479,3 @@
}
#endif
-
-#ifdef XEN
-#ifdef IA64
-// this is a temporary hack until real console input is implemented
-irqreturn_t guest_forward_keyboard_input(int irq, void *nada, struct pt_regs
*regs)
-{
- domain_pend_keyboard_interrupt(irq);
-}
-
-void serial_input_init(void)
-{
- int retval;
- int irq = 0x30; // FIXME
-
- retval =
request_irq(irq,guest_forward_keyboard_input,SA_INTERRUPT,"siminput",NULL);
- if (retval) {
- printk("serial_input_init: broken request_irq call\n");
- while(1);
- }
-}
-#endif
-#endif
diff -r 0255f48b757f -r 7f581d389113 xen/arch/ia64/xen/xenirq.c
--- a/xen/arch/ia64/xen/xenirq.c Sun Dec 4 20:12:00 2005 +0100
+++ b/xen/arch/ia64/xen/xenirq.c Wed Dec 14 21:00:58 2005 +0900
@@ -35,7 +35,8 @@
int
xen_do_IRQ(ia64_vector vector)
{
- if (vector != IA64_TIMER_VECTOR && vector != IA64_IPI_VECTOR) {
+ if (vector != IA64_TIMER_VECTOR && vector != IA64_IPI_VECTOR &&
+ vector != 0x30) {//XXX
extern void vcpu_pend_interrupt(void *, int);
#if 0
if (firsttime[vector]) {
diff -r 0255f48b757f -r 7f581d389113 xen/drivers/char/console.c
--- a/xen/drivers/char/console.c Sun Dec 4 20:12:00 2005 +0100
+++ b/xen/drivers/char/console.c Wed Dec 14 21:00:58 2005 +0900
@@ -286,7 +286,7 @@
send_guest_virq(dom0->vcpu[0], VIRQ_CONSOLE);
}
-static void serial_rx(char c, struct cpu_user_regs *regs)
+void serial_rx(char c, struct cpu_user_regs *regs)
{
static int switch_code_count = 0;
diff -r 0255f48b757f -r 7f581d389113 xen/include/xen/serial.h
--- a/xen/include/xen/serial.h Sun Dec 4 20:12:00 2005 +0100
+++ b/xen/include/xen/serial.h Wed Dec 14 21:00:58 2005 +0900
@@ -14,6 +14,7 @@
/* Register a character-receive hook on the specified COM port. */
typedef void (*serial_rx_fn)(char, struct cpu_user_regs *);
void serial_set_rx_handler(int handle, serial_rx_fn fn);
+void serial_rx(char c, struct cpu_user_regs *regs);// default rx handler
/* Number of characters we buffer for a polling receiver. */
#define SERIAL_RXBUFSZ 32
--
yamahata
_______________________________________________
Xen-ia64-devel mailing list
Xen-ia64-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ia64-devel
|