From: Jack Lange Date: Fri, 18 Jul 2008 05:02:56 +0000 (+0000) Subject: *** empty log message *** X-Git-Tag: boots-puppy-iso-to-command-prompt~11 X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=a933375191c6bf937a323a1ad1ba2c48eccbee3c *** empty log message *** --- diff --git a/palacios/src/devices/serial.c b/palacios/src/devices/serial.c index 690123c..65bae06 100644 --- a/palacios/src/devices/serial.c +++ b/palacios/src/devices/serial.c @@ -134,18 +134,52 @@ struct modem_status_reg { }; -struct serial_port { - struct irq_enable_reg ier; - struct irq_id_reg iid; - struct fifo_ctrl_reg fcr; - struct line_ctrl_reg lcr; - struct modem_ctrl_reg mcr; - struct line_status_reg lsr; - struct modem_status_reg msr; +#define SERIAL_BUF_LEN 256 + +struct serial_buffer { + uint_t head; // most recent data + uint_t tail; // oldest char + char buffer[SERIAL_BUF_LEN]; +}; + +int queue_data(struct serial_buffer * buf, char data) { + int next_loc = (buf->head + 1) % SERIAL_BUF_LEN; + + if (next_loc == buf->tail) { + return -1; + } + + buf->buffer[next_loc] = data; + buf->head = next_loc; + + return 0; +} + +int dequeue_data(struct serial_buffer * buf, char * data) { + int next_tail = (buf->tail + 1) % SERIAL_BUF_LEN; + if (buf->head == buf->tail) { + return -1; + } - char tx_buffer[256]; - char rx_buffer[256]; + *data = buf->buffer[buf->tail]; + buf->tail = next_tail; + + return 0; +} + + +struct serial_port { + char ier; + char iir; + char fcr; + char lcr; + char mcr; + char lsr; + char msr; + + struct serial_buffer tx_buffer; + struct serial_buffer rx_buffer; }; @@ -158,73 +192,293 @@ struct serial_state { int write_data_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) { - PrintDebug("Write to Data Port\n"); - - return -1; + struct serial_state * state = (struct serial_state *)dev->private_data; + char * val = (char *)src; + PrintDebug("Write to Data Port 0x%x (val=%x)\n", port, *(char*)src); + + if (length != 1) { + PrintDebug("Invalid length(%d) in write to 0x%x\n", length, port); + return -1; + } + + switch (port) { + case COM1_DATA_PORT: + queue_data(&(state->com1.tx_buffer), *val); + break; + case COM2_DATA_PORT: + queue_data(&(state->com2.tx_buffer), *val); + break; + case COM3_DATA_PORT: + queue_data(&(state->com3.tx_buffer), *val); + break; + case COM4_DATA_PORT: + queue_data(&(state->com4.tx_buffer), *val); + break; + default: + return -1; + } + + + return length; } + + int read_data_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) { - PrintDebug("Read from Data Port\n"); + struct serial_state * state = (struct serial_state *)dev->private_data; + char * val = (char *)dst; + PrintDebug("Read from Data Port 0x%x\n", port); + + if (length != 1) { + PrintDebug("Invalid length(%d) in write to 0x%x\n", length, port); + return -1; + } + + switch (port) { + case COM1_DATA_PORT: + dequeue_data(&(state->com1.tx_buffer), val); + break; + case COM2_DATA_PORT: + dequeue_data(&(state->com2.tx_buffer), val); + break; + case COM3_DATA_PORT: + dequeue_data(&(state->com3.tx_buffer), val); + break; + case COM4_DATA_PORT: + dequeue_data(&(state->com4.tx_buffer), val); + break; + default: + return -1; + } + + + return length; +} + + + +int handle_ier_write(struct serial_port * com, struct irq_enable_reg * ier) { + + return -1; } int write_ctrl_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) { - PrintDebug("Write to Control Port\n"); + struct serial_state * state = (struct serial_state *)dev->private_data; + char * val = (char *)src; + PrintDebug("Write to Control Port (val=%x)\n", *(char *)src); + + if (length != 1) { + PrintDebug("Invalid Write length to control port\n", port, port); + return -1; + } + + switch (port) { + case COM1_IRQ_ENABLE_PORT: + if (handle_ier_write(&(state->com1), (struct irq_enable_reg *)val) == -1) { + return -1; + } + break; + case COM2_IRQ_ENABLE_PORT: + if (handle_ier_write(&(state->com2), (struct irq_enable_reg *)val) == -1) { + return -1; + } + break; + case COM3_IRQ_ENABLE_PORT: + if (handle_ier_write(&(state->com3), (struct irq_enable_reg *)val) == -1) { + return -1; + } + break; + case COM4_IRQ_ENABLE_PORT: + if (handle_ier_write(&(state->com4), (struct irq_enable_reg *)val) == -1) { + return -1; + } + break; + + case COM1_FIFO_CTRL_PORT: + case COM2_FIFO_CTRL_PORT: + case COM3_FIFO_CTRL_PORT: + case COM4_FIFO_CTRL_PORT: + + case COM1_LINE_CTRL_PORT: + case COM2_LINE_CTRL_PORT: + case COM3_LINE_CTRL_PORT: + case COM4_LINE_CTRL_PORT: + + case COM1_MODEM_CTRL_PORT: + case COM2_MODEM_CTRL_PORT: + case COM3_MODEM_CTRL_PORT: + case COM4_MODEM_CTRL_PORT: + + + + default: + return -1; + } + return -1; } + + + int read_ctrl_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) { + struct serial_state * state = (struct serial_state *)dev->private_data; + char * val = (char *)dst; PrintDebug("Read from Control Port\n"); - return -1; + + if (length != 1) { + PrintDebug("Invalid Read length to control port\n"); + return -1; + } + + switch (port) { + case COM1_IRQ_ENABLE_PORT: + *val = state->com1.ier; + break; + case COM2_IRQ_ENABLE_PORT: + *val = state->com2.ier; + break; + case COM3_IRQ_ENABLE_PORT: + *val = state->com3.ier; + break; + case COM4_IRQ_ENABLE_PORT: + *val = state->com4.ier; + break; + + case COM1_FIFO_CTRL_PORT: + *val = state->com1.fcr; + break; + case COM2_FIFO_CTRL_PORT: + *val = state->com2.fcr; + break; + case COM3_FIFO_CTRL_PORT: + *val = state->com3.fcr; + break; + case COM4_FIFO_CTRL_PORT: + *val = state->com4.fcr; + break; + + case COM1_LINE_CTRL_PORT: + *val = state->com1.lcr; + break; + case COM2_LINE_CTRL_PORT: + *val = state->com2.lcr; + break; + case COM3_LINE_CTRL_PORT: + *val = state->com3.lcr; + break; + case COM4_LINE_CTRL_PORT: + *val = state->com4.lcr; + break; + + case COM1_MODEM_CTRL_PORT: + *val = state->com1.mcr; + break; + case COM2_MODEM_CTRL_PORT: + *val = state->com2.mcr; + break; + case COM3_MODEM_CTRL_PORT: + *val = state->com3.mcr; + break; + case COM4_MODEM_CTRL_PORT: + *val = state->com4.mcr; + break; + + default: + return -1; + } + + return length; } int write_status_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) { - PrintDebug("Write to Status Port\n"); + PrintDebug("Write to Status Port 0x%x (val=%x)\n", port, *(char *)src); return -1; } int read_status_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) { - PrintDebug("Read from Status Port\n"); - return -1; + struct serial_state * state = (struct serial_state *)dev->private_data; + char * val = (char *)dst; + PrintDebug("Read from Status Port 0x%x\n", port); + + if (length != 1) { + PrintDebug("Invalid Read length to control port\n"); + return -1; + } + + switch (port) { + case COM1_LINE_STATUS_PORT: + *val = state->com1.lsr; + break; + case COM2_LINE_STATUS_PORT: + *val = state->com2.lsr; + break; + case COM3_LINE_STATUS_PORT: + *val = state->com3.lsr; + break; + case COM4_LINE_STATUS_PORT: + *val = state->com4.lsr; + break; + + case COM1_MODEM_STATUS_PORT: + *val = state->com1.msr; + break; + case COM2_MODEM_STATUS_PORT: + *val = state->com2.msr; + break; + case COM3_MODEM_STATUS_PORT: + *val = state->com3.msr; + break; + case COM4_MODEM_STATUS_PORT: + *val = state->com4.msr; + break; + + default: + return -1; + } + + + + return length; } +static int init_serial_port(struct serial_port * com) { + //struct irq_enable_reg * ier = (struct irq_enable_reg *)&(com->ier); + //struct irq_id_reg * iir = (struct irq_id_reg *)&(com->iir); + //struct fifo_ctrl_reg * fcr = (struct fifo_ctrl_reg *)&(com->fcr); + //struct line_ctrl_reg * lcr = (struct line_ctrl_reg *)&(com->lcr); + //struct modem_ctrl_reg * mcr = (struct modem_ctrl_reg *)&(com->mcr); + //struct line_status_reg * lsr = (struct line_status_reg *)&(com->lsr); + //struct modem_status_reg * msr = (struct modem_status_reg *)&(com->msr); + + com->ier = 0x00; + com->iir = 0x01; + com->fcr = 0x00; + com->lcr = 0x00; + com->mcr = 0x00; + com->lsr = 0x60; + com->msr = 0x00; + return 0; +} int serial_init(struct vm_device * dev) { struct serial_state * state = (struct serial_state *)dev->private_data; - state->com1.ier.rsvd = 0; - state->com1.iid.rsvd = 0; - state->com1.fcr.rsvd = 0; - state->com1.mcr.rsvd = 0; - state->com1.iid.pending = 1; - - state->com2.ier.rsvd = 0; - state->com2.iid.rsvd = 0; - state->com2.fcr.rsvd = 0; - state->com2.mcr.rsvd = 0; - state->com2.iid.pending = 1; - - state->com3.ier.rsvd = 0; - state->com3.iid.rsvd = 0; - state->com3.fcr.rsvd = 0; - state->com3.mcr.rsvd = 0; - state->com3.iid.pending = 1; - - state->com4.ier.rsvd = 0; - state->com4.iid.rsvd = 0; - state->com4.fcr.rsvd = 0; - state->com4.mcr.rsvd = 0; - state->com4.iid.pending = 1; + init_serial_port(&(state->com1)); + init_serial_port(&(state->com2)); + init_serial_port(&(state->com3)); + init_serial_port(&(state->com4)); dev_hook_io(dev, COM1_DATA_PORT, &read_data_port, &write_data_port); dev_hook_io(dev, COM1_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);