* 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_ringbuffer.h>
#include <palacios/vmm_lock.h>
#include <palacios/vmm_intr.h>
-#include <palacios/vmm_host_events.h>
#include <palacios/vm_guest.h>
#include <devices/serial.h>
struct serial_buffer rx_buffer;
uint_t irq_number;
- struct v3_stream_ops *stream_ops;
- void *backend_data;
+
+ void * backend_data;
+ struct v3_dev_char_ops * ops;
};
struct serial_state {
- struct serial_port com1;
- struct serial_port com2;
- struct serial_port com3;
- struct serial_port com4;
+ struct serial_port coms[4];
-
};
static struct serial_port * get_com_from_port(struct serial_state * serial, uint16_t port) {
if ((port >= COM1_DATA_PORT) && (port <= COM1_SCRATCH_PORT)) {
- return &(serial->com1);
+ return &(serial->coms[0]);
} else if ((port >= COM2_DATA_PORT) && (port <= COM2_SCRATCH_PORT)) {
- return &(serial->com2);
+ return &(serial->coms[1]);
} else if ((port >= COM3_DATA_PORT) && (port <= COM3_SCRATCH_PORT)) {
- return &(serial->com3);
+ return &(serial->coms[2]);
} else if ((port >= COM4_DATA_PORT) && (port <= COM4_SCRATCH_PORT)) {
- return &(serial->com4);
+ return &(serial->coms[3]);
} else {
PrintError("Error: Could not find serial port associated with IO port %d\n", port);
return NULL;
}
}
-static int updateIRQ(struct serial_port * com, struct vm_device * dev) {
+static int updateIRQ(struct v3_vm_info * vm, struct serial_port * com) {
if ( (com->ier.erbfi == 0x1) &&
(receive_buffer_trigger( getNumber(&(com->rx_buffer)), com->fcr.rx_trigger)) ) {
- PrintDebug("UART: receive buffer interrupt(trigger level reached)");
+ PrintDebug("UART: receive buffer interrupt(trigger level reached)\n");
com->iir.iid = RX_IRQ_TRIGGER_LEVEL;
- v3_raise_irq(dev->vm, com->irq_number);
+ v3_raise_irq(vm, com->irq_number);
}
if ( (com->iir.iid == RX_IRQ_TRIGGER_LEVEL) &&
} else if ( (com->ier.etbei == 0x1) &&
(getNumber(&(com->tx_buffer)) != SERIAL_BUF_LEN )) {
- PrintDebug("UART: transmit buffer interrupt(buffer not full)");
+ PrintDebug("UART: transmit buffer interrupt(buffer not full)\n");
com->iir.iid = TX_IRQ_THRE;
com->iir.pending = 0;
- v3_raise_irq(dev->vm, com->irq_number);
+ v3_raise_irq(vm, com->irq_number);
}
return 1;
}
-static int queue_data(struct serial_buffer * buf, uint8_t data,
- struct serial_port * com, struct vm_device * dev) {
-
+static int queue_data(struct v3_vm_info * vm, struct serial_port * com,
+ struct serial_buffer * buf, uint8_t data) {
int next_loc = (buf->head + 1) % SERIAL_BUF_LEN;
if (buf->full == 1) {
com->lsr.temt = 0;
}
- updateIRQ(com, dev);
+ updateIRQ(vm, com);
return 0;
}
-static int dequeue_data(struct serial_buffer * buf, uint8_t * data,
- struct serial_port * com, struct vm_device * dev) {
+static int dequeue_data(struct v3_vm_info * vm, struct serial_port * com,
+ struct serial_buffer * buf, uint8_t * data) {
int next_tail = (buf->tail + 1) % SERIAL_BUF_LEN;
com->lsr.temt = 1;
}
- updateIRQ(com, dev);
+ updateIRQ(vm, com);
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;
+ void * src, uint_t length, void * priv_data) {
+ struct serial_state * state = priv_data;
uint8_t * val = (uint8_t *)src;
struct serial_port * com_port = NULL;
PrintDebug("Write to Data Port 0x%x (val=%x)\n", port, *val);
if (length != 1) {
- PrintDebug("Invalid length(%d) in write to 0x%x\n", length, port);
+ PrintError("Invalid length(%d) in write to 0x%x\n", length, port);
return -1;
}
com_port = get_com_from_port(state, port);
if (com_port == NULL) {
- PrintDebug("UART:read from NOBODY");
+ PrintError("UART:read from NOBODY\n");
return -1;
}
if (com_port->lcr.dlab == 1) {
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);
+
+
+ /* JRL: Some buffering would probably be a good idea here.... */
+ if (com_port->ops) {
+ com_port->ops->write(val, 1, com_port->backend_data);
+ } else {
+ queue_data(core->vm_info, com_port, &(com_port->tx_buffer), *val);
}
}
-
return length;
}
static int read_data_port(struct guest_info * core, uint16_t port,
- void * dst, uint_t length, struct vm_device * dev) {
- struct serial_state * state = (struct serial_state *)dev->private_data;
+ void * dst, uint_t length, void * priv_data) {
+ struct serial_state * state = priv_data;
uint8_t * val = (uint8_t *)dst;
struct serial_port * com_port = NULL;
PrintDebug("Read from Data Port 0x%x\n", port);
if (length != 1) {
- PrintDebug("Invalid length(%d) in write to 0x%x\n", length, port);
+ PrintError("Invalid length(%d) in write to 0x%x\n", length, port);
return -1;
}
com_port = get_com_from_port(state, port);
if (com_port == NULL) {
- PrintDebug("UART:read from NOBODY");
+ PrintError("UART:read from NOBODY\n");
return -1;
}
if (com_port->lcr.dlab == 1) {
*val = com_port->dll.data;
} else {
- dequeue_data(&(com_port->rx_buffer), val, com_port, dev);
- }
-
+ dequeue_data(core->vm_info, com_port, &(com_port->rx_buffer), val);
+ }
+
return length;
}
static int write_ctrl_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;
+ uint_t length, void * priv_data) {
+ struct serial_state * state = priv_data;
uint8_t val = *(uint8_t *)src;
struct serial_port * com_port = NULL;
PrintDebug("UART:Write to Control Port (val=%x)\n", val);
if (length != 1) {
- PrintDebug("UART:Invalid Write length to control port%d\n", port);
+ PrintError("UART:Invalid Write length to control port%d\n", port);
return -1;
}
case COM2_FIFO_CTRL_PORT:
case COM3_FIFO_CTRL_PORT:
case COM4_FIFO_CTRL_PORT: {
- PrintDebug("UART:Write to FCR");
+ PrintDebug("UART:Write to FCR\n");
if (handle_fcr_write(com_port, val) == -1) {
return -1;
case COM2_LINE_CTRL_PORT:
case COM3_LINE_CTRL_PORT:
case COM4_LINE_CTRL_PORT: {
- PrintDebug("UART:Write to LCR");
+ PrintDebug("UART:Write to LCR\n");
com_port->lcr.val = val;
break;
}
case COM2_MODEM_CTRL_PORT:
case COM3_MODEM_CTRL_PORT:
case COM4_MODEM_CTRL_PORT: {
- PrintDebug("UART:Write to MCR");
+ PrintDebug("UART:Write to MCR\n");
com_port->mcr.val = val;
break;
}
case COM2_SCRATCH_PORT:
case COM3_SCRATCH_PORT:
case COM4_SCRATCH_PORT: {
- PrintDebug("UART:Write to SCRATCH");
+ PrintDebug("UART:Write to SCRATCH\n");
com_port->scr.data = val;
break;
}
default:
- PrintDebug("UART:Write to NOBODY, ERROR");
+ PrintError("UART:Write to NOBODY, ERROR\n");
return -1;
}
static int read_ctrl_port(struct guest_info * core, uint16_t port, void * dst,
- uint_t length, struct vm_device * dev) {
- struct serial_state * state = (struct serial_state *)dev->private_data;
+ uint_t length, void * priv_data) {
+ struct serial_state * state = priv_data;
uint8_t * val = (uint8_t *)dst;
struct serial_port * com_port = NULL;
PrintDebug("Read from Control Port\n");
if (length != 1) {
- PrintDebug("Invalid Read length to control port\n");
+ PrintError("Invalid Read length to control port\n");
return -1;
}
case COM2_IRQ_ENABLE_PORT:
case COM3_IRQ_ENABLE_PORT:
case COM4_IRQ_ENABLE_PORT: {
- PrintDebug("UART:read from IER");
+ PrintDebug("UART:read from IER\n");
if (com_port->lcr.dlab == 1) {
*val = com_port->dlm.data;
break;
}
- case COM1_FIFO_CTRL_PORT:
- case COM2_FIFO_CTRL_PORT:
- case COM3_FIFO_CTRL_PORT:
- case COM4_FIFO_CTRL_PORT:
- PrintDebug("UART:read from FCR");
- *val = com_port->fcr.val;
+ case COM1_IIR_PORT:
+ case COM2_IIR_PORT:
+ case COM3_IIR_PORT:
+ case COM4_IIR_PORT:
+ PrintDebug("UART:read from IIR\n");
+ *val = com_port->iir.val;
break;
case COM1_LINE_CTRL_PORT:
case COM2_LINE_CTRL_PORT:
case COM3_LINE_CTRL_PORT:
case COM4_LINE_CTRL_PORT:
- PrintDebug("UART:read from LCR");
+ PrintDebug("UART:read from LCR\n");
*val = com_port->lcr.val;
break;
case COM2_MODEM_CTRL_PORT:
case COM3_MODEM_CTRL_PORT:
case COM4_MODEM_CTRL_PORT:
- PrintDebug("UART:read from MCR");
+ PrintDebug("UART:read from MCR\n");
*val = com_port->mcr.val;
break;
case COM2_SCRATCH_PORT:
case COM3_SCRATCH_PORT:
case COM4_SCRATCH_PORT:
- PrintDebug("UART:read from SCRATCH");
+ PrintDebug("UART:read from SCRATCH\n");
*val = com_port->scr.data;
break;
default:
- PrintDebug("UART:read from NOBODY");
+ PrintError("UART:read from NOBODY\n");
return -1;
}
static int write_status_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;
+ uint_t length, void * priv_data) {
+ struct serial_state * state = priv_data;
uint8_t val = *(uint8_t *)src;
struct serial_port * com_port = NULL;
PrintDebug("Write to Status Port (val=%x)\n", val);
if (length != 1) {
- PrintDebug("Invalid Write length to status port %d\n", port);
+ PrintError("Invalid Write length to status port %d\n", port);
return -1;
}
case COM2_LINE_STATUS_PORT:
case COM3_LINE_STATUS_PORT:
case COM4_LINE_STATUS_PORT:
- PrintDebug("UART:write to LSR");
+ PrintDebug("UART:write to LSR\n");
com_port->lsr.val = val;
break;
case COM2_MODEM_STATUS_PORT:
case COM3_MODEM_STATUS_PORT:
case COM4_MODEM_STATUS_PORT:
- PrintDebug("UART:write to MSR");
+ PrintDebug("UART:write to MSR\n");
com_port->msr.val = val;
break;
default:
- PrintDebug("UART:write to NOBODY");
+ PrintError("UART:write to NOBODY\n");
return -1;
}
}
static int read_status_port(struct guest_info * core, uint16_t port, void * dst,
- uint_t length, struct vm_device * dev) {
- struct serial_state * state = (struct serial_state *)dev->private_data;
+ uint_t length, void * priv_data) {
+ struct serial_state * state = priv_data;
uint8_t * val = (uint8_t *)dst;
struct serial_port * com_port = NULL;
PrintDebug("Read from Status Port 0x%x\n", port);
- if (length != 1) {
- PrintDebug("Invalid Read length to control port\n");
- return -1;
- }
-
com_port = get_com_from_port(state, port);
if (com_port == NULL) {
case COM2_LINE_STATUS_PORT:
case COM3_LINE_STATUS_PORT:
case COM4_LINE_STATUS_PORT:
- PrintDebug("UART:read from LSR");
+
+ if (length != 1) {
+ PrintError("Invalid Read length to control port\n");
+ return -1;
+ }
+
+ PrintDebug("UART:read from LSR\n");
*val = com_port->lsr.val;
com_port->lsr.oe = 0; // Why do we clear this??
case COM2_MODEM_STATUS_PORT:
case COM3_MODEM_STATUS_PORT:
case COM4_MODEM_STATUS_PORT:
- PrintDebug("UART:read from COM4 MSR");
+ PrintDebug("UART:read from COM4 MSR (length = %d)\n", length);
+
+ if (length > 2) {
+ PrintError("Invalid Read length to MSR port\n");
+ return -1;
+ }
+
+ if (length == 2) {
+ /* Windows XP expects to be able to read this register and the next in one go */
+
+ if (read_ctrl_port(core, port + 1, val + 1, 1, priv_data) < 0) {
+ PrintError("Error reading control port for word size read of Status register\n");
+ return -1;
+ }
+ }
+
+ // always read low byte...
+
*val = com_port->msr.val;
break;
default:
- PrintDebug("UART:read from NOBODY");
+ PrintError("UART:read from NOBODY (length = %d)\n", length);
return -1;
}
return length;
}
-static int serial_deinit(struct vm_device * dev) {
-
-
- v3_dev_unhook_io(dev, COM1_DATA_PORT);
- v3_dev_unhook_io(dev, COM1_IRQ_ENABLE_PORT);
- v3_dev_unhook_io(dev, COM1_FIFO_CTRL_PORT);
- v3_dev_unhook_io(dev, COM1_LINE_CTRL_PORT);
- v3_dev_unhook_io(dev, COM1_MODEM_CTRL_PORT);
- v3_dev_unhook_io(dev, COM1_LINE_STATUS_PORT);
- v3_dev_unhook_io(dev, COM1_MODEM_STATUS_PORT);
- v3_dev_unhook_io(dev, COM1_SCRATCH_PORT);
-
- v3_dev_unhook_io(dev, COM2_DATA_PORT);
- v3_dev_unhook_io(dev, COM2_IRQ_ENABLE_PORT);
- v3_dev_unhook_io(dev, COM2_FIFO_CTRL_PORT);
- v3_dev_unhook_io(dev, COM2_LINE_CTRL_PORT);
- v3_dev_unhook_io(dev, COM2_MODEM_CTRL_PORT);
- v3_dev_unhook_io(dev, COM2_LINE_STATUS_PORT);
- v3_dev_unhook_io(dev, COM2_MODEM_STATUS_PORT);
- v3_dev_unhook_io(dev, COM2_SCRATCH_PORT);
-
- v3_dev_unhook_io(dev, COM3_DATA_PORT);
- v3_dev_unhook_io(dev, COM3_IRQ_ENABLE_PORT);
- v3_dev_unhook_io(dev, COM3_FIFO_CTRL_PORT);
- v3_dev_unhook_io(dev, COM3_LINE_CTRL_PORT);
- v3_dev_unhook_io(dev, COM3_MODEM_CTRL_PORT);
- v3_dev_unhook_io(dev, COM3_LINE_STATUS_PORT);
- v3_dev_unhook_io(dev, COM3_MODEM_STATUS_PORT);
- v3_dev_unhook_io(dev, COM3_SCRATCH_PORT);
-
- v3_dev_unhook_io(dev, COM4_DATA_PORT);
- v3_dev_unhook_io(dev, COM4_IRQ_ENABLE_PORT);
- v3_dev_unhook_io(dev, COM4_FIFO_CTRL_PORT);
- v3_dev_unhook_io(dev, COM4_LINE_CTRL_PORT);
- v3_dev_unhook_io(dev, COM4_MODEM_CTRL_PORT);
- v3_dev_unhook_io(dev, COM4_LINE_STATUS_PORT);
- v3_dev_unhook_io(dev, COM4_MODEM_STATUS_PORT);
- v3_dev_unhook_io(dev, COM4_SCRATCH_PORT);
+static int serial_free(struct serial_state * state) {
+ V3_Free(state);
return 0;
}
static struct v3_device_ops dev_ops = {
- //.init = serial_init,
- .free = serial_deinit,
- .reset = NULL,
- .start = NULL,
- .stop = NULL,
+ .free = (int (*)(void *))serial_free,
};
com->rx_buffer.full = 0;
memset(com->rx_buffer.buffer, 0, SERIAL_BUF_LEN);
+ com->ops = NULL;
+ com->backend_data = NULL;
+
+ return 0;
+}
+
+static int serial_input(struct v3_vm_info * vm, uint8_t * buf, uint64_t len, void * priv_data){
+ struct serial_port * com_port = (struct serial_port *)priv_data;
+ int i;
+
+ for(i = 0; i < len; i++){
+ queue_data(vm, com_port, &(com_port->rx_buffer), buf[i]);
+ }
+
+ return len;
+}
+
+
+static int connect_fn(struct v3_vm_info * vm,
+ void * frontend_data,
+ struct v3_dev_char_ops * ops,
+ v3_cfg_tree_t * cfg,
+ void * private_data,
+ void ** push_fn_arg) {
+
+ struct serial_state * serial = (struct serial_state *)frontend_data;
+ struct serial_port * com = NULL;
+ char * com_port = v3_cfg_val(cfg, "com_port");
+ int com_idx = 0;
+
+ if (com_port == NULL) {
+ PrintError("Invalid Serial frontend config: missing \"com_port\"\n");
+ return -1;
+ }
+
+ com_idx = atoi(com_port) - 1;
+
+ if ((com_idx > 3) || (com_idx < 0)) {
+ PrintError("Invalid Com port (%s) \n", com_port);
+ return -1;
+ }
+
+ com = &(serial->coms[com_idx]);
+
+ com->ops = ops;
+ com->backend_data = private_data;
+
+ com->ops->push = serial_input;
+ *push_fn_arg = com;
+
return 0;
}
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));
+ struct serial_state * state = NULL;
char * dev_id = v3_cfg_val(cfg, "ID");
+ int ret = 0;
- PrintDebug("UART: init_device\n");
- init_serial_port(&(state->com1));
- init_serial_port(&(state->com2));
- init_serial_port(&(state->com3));
- init_serial_port(&(state->com4));
+ state = (struct serial_state *)V3_Malloc(sizeof(struct serial_state));
+
+ if (state == NULL) {
+ PrintError("Could not allocate Serial Device\n");
+ return -1;
+ }
+
+ memset(state, 0, sizeof(struct serial_state));
- state->com1.irq_number = COM1_IRQ;
- state->com2.irq_number = COM2_IRQ;
- state->com3.irq_number = COM3_IRQ;
- state->com4.irq_number = COM4_IRQ;
+ init_serial_port(&(state->coms[0]));
+ init_serial_port(&(state->coms[1]));
+ init_serial_port(&(state->coms[2]));
+ init_serial_port(&(state->coms[3]));
+ state->coms[0].irq_number = COM1_IRQ;
+ state->coms[1].irq_number = COM2_IRQ;
+ state->coms[2].irq_number = COM3_IRQ;
+ state->coms[3].irq_number = COM4_IRQ;
- struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, state);
- if (v3_attach_device(vm, dev) == -1) {
+ struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, state);
+
+ if (dev == NULL) {
PrintError("Could not attach device %s\n", dev_id);
+ V3_Free(state);
return -1;
}
- 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, COM1_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM1_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM1_LINE_STATUS_PORT, &read_status_port, &write_status_port);
- v3_dev_hook_io(dev, COM1_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
- v3_dev_hook_io(dev, COM1_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
-
- v3_dev_hook_io(dev, COM2_DATA_PORT, &read_data_port, &write_data_port);
- v3_dev_hook_io(dev, COM2_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM2_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM2_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM2_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM2_LINE_STATUS_PORT, &read_status_port, &write_status_port);
- v3_dev_hook_io(dev, COM2_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
- v3_dev_hook_io(dev, COM2_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
-
- v3_dev_hook_io(dev, COM3_DATA_PORT, &read_data_port, &write_data_port);
- v3_dev_hook_io(dev, COM3_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM3_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM3_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM3_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM3_LINE_STATUS_PORT, &read_status_port, &write_status_port);
- v3_dev_hook_io(dev, COM3_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
- v3_dev_hook_io(dev, COM3_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
-
- v3_dev_hook_io(dev, COM4_DATA_PORT, &read_data_port, &write_data_port);
- v3_dev_hook_io(dev, COM4_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM4_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM4_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM4_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM4_LINE_STATUS_PORT, &read_status_port, &write_status_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 device attached\n");
+
+ ret |= v3_dev_hook_io(dev, COM1_DATA_PORT, &read_data_port, &write_data_port);
+ ret |= v3_dev_hook_io(dev, COM1_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
+ ret |= v3_dev_hook_io(dev, COM1_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+ ret |= v3_dev_hook_io(dev, COM1_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+ ret |= v3_dev_hook_io(dev, COM1_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+ ret |= v3_dev_hook_io(dev, COM1_LINE_STATUS_PORT, &read_status_port, &write_status_port);
+ ret |= v3_dev_hook_io(dev, COM1_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
+ ret |= v3_dev_hook_io(dev, COM1_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
+
+ ret |= v3_dev_hook_io(dev, COM2_DATA_PORT, &read_data_port, &write_data_port);
+ ret |= v3_dev_hook_io(dev, COM2_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
+ ret |= v3_dev_hook_io(dev, COM2_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+ ret |= v3_dev_hook_io(dev, COM2_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+ ret |= v3_dev_hook_io(dev, COM2_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+ ret |= v3_dev_hook_io(dev, COM2_LINE_STATUS_PORT, &read_status_port, &write_status_port);
+ ret |= v3_dev_hook_io(dev, COM2_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
+ ret |= v3_dev_hook_io(dev, COM2_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
+
+ ret |= v3_dev_hook_io(dev, COM3_DATA_PORT, &read_data_port, &write_data_port);
+ ret |= v3_dev_hook_io(dev, COM3_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
+ ret |= v3_dev_hook_io(dev, COM3_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+ ret |= v3_dev_hook_io(dev, COM3_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+ ret |= v3_dev_hook_io(dev, COM3_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+ ret |= v3_dev_hook_io(dev, COM3_LINE_STATUS_PORT, &read_status_port, &write_status_port);
+ ret |= v3_dev_hook_io(dev, COM3_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
+ ret |= v3_dev_hook_io(dev, COM3_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
+
+ ret |= v3_dev_hook_io(dev, COM4_DATA_PORT, &read_data_port, &write_data_port);
+ ret |= v3_dev_hook_io(dev, COM4_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
+ ret |= v3_dev_hook_io(dev, COM4_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+ ret |= v3_dev_hook_io(dev, COM4_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+ ret |= v3_dev_hook_io(dev, COM4_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+ ret |= v3_dev_hook_io(dev, COM4_LINE_STATUS_PORT, &read_status_port, &write_status_port);
+ ret |= v3_dev_hook_io(dev, COM4_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
+ ret |= v3_dev_hook_io(dev, COM4_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
+
+ if (ret != 0) {
+ PrintError("Error hooking Serial IO ports\n");
+ v3_remove_device(dev);
+ return -1;
+ }
+
+ 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);
+ if (v3_dev_add_char_frontend(vm, dev_id, connect_fn, (void *)state) == -1) {
+ PrintError("Could not register %s as frontend\n", dev_id);
+ v3_remove_device(dev);
+ return -1;
+ }
+
- state->com1.stream_ops = ops;
- state->com1.backend_data = private_data;
- /* bind to other ports here */
return 0;
}
+
+
+
device_register("SERIAL", serial_init)