2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2010, Rumou Duan <duanrumou@gmail.com>
11 * Copyright (c) 2010, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Author: Rumou Duan <duanrumou@gmail.com>
15 * Lei Xia <lxia@northwestern.edu>
17 * This is free software. You are permitted to use,
18 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
22 #include <palacios/vmm.h>
23 #include <palacios/vmm_dev_mgr.h>
24 #include <palacios/vmm_types.h>
26 #include <palacios/vmm_ringbuffer.h>
27 #include <palacios/vmm_lock.h>
28 #include <palacios/vmm_intr.h>
29 #include <palacios/vm_guest.h>
31 #include <devices/serial.h>
34 #ifndef V3_CONFIG_DEBUG_SERIAL
36 #define PrintDebug(fmt, args...)
40 #define COM1_DATA_PORT 0x3f8
41 #define COM1_IRQ_ENABLE_PORT 0x3f9
42 #define COM1_DIV_LATCH_LSB_PORT 0x3f8
43 #define COM1_DIV_LATCH_MSB_PORT 0x3f9
44 #define COM1_IIR_PORT 0x3fa
45 #define COM1_FIFO_CTRL_PORT 0x3fa
46 #define COM1_LINE_CTRL_PORT 0x3fb
47 #define COM1_MODEM_CTRL_PORT 0x3fc
48 #define COM1_LINE_STATUS_PORT 0x3fd
49 #define COM1_MODEM_STATUS_PORT 0x3fe
50 #define COM1_SCRATCH_PORT 0x3ff
52 #define COM2_DATA_PORT 0x2f8
53 #define COM2_IRQ_ENABLE_PORT 0x2f9
54 #define COM2_DIV_LATCH_LSB_PORT 0x2f8
55 #define COM2_DIV_LATCH_MSB_PORT 0x2f9
56 #define COM2_IIR_PORT 0x2fa
57 #define COM2_FIFO_CTRL_PORT 0x2fa
58 #define COM2_LINE_CTRL_PORT 0x2fb
59 #define COM2_MODEM_CTRL_PORT 0x2fc
60 #define COM2_LINE_STATUS_PORT 0x2fd
61 #define COM2_MODEM_STATUS_PORT 0x2fe
62 #define COM2_SCRATCH_PORT 0x2ff
64 #define COM3_DATA_PORT 0x3e8
65 #define COM3_IRQ_ENABLE_PORT 0x3e9
66 #define COM3_DIV_LATCH_LSB_PORT 0x3e8
67 #define COM3_DIV_LATCH_MSB_PORT 0x3e9
68 #define COM3_IIR_PORT 0x3ea
69 #define COM3_FIFO_CTRL_PORT 0x3ea
70 #define COM3_LINE_CTRL_PORT 0x3eb
71 #define COM3_MODEM_CTRL_PORT 0x3ec
72 #define COM3_LINE_STATUS_PORT 0x3ed
73 #define COM3_MODEM_STATUS_PORT 0x3ee
74 #define COM3_SCRATCH_PORT 0x3ef
76 #define COM4_DATA_PORT 0x2e8
77 #define COM4_IRQ_ENABLE_PORT 0x2e9
78 #define COM4_DIV_LATCH_LSB_PORT 0x2e8
79 #define COM4_DIV_LATCH_MSB_PORT 0x2e9
80 #define COM4_IIR_PORT 0x2ea
81 #define COM4_FIFO_CTRL_PORT 0x2ea
82 #define COM4_LINE_CTRL_PORT 0x2eb
83 #define COM4_MODEM_CTRL_PORT 0x2ec
84 #define COM4_LINE_STATUS_PORT 0x2ed
85 #define COM4_MODEM_STATUS_PORT 0x2ee
86 #define COM4_SCRATCH_PORT 0x2ef
89 // Interrupt IDs (in priority order, highest is first)
90 #define STATUS_IRQ_LSR_OE_SET 0x3
91 #define STATUS_IRQ_LSR_PE_SET 0x3
92 #define STATUS_IRQ_LSR_FE_SET 0x3
93 #define STATUS_IRQ_LSR_BI_SET 0x3
95 #define RX_IRQ_TRIGGER_LEVEL 0x2
97 #define TX_IRQ_THRE 0x1
98 #define MODEL_IRQ_DELTA_SET 0x0
106 #define RX_BUFFER 0x1
107 #define TX_BUFFER 0x2
109 //initial value for registers
111 #define IER_INIT_VAL 0x3
112 //receive data available interrupt and THRE interrupt are enabled
113 #define IIR_INIT_VAL 0x1
114 //No Pending Interrupt bit is set.
115 #define FCR_INIT_VAL 0xc0
116 //fifo control register is set to 0
117 #define LCR_INIT_VAL 0x3
118 #define MCR_INIT_VAL 0x0
119 #define LSR_INIT_VAL 0x60
120 #define MSR_INIT_VAL 0x0
121 #define DLL_INIT_VAL 0x1
122 #define DLM_INIT_VAL 0x0
126 //receiver buffer register
127 struct rbr_register {
131 // transmitter holding register
132 struct thr_register {
136 //interrupt enable register
137 struct ier_register {
141 uint8_t erbfi : 1; // Enable Receiver Buffer full interrupt
142 uint8_t etbei : 1; // Enable Transmit buffer empty interrupt
143 uint8_t elsi : 1; // Enable Line Status Interrupt
144 uint8_t edssi : 1; // Enable Delta Status signals interrupt
145 uint8_t rsvd : 4; // MBZ
146 } __attribute__((packed));
147 } __attribute__((packed));
148 } __attribute__((packed));
151 //interrupt identification register
152 struct iir_register {
156 uint8_t pending : 1; // Interrupt pending (0=interrupt pending)
157 uint8_t iid : 3; // Interrupt Identification
158 uint8_t rsvd : 2; // MBZ
159 uint8_t fifo_en : 2; // FIFO enable
160 } __attribute__((packed));
161 } __attribute__((packed));
162 } __attribute__((packed));
164 //FIFO control register
165 struct fcr_register {
169 uint8_t enable : 1; // enable fifo
170 uint8_t rfres : 1; // RX FIFO reset
171 uint8_t xfres : 1; // TX FIFO reset
172 uint8_t dma_sel : 1; // DMA mode select
173 uint8_t rsvd : 2; // MBZ
174 uint8_t rx_trigger: 2; // RX FIFO trigger level select
175 } __attribute__((packed));
176 } __attribute__((packed));
177 } __attribute__((packed));
180 //line control register
181 struct lcr_register {
185 uint8_t word_len : 2; // word length select
186 uint8_t stop_bits : 1; // Stop Bit select
187 uint8_t parity_enable : 1; // Enable parity
188 uint8_t even_sel : 1; // Even Parity Select
189 uint8_t stick_parity : 1; // Stick Parity Select
190 uint8_t sbr : 1; // Set Break
191 uint8_t dlab : 1; // Divisor latch access bit
192 } __attribute__((packed));
193 } __attribute__((packed));
194 } __attribute__((packed));
197 //modem control register
198 struct mcr_register {
206 uint8_t loop : 1; // loopback mode
207 uint8_t rsvd : 3; // MBZ
208 } __attribute__((packed));
209 } __attribute__((packed));
210 } __attribute__((packed));
213 //line status register
214 struct lsr_register {
218 uint8_t dr : 1; // data ready
219 uint8_t oe : 1; // Overrun error
220 uint8_t pe : 1; // Parity Error
221 uint8_t fe : 1; // Framing Error
222 uint8_t brk : 1; // broken line detected
223 uint8_t thre : 1; // Transmitter holding register empty
224 uint8_t temt : 1; // Transmitter Empty
225 uint8_t fifo_err : 1; // at least one error is pending in the RX FIFO chain
226 } __attribute__((packed));
227 } __attribute__((packed));
228 } __attribute__((packed));
231 struct msr_register {
235 uint8_t dcts : 1; // Delta Clear To Send
236 uint8_t ddsr : 1; // Delta Data Set Ready
237 uint8_t teri : 1; // Trailing Edge Ring Indicator
238 uint8_t ddcd : 1; // Delta Data Carrier Detect
239 uint8_t cts : 1; // Clear to Send
240 uint8_t dsr : 1; // Data Set Ready
241 uint8_t ri : 1; // Ring Indicator
242 uint8_t dcd : 1; // Data Carrier Detect
243 } __attribute__((packed));
244 } __attribute__((packed));
245 } __attribute__((packed));
248 struct scr_register {
253 struct dll_register {
258 struct dlm_register {
261 #define SERIAL_BUF_LEN 128
263 struct serial_buffer {
264 int head; // most recent data
265 int tail; // oldest char
267 uint8_t buffer[SERIAL_BUF_LEN];
271 struct rbr_register rbr;
272 struct thr_register thr;
273 struct ier_register ier;
274 struct iir_register iir;
275 struct fcr_register fcr;
276 struct lcr_register lcr;
277 struct mcr_register mcr;
278 struct lsr_register lsr;
279 struct msr_register msr;
280 struct scr_register scr;
281 struct dll_register dll;
282 struct dlm_register dlm;
285 struct serial_buffer tx_buffer;
286 struct serial_buffer rx_buffer;
291 struct v3_dev_char_ops * ops;
296 struct serial_state {
297 struct serial_port coms[4];
303 static struct serial_port * get_com_from_port(struct serial_state * serial, uint16_t port) {
304 if ((port >= COM1_DATA_PORT) && (port <= COM1_SCRATCH_PORT)) {
305 return &(serial->coms[0]);
306 } else if ((port >= COM2_DATA_PORT) && (port <= COM2_SCRATCH_PORT)) {
307 return &(serial->coms[1]);
308 } else if ((port >= COM3_DATA_PORT) && (port <= COM3_SCRATCH_PORT)) {
309 return &(serial->coms[2]);
310 } else if ((port >= COM4_DATA_PORT) && (port <= COM4_SCRATCH_PORT)) {
311 return &(serial->coms[3]);
313 PrintError("Error: Could not find serial port associated with IO port %d\n", port);
318 static inline bool receive_buffer_trigger(int number, int trigger_number) {
320 switch (trigger_number) {
322 return (number >= 1);
324 return (number >= 4);
326 return (number >= 8);
328 return (number >= 14);
334 static int getNumber(struct serial_buffer * buf) {
335 int number = buf->head - buf->tail;
337 if (buf->full == 1) {
338 return SERIAL_BUF_LEN;
339 } else if (number >= 0) {
342 return SERIAL_BUF_LEN + number;
346 static int updateIRQ(struct v3_vm_info * vm, struct serial_port * com) {
348 if ( (com->ier.erbfi == 0x1) &&
349 (receive_buffer_trigger( getNumber(&(com->rx_buffer)), com->fcr.rx_trigger)) ) {
351 PrintDebug("UART: receive buffer interrupt(trigger level reached)\n");
353 com->iir.iid = RX_IRQ_TRIGGER_LEVEL;
354 v3_raise_irq(vm, com->irq_number);
357 if ( (com->iir.iid == RX_IRQ_TRIGGER_LEVEL) &&
358 (!(receive_buffer_trigger( getNumber(&(com->rx_buffer)), com->fcr.rx_trigger))) ) {
360 com->iir.iid = 0x0; //reset interrupt identification register
361 com->iir.pending = 0x1;
364 if ( (com->iir.iid == TX_IRQ_THRE) &&
365 (getNumber(&(com->tx_buffer)) == SERIAL_BUF_LEN)) {
367 com->iir.iid = 0x0; //reset interrupt identification register
368 com->iir.pending = 0x1;
370 } else if ( (com->ier.etbei == 0x1) &&
371 (getNumber(&(com->tx_buffer)) != SERIAL_BUF_LEN )) {
373 PrintDebug("UART: transmit buffer interrupt(buffer not full)\n");
375 com->iir.iid = TX_IRQ_THRE;
376 com->iir.pending = 0;
378 v3_raise_irq(vm, com->irq_number);
385 static int queue_data(struct v3_vm_info * vm, struct serial_port * com,
386 struct serial_buffer * buf, uint8_t data) {
387 int next_loc = (buf->head + 1) % SERIAL_BUF_LEN;
389 if (buf->full == 1) {
390 PrintDebug("Buffer is full!\n");
392 if (buf == &(com->rx_buffer)) {
393 com->lsr.oe = 1; //overrun error bit set
401 buf->buffer[next_loc] = data;
402 buf->head = next_loc;
404 if (buf->head == buf->tail) {
408 if (buf == &(com->rx_buffer)) {
409 com->lsr.dr = 1; //as soon as new data arrives at receive buffer, set data ready bit in lsr.
412 if (buf == &(com->tx_buffer)) {
413 com->lsr.thre = 0; //reset thre and temt bits.
420 static int dequeue_data(struct v3_vm_info * vm, struct serial_port * com,
421 struct serial_buffer * buf, uint8_t * data) {
423 int next_tail = (buf->tail + 1) % SERIAL_BUF_LEN;
426 if ( (buf->head == buf->tail) && (buf->full != 1) ) {
427 PrintDebug("no data to delete!\n");
431 if (buf->full == 1) {
436 *data = buf->buffer[next_tail];
437 buf->buffer[next_tail] = 0;
438 buf->tail = next_tail;
440 if ( (buf == &(com->rx_buffer)) && (getNumber(&(com->rx_buffer)) == 0) ) {
444 if ((buf == &(com->tx_buffer)) && (getNumber(&(com->tx_buffer)) == 0)) {
454 static int write_data_port(struct guest_info * core, uint16_t port,
455 void * src, uint_t length, void * priv_data) {
456 struct serial_state * state = priv_data;
457 uint8_t * val = (uint8_t *)src;
458 struct serial_port * com_port = NULL;
460 PrintDebug("Write to Data Port 0x%x (val=%x)\n", port, *val);
463 PrintError("Invalid length(%d) in write to 0x%x\n", length, port);
467 if ((port != COM1_DATA_PORT) && (port != COM2_DATA_PORT) &&
468 (port != COM3_DATA_PORT) && (port != COM4_DATA_PORT)) {
469 PrintError("Serial Read data port for illegal port Number (%d)\n", port);
473 com_port = get_com_from_port(state, port);
475 if (com_port == NULL) {
476 PrintError("UART:read from NOBODY\n");
481 // dlab is always checked first
482 if (com_port->lcr.dlab == 1) {
483 com_port->dll.data = *val;
487 /* JRL: Some buffering would probably be a good idea here.... */
489 com_port->ops->output(val, 1, com_port->backend_data);
491 queue_data(core->vm_info, com_port, &(com_port->tx_buffer), *val);
492 updateIRQ(core->vm_info, com_port);
501 static int read_data_port(struct guest_info * core, uint16_t port,
502 void * dst, uint_t length, void * priv_data) {
503 struct serial_state * state = priv_data;
504 uint8_t * val = (uint8_t *)dst;
505 struct serial_port * com_port = NULL;
507 PrintDebug("Read from Data Port 0x%x\n", port);
510 PrintError("Invalid length(%d) in write to 0x%x\n", length, port);
514 if ((port != COM1_DATA_PORT) && (port != COM2_DATA_PORT) &&
515 (port != COM3_DATA_PORT) && (port != COM4_DATA_PORT)) {
516 PrintError("Serial Read data port for illegal port Number (%d)\n", port);
520 com_port = get_com_from_port(state, port);
522 if (com_port == NULL) {
523 PrintError("UART:read from NOBODY\n");
527 if (com_port->lcr.dlab == 1) {
528 *val = com_port->dll.data;
530 dequeue_data(core->vm_info, com_port, &(com_port->rx_buffer), val);
538 static int handle_fcr_write(struct serial_port * com, uint8_t value) {
540 com->fcr.enable = value & 0x1;
542 if (com->fcr.enable == 0x1) {
543 com->fcr.val = value;
545 com->fcr.enable = 1; // Do we need to set this??
547 //if rfres set, clear receive buffer.
548 if (com->fcr.rfres == 0x1) {
549 com->rx_buffer.head = 0;
550 com->rx_buffer.tail = 0;
551 com->rx_buffer.full = 0;
552 memset(com->rx_buffer.buffer, 0, SERIAL_BUF_LEN);
556 //if xfres set, clear transmit buffer.
557 if (com->fcr.xfres == 0x1) {
558 com->tx_buffer.head = 0;
559 com->tx_buffer.tail = 0;
560 com->tx_buffer.full = 0;
561 memset(com->tx_buffer.buffer, 0, SERIAL_BUF_LEN);
565 //clear both buffers.
566 com->tx_buffer.head = 0;
567 com->tx_buffer.tail = 0;
568 com->tx_buffer.full = 0;
569 com->rx_buffer.head = 0;
570 com->rx_buffer.tail = 0;
571 com->rx_buffer.full = 0;
573 memset(com->rx_buffer.buffer, 0, SERIAL_BUF_LEN);
574 memset(com->tx_buffer.buffer, 0, SERIAL_BUF_LEN);
584 static int write_ctrl_port(struct guest_info * core, uint16_t port, void * src,
585 uint_t length, void * priv_data) {
586 struct serial_state * state = priv_data;
587 uint8_t val = *(uint8_t *)src;
588 struct serial_port * com_port = NULL;
590 PrintDebug("UART:Write to Control Port (val=%x)\n", val);
593 PrintError("UART:Invalid Write length to control port%d\n", port);
597 com_port = get_com_from_port(state, port);
599 if (com_port == NULL) {
600 PrintError("Could not find serial port corresponding to IO port %d\n", port);
604 //always check dlab first
606 case COM1_IRQ_ENABLE_PORT:
607 case COM2_IRQ_ENABLE_PORT:
608 case COM3_IRQ_ENABLE_PORT:
609 case COM4_IRQ_ENABLE_PORT: {
610 PrintDebug("UART:Write to IER/LATCH port: dlab is %x\n", com_port->lcr.dlab);
612 if (com_port->lcr.dlab == 1) {
613 com_port->dlm.data = val;
615 com_port->ier.val = val;
620 case COM1_FIFO_CTRL_PORT:
621 case COM2_FIFO_CTRL_PORT:
622 case COM3_FIFO_CTRL_PORT:
623 case COM4_FIFO_CTRL_PORT: {
624 PrintDebug("UART:Write to FCR\n");
626 if (handle_fcr_write(com_port, val) == -1) {
632 case COM1_LINE_CTRL_PORT:
633 case COM2_LINE_CTRL_PORT:
634 case COM3_LINE_CTRL_PORT:
635 case COM4_LINE_CTRL_PORT: {
636 PrintDebug("UART:Write to LCR\n");
637 com_port->lcr.val = val;
640 case COM1_MODEM_CTRL_PORT:
641 case COM2_MODEM_CTRL_PORT:
642 case COM3_MODEM_CTRL_PORT:
643 case COM4_MODEM_CTRL_PORT: {
644 PrintDebug("UART:Write to MCR\n");
645 com_port->mcr.val = val;
648 case COM1_SCRATCH_PORT:
649 case COM2_SCRATCH_PORT:
650 case COM3_SCRATCH_PORT:
651 case COM4_SCRATCH_PORT: {
652 PrintDebug("UART:Write to SCRATCH\n");
653 com_port->scr.data = val;
657 PrintError("UART:Write to NOBODY, ERROR\n");
668 static int read_ctrl_port(struct guest_info * core, uint16_t port, void * dst,
669 uint_t length, void * priv_data) {
670 struct serial_state * state = priv_data;
671 uint8_t * val = (uint8_t *)dst;
672 struct serial_port * com_port = NULL;
674 PrintDebug("Read from Control Port\n");
677 PrintError("Invalid Read length to control port\n");
681 com_port = get_com_from_port(state, port);
683 if (com_port == NULL) {
684 PrintError("Could not find serial port corresponding to IO port %d\n", port);
688 //always check dlab first
690 case COM1_IRQ_ENABLE_PORT:
691 case COM2_IRQ_ENABLE_PORT:
692 case COM3_IRQ_ENABLE_PORT:
693 case COM4_IRQ_ENABLE_PORT: {
694 PrintDebug("UART:read from IER\n");
696 if (com_port->lcr.dlab == 1) {
697 *val = com_port->dlm.data;
699 *val = com_port->ier.val;
708 PrintDebug("UART:read from IIR\n");
709 *val = com_port->iir.val;
712 case COM1_LINE_CTRL_PORT:
713 case COM2_LINE_CTRL_PORT:
714 case COM3_LINE_CTRL_PORT:
715 case COM4_LINE_CTRL_PORT:
716 PrintDebug("UART:read from LCR\n");
717 *val = com_port->lcr.val;
720 case COM1_MODEM_CTRL_PORT:
721 case COM2_MODEM_CTRL_PORT:
722 case COM3_MODEM_CTRL_PORT:
723 case COM4_MODEM_CTRL_PORT:
724 PrintDebug("UART:read from MCR\n");
725 *val = com_port->mcr.val;
728 case COM1_SCRATCH_PORT:
729 case COM2_SCRATCH_PORT:
730 case COM3_SCRATCH_PORT:
731 case COM4_SCRATCH_PORT:
732 PrintDebug("UART:read from SCRATCH\n");
733 *val = com_port->scr.data;
737 PrintError("UART:read from NOBODY\n");
745 static int write_status_port(struct guest_info * core, uint16_t port, void * src,
746 uint_t length, void * priv_data) {
747 struct serial_state * state = priv_data;
748 uint8_t val = *(uint8_t *)src;
749 struct serial_port * com_port = NULL;
751 PrintDebug("Write to Status Port (val=%x)\n", val);
754 PrintError("Invalid Write length to status port %d\n", port);
758 com_port = get_com_from_port(state, port);
760 if (com_port == NULL) {
761 PrintError("Could not find serial port corresponding to IO port %d\n", port);
766 case COM1_LINE_STATUS_PORT:
767 case COM2_LINE_STATUS_PORT:
768 case COM3_LINE_STATUS_PORT:
769 case COM4_LINE_STATUS_PORT:
770 PrintDebug("UART:write to LSR\n");
771 com_port->lsr.val = val;
774 case COM1_MODEM_STATUS_PORT:
775 case COM2_MODEM_STATUS_PORT:
776 case COM3_MODEM_STATUS_PORT:
777 case COM4_MODEM_STATUS_PORT:
778 PrintDebug("UART:write to MSR\n");
779 com_port->msr.val = val;
783 PrintError("UART:write to NOBODY\n");
790 static int read_status_port(struct guest_info * core, uint16_t port, void * dst,
791 uint_t length, void * priv_data) {
792 struct serial_state * state = priv_data;
793 uint8_t * val = (uint8_t *)dst;
794 struct serial_port * com_port = NULL;
796 PrintDebug("Read from Status Port 0x%x\n", port);
798 com_port = get_com_from_port(state, port);
800 if (com_port == NULL) {
801 PrintError("Could not find serial port corresponding to IO port %d\n", port);
806 case COM1_LINE_STATUS_PORT:
807 case COM2_LINE_STATUS_PORT:
808 case COM3_LINE_STATUS_PORT:
809 case COM4_LINE_STATUS_PORT:
812 PrintError("Invalid Read length to control port\n");
816 PrintDebug("UART:read from LSR\n");
818 *val = com_port->lsr.val;
819 com_port->lsr.oe = 0; // Why do we clear this??
823 case COM1_MODEM_STATUS_PORT:
824 case COM2_MODEM_STATUS_PORT:
825 case COM3_MODEM_STATUS_PORT:
826 case COM4_MODEM_STATUS_PORT:
827 PrintDebug("UART:read from COM4 MSR (length = %d)\n", length);
830 PrintError("Invalid Read length to MSR port\n");
835 /* Windows XP expects to be able to read this register and the next in one go */
837 if (read_ctrl_port(core, port + 1, val + 1, 1, priv_data) < 0) {
838 PrintError("Error reading control port for word size read of Status register\n");
843 // always read low byte...
845 *val = com_port->msr.val;
849 PrintError("UART:read from NOBODY (length = %d)\n", length);
856 static int serial_free(struct serial_state * state) {
864 #ifdef V3_CONFIG_CHECKPOINT
866 #include <palacios/vmm_sprintf.h>
868 static int serial_buffer_save(struct v3_chkpt_ctx * ctx, int port, struct serial_buffer *sb) {
872 snprintf(keyname,128,"COM%d_SB_HEAD", port);
873 V3_CHKPT_SAVE(ctx,keyname,sb->head,failout);
874 snprintf(keyname,128,"COM%d_SB_TAIL", port);
875 V3_CHKPT_SAVE(ctx,keyname,sb->tail,failout);
876 snprintf(keyname,128,"COM%d_SB_FULL", port);
877 V3_CHKPT_SAVE(ctx,keyname,sb->full,failout);
878 snprintf(keyname,128,"COM%d_SB_DATA", port);
879 V3_CHKPT_SAVE(ctx,keyname,sb->buffer,failout);
884 PrintError("Failed to save serial buffer\n");
889 static int serial_buffer_load(struct v3_chkpt_ctx * ctx, int port, struct serial_buffer *sb) {
893 snprintf(keyname,128,"COM%d_SB_HEAD", port);
894 V3_CHKPT_LOAD(ctx,keyname,sb->head,failout);
895 snprintf(keyname,128,"COM%d_SB_TAIL", port);
896 V3_CHKPT_LOAD(ctx,keyname,sb->tail,failout);
897 snprintf(keyname,128,"COM%d_SB_FULL", port);
898 V3_CHKPT_LOAD(ctx,keyname,sb->full,failout);
899 snprintf(keyname,128,"COM%d_SB_DATA", port);
900 V3_CHKPT_LOAD(ctx,keyname,sb->buffer,failout);
905 PrintError("Failed to load serial buffer\n");
909 static int serial_save(struct v3_chkpt_ctx * ctx, void * private_data) {
910 struct serial_state *state = (struct serial_state *)private_data;
911 struct serial_port *serial;
916 serial = &(state->coms[i]);
917 snprintf(keyname, 128,"COM%d_RBR",i);
918 V3_CHKPT_SAVE(ctx, keyname, serial->rbr.data,failout);
919 snprintf(keyname, 128,"COM%d_THR",i);
920 V3_CHKPT_SAVE(ctx, keyname, serial->thr.data,failout);
921 snprintf(keyname, 128,"COM%d_IER",i);
922 V3_CHKPT_SAVE(ctx, keyname, serial->ier.val,failout);
923 snprintf(keyname, 128,"COM%d_IIR",i);
924 V3_CHKPT_SAVE(ctx, keyname, serial->iir.val,failout);
925 snprintf(keyname, 128,"COM%d_FCR",i);
926 V3_CHKPT_SAVE(ctx, keyname, serial->fcr.val,failout);
927 snprintf(keyname, 128,"COM%d_LCR",i);
928 V3_CHKPT_SAVE(ctx, keyname, serial->lcr.val,failout);
929 snprintf(keyname, 128,"COM%d_MCR",i);
930 V3_CHKPT_SAVE(ctx, keyname, serial->mcr.val,failout);
931 snprintf(keyname, 128,"COM%d_LSR",i);
932 V3_CHKPT_SAVE(ctx, keyname, serial->lsr.val,failout);
933 snprintf(keyname, 128,"COM%d_MSR",i);
934 V3_CHKPT_SAVE(ctx, keyname, serial->msr.val,failout);
935 snprintf(keyname, 128,"COM%d_SCR",i);
936 V3_CHKPT_SAVE(ctx, keyname, serial->scr.data,failout);
937 snprintf(keyname, 128,"COM%d_DLL",i);
938 V3_CHKPT_SAVE(ctx, keyname, serial->dll.data,failout);
939 snprintf(keyname, 128,"COM%d_DLM",i);
940 V3_CHKPT_SAVE(ctx, keyname, serial->dlm.data,failout);
942 if (serial_buffer_save(ctx, i, &(serial->tx_buffer))) {
943 PrintError("Failed to save serial tx buffer %d\n",i);
947 if (serial_buffer_save(ctx, i, &(serial->rx_buffer))) {
948 PrintError("Failed to save serial rx buffer %d\n",i);
952 V3_CHKPT_SAVE(ctx, keyname, serial->irq_number,failout);
958 PrintError("Failed to save serial device\n");
963 static int serial_load(struct v3_chkpt_ctx * ctx, void * private_data) {
964 struct serial_state *state = (struct serial_state *)private_data;
965 struct serial_port *serial;
970 serial = &(state->coms[i]);
971 snprintf(keyname, 128,"COM%d_RBR",i);
972 V3_CHKPT_LOAD(ctx, keyname, serial->rbr.data,failout);
973 snprintf(keyname, 128,"COM%d_THR",i);
974 V3_CHKPT_LOAD(ctx, keyname, serial->thr.data,failout);
975 snprintf(keyname, 128,"COM%d_IER",i);
976 V3_CHKPT_LOAD(ctx, keyname, serial->ier.val,failout);
977 snprintf(keyname, 128,"COM%d_IIR",i);
978 V3_CHKPT_LOAD(ctx, keyname, serial->iir.val,failout);
979 snprintf(keyname, 128,"COM%d_FCR",i);
980 V3_CHKPT_LOAD(ctx, keyname, serial->fcr.val,failout);
981 snprintf(keyname, 128,"COM%d_LCR",i);
982 V3_CHKPT_LOAD(ctx, keyname, serial->lcr.val,failout);
983 snprintf(keyname, 128,"COM%d_MCR",i);
984 V3_CHKPT_LOAD(ctx, keyname, serial->mcr.val,failout);
985 snprintf(keyname, 128,"COM%d_LSR",i);
986 V3_CHKPT_LOAD(ctx, keyname, serial->lsr.val,failout);
987 snprintf(keyname, 128,"COM%d_MSR",i);
988 V3_CHKPT_LOAD(ctx, keyname, serial->msr.val,failout);
989 snprintf(keyname, 128,"COM%d_SCR",i);
990 V3_CHKPT_LOAD(ctx, keyname, serial->scr.data,failout);
991 snprintf(keyname, 128,"COM%d_DLL",i);
992 V3_CHKPT_LOAD(ctx, keyname, serial->dll.data,failout);
993 snprintf(keyname, 128,"COM%d_DLM",i);
994 V3_CHKPT_LOAD(ctx, keyname, serial->dlm.data,failout);
996 if (serial_buffer_load(ctx, i, &(serial->tx_buffer))) {
997 PrintError("Failed to load serial tx buffer %d\n",i);
1001 if (serial_buffer_load(ctx, i, &(serial->rx_buffer))) {
1002 PrintError("Failed to load serial rx buffer %d\n",i);
1006 V3_CHKPT_LOAD(ctx, keyname, serial->irq_number,failout);
1012 PrintError("Failed to load serial device\n");
1019 static struct v3_device_ops dev_ops = {
1020 .free = (int (*)(void *))serial_free,
1021 #ifdef V3_CONFIG_CHECKPOINT
1022 .save = serial_save,
1029 static int init_serial_port(struct serial_port * com) {
1031 com->ier.val = IER_INIT_VAL;
1032 com->iir.val = IIR_INIT_VAL;
1033 com->fcr.val = FCR_INIT_VAL;
1034 com->lcr.val = LCR_INIT_VAL;
1035 com->mcr.val = MCR_INIT_VAL;
1036 com->lsr.val = LSR_INIT_VAL;
1037 com->msr.val = MSR_INIT_VAL;
1039 com->dll.data = DLL_INIT_VAL;
1040 com->dlm.data = DLM_INIT_VAL;
1042 com->tx_buffer.head = 0;
1043 com->tx_buffer.tail = 0;
1044 com->tx_buffer.full = 0;
1045 memset(com->tx_buffer.buffer, 0, SERIAL_BUF_LEN);
1047 com->rx_buffer.head = 0;
1048 com->rx_buffer.tail = 0;
1049 com->rx_buffer.full = 0;
1050 memset(com->rx_buffer.buffer, 0, SERIAL_BUF_LEN);
1053 com->backend_data = NULL;
1058 static uint64_t serial_input(struct v3_vm_info * vm, uint8_t * buf, uint64_t len, void * priv_data){
1059 struct serial_port * com_port = (struct serial_port *)priv_data;
1062 for(i = 0; i < len; i++){
1063 queue_data(vm, com_port, &(com_port->rx_buffer), buf[i]);
1066 updateIRQ(vm, com_port);
1072 static int connect_fn(struct v3_vm_info * vm,
1073 void * frontend_data,
1074 struct v3_dev_char_ops * ops,
1075 v3_cfg_tree_t * cfg,
1076 void * private_data,
1077 void ** push_fn_arg) {
1079 struct serial_state * serial = (struct serial_state *)frontend_data;
1080 struct serial_port * com = NULL;
1081 char * com_port = v3_cfg_val(cfg, "com_port");
1084 if (com_port == NULL) {
1085 PrintError("Invalid Serial frontend config: missing \"com_port\"\n");
1089 com_idx = atoi(com_port) - 1;
1091 if ((com_idx > 3) || (com_idx < 0)) {
1092 PrintError("Invalid Com port (%s) \n", com_port);
1096 com = &(serial->coms[com_idx]);
1099 com->backend_data = private_data;
1101 com->ops->input = serial_input;
1107 static int serial_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
1108 struct serial_state * state = NULL;
1109 char * dev_id = v3_cfg_val(cfg, "ID");
1112 state = (struct serial_state *)V3_Malloc(sizeof(struct serial_state));
1114 if (state == NULL) {
1115 PrintError("Could not allocate Serial Device\n");
1119 memset(state, 0, sizeof(struct serial_state));
1121 init_serial_port(&(state->coms[0]));
1122 init_serial_port(&(state->coms[1]));
1123 init_serial_port(&(state->coms[2]));
1124 init_serial_port(&(state->coms[3]));
1126 state->coms[0].irq_number = COM1_IRQ;
1127 state->coms[1].irq_number = COM2_IRQ;
1128 state->coms[2].irq_number = COM3_IRQ;
1129 state->coms[3].irq_number = COM4_IRQ;
1132 struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, state);
1135 PrintError("Could not attach device %s\n", dev_id);
1140 PrintDebug("Serial device attached\n");
1142 ret |= v3_dev_hook_io(dev, COM1_DATA_PORT, &read_data_port, &write_data_port);
1143 ret |= v3_dev_hook_io(dev, COM1_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
1144 ret |= v3_dev_hook_io(dev, COM1_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1145 ret |= v3_dev_hook_io(dev, COM1_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1146 ret |= v3_dev_hook_io(dev, COM1_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1147 ret |= v3_dev_hook_io(dev, COM1_LINE_STATUS_PORT, &read_status_port, &write_status_port);
1148 ret |= v3_dev_hook_io(dev, COM1_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
1149 ret |= v3_dev_hook_io(dev, COM1_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
1151 ret |= v3_dev_hook_io(dev, COM2_DATA_PORT, &read_data_port, &write_data_port);
1152 ret |= v3_dev_hook_io(dev, COM2_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
1153 ret |= v3_dev_hook_io(dev, COM2_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1154 ret |= v3_dev_hook_io(dev, COM2_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1155 ret |= v3_dev_hook_io(dev, COM2_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1156 ret |= v3_dev_hook_io(dev, COM2_LINE_STATUS_PORT, &read_status_port, &write_status_port);
1157 ret |= v3_dev_hook_io(dev, COM2_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
1158 ret |= v3_dev_hook_io(dev, COM2_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
1160 ret |= v3_dev_hook_io(dev, COM3_DATA_PORT, &read_data_port, &write_data_port);
1161 ret |= v3_dev_hook_io(dev, COM3_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
1162 ret |= v3_dev_hook_io(dev, COM3_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1163 ret |= v3_dev_hook_io(dev, COM3_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1164 ret |= v3_dev_hook_io(dev, COM3_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1165 ret |= v3_dev_hook_io(dev, COM3_LINE_STATUS_PORT, &read_status_port, &write_status_port);
1166 ret |= v3_dev_hook_io(dev, COM3_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
1167 ret |= v3_dev_hook_io(dev, COM3_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
1169 ret |= v3_dev_hook_io(dev, COM4_DATA_PORT, &read_data_port, &write_data_port);
1170 ret |= v3_dev_hook_io(dev, COM4_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
1171 ret |= v3_dev_hook_io(dev, COM4_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1172 ret |= v3_dev_hook_io(dev, COM4_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1173 ret |= v3_dev_hook_io(dev, COM4_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1174 ret |= v3_dev_hook_io(dev, COM4_LINE_STATUS_PORT, &read_status_port, &write_status_port);
1175 ret |= v3_dev_hook_io(dev, COM4_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
1176 ret |= v3_dev_hook_io(dev, COM4_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
1179 PrintError("Error hooking Serial IO ports\n");
1180 v3_remove_device(dev);
1184 PrintDebug("Serial ports hooked\n");
1188 if (v3_dev_add_char_frontend(vm, dev_id, connect_fn, (void *)state) == -1) {
1189 PrintError("Could not register %s as frontend\n", dev_id);
1190 v3_remove_device(dev);
1202 device_register("SERIAL", serial_init)