* All rights reserved.
*
* Author: Rumou Duan <duanrumou@gmail.com>
+ * Lei Xia <lxia@northwestern.edu>
*
* This is free software. You are permitted to use,
* redistribute, and modify it as specified in the file "V3VEE_LICENSE".
#include <palacios/vmm_host_events.h>
#include <palacios/vm_guest.h>
+#include <devices/serial.h>
+
+
+#ifndef CONFIG_DEBUG_SERIAL
+#undef PrintDebug
+#define PrintDebug(fmt, args...)
+#endif
+
#define COM1_DATA_PORT 0x3f8
#define COM1_IRQ_ENABLE_PORT 0x3f9
struct serial_buffer tx_buffer;
struct serial_buffer rx_buffer;
uint_t irq_number;
+
+ struct v3_stream_ops *stream_ops;
+ void *backend_data;
+
+ struct vm_device * vm_dev;
};
return 0;
}
-/*
-static void printBuffer(struct serial_buffer * buf) {
- int i = 0;
-
- for (i = 0; i < SERIAL_BUF_LEN; i++) {
- PrintDebug(" %d ", buf->buffer[i]);
- }
-
- PrintDebug("\n the number of elements is %d \n", getNumber(buf));
-}
-*/
-
-//note: write to data port is NOT implemented and corresponding codes are commented out
static int write_data_port(struct guest_info * core, uint16_t port,
void * src, uint_t length, struct vm_device * dev) {
struct serial_state * state = (struct serial_state *)dev->private_data;
com_port->dll.data = *val;
} else {
queue_data(&(com_port->tx_buffer), *val, com_port, dev);
+ if (com_port->stream_ops) {
+ uint8_t c;
+ dequeue_data(&(com_port->tx_buffer), &c, com_port, dev);
+ com_port->stream_ops->write(&c,1,com_port->backend_data);
+ }
}
*val = com_port->dll.data;
} else {
dequeue_data(&(com_port->rx_buffer), val, com_port, dev);
- }
-
+ }
+
return length;
}
return 0;
}
+static int serial_input(char *buf, uint_t len, void *front_data){
+ struct serial_port *com_port = (struct serial_port *)front_data;
+ int i;
+
+ for(i=0; i<len; i++){
+ queue_data(&(com_port->rx_buffer), buf[i], com_port, com_port->vm_dev);
+ }
+
+ return len;
+}
+
static int serial_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
struct serial_state * state = (struct serial_state *)V3_Malloc(sizeof(struct serial_state));
char * dev_id = v3_cfg_val(cfg, "ID");
- PrintDebug("UART: init_device\n");
init_serial_port(&(state->com1));
init_serial_port(&(state->com2));
init_serial_port(&(state->com3));
state->com3.irq_number = COM3_IRQ;
state->com4.irq_number = COM4_IRQ;
-
struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, state);
-
if (v3_attach_device(vm, dev) == -1) {
PrintError("Could not attach device %s\n", dev_id);
return -1;
}
+ state->com1.vm_dev = dev;
+ state->com2.vm_dev = dev;
+ state->com3.vm_dev = dev;
+ state->com4.vm_dev = dev;
+
+ PrintDebug("Serial device attached\n");
+
v3_dev_hook_io(dev, COM1_DATA_PORT, &read_data_port, &write_data_port);
v3_dev_hook_io(dev, COM1_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
v3_dev_hook_io(dev, COM1_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
v3_dev_hook_io(dev, COM4_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
v3_dev_hook_io(dev, COM4_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
+ PrintDebug("Serial ports hooked\n");
+
+ return 0;
+}
+
+int v3_stream_register_serial(struct vm_device * serial_dev, struct v3_stream_ops * ops, void * private_data)
+{
+ struct serial_state *state = (struct serial_state *)(serial_dev->private_data);
+
+ state->com1.stream_ops = ops;
+ state->com1.backend_data = private_data;
+ /* bind to other ports here */
+
+ ops->input = serial_input;
+ ops->front_data = &(state->com1);
+
return 0;
}