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>
16 & Peter Dinda <pdinda@northwestern.edu>
18 * This is free software. You are permitted to use,
19 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
23 #include <palacios/vmm.h>
24 #include <palacios/vmm_dev_mgr.h>
25 #include <palacios/vmm_types.h>
27 #include <palacios/vmm_ringbuffer.h>
28 #include <palacios/vmm_lock.h>
29 #include <palacios/vmm_intr.h>
30 #include <palacios/vm_guest.h>
32 #include <devices/serial.h>
35 #ifndef V3_CONFIG_DEBUG_SERIAL
37 #define PrintDebug(fmt, args...)
42 This is an implementation of a 16450 and 16550A-compatible UART (fifo-capable), based on
43 the TI 16550D spec (http://www.ti.com/lit/ds/symlink/pc16550d.pdf) and the Altera
44 16450 spec (ftp://ftp.altera.com/pub/lit_req/document/ds/ds16450.pdf)
48 // This is not yet tested - enable at your own risk!
53 #define COM1_DATA_PORT 0x3f8
54 #define COM1_IRQ_ENABLE_PORT 0x3f9
55 #define COM1_DIV_LATCH_LSB_PORT 0x3f8
56 #define COM1_DIV_LATCH_MSB_PORT 0x3f9
57 #define COM1_IIR_PORT 0x3fa
58 #define COM1_FIFO_CTRL_PORT 0x3fa
59 #define COM1_LINE_CTRL_PORT 0x3fb
60 #define COM1_MODEM_CTRL_PORT 0x3fc
61 #define COM1_LINE_STATUS_PORT 0x3fd
62 #define COM1_MODEM_STATUS_PORT 0x3fe
63 #define COM1_SCRATCH_PORT 0x3ff
65 #define COM2_DATA_PORT 0x2f8
66 #define COM2_IRQ_ENABLE_PORT 0x2f9
67 #define COM2_DIV_LATCH_LSB_PORT 0x2f8
68 #define COM2_DIV_LATCH_MSB_PORT 0x2f9
69 #define COM2_IIR_PORT 0x2fa
70 #define COM2_FIFO_CTRL_PORT 0x2fa
71 #define COM2_LINE_CTRL_PORT 0x2fb
72 #define COM2_MODEM_CTRL_PORT 0x2fc
73 #define COM2_LINE_STATUS_PORT 0x2fd
74 #define COM2_MODEM_STATUS_PORT 0x2fe
75 #define COM2_SCRATCH_PORT 0x2ff
77 #define COM3_DATA_PORT 0x3e8
78 #define COM3_IRQ_ENABLE_PORT 0x3e9
79 #define COM3_DIV_LATCH_LSB_PORT 0x3e8
80 #define COM3_DIV_LATCH_MSB_PORT 0x3e9
81 #define COM3_IIR_PORT 0x3ea
82 #define COM3_FIFO_CTRL_PORT 0x3ea
83 #define COM3_LINE_CTRL_PORT 0x3eb
84 #define COM3_MODEM_CTRL_PORT 0x3ec
85 #define COM3_LINE_STATUS_PORT 0x3ed
86 #define COM3_MODEM_STATUS_PORT 0x3ee
87 #define COM3_SCRATCH_PORT 0x3ef
89 #define COM4_DATA_PORT 0x2e8
90 #define COM4_IRQ_ENABLE_PORT 0x2e9
91 #define COM4_DIV_LATCH_LSB_PORT 0x2e8
92 #define COM4_DIV_LATCH_MSB_PORT 0x2e9
93 #define COM4_IIR_PORT 0x2ea
94 #define COM4_FIFO_CTRL_PORT 0x2ea
95 #define COM4_LINE_CTRL_PORT 0x2eb
96 #define COM4_MODEM_CTRL_PORT 0x2ec
97 #define COM4_LINE_STATUS_PORT 0x2ed
98 #define COM4_MODEM_STATUS_PORT 0x2ee
99 #define COM4_SCRATCH_PORT 0x2ef
102 // Interrupt IDs (in priority order, highest is first)
103 #define RX_IRQ_STATUS 0x3
104 #define RX_IRQ_DR 0x2
105 #define RX_IRQ_TRIGGER_LEVEL 0x2
107 #define TX_IRQ_THRE 0x1
108 #define MODEM_IRQ_DELTA_SET 0x0
116 #define RX_BUFFER 0x1
117 #define TX_BUFFER 0x2
119 //initial value for registers
121 // Per TI spec: http://www.ti.com/lit/ds/symlink/pc16550d.pdf
122 // all interrupt enables off
123 #define IER_INIT_VAL 0x0
124 // no pending interrupts (active low flag)
125 #define IIR_INIT_VAL 0x1
126 // fifos disabled (comes up in 16450 mode)
127 #define FCR_INIT_VAL 0x0
128 // 5 bits, 1 stop bit, no parity, no break, divisor latch off
129 #define LCR_INIT_VAL 0x0
130 // not DTR, not RTS, not OUT1, not OUT2, not loopback
131 #define MCR_INIT_VAL 0x0
132 // tx registers empty, no errors, no data available
133 #define LSR_INIT_VAL 0x60
134 // not cts, not dsr, not ring, etc.
135 #define MSR_INIT_VAL 0x0
136 // baud rate 115200 (divisor is 1)
137 #define DLL_INIT_VAL 0x1
138 #define DLM_INIT_VAL 0x0
140 //receiver buffer register
141 struct rbr_register {
145 // transmitter holding register
146 struct thr_register {
150 //interrupt enable register
151 struct ier_register {
155 uint8_t erbfi : 1; // Enable Receiver Buffer full interrupt
156 uint8_t etbei : 1; // Enable Transmit buffer empty interrupt
157 uint8_t elsi : 1; // Enable Line Status Interrupt
158 uint8_t edssi : 1; // Enable Delta Status signals interrupt
159 uint8_t rsvd : 4; // MBZ
160 } __attribute__((packed));
161 } __attribute__((packed));
162 } __attribute__((packed));
165 //interrupt identification register
166 struct iir_register {
170 uint8_t pending : 1; // Interrupt pending (0=interrupt pending)
171 uint8_t iid : 3; // Interrupt Identification
172 uint8_t rsvd : 2; // MBZ
173 uint8_t fifo_en : 2; // FIFO enable
174 } __attribute__((packed));
175 } __attribute__((packed));
176 } __attribute__((packed));
178 //FIFO control register
179 struct fcr_register {
183 uint8_t enable : 1; // enable fifo
184 uint8_t rfres : 1; // RX FIFO reset
185 uint8_t xfres : 1; // TX FIFO reset
186 uint8_t dma_sel : 1; // DMA mode select
187 uint8_t rsvd : 2; // MBZ
188 uint8_t rx_trigger: 2; // RX FIFO trigger level select
189 } __attribute__((packed));
190 } __attribute__((packed));
191 } __attribute__((packed));
194 //line control register
195 struct lcr_register {
199 uint8_t word_len : 2; // word length select
200 uint8_t stop_bits : 1; // Stop Bit select
201 uint8_t parity_enable : 1; // Enable parity
202 uint8_t even_sel : 1; // Even Parity Select
203 uint8_t stick_parity : 1; // Stick Parity Select (e.g., force mark or space)
204 uint8_t sbr : 1; // Set Break
205 uint8_t dlab : 1; // Divisor latch access bit
206 } __attribute__((packed));
207 } __attribute__((packed));
208 } __attribute__((packed));
211 //modem control register
212 struct mcr_register {
220 uint8_t loop : 1; // loopback mode
221 uint8_t rsvd : 3; // MBZ
222 } __attribute__((packed));
223 } __attribute__((packed));
224 } __attribute__((packed));
227 //line status register
228 struct lsr_register {
232 uint8_t dr : 1; // data ready
233 uint8_t oe : 1; // Overrun error
234 uint8_t pe : 1; // Parity Error
235 uint8_t fe : 1; // Framing Error
236 uint8_t brk : 1; // broken line detected
237 uint8_t thre : 1; // Transmitter holding register empty
238 uint8_t temt : 1; // Transmitter Empty
239 uint8_t fifo_err : 1; // at least one error is pending in the RX FIFO chain
240 } __attribute__((packed));
241 } __attribute__((packed));
242 } __attribute__((packed));
245 struct msr_register {
249 uint8_t dcts : 1; // Delta Clear To Send
250 uint8_t ddsr : 1; // Delta Data Set Ready
251 uint8_t teri : 1; // Trailing Edge Ring Indicator
252 uint8_t ddcd : 1; // Delta Data Carrier Detect
253 uint8_t cts : 1; // Clear to Send
254 uint8_t dsr : 1; // Data Set Ready
255 uint8_t ri : 1; // Ring Indicator
256 uint8_t dcd : 1; // Data Carrier Detect
257 } __attribute__((packed));
258 } __attribute__((packed));
259 } __attribute__((packed));
262 struct scr_register {
267 struct dll_register {
272 struct dlm_register {
275 #define SERIAL_BUF_LEN 16
277 struct serial_buffer {
278 int head; // most recent data
279 int tail; // oldest char
281 uint8_t buffer[SERIAL_BUF_LEN];
285 struct rbr_register rbr;
286 struct thr_register thr;
287 struct ier_register ier;
288 struct iir_register iir;
289 struct fcr_register fcr;
290 struct lcr_register lcr;
291 struct mcr_register mcr;
292 struct lsr_register lsr;
293 struct msr_register msr;
294 struct scr_register scr;
295 struct dll_register dll;
296 struct dlm_register dlm;
299 struct serial_buffer tx_buffer;
300 struct serial_buffer rx_buffer;
304 Multiple interrupt conditions can be active simultaneously.
305 The chip does a priority encoding to determine which one shows up in the iid
307 INT_RX_STAT 1 line status change cleared by LSR read
308 INT_RX_DATA 2 rx data available cleared by RBR read or when FIFO below trigger level
309 INT_RX_TIMEOUT 2 rx fifo lonely cleared by RBR read
310 INT_TX_EMPTY 3 tx space available cleared by IIR read (if in iid) or write to THR
311 INT_MD_STAT 4 modem status change cleared by MSR read
314 #define INT_RX_STAT 1
315 #define INT_RX_DATA 2
316 #define INT_RX_TIMEOUT 4
317 #define INT_TX_EMPTY 8
318 #define INT_MD_STAT 16
319 #define INT_MASK 0x1f
320 // whether we currently have an IRQ raised
321 #define IRQ_RAISED_MASK 128
323 uint8_t int_state; // all currently signaled interrupts, not just the one being delivered
328 struct v3_dev_char_ops * ops;
333 struct serial_state {
334 struct serial_port coms[4];
340 static struct serial_port * get_com_from_port(struct serial_state * serial, uint16_t port) {
341 if ((port >= COM1_DATA_PORT) && (port <= COM1_SCRATCH_PORT)) {
342 PrintDebug(VM_NONE, VCORE_NONE, "UART: COM1\n");
343 return &(serial->coms[0]);
344 } else if ((port >= COM2_DATA_PORT) && (port <= COM2_SCRATCH_PORT)) {
345 PrintDebug(VM_NONE, VCORE_NONE, "UART: COM2\n");
346 return &(serial->coms[1]);
347 } else if ((port >= COM3_DATA_PORT) && (port <= COM3_SCRATCH_PORT)) {
348 PrintDebug(VM_NONE, VCORE_NONE, "UART: COM3\n");
349 return &(serial->coms[2]);
350 } else if ((port >= COM4_DATA_PORT) && (port <= COM4_SCRATCH_PORT)) {
351 PrintDebug(VM_NONE, VCORE_NONE, "UART: COM4\n");
352 return &(serial->coms[3]);
354 PrintError(VM_NONE, VCORE_NONE, "UART: Error: Could not find serial port associated with IO port %d\n", port);
359 static inline bool receive_buffer_trigger(int number, int trigger_number) {
361 switch (trigger_number) {
363 return (number >= 1);
365 return (number >= 4);
367 return (number >= 8);
369 return (number >= 14);
376 static int getNumber(struct serial_buffer * buf) {
377 int number = buf->head - buf->tail;
379 if (buf->full == 1) {
380 return SERIAL_BUF_LEN;
381 } else if (number >= 0) {
384 return SERIAL_BUF_LEN + number;
391 static inline int can_queue(struct serial_buffer * buf)
396 static inline int can_dequeue(struct serial_buffer * buf)
398 return !( (buf->head == buf->tail) && (buf->full != 1) );
402 static inline int peek_queue(struct serial_buffer *buf, uint8_t *data)
404 int next_tail = (buf->tail + 1) % SERIAL_BUF_LEN;
406 *data = buf->buffer[next_tail];
412 // 0 = successfully queued byte
414 // caller responsible for locking
415 // caller responsible for updateIRQ
416 static int queue_data(struct v3_vm_info * vm, struct serial_port * com,
417 struct serial_buffer * buf, uint8_t data) {
418 int next_loc = (buf->head + 1) % SERIAL_BUF_LEN;
420 PrintDebug(vm, VCORE_NONE,"UART: queue 0x%x ('%c') to %s buffer\n", data, data,
421 buf == &(com->rx_buffer) ? "RX" : "TX");
423 if (!can_queue(buf)) {
424 PrintDebug(vm, VCORE_NONE, "UART: Buffer is full!\n");
426 // We will not consider this an overrun, instead,
427 // we push the problem back to the caller
433 buf->buffer[next_loc] = data;
434 buf->head = next_loc;
436 if (buf->head == buf->tail) {
440 if (buf == &(com->rx_buffer)) {
441 com->lsr.dr = 1; //as soon as new data arrives at receive buffer, set data ready bit in lsr.
443 // Set INT_RX_DATA if fifo is now above trigger level or fifos are off
445 if ( (com->fcr.enable && (receive_buffer_trigger( getNumber(&(com->rx_buffer)), com->fcr.rx_trigger)))
446 || !com->fcr.enable) {
448 com->int_state |= INT_RX_DATA;
450 PrintDebug(vm, VCORE_NONE, "UART: Set data ready and raised INT_RX_DATA\n");
456 if ((buf == &(com->tx_buffer))) {
457 // at least one item in the TX queue now
459 com->lsr.thre = 0; //reset thre and temt bits.
462 // TX EMPTY deasserted
463 com->int_state &= ~INT_TX_EMPTY;
465 PrintDebug(vm, VCORE_NONE, "UART: lowered INT_TX_EMPTY\n");
474 // <0 = data not returned
475 // caller responsible for locking
476 // caller responsible for doing updateIRQ
477 static int dequeue_data(struct v3_vm_info * vm, struct serial_port * com,
478 struct serial_buffer * buf, uint8_t * data)
482 PrintDebug(vm, VCORE_NONE,"UART: dequeue from %s buffer\n",
483 buf == &(com->rx_buffer) ? "RX" : "TX");
485 if (!can_dequeue(buf)) {
486 PrintDebug(vm, VCORE_NONE, "UART: queue is empty - no state change, returning '!'\n");
487 *data='!'; // just in case it uses what's there, blindly
488 // for both rx and tx queues, we signaled when we droped to zero
489 // so we don't resignal here, so no need to call updateIRQ
493 int next_tail = (buf->tail + 1) % SERIAL_BUF_LEN;
496 if (buf->full == 1) {
501 *data = buf->buffer[next_tail];
503 buf->buffer[next_tail] = 0;
504 buf->tail = next_tail;
506 PrintDebug(vm,VCORE_NONE,"UART: dequeue will return 0x%x ('%c')\n", *data, *data);
508 if (buf == &(com->rx_buffer)) {
510 // Reset INT_RX_DATA if RBR read with if fifo is now below trigger level or fifos are off
512 if ( (com->fcr.enable && (!receive_buffer_trigger( getNumber(&(com->rx_buffer)), com->fcr.rx_trigger)))
513 || !com->fcr.enable) {
514 PrintDebug(vm, VCORE_NONE, "UART: lowering INT_RX_DATA since we're below threshold\n");
515 com->int_state &= ~INT_RX_DATA;
519 // Reset DR if we have dropped to zero bytes
520 if (getNumber(&(com->rx_buffer)) ==0) {
521 PrintDebug(vm, VCORE_NONE, "UART: setting DR to zero since we have zero bytes\n");
523 // should have lowered INT_RX_DATA earlier
527 com->int_state &= ~INT_RX_TIMEOUT;
531 if ((buf == &(com->tx_buffer)) && (getNumber(&(com->tx_buffer)) == 0)) {
535 // Aassert TX empty when we truly drop to zero;
536 com->int_state |= INT_TX_EMPTY;
544 // Caller is assumed to have acquired the lock
546 static int pump_transmit(struct v3_vm_info * vm, struct serial_port * com)
547 // Now we will pump transmit data to the backend, if any
552 while (can_dequeue(&(com->tx_buffer))) {
553 if (com->ops) { // do we have a back-end to toss it to?
555 // let's take a peek and see if we can send it
556 peek_queue(&(com->tx_buffer),&buf);
557 rc = com->ops->output(&buf, 1, com->backend_data);
559 PrintError(vm, VCORE_NONE, "UART: backend write returned error\n");
560 // we need to give up at this point -
563 // no room to send it
564 PrintDebug(vm, VCORE_NONE, "UART: backend write would block\n");
565 // we do nothing but we don't want to iterate again
568 // it was sent, now we need to remove it from the queue for real
569 // as well as update the device state
570 if (dequeue_data(vm,com,&(com->tx_buffer),&buf)) {
571 PrintError(vm, VCORE_NONE, "UART: uh... dequeue_data failed after successful peek?!\n");
574 // we have already sent the byte to the backend, so we
575 // just discard it now and continue to the next one
577 } else { // there is no backend
578 if (dequeue_data(vm,com,&(com->tx_buffer),&buf)) {
579 PrintError(vm, VCORE_NONE, "UART: uh... dequeue_data failed after successful can_dequeue?!\n");
581 // no backend, so just discard the data
587 static int updateIRQ(struct v3_vm_info * vm, struct serial_port * com) {
591 PrintDebug(vm,VCORE_NONE, "UART: updateIRQ before pending check: iir.pending=%d iir.iid=%d int_state=0x%x\n",
592 com->iir.pending, com->iir.iid, com->int_state);
594 // if we have have raised an irq, we need to lower it if it's been handled
595 // we should also presumably lower it if the guest decided to
596 // disable the interrupt
597 if (!com->iir.pending && (com->int_state & IRQ_RAISED_MASK)) { // active low pending, and we have raised
598 switch (com->iir.iid) {
600 if (!(com->int_state & INT_RX_STAT) || // now low or
601 ((com->int_state & INT_RX_STAT) && !com->ier.elsi)) { // no longer enabled
602 // no longer asserted
603 v3_lower_irq(vm, com->irq_number);
604 com->int_state &= ~IRQ_RAISED_MASK;
607 PrintDebug(vm, VCORE_NONE, "UART: lowered irq on reset of INT_RX_STAT\n");
611 // case RX_IRQ_TRIGGER_LEVEL: is the smae
612 if (!(com->int_state & INT_RX_DATA) ||
613 ((com->int_state & INT_RX_STAT) && !com->ier.erbfi)) {
614 // no longer asserted
615 v3_lower_irq(vm, com->irq_number);
616 com->int_state &= ~IRQ_RAISED_MASK;
619 PrintDebug(vm, VCORE_NONE, "UART: lowered irq on reset of INT_RX_DATA\n");
623 if (!(com->int_state & INT_RX_TIMEOUT) ||
624 ((com->int_state & INT_RX_TIMEOUT) && !com->ier.erbfi)) {
625 // no longer asserted
626 v3_lower_irq(vm, com->irq_number);
627 com->int_state &= ~IRQ_RAISED_MASK;
630 PrintDebug(vm, VCORE_NONE, "UART: lowered irq on reset of INT_RX_TIMEOUT\n");
634 if (!(com->int_state & INT_TX_EMPTY) ||
635 ((com->int_state & INT_TX_EMPTY) && !com->ier.etbei)) {
636 // no longer asserted
637 v3_lower_irq(vm, com->irq_number);
638 com->int_state &= ~IRQ_RAISED_MASK;
641 PrintDebug(vm, VCORE_NONE, "UART: lowered irq on reset of INT_TX_EMPTY\n");
644 case MODEM_IRQ_DELTA_SET:
645 if (!(com->int_state & INT_MD_STAT) ||
646 ((com->int_state & INT_MD_STAT) && !com->ier.edssi)) {
647 // no longer asserted
648 v3_lower_irq(vm, com->irq_number);
649 com->int_state &= ~IRQ_RAISED_MASK;
652 PrintDebug(vm, VCORE_NONE, "UART: lowered irq on reset of INT_MD_STAT\n");
658 PrintDebug(vm,VCORE_NONE, "UART: updateIRQ before transmit-pump: iir.pending=%d iir.iid=%d int_state=0x%x\n",
659 com->iir.pending, com->iir.iid, com->int_state);
661 if (pump_transmit(vm,com)) {
662 PrintError(vm,VCORE_NONE, "UART: pump_transmit failed - eh?\n");
665 // At this point, INT_TX_EMPTY might have also been raised
667 // even if pump_transmit wasn't able to do anything, we need to
668 // raise the interrupt - this is the case, for example, if the
669 // guest does an interrupt enable of the tx empty interrupt before
671 com->int_state |= INT_TX_EMPTY;
674 PrintDebug(vm,VCORE_NONE, "UART: updateIRQ before priority encode: iir.pending=%d iir.iid=%d int_state=0x%x\n",
675 com->iir.pending, com->iir.iid, com->int_state);
678 if (!(com->int_state & IRQ_RAISED_MASK)) {
679 // We can inject a new interrupt since the last one is done
680 // Now we do the priority encode
681 if ((com->int_state & INT_RX_STAT) && com->ier.elsi ) {
684 com->iir.iid = RX_IRQ_STATUS;
685 v3_raise_irq(vm,com->irq_number);
686 com->int_state |= IRQ_RAISED_MASK;
687 PrintDebug(vm, VCORE_NONE, "UART: raised irq on set of INT_RX_STAT\n");
688 } else if ((com->int_state & INT_RX_DATA) && com->ier.erbfi) {
689 // 2nd highest priority
691 com->iir.iid = RX_IRQ_DR;
692 v3_raise_irq(vm,com->irq_number);
693 com->int_state |= IRQ_RAISED_MASK;
694 PrintDebug(vm, VCORE_NONE, "UART: raised irq on set of INT_RX_DATA\n");
695 } else if ((com->int_state & INT_RX_TIMEOUT) && com->ier.erbfi) {
696 // Also 2nd highest priority
698 com->iir.iid = FIFO_IRQ;
699 v3_raise_irq(vm,com->irq_number);
700 com->int_state |= IRQ_RAISED_MASK;
701 PrintDebug(vm, VCORE_NONE, "UART: raised irq on set of INT_RX_TIMEOUT\n");
702 } else if ((com->int_state & INT_TX_EMPTY) && com->ier.etbei) {
703 // 3rd highest priority
705 com->iir.iid = TX_IRQ_THRE;
706 v3_raise_irq(vm,com->irq_number);
707 com->int_state |= IRQ_RAISED_MASK;
708 PrintDebug(vm, VCORE_NONE, "UART: raised irq on set of INT_TX_EMPTY\n");
709 } else if ((com->int_state & INT_MD_STAT) && com->ier.edssi) {
710 // 4th highest priority
712 com->iir.iid = MODEM_IRQ_DELTA_SET;
713 v3_raise_irq(vm,com->irq_number);
714 com->int_state |= IRQ_RAISED_MASK;
715 PrintDebug(vm, VCORE_NONE, "UART: raised irq on set of INT_MD_STAT\n");
726 static int write_data_port(struct guest_info * core, uint16_t port,
727 void * src, uint_t length, void * priv_data) {
728 struct serial_state * state = priv_data;
729 uint8_t * val = (uint8_t *)src;
730 struct serial_port * com_port = NULL;
733 PrintDebug(core->vm_info, core, "UART: Write to Data Port 0x%x (val=%x, '%c')\n", port, *val, *val);
736 PrintError(core->vm_info, core, "UART: Invalid length(%d) in write to 0x%x\n", length, port);
740 if ((port != COM1_DATA_PORT) && (port != COM2_DATA_PORT) &&
741 (port != COM3_DATA_PORT) && (port != COM4_DATA_PORT)) {
742 PrintError(core->vm_info, core, "UART: Serial write data port for illegal port Number (%d)\n", port);
746 com_port = get_com_from_port(state, port);
748 if (com_port == NULL) {
749 PrintError(core->vm_info, core, "UART: write of unknown port %d - lookup failed?!\n",port);
753 irq_status = v3_lock_irqsave(com_port->lock);
755 // dlab is always checked first
756 if (com_port->lcr.dlab == 1) {
757 PrintDebug(core->vm_info, core, "UART: Write to DLM, old DLM is 0x%x\n",com_port->dlm.data);
758 com_port->dll.data = *val;
759 PrintDebug(core->vm_info, core, "UART: Write to DLM, new DLM is 0x%x\n",com_port->dlm.data);
761 // queue data to send and update interrupts
762 PrintDebug(core->vm_info, core, "UART: queue transmission of 0x%x ('%c')\n",*val,*val);
763 if (queue_data(core->vm_info, com_port, &(com_port->tx_buffer), *val)) {
764 PrintError(core->vm_info,core, "UART: no room for transmitted data - dropped\n");
765 // note that it must "succeed" since this is a device port
767 updateIRQ(core->vm_info, com_port);
771 v3_unlock_irqrestore(com_port->lock, irq_status);
778 static int read_data_port(struct guest_info * core, uint16_t port,
779 void * dst, uint_t length, void * priv_data) {
780 struct serial_state * state = priv_data;
781 uint8_t * val = (uint8_t *)dst;
782 struct serial_port * com_port = NULL;
785 PrintDebug(core->vm_info, core, "UART: Read from Data Port 0x%x\n", port);
788 PrintError(core->vm_info, core, "UART: Invalid length(%d) in write to 0x%x\n", length, port);
792 if ((port != COM1_DATA_PORT) && (port != COM2_DATA_PORT) &&
793 (port != COM3_DATA_PORT) && (port != COM4_DATA_PORT)) {
794 PrintError(core->vm_info, core, "UART: Serial Read data port for illegal port Number (%d)\n", port);
798 com_port = get_com_from_port(state, port);
800 if (com_port == NULL) {
801 PrintError(core->vm_info, core, "UART: write of unknown port %d - lookup failed?!\n",port);
805 irq_status = v3_lock_irqsave(com_port->lock);
807 if (com_port->lcr.dlab == 1) {
808 *val = com_port->dll.data;
809 PrintDebug(core->vm_info, core, "UART: read of DLL returning 0x%x\n",*val);
811 if (dequeue_data(core->vm_info, com_port, &(com_port->rx_buffer), val)) {
812 PrintError(core->vm_info, core, "UART: no received data available - returning garbaage\n");
813 // note that it must "succeed" since this is device port read
815 updateIRQ(core->vm_info, com_port);
817 PrintDebug(core->vm_info, core, "UART: dequeued received data 0x%x ('%c')\n",*val,*val);
820 v3_unlock_irqrestore(com_port->lock, irq_status);
826 static void flush_buffer(struct serial_buffer *buf)
831 memset(buf->buffer, 0, SERIAL_BUF_LEN);
835 // caller is assumed to have acquired the lock
836 // caller is responsible for updateIRQ
837 static void handle_fcr_write(struct serial_port * com, uint8_t value) {
841 if ((!com->fcr.enable && (value & 0x1)) || (com->fcr.enable && !(value & 0x1))) {
842 // switch of modes from 16450<->16550
843 // flush fifos, reset state
844 flush_buffer(&(com->rx_buffer));
845 flush_buffer(&(com->tx_buffer));
847 com->int_state &= ~INT_RX_DATA; // no data in rx buffer - lower
851 com->int_state |= INT_TX_EMPTY; // tx buffer empty - raise
854 if (!(value & 0x1)) { // disabling
855 // enable->disable requires flush and state reset, handled above
856 // disable->disable doesn't require flush, I don't think
858 com->iir.fifo_en = 0;
859 // reset does not change rest of fcr register
861 com->fcr.val = value;
862 com->fcr.rsvd = 0; // we are not some weird chip
864 //if rfres set, clear receive buffer.
865 if (com->fcr.rfres == 0x1) {
866 flush_buffer(&(com->rx_buffer));
867 com->fcr.rfres = 0; // bit is self-clearing
869 com->int_state &= ~INT_RX_DATA; // no data in rx buffer - lower
872 //if xfres set, clear transmit buffer.
873 if (com->fcr.xfres == 0x1) {
874 flush_buffer(&(com->tx_buffer));
875 com->fcr.xfres = 0; // bit is self-clearing
878 com->int_state |= INT_TX_EMPTY; // tx buffer empty -raise
881 com->iir.fifo_en = 0x3; // We are a 16550A
882 com->iir.fifo_en = 0x0; // We are a 16450A
884 // 00 => 8250/16450 (latter if have scratchpad)
890 // does nothing since a 16450 has no fcr
893 // caller must update irq!
900 static int handle_multiple(int (*func)(struct guest_info *core,
901 uint16_t port, void *dst,
902 uint_t length, void *priv_data),
903 struct guest_info *core, uint16_t port,
904 void *dst, uint_t length, void *priv_data)
910 return func(core,port,dst,length,priv_data);
912 for (i=0;i<length;i++) {
913 rc = func(core,port+i,dst+i,1,priv_data);
922 static int write_ctrl_port(struct guest_info * core, uint16_t port, void * src,
923 uint_t length, void * priv_data) {
924 struct serial_state * state = priv_data;
925 uint8_t val = *(uint8_t *)src;
926 struct serial_port * com_port = NULL;
930 PrintDebug(core->vm_info, core, "UART: Write to Control Port (val=%x)\n", val);
933 PrintError(core->vm_info, core, "UART: Invalid Write length to control port%d\n", port);
937 com_port = get_com_from_port(state, port);
939 if (com_port == NULL) {
940 PrintError(core->vm_info, core, "UART: Could not find serial port corresponding to IO port %d\n", port);
944 irq_status = v3_lock_irqsave(com_port->lock);
948 //always check dlab first
950 case COM1_IRQ_ENABLE_PORT:
951 case COM2_IRQ_ENABLE_PORT:
952 case COM3_IRQ_ENABLE_PORT:
953 case COM4_IRQ_ENABLE_PORT: {
954 PrintDebug(core->vm_info, core, "UART: Write to IER/LATCH port: dlab is %x\n", com_port->lcr.dlab);
956 if (com_port->lcr.dlab == 1) {
957 PrintDebug(core->vm_info, core, "UART: Write to DLM, old DLM is 0x%x\n",com_port->dlm.data);
958 com_port->dlm.data = val;
959 PrintDebug(core->vm_info, core, "UART: Write to DLM, new DLM is 0x%x\n",com_port->dlm.data);
961 PrintDebug(core->vm_info, core, "UART: Write to IER, old IER is erbfi=%d etbei=%d elsi=%d edssi=%d\n",
962 com_port->ier.erbfi,com_port->ier.etbei,com_port->ier.elsi,com_port->ier.edssi);
963 com_port->ier.val = val;
964 com_port->ier.rsvd = 0; // we are not some weird chip
965 PrintDebug(core->vm_info, core, "UART: Write to IER, new IER is erbfi=%d etbei=%d elsi=%d edssi=%d\n",
966 com_port->ier.erbfi,com_port->ier.etbei,com_port->ier.elsi,com_port->ier.edssi);
967 // some signaled interrupt might now need to fire
970 updateIRQ(core->vm_info,com_port);
974 case COM1_FIFO_CTRL_PORT:
975 case COM2_FIFO_CTRL_PORT:
976 case COM3_FIFO_CTRL_PORT:
977 case COM4_FIFO_CTRL_PORT: {
978 PrintDebug(core->vm_info, core, "UART: Write to FCR, old FCR is enable=%d rfres=%d xfres=%d dma_sel=%d rx_trigger=%d\n",
979 com_port->fcr.enable, com_port->fcr.rfres, com_port->fcr.xfres, com_port->fcr.dma_sel, com_port->fcr.rx_trigger);
981 handle_fcr_write(com_port, val); // cannot fail
983 PrintDebug(core->vm_info, core, "UART: Write to FCR, new FCR is enable=%d rfres=%d xfres=%d dma_sel=%d rx_trigger=%d\n",
984 com_port->fcr.enable, com_port->fcr.rfres, com_port->fcr.xfres, com_port->fcr.dma_sel, com_port->fcr.rx_trigger);
986 updateIRQ(core->vm_info,com_port);
990 case COM1_LINE_CTRL_PORT:
991 case COM2_LINE_CTRL_PORT:
992 case COM3_LINE_CTRL_PORT:
993 case COM4_LINE_CTRL_PORT: {
994 PrintDebug(core->vm_info, core, "UART: Write to LCR, old LCR is word_len=%d stop_bits=%d parity_enable=%d even_sel=%d stick_parity=%d sbr=%d dlab=%d\n",
995 com_port->lcr.word_len,com_port->lcr.stop_bits,com_port->lcr.parity_enable,com_port->lcr.even_sel,com_port->lcr.stick_parity,com_port->lcr.sbr,com_port->lcr.dlab);
997 com_port->lcr.val = val;
1000 PrintDebug(core->vm_info, core, "UART: Write to LCR, new LCR is word_len=%d stop_bits=%d parity_enable=%d even_sel=%d stick_parity=%d sbr=%d dlab=%d\n",
1001 com_port->lcr.word_len,com_port->lcr.stop_bits,com_port->lcr.parity_enable,com_port->lcr.even_sel,com_port->lcr.stick_parity,com_port->lcr.sbr,com_port->lcr.dlab);
1003 updateIRQ(core->vm_info, com_port);
1007 case COM1_MODEM_CTRL_PORT:
1008 case COM2_MODEM_CTRL_PORT:
1009 case COM3_MODEM_CTRL_PORT:
1010 case COM4_MODEM_CTRL_PORT: {
1011 PrintDebug(core->vm_info, core, "UART: Write to MCR, old MCR is dtr=%d rts=%d out1=%d out2=%d loop=%d\n",
1012 com_port->mcr.dtr,com_port->mcr.rts,com_port->mcr.out1,com_port->mcr.out2,com_port->mcr.loop);
1014 com_port->mcr.val = val;
1015 com_port->mcr.rsvd = 0; // we are not some weird chip
1017 PrintDebug(core->vm_info, core, "UART: Write to MCR, new MCR is dtr=%d rts=%d out1=%d out2=%d loop=%d\n",
1018 com_port->mcr.dtr,com_port->mcr.rts,com_port->mcr.out1,com_port->mcr.out2,com_port->mcr.loop);
1020 updateIRQ(core->vm_info, com_port);
1024 case COM1_SCRATCH_PORT:
1025 case COM2_SCRATCH_PORT:
1026 case COM3_SCRATCH_PORT:
1027 case COM4_SCRATCH_PORT: {
1028 PrintDebug(core->vm_info, core, "UART: Write to SCRATCH, old value is 0x%x\n",com_port->scr.data);
1030 com_port->scr.data = val;
1032 PrintDebug(core->vm_info, core, "UART: Write to SCRATCH, new value is 0x%x\n",com_port->scr.data);
1036 PrintError(core->vm_info, core, "UART: Write to unknown port %d, ERROR\n",port);
1040 v3_unlock_irqrestore(com_port->lock,irq_status);
1048 static int read_ctrl_port(struct guest_info * core, uint16_t port, void * dst,
1049 uint_t length, void * priv_data) {
1050 struct serial_state * state = priv_data;
1051 uint8_t * val = (uint8_t *)dst;
1052 struct serial_port * com_port = NULL;
1056 PrintDebug(core->vm_info, core, "UART: Read from Control Port\n");
1059 PrintError(core->vm_info, core, "UART: Invalid Read length to control port\n");
1063 com_port = get_com_from_port(state, port);
1065 if (com_port == NULL) {
1066 PrintError(core->vm_info, core, "UART: Could not find serial port corresponding to IO port %d\n", port);
1070 irq_status = v3_lock_irqsave(com_port->lock);
1074 //always check dlab first
1076 case COM1_IRQ_ENABLE_PORT:
1077 case COM2_IRQ_ENABLE_PORT:
1078 case COM3_IRQ_ENABLE_PORT:
1079 case COM4_IRQ_ENABLE_PORT: {
1080 PrintDebug(core->vm_info, core, "UART: Read from IER/LATCH port: dlab is %x\n", com_port->lcr.dlab);
1082 if (com_port->lcr.dlab == 1) {
1083 PrintDebug(core->vm_info, core, "UART: Read of DLM, value 0x%x\n",com_port->dlm.data);
1084 *val = com_port->dlm.data;
1086 *val = com_port->ier.val;
1087 PrintDebug(core->vm_info, core, "UART: Read of IER is val=0x%x - erbfi=%d etbei=%d elsi=%d edssi=%d\n",
1088 com_port->ier.val, com_port->ier.erbfi,com_port->ier.etbei,com_port->ier.elsi,com_port->ier.edssi);
1097 PrintDebug(core->vm_info, core, "UART: read from IIR is val=0x%x - pending=%d iid=%d fifo_en=%d\n",
1098 com_port->iir.val,com_port->iir.pending,com_port->iir.iid,com_port->iir.fifo_en);
1099 *val = com_port->iir.val;
1101 if ((com_port->int_state & IRQ_RAISED_MASK) &&
1102 !com_port->iir.pending && com_port->iir.iid==TX_IRQ_THRE) {
1103 // we are firing a TX_IRQ_THRE interrupt, therefore
1104 // this read resets it
1106 com_port->int_state &= ~INT_TX_EMPTY;
1108 updateIRQ(core->vm_info,com_port);
1113 case COM1_LINE_CTRL_PORT:
1114 case COM2_LINE_CTRL_PORT:
1115 case COM3_LINE_CTRL_PORT:
1116 case COM4_LINE_CTRL_PORT:
1117 PrintDebug(core->vm_info, core, "UART: read from LCR is val=0x%x - word_len=%d stop_bits=%d parity_enable=%d even_sel=%d stick_parity=%d sbr=%d dlab=%d\n",
1118 com_port->lcr.val,com_port->lcr.word_len, com_port->lcr.stop_bits,com_port->lcr.parity_enable,com_port->lcr.even_sel,com_port->lcr.stick_parity,com_port->lcr.sbr,com_port->lcr.dlab);
1119 *val = com_port->lcr.val;
1122 case COM1_MODEM_CTRL_PORT:
1123 case COM2_MODEM_CTRL_PORT:
1124 case COM3_MODEM_CTRL_PORT:
1125 case COM4_MODEM_CTRL_PORT:
1126 PrintDebug(core->vm_info, core, "UART: read from MCR is val=0x%x - dtr=%d rts=%d out1=%d out2=%d loop=%d\n",
1127 com_port->mcr.val,com_port->mcr.dtr,com_port->mcr.rts,com_port->mcr.out1,com_port->mcr.out2,com_port->mcr.loop);
1128 *val = com_port->mcr.val;
1131 case COM1_SCRATCH_PORT:
1132 case COM2_SCRATCH_PORT:
1133 case COM3_SCRATCH_PORT:
1134 case COM4_SCRATCH_PORT:
1135 PrintDebug(core->vm_info, core, "UART: read from SCRATCH is val=0x%x\n",com_port->scr.data);
1136 *val = com_port->scr.data;
1140 PrintError(core->vm_info, core, "UART: read from unknown port %d\n",port);
1144 v3_unlock_irqrestore(com_port->lock,irq_status);
1150 static int write_status_port(struct guest_info * core, uint16_t port, void * src,
1151 uint_t length, void * priv_data) {
1152 struct serial_state * state = priv_data;
1153 uint8_t val = *(uint8_t *)src;
1154 struct serial_port * com_port = NULL;
1158 PrintDebug(core->vm_info, core, "UART: Write to Status Port (val=0x%x)\n", val);
1161 PrintError(core->vm_info, core, "UART: Invalid Write length (%d) to status port %d\n", length, port);
1165 com_port = get_com_from_port(state, port);
1167 if (com_port == NULL) {
1168 PrintError(core->vm_info, core, "UART: Could not find serial port corresponding to IO port %d\n", port);
1172 irq_status = v3_lock_irqsave(com_port->lock);
1177 case COM1_LINE_STATUS_PORT:
1178 case COM2_LINE_STATUS_PORT:
1179 case COM3_LINE_STATUS_PORT:
1180 case COM4_LINE_STATUS_PORT:
1181 PrintDebug(core->vm_info, core, "UART: Write to LSR, old value is 0x%x - dr=%d oe=%d pe=%d fe=%d brk=%d thre=%d temt=%d fifo_err=%d\n",
1182 com_port->lsr.val,com_port->lsr.dr,com_port->lsr.oe,com_port->lsr.pe,com_port->lsr.fe,com_port->lsr.brk,com_port->lsr.thre,com_port->lsr.temt,com_port->lsr.fifo_err);
1184 com_port->lsr.val = val;
1187 PrintDebug(core->vm_info, core, "UART: Write to LSR, new value is 0x%x - dr=%d oe=%d pe=%d fe=%d brk=%d thre=%d temt=%d fifo_err=%d\n",
1188 com_port->lsr.val,com_port->lsr.dr,com_port->lsr.oe,com_port->lsr.pe,com_port->lsr.fe,com_port->lsr.brk,com_port->lsr.thre,com_port->lsr.temt,com_port->lsr.fifo_err);
1190 updateIRQ(core->vm_info, com_port);
1194 case COM1_MODEM_STATUS_PORT:
1195 case COM2_MODEM_STATUS_PORT:
1196 case COM3_MODEM_STATUS_PORT:
1197 case COM4_MODEM_STATUS_PORT:
1199 PrintDebug(core->vm_info,core,"UART: Write to MSR, old value is 0x%x - dcts=%d ddsr=%d teri=%d ddcd=%d cts=%d dsr=%d ri=%d dcd=%d\n",
1200 com_port->msr.val,com_port->msr.dcts,com_port->msr.ddsr,com_port->msr.teri,com_port->msr.ddcd,com_port->msr.cts,com_port->msr.dsr,com_port->msr.ri,com_port->msr.dcd);
1202 com_port->msr.val = val;
1205 PrintDebug(core->vm_info,core,"UART: Write to MSR, new value is 0x%x - dcts=%d ddsr=%d teri=%d ddcd=%d cts=%d dsr=%d ri=%d dcd=%d\n",
1206 com_port->msr.val,com_port->msr.dcts,com_port->msr.ddsr,com_port->msr.teri,com_port->msr.ddcd,com_port->msr.cts,com_port->msr.dsr,com_port->msr.ri,com_port->msr.dcd);
1208 updateIRQ(core->vm_info, com_port);
1213 PrintError(core->vm_info, core, "UART: write to unsupported port %d\n",port);
1217 v3_unlock_irqrestore(com_port->lock,irq_status);
1223 static int read_status_port(struct guest_info * core, uint16_t port, void * dst,
1224 uint_t length, void * priv_data) {
1225 struct serial_state * state = priv_data;
1226 uint8_t * val = (uint8_t *)dst;
1227 struct serial_port * com_port = NULL;
1231 if (length==2 && (port==COM1_MODEM_STATUS_PORT ||
1232 port==COM2_MODEM_STATUS_PORT ||
1233 port==COM3_MODEM_STATUS_PORT ||
1234 port==COM4_MODEM_STATUS_PORT) ) {
1235 return handle_multiple(read_status_port,core,port,dst,length, priv_data);
1236 } else if (length!=1) {
1237 PrintError(core->vm_info, core, "UART: Invalid Read length (%d) from status port %d\n", length, port);
1241 PrintDebug(core->vm_info, core, "UART: Read from Status Port 0x%x\n", port);
1243 com_port = get_com_from_port(state, port);
1245 if (com_port == NULL) {
1246 PrintError(core->vm_info, core, "UART: Could not find serial port corresponding to IO port %d\n", port);
1250 irq_status = v3_lock_irqsave(com_port->lock);
1254 case COM1_LINE_STATUS_PORT:
1255 case COM2_LINE_STATUS_PORT:
1256 case COM3_LINE_STATUS_PORT:
1257 case COM4_LINE_STATUS_PORT:
1259 PrintDebug(core->vm_info, core, "UART: Read from LSR is 0x%x - dr=%d oe=%d pe=%d fe=%d brk=%d thre=%d temt=%d fifo_err=%d\n",
1260 com_port->lsr.val,com_port->lsr.dr,com_port->lsr.oe,com_port->lsr.pe,com_port->lsr.fe,com_port->lsr.brk,com_port->lsr.thre,com_port->lsr.temt,com_port->lsr.fifo_err);
1262 *val = com_port->lsr.val;
1265 // Reading the LSR resets the line error state
1266 com_port->lsr.oe = 0;
1267 com_port->lsr.pe = 0;
1268 com_port->lsr.fe = 0;
1269 com_port->lsr.brk = 0;
1270 com_port->lsr.fifo_err = 0;
1272 // and clears any interrupt we set due to it
1273 com_port->int_state &= ~INT_RX_STAT;
1275 updateIRQ(core->vm_info,com_port);
1280 case COM1_MODEM_STATUS_PORT:
1281 case COM2_MODEM_STATUS_PORT:
1282 case COM3_MODEM_STATUS_PORT:
1283 case COM4_MODEM_STATUS_PORT:
1284 PrintDebug(core->vm_info,core,"UART: read of MSR is 0x%x - dcts=%d ddsr=%d teri=%d ddcd=%d cts=%d dsr=%d ri=%d dcd=%d\n",
1285 com_port->msr.val,com_port->msr.dcts,com_port->msr.ddsr,com_port->msr.teri,com_port->msr.ddcd,com_port->msr.cts,com_port->msr.dsr,com_port->msr.ri,com_port->msr.dcd);
1287 *val = com_port->msr.val;
1289 // MSR read resets any interrupt due to modem error
1290 com_port->int_state &= ~INT_MD_STAT;
1292 updateIRQ(core->vm_info,com_port);
1297 PrintError(core->vm_info, core, "UART: read of unknown port %d (length = %d)\n", port, length);
1301 v3_unlock_irqrestore(com_port->lock, irq_status);
1307 static int deinit_serial_port(struct serial_port *);
1309 static int serial_free(struct serial_state * state) {
1311 deinit_serial_port(&(state->coms[0]));
1312 deinit_serial_port(&(state->coms[1]));
1313 deinit_serial_port(&(state->coms[2]));
1314 deinit_serial_port(&(state->coms[3]));
1322 #ifdef V3_CONFIG_CHECKPOINT
1324 #include <palacios/vmm_sprintf.h>
1326 static int serial_buffer_save(struct v3_chkpt_ctx * ctx, int port, struct serial_buffer *sb, char * bufname) {
1330 snprintf(keyname,128,"COM%d_%s_HEAD", port, bufname);
1331 V3_CHKPT_SAVE(ctx,keyname,sb->head,failout);
1332 snprintf(keyname,128,"COM%d_%s_TAIL", port, bufname);
1333 V3_CHKPT_SAVE(ctx,keyname,sb->tail,failout);
1334 snprintf(keyname,128,"COM%d_%s_FULL", port, bufname);
1335 V3_CHKPT_SAVE(ctx,keyname,sb->full,failout);
1336 snprintf(keyname,128,"COM%d_%s_DATA", port, bufname);
1337 V3_CHKPT_SAVE(ctx,keyname,sb->buffer,failout);
1342 PrintError(VM_NONE, VCORE_NONE, "Failed to save serial buffer\n");
1347 static int serial_buffer_load(struct v3_chkpt_ctx * ctx, int port, struct serial_buffer *sb, char * bufname) {
1351 snprintf(keyname,128,"COM%d_%s_HEAD", port, bufname);
1352 V3_CHKPT_LOAD(ctx,keyname,sb->head,failout);
1353 snprintf(keyname,128,"COM%d_%s_TAIL", port, bufname);
1354 V3_CHKPT_LOAD(ctx,keyname,sb->tail,failout);
1355 snprintf(keyname,128,"COM%d_%s_FULL", port, bufname);
1356 V3_CHKPT_LOAD(ctx,keyname,sb->full,failout);
1357 snprintf(keyname,128,"COM%d_%s_DATA", port, bufname);
1358 V3_CHKPT_LOAD(ctx,keyname,sb->buffer,failout);
1363 PrintError(VM_NONE, VCORE_NONE, "Failed to load serial buffer\n");
1367 static int serial_save(struct v3_chkpt_ctx * ctx, void * private_data) {
1368 struct serial_state *state = (struct serial_state *)private_data;
1369 struct serial_port *serial;
1374 serial = &(state->coms[i]);
1375 snprintf(keyname, 128,"COM%d_RBR",i);
1376 V3_CHKPT_SAVE(ctx, keyname, serial->rbr.data,failout);
1377 snprintf(keyname, 128,"COM%d_THR",i);
1378 V3_CHKPT_SAVE(ctx, keyname, serial->thr.data,failout);
1379 snprintf(keyname, 128,"COM%d_IER",i);
1380 V3_CHKPT_SAVE(ctx, keyname, serial->ier.val,failout);
1381 snprintf(keyname, 128,"COM%d_IIR",i);
1382 V3_CHKPT_SAVE(ctx, keyname, serial->iir.val,failout);
1383 snprintf(keyname, 128,"COM%d_FCR",i);
1384 V3_CHKPT_SAVE(ctx, keyname, serial->fcr.val,failout);
1385 snprintf(keyname, 128,"COM%d_LCR",i);
1386 V3_CHKPT_SAVE(ctx, keyname, serial->lcr.val,failout);
1387 snprintf(keyname, 128,"COM%d_MCR",i);
1388 V3_CHKPT_SAVE(ctx, keyname, serial->mcr.val,failout);
1389 snprintf(keyname, 128,"COM%d_LSR",i);
1390 V3_CHKPT_SAVE(ctx, keyname, serial->lsr.val,failout);
1391 snprintf(keyname, 128,"COM%d_MSR",i);
1392 V3_CHKPT_SAVE(ctx, keyname, serial->msr.val,failout);
1393 snprintf(keyname, 128,"COM%d_SCR",i);
1394 V3_CHKPT_SAVE(ctx, keyname, serial->scr.data,failout);
1395 snprintf(keyname, 128,"COM%d_DLL",i);
1396 V3_CHKPT_SAVE(ctx, keyname, serial->dll.data,failout);
1397 snprintf(keyname, 128,"COM%d_DLM",i);
1398 V3_CHKPT_SAVE(ctx, keyname, serial->dlm.data,failout);
1399 snprintf(keyname, 128,"COM%d_int_state",i);
1400 V3_CHKPT_SAVE(ctx, keyname, serial->int_state,failout);
1402 if (serial_buffer_save(ctx, i, &(serial->tx_buffer), "TX")) {
1403 PrintError(VM_NONE, VCORE_NONE, "Failed to save serial tx buffer %d\n",i);
1407 if (serial_buffer_save(ctx, i, &(serial->rx_buffer), "RX")) {
1408 PrintError(VM_NONE, VCORE_NONE, "Failed to save serial rx buffer %d\n",i);
1412 snprintf(keyname, 128,"COM%d_IRQ_NUM",i);
1413 V3_CHKPT_SAVE(ctx, keyname, serial->irq_number,failout);
1419 PrintError(VM_NONE, VCORE_NONE, "Failed to save serial device\n");
1424 static int serial_load(struct v3_chkpt_ctx * ctx, void * private_data) {
1425 struct serial_state *state = (struct serial_state *)private_data;
1426 struct serial_port *serial;
1431 serial = &(state->coms[i]);
1432 snprintf(keyname, 128,"COM%d_RBR",i);
1433 V3_CHKPT_LOAD(ctx, keyname, serial->rbr.data,failout);
1434 snprintf(keyname, 128,"COM%d_THR",i);
1435 V3_CHKPT_LOAD(ctx, keyname, serial->thr.data,failout);
1436 snprintf(keyname, 128,"COM%d_IER",i);
1437 V3_CHKPT_LOAD(ctx, keyname, serial->ier.val,failout);
1438 snprintf(keyname, 128,"COM%d_IIR",i);
1439 V3_CHKPT_LOAD(ctx, keyname, serial->iir.val,failout);
1440 snprintf(keyname, 128,"COM%d_FCR",i);
1441 V3_CHKPT_LOAD(ctx, keyname, serial->fcr.val,failout);
1442 snprintf(keyname, 128,"COM%d_LCR",i);
1443 V3_CHKPT_LOAD(ctx, keyname, serial->lcr.val,failout);
1444 snprintf(keyname, 128,"COM%d_MCR",i);
1445 V3_CHKPT_LOAD(ctx, keyname, serial->mcr.val,failout);
1446 snprintf(keyname, 128,"COM%d_LSR",i);
1447 V3_CHKPT_LOAD(ctx, keyname, serial->lsr.val,failout);
1448 snprintf(keyname, 128,"COM%d_MSR",i);
1449 V3_CHKPT_LOAD(ctx, keyname, serial->msr.val,failout);
1450 snprintf(keyname, 128,"COM%d_SCR",i);
1451 V3_CHKPT_LOAD(ctx, keyname, serial->scr.data,failout);
1452 snprintf(keyname, 128,"COM%d_DLL",i);
1453 V3_CHKPT_LOAD(ctx, keyname, serial->dll.data,failout);
1454 snprintf(keyname, 128,"COM%d_DLM",i);
1455 V3_CHKPT_LOAD(ctx, keyname, serial->dlm.data,failout);
1456 snprintf(keyname, 128,"COM%d_int_state",i);
1457 V3_CHKPT_LOAD(ctx, keyname, serial->int_state,failout);
1459 if (serial_buffer_load(ctx, i, &(serial->tx_buffer), "RX")) {
1460 PrintError(VM_NONE, VCORE_NONE, "Failed to load serial tx buffer %d\n",i);
1464 if (serial_buffer_load(ctx, i, &(serial->rx_buffer), "TX")) {
1465 PrintError(VM_NONE, VCORE_NONE, "Failed to load serial rx buffer %d\n",i);
1469 snprintf(keyname, 128,"COM%d_IRQ_NUM",i);
1470 V3_CHKPT_LOAD(ctx, keyname, serial->irq_number,failout);
1476 PrintError(VM_NONE, VCORE_NONE,"Failed to load serial device\n");
1483 static struct v3_device_ops dev_ops = {
1484 .free = (int (*)(void *))serial_free,
1485 #ifdef V3_CONFIG_CHECKPOINT
1486 .save = serial_save,
1493 static int init_serial_port(struct serial_port * com) {
1496 memset(com, 0, sizeof(*com));
1498 com->ier.val = IER_INIT_VAL;
1499 com->iir.val = IIR_INIT_VAL;
1500 com->fcr.val = FCR_INIT_VAL;
1501 com->lcr.val = LCR_INIT_VAL;
1502 com->mcr.val = MCR_INIT_VAL;
1503 com->lsr.val = LSR_INIT_VAL;
1504 com->msr.val = MSR_INIT_VAL;
1506 com->dll.data = DLL_INIT_VAL;
1507 com->dlm.data = DLM_INIT_VAL;
1509 flush_buffer(&(com->tx_buffer));
1510 flush_buffer(&(com->rx_buffer));
1512 v3_lock_init(&(com->lock));
1515 com->backend_data = NULL;
1520 static int deinit_serial_port(struct serial_port * com) {
1522 v3_lock_deinit(&(com->lock));
1527 static sint64_t serial_input(struct v3_vm_info * vm, uint8_t * buf, sint64_t len, void * priv_data){
1528 struct serial_port * com_port = (struct serial_port *)priv_data;
1532 irq_status = v3_lock_irqsave(com_port->lock);
1534 for(i = 0; i < len; i++){
1535 if (queue_data(vm, com_port, &(com_port->rx_buffer), buf[i])) {
1540 updateIRQ(vm, com_port);
1542 v3_unlock_irqrestore(com_port->lock,irq_status);
1548 static int connect_fn(struct v3_vm_info * vm,
1549 void * frontend_data,
1550 struct v3_dev_char_ops * ops,
1551 v3_cfg_tree_t * cfg,
1552 void * private_data,
1553 void ** push_fn_arg) {
1555 struct serial_state * serial = (struct serial_state *)frontend_data;
1556 struct serial_port * com = NULL;
1557 char * com_port = v3_cfg_val(cfg, "com_port");
1560 if (com_port == NULL) {
1561 PrintError(vm, VCORE_NONE, "UART: Invalid Serial frontend config: missing \"com_port\"\n");
1565 com_idx = atoi(com_port) - 1;
1567 if ((com_idx > 3) || (com_idx < 0)) {
1568 PrintError(vm, VCORE_NONE, "UART: Invalid Com port (%s) \n", com_port);
1572 com = &(serial->coms[com_idx]);
1575 com->backend_data = private_data;
1577 com->ops->input = serial_input;
1583 static int serial_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
1584 struct serial_state * state = NULL;
1585 char * dev_id = v3_cfg_val(cfg, "ID");
1588 state = (struct serial_state *)V3_Malloc(sizeof(struct serial_state));
1590 if (state == NULL) {
1591 PrintError(vm,VCORE_NONE, "UART: Could not allocate Serial Device\n");
1595 memset(state, 0, sizeof(struct serial_state));
1597 init_serial_port(&(state->coms[0]));
1598 init_serial_port(&(state->coms[1]));
1599 init_serial_port(&(state->coms[2]));
1600 init_serial_port(&(state->coms[3]));
1602 state->coms[0].irq_number = COM1_IRQ;
1603 state->coms[1].irq_number = COM2_IRQ;
1604 state->coms[2].irq_number = COM3_IRQ;
1605 state->coms[3].irq_number = COM4_IRQ;
1608 struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, state);
1611 PrintError(vm, VCORE_NONE, "UART: Could not attach device %s\n", dev_id);
1616 PrintDebug(vm, VCORE_NONE, "UART: Serial device attached\n");
1618 ret |= v3_dev_hook_io(dev, COM1_DATA_PORT, &read_data_port, &write_data_port);
1619 ret |= v3_dev_hook_io(dev, COM1_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
1620 ret |= v3_dev_hook_io(dev, COM1_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1621 ret |= v3_dev_hook_io(dev, COM1_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1622 ret |= v3_dev_hook_io(dev, COM1_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1623 ret |= v3_dev_hook_io(dev, COM1_LINE_STATUS_PORT, &read_status_port, &write_status_port);
1624 ret |= v3_dev_hook_io(dev, COM1_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
1625 ret |= v3_dev_hook_io(dev, COM1_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
1627 ret |= v3_dev_hook_io(dev, COM2_DATA_PORT, &read_data_port, &write_data_port);
1628 ret |= v3_dev_hook_io(dev, COM2_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
1629 ret |= v3_dev_hook_io(dev, COM2_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1630 ret |= v3_dev_hook_io(dev, COM2_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1631 ret |= v3_dev_hook_io(dev, COM2_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1632 ret |= v3_dev_hook_io(dev, COM2_LINE_STATUS_PORT, &read_status_port, &write_status_port);
1633 ret |= v3_dev_hook_io(dev, COM2_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
1634 ret |= v3_dev_hook_io(dev, COM2_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
1636 ret |= v3_dev_hook_io(dev, COM3_DATA_PORT, &read_data_port, &write_data_port);
1637 ret |= v3_dev_hook_io(dev, COM3_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
1638 ret |= v3_dev_hook_io(dev, COM3_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1639 ret |= v3_dev_hook_io(dev, COM3_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1640 ret |= v3_dev_hook_io(dev, COM3_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1641 ret |= v3_dev_hook_io(dev, COM3_LINE_STATUS_PORT, &read_status_port, &write_status_port);
1642 ret |= v3_dev_hook_io(dev, COM3_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
1643 ret |= v3_dev_hook_io(dev, COM3_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
1645 ret |= v3_dev_hook_io(dev, COM4_DATA_PORT, &read_data_port, &write_data_port);
1646 ret |= v3_dev_hook_io(dev, COM4_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
1647 ret |= v3_dev_hook_io(dev, COM4_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1648 ret |= v3_dev_hook_io(dev, COM4_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1649 ret |= v3_dev_hook_io(dev, COM4_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1650 ret |= v3_dev_hook_io(dev, COM4_LINE_STATUS_PORT, &read_status_port, &write_status_port);
1651 ret |= v3_dev_hook_io(dev, COM4_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
1652 ret |= v3_dev_hook_io(dev, COM4_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
1655 PrintError(vm, VCORE_NONE, "UART: Error hooking Serial IO ports\n");
1656 v3_remove_device(dev);
1660 PrintDebug(vm, VCORE_NONE, "UART: Serial ports hooked\n");
1664 if (v3_dev_add_char_frontend(vm, dev_id, connect_fn, (void *)state) == -1) {
1665 PrintError(vm, VCORE_NONE, "UART: Could not register %s as frontend\n", dev_id);
1666 v3_remove_device(dev);
1678 device_register("SERIAL", serial_init)