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/vmm_host_events.h>
30 #include <palacios/vm_guest.h>
32 #include <devices/serial.h>
35 #ifndef CONFIG_DEBUG_SERIAL
37 #define PrintDebug(fmt, args...)
41 #define COM1_DATA_PORT 0x3f8
42 #define COM1_IRQ_ENABLE_PORT 0x3f9
43 #define COM1_DIV_LATCH_LSB_PORT 0x3f8
44 #define COM1_DIV_LATCH_MSB_PORT 0x3f9
45 #define COM1_IIR_PORT 0x3fa
46 #define COM1_FIFO_CTRL_PORT 0x3fa
47 #define COM1_LINE_CTRL_PORT 0x3fb
48 #define COM1_MODEM_CTRL_PORT 0x3fc
49 #define COM1_LINE_STATUS_PORT 0x3fd
50 #define COM1_MODEM_STATUS_PORT 0x3fe
51 #define COM1_SCRATCH_PORT 0x3ff
53 #define COM2_DATA_PORT 0x2f8
54 #define COM2_IRQ_ENABLE_PORT 0x2f9
55 #define COM2_DIV_LATCH_LSB_PORT 0x2f8
56 #define COM2_DIV_LATCH_MSB_PORT 0x2f9
57 #define COM2_IIR_PORT 0x2fa
58 #define COM2_FIFO_CTRL_PORT 0x2fa
59 #define COM2_LINE_CTRL_PORT 0x2fb
60 #define COM2_MODEM_CTRL_PORT 0x2fc
61 #define COM2_LINE_STATUS_PORT 0x2fd
62 #define COM2_MODEM_STATUS_PORT 0x2fe
63 #define COM2_SCRATCH_PORT 0x2ff
65 #define COM3_DATA_PORT 0x3e8
66 #define COM3_IRQ_ENABLE_PORT 0x3e9
67 #define COM3_DIV_LATCH_LSB_PORT 0x3e8
68 #define COM3_DIV_LATCH_MSB_PORT 0x3e9
69 #define COM3_IIR_PORT 0x3ea
70 #define COM3_FIFO_CTRL_PORT 0x3ea
71 #define COM3_LINE_CTRL_PORT 0x3eb
72 #define COM3_MODEM_CTRL_PORT 0x3ec
73 #define COM3_LINE_STATUS_PORT 0x3ed
74 #define COM3_MODEM_STATUS_PORT 0x3ee
75 #define COM3_SCRATCH_PORT 0x3ef
77 #define COM4_DATA_PORT 0x2e8
78 #define COM4_IRQ_ENABLE_PORT 0x2e9
79 #define COM4_DIV_LATCH_LSB_PORT 0x2e8
80 #define COM4_DIV_LATCH_MSB_PORT 0x2e9
81 #define COM4_IIR_PORT 0x2ea
82 #define COM4_FIFO_CTRL_PORT 0x2ea
83 #define COM4_LINE_CTRL_PORT 0x2eb
84 #define COM4_MODEM_CTRL_PORT 0x2ec
85 #define COM4_LINE_STATUS_PORT 0x2ed
86 #define COM4_MODEM_STATUS_PORT 0x2ee
87 #define COM4_SCRATCH_PORT 0x2ef
90 // Interrupt IDs (in priority order, highest is first)
91 #define STATUS_IRQ_LSR_OE_SET 0x3
92 #define STATUS_IRQ_LSR_PE_SET 0x3
93 #define STATUS_IRQ_LSR_FE_SET 0x3
94 #define STATUS_IRQ_LSR_BI_SET 0x3
96 #define RX_IRQ_TRIGGER_LEVEL 0x2
98 #define TX_IRQ_THRE 0x1
99 #define MODEL_IRQ_DELTA_SET 0x0
107 #define RX_BUFFER 0x1
108 #define TX_BUFFER 0x2
110 //initial value for registers
112 #define IER_INIT_VAL 0x3
113 //receive data available interrupt and THRE interrupt are enabled
114 #define IIR_INIT_VAL 0x1
115 //No Pending Interrupt bit is set.
116 #define FCR_INIT_VAL 0xc0
117 //fifo control register is set to 0
118 #define LCR_INIT_VAL 0x3
119 #define MCR_INIT_VAL 0x0
120 #define LSR_INIT_VAL 0x60
121 #define MSR_INIT_VAL 0x0
122 #define DLL_INIT_VAL 0x1
123 #define DLM_INIT_VAL 0x0
127 //receiver buffer register
128 struct rbr_register {
132 // transmitter holding register
133 struct thr_register {
137 //interrupt enable register
138 struct ier_register {
142 uint8_t erbfi : 1; // Enable Receiver Buffer full interrupt
143 uint8_t etbei : 1; // Enable Transmit buffer empty interrupt
144 uint8_t elsi : 1; // Enable Line Status Interrupt
145 uint8_t edssi : 1; // Enable Delta Status signals interrupt
146 uint8_t rsvd : 4; // MBZ
147 } __attribute__((packed));
148 } __attribute__((packed));
149 } __attribute__((packed));
152 //interrupt identification register
153 struct iir_register {
157 uint8_t pending : 1; // Interrupt pending (0=interrupt pending)
158 uint8_t iid : 3; // Interrupt Identification
159 uint8_t rsvd : 2; // MBZ
160 uint8_t fifo_en : 2; // FIFO enable
161 } __attribute__((packed));
162 } __attribute__((packed));
163 } __attribute__((packed));
165 //FIFO control register
166 struct fcr_register {
170 uint8_t enable : 1; // enable fifo
171 uint8_t rfres : 1; // RX FIFO reset
172 uint8_t xfres : 1; // TX FIFO reset
173 uint8_t dma_sel : 1; // DMA mode select
174 uint8_t rsvd : 2; // MBZ
175 uint8_t rx_trigger: 2; // RX FIFO trigger level select
176 } __attribute__((packed));
177 } __attribute__((packed));
178 } __attribute__((packed));
181 //line control register
182 struct lcr_register {
186 uint8_t word_len : 2; // word length select
187 uint8_t stop_bits : 1; // Stop Bit select
188 uint8_t parity_enable : 1; // Enable parity
189 uint8_t even_sel : 1; // Even Parity Select
190 uint8_t stick_parity : 1; // Stick Parity Select
191 uint8_t sbr : 1; // Set Break
192 uint8_t dlab : 1; // Divisor latch access bit
193 } __attribute__((packed));
194 } __attribute__((packed));
195 } __attribute__((packed));
198 //modem control register
199 struct mcr_register {
207 uint8_t loop : 1; // loopback mode
208 uint8_t rsvd : 3; // MBZ
209 } __attribute__((packed));
210 } __attribute__((packed));
211 } __attribute__((packed));
214 //line status register
215 struct lsr_register {
219 uint8_t dr : 1; // data ready
220 uint8_t oe : 1; // Overrun error
221 uint8_t pe : 1; // Parity Error
222 uint8_t fe : 1; // Framing Error
223 uint8_t brk : 1; // broken line detected
224 uint8_t thre : 1; // Transmitter holding register empty
225 uint8_t temt : 1; // Transmitter Empty
226 uint8_t fifo_err : 1; // at least one error is pending in the RX FIFO chain
227 } __attribute__((packed));
228 } __attribute__((packed));
229 } __attribute__((packed));
232 struct msr_register {
236 uint8_t dcts : 1; // Delta Clear To Send
237 uint8_t ddsr : 1; // Delta Data Set Ready
238 uint8_t teri : 1; // Trailing Edge Ring Indicator
239 uint8_t ddcd : 1; // Delta Data Carrier Detect
240 uint8_t cts : 1; // Clear to Send
241 uint8_t dsr : 1; // Data Set Ready
242 uint8_t ri : 1; // Ring Indicator
243 uint8_t dcd : 1; // Data Carrier Detect
244 } __attribute__((packed));
245 } __attribute__((packed));
246 } __attribute__((packed));
249 struct scr_register {
254 struct dll_register {
259 struct dlm_register {
262 #define SERIAL_BUF_LEN 16
264 struct serial_buffer {
265 int head; // most recent data
266 int tail; // oldest char
268 uint8_t buffer[SERIAL_BUF_LEN];
272 struct rbr_register rbr;
273 struct thr_register thr;
274 struct ier_register ier;
275 struct iir_register iir;
276 struct fcr_register fcr;
277 struct lcr_register lcr;
278 struct mcr_register mcr;
279 struct lsr_register lsr;
280 struct msr_register msr;
281 struct scr_register scr;
282 struct dll_register dll;
283 struct dlm_register dlm;
286 struct serial_buffer tx_buffer;
287 struct serial_buffer rx_buffer;
290 struct v3_stream_ops *stream_ops;
293 struct vm_device * vm_dev;
297 struct serial_state {
298 struct serial_port com1;
299 struct serial_port com2;
300 struct serial_port com3;
301 struct serial_port com4;
306 static struct serial_port * get_com_from_port(struct serial_state * serial, uint16_t port) {
307 if ((port >= COM1_DATA_PORT) && (port <= COM1_SCRATCH_PORT)) {
308 return &(serial->com1);
309 } else if ((port >= COM2_DATA_PORT) && (port <= COM2_SCRATCH_PORT)) {
310 return &(serial->com2);
311 } else if ((port >= COM3_DATA_PORT) && (port <= COM3_SCRATCH_PORT)) {
312 return &(serial->com3);
313 } else if ((port >= COM4_DATA_PORT) && (port <= COM4_SCRATCH_PORT)) {
314 return &(serial->com4);
316 PrintError("Error: Could not find serial port associated with IO port %d\n", port);
321 static inline bool receive_buffer_trigger(int number, int trigger_number) {
323 switch (trigger_number) {
325 return (number >= 1);
327 return (number >= 4);
329 return (number >= 8);
331 return (number >= 14);
337 static int getNumber(struct serial_buffer * buf) {
338 int number = buf->head - buf->tail;
340 if (buf->full == 1) {
341 return SERIAL_BUF_LEN;
342 } else if (number >= 0) {
345 return SERIAL_BUF_LEN + number;
349 static int updateIRQ(struct serial_port * com, struct vm_device * dev) {
351 if ( (com->ier.erbfi == 0x1) &&
352 (receive_buffer_trigger( getNumber(&(com->rx_buffer)), com->fcr.rx_trigger)) ) {
354 PrintDebug("UART: receive buffer interrupt(trigger level reached)");
356 com->iir.iid = RX_IRQ_TRIGGER_LEVEL;
357 v3_raise_irq(dev->vm, com->irq_number);
360 if ( (com->iir.iid == RX_IRQ_TRIGGER_LEVEL) &&
361 (!(receive_buffer_trigger( getNumber(&(com->rx_buffer)), com->fcr.rx_trigger))) ) {
363 com->iir.iid = 0x0; //reset interrupt identification register
364 com->iir.pending = 0x1;
367 if ( (com->iir.iid == TX_IRQ_THRE) &&
368 (getNumber(&(com->tx_buffer)) == SERIAL_BUF_LEN)) {
370 com->iir.iid = 0x0; //reset interrupt identification register
371 com->iir.pending = 0x1;
373 } else if ( (com->ier.etbei == 0x1) &&
374 (getNumber(&(com->tx_buffer)) != SERIAL_BUF_LEN )) {
376 PrintDebug("UART: transmit buffer interrupt(buffer not full)");
378 com->iir.iid = TX_IRQ_THRE;
379 com->iir.pending = 0;
381 v3_raise_irq(dev->vm, com->irq_number);
388 static int queue_data(struct serial_buffer * buf, uint8_t data,
389 struct serial_port * com, struct vm_device * dev) {
391 int next_loc = (buf->head + 1) % SERIAL_BUF_LEN;
393 if (buf->full == 1) {
394 PrintDebug("Buffer is full!\n");
396 if (buf == &(com->rx_buffer)) {
397 com->lsr.oe = 1; //overrun error bit set
403 buf->buffer[next_loc] = data;
404 buf->head = next_loc;
406 if (buf->head == buf->tail) {
410 if (buf == &(com->rx_buffer)) {
411 com->lsr.dr = 1; //as soon as new data arrives at receive buffer, set data ready bit in lsr.
414 if (buf == &(com->tx_buffer)) {
415 com->lsr.thre = 0; //reset thre and temt bits.
424 static int dequeue_data(struct serial_buffer * buf, uint8_t * data,
425 struct serial_port * com, struct vm_device * dev) {
427 int next_tail = (buf->tail + 1) % SERIAL_BUF_LEN;
430 if ( (buf->head == buf->tail) && (buf->full != 1) ) {
431 PrintDebug("no data to delete!\n");
435 if (buf->full == 1) {
440 *data = buf->buffer[next_tail];
441 buf->buffer[next_tail] = 0;
442 buf->tail = next_tail;
444 if ( (buf == &(com->rx_buffer)) && (getNumber(&(com->rx_buffer)) == 0) ) {
448 if ((buf == &(com->tx_buffer)) && (getNumber(&(com->tx_buffer)) == 0)) {
458 static int write_data_port(struct guest_info * core, uint16_t port,
459 void * src, uint_t length, struct vm_device * dev) {
460 struct serial_state * state = (struct serial_state *)dev->private_data;
461 uint8_t * val = (uint8_t *)src;
462 struct serial_port * com_port = NULL;
464 PrintDebug("Write to Data Port 0x%x (val=%x)\n", port, *val);
467 PrintDebug("Invalid length(%d) in write to 0x%x\n", length, port);
471 if ((port != COM1_DATA_PORT) && (port != COM2_DATA_PORT) &&
472 (port != COM3_DATA_PORT) && (port != COM4_DATA_PORT)) {
473 PrintError("Serial Read data port for illegal port Number (%d)\n", port);
477 com_port = get_com_from_port(state, port);
479 if (com_port == NULL) {
480 PrintDebug("UART:read from NOBODY");
485 // dlab is always checked first
486 if (com_port->lcr.dlab == 1) {
487 com_port->dll.data = *val;
489 queue_data(&(com_port->tx_buffer), *val, com_port, dev);
490 if (com_port->stream_ops) {
492 dequeue_data(&(com_port->tx_buffer), &c, com_port, dev);
493 com_port->stream_ops->write(&c,1,com_port->backend_data);
503 static int read_data_port(struct guest_info * core, uint16_t port,
504 void * dst, uint_t length, struct vm_device * dev) {
505 struct serial_state * state = (struct serial_state *)dev->private_data;
506 uint8_t * val = (uint8_t *)dst;
507 struct serial_port * com_port = NULL;
509 PrintDebug("Read from Data Port 0x%x\n", port);
512 PrintDebug("Invalid length(%d) in write to 0x%x\n", length, port);
516 if ((port != COM1_DATA_PORT) && (port != COM2_DATA_PORT) &&
517 (port != COM3_DATA_PORT) && (port != COM4_DATA_PORT)) {
518 PrintError("Serial Read data port for illegal port Number (%d)\n", port);
522 com_port = get_com_from_port(state, port);
524 if (com_port == NULL) {
525 PrintDebug("UART:read from NOBODY");
529 if (com_port->lcr.dlab == 1) {
530 *val = com_port->dll.data;
532 dequeue_data(&(com_port->rx_buffer), val, com_port, dev);
540 static int handle_fcr_write(struct serial_port * com, uint8_t value) {
542 com->fcr.enable = value & 0x1;
544 if (com->fcr.enable == 0x1) {
545 com->fcr.val = value;
547 com->fcr.enable = 1; // Do we need to set this??
549 //if rfres set, clear receive buffer.
550 if (com->fcr.rfres == 0x1) {
551 com->rx_buffer.head = 0;
552 com->rx_buffer.tail = 0;
553 com->rx_buffer.full = 0;
554 memset(com->rx_buffer.buffer, 0, SERIAL_BUF_LEN);
558 //if xfres set, clear transmit buffer.
559 if (com->fcr.xfres == 0x1) {
560 com->tx_buffer.head = 0;
561 com->tx_buffer.tail = 0;
562 com->tx_buffer.full = 0;
563 memset(com->tx_buffer.buffer, 0, SERIAL_BUF_LEN);
567 //clear both buffers.
568 com->tx_buffer.head = 0;
569 com->tx_buffer.tail = 0;
570 com->tx_buffer.full = 0;
571 com->rx_buffer.head = 0;
572 com->rx_buffer.tail = 0;
573 com->rx_buffer.full = 0;
575 memset(com->rx_buffer.buffer, 0, SERIAL_BUF_LEN);
576 memset(com->tx_buffer.buffer, 0, SERIAL_BUF_LEN);
586 static int write_ctrl_port(struct guest_info * core, uint16_t port, void * src,
587 uint_t length, struct vm_device * dev) {
588 struct serial_state * state = (struct serial_state *)dev->private_data;
589 uint8_t val = *(uint8_t *)src;
590 struct serial_port * com_port = NULL;
592 PrintDebug("UART:Write to Control Port (val=%x)\n", val);
595 PrintDebug("UART:Invalid Write length to control port%d\n", port);
599 com_port = get_com_from_port(state, port);
601 if (com_port == NULL) {
602 PrintError("Could not find serial port corresponding to IO port %d\n", port);
606 //always check dlab first
608 case COM1_IRQ_ENABLE_PORT:
609 case COM2_IRQ_ENABLE_PORT:
610 case COM3_IRQ_ENABLE_PORT:
611 case COM4_IRQ_ENABLE_PORT: {
612 PrintDebug("UART:Write to IER/LATCH port: dlab is %x\n", com_port->lcr.dlab);
614 if (com_port->lcr.dlab == 1) {
615 com_port->dlm.data = val;
617 com_port->ier.val = val;
622 case COM1_FIFO_CTRL_PORT:
623 case COM2_FIFO_CTRL_PORT:
624 case COM3_FIFO_CTRL_PORT:
625 case COM4_FIFO_CTRL_PORT: {
626 PrintDebug("UART:Write to FCR");
628 if (handle_fcr_write(com_port, val) == -1) {
634 case COM1_LINE_CTRL_PORT:
635 case COM2_LINE_CTRL_PORT:
636 case COM3_LINE_CTRL_PORT:
637 case COM4_LINE_CTRL_PORT: {
638 PrintDebug("UART:Write to LCR");
639 com_port->lcr.val = val;
642 case COM1_MODEM_CTRL_PORT:
643 case COM2_MODEM_CTRL_PORT:
644 case COM3_MODEM_CTRL_PORT:
645 case COM4_MODEM_CTRL_PORT: {
646 PrintDebug("UART:Write to MCR");
647 com_port->mcr.val = val;
650 case COM1_SCRATCH_PORT:
651 case COM2_SCRATCH_PORT:
652 case COM3_SCRATCH_PORT:
653 case COM4_SCRATCH_PORT: {
654 PrintDebug("UART:Write to SCRATCH");
655 com_port->scr.data = val;
659 PrintDebug("UART:Write to NOBODY, ERROR");
670 static int read_ctrl_port(struct guest_info * core, uint16_t port, void * dst,
671 uint_t length, struct vm_device * dev) {
672 struct serial_state * state = (struct serial_state *)dev->private_data;
673 uint8_t * val = (uint8_t *)dst;
674 struct serial_port * com_port = NULL;
676 PrintDebug("Read from Control Port\n");
679 PrintDebug("Invalid Read length to control port\n");
683 com_port = get_com_from_port(state, port);
685 if (com_port == NULL) {
686 PrintError("Could not find serial port corresponding to IO port %d\n", port);
690 //always check dlab first
692 case COM1_IRQ_ENABLE_PORT:
693 case COM2_IRQ_ENABLE_PORT:
694 case COM3_IRQ_ENABLE_PORT:
695 case COM4_IRQ_ENABLE_PORT: {
696 PrintDebug("UART:read from IER");
698 if (com_port->lcr.dlab == 1) {
699 *val = com_port->dlm.data;
701 *val = com_port->ier.val;
706 case COM1_FIFO_CTRL_PORT:
707 case COM2_FIFO_CTRL_PORT:
708 case COM3_FIFO_CTRL_PORT:
709 case COM4_FIFO_CTRL_PORT:
710 PrintDebug("UART:read from FCR");
711 *val = com_port->fcr.val;
714 case COM1_LINE_CTRL_PORT:
715 case COM2_LINE_CTRL_PORT:
716 case COM3_LINE_CTRL_PORT:
717 case COM4_LINE_CTRL_PORT:
718 PrintDebug("UART:read from LCR");
719 *val = com_port->lcr.val;
722 case COM1_MODEM_CTRL_PORT:
723 case COM2_MODEM_CTRL_PORT:
724 case COM3_MODEM_CTRL_PORT:
725 case COM4_MODEM_CTRL_PORT:
726 PrintDebug("UART:read from MCR");
727 *val = com_port->mcr.val;
730 case COM1_SCRATCH_PORT:
731 case COM2_SCRATCH_PORT:
732 case COM3_SCRATCH_PORT:
733 case COM4_SCRATCH_PORT:
734 PrintDebug("UART:read from SCRATCH");
735 *val = com_port->scr.data;
739 PrintDebug("UART:read from NOBODY");
747 static int write_status_port(struct guest_info * core, uint16_t port, void * src,
748 uint_t length, struct vm_device * dev) {
749 struct serial_state * state = (struct serial_state *)dev->private_data;
750 uint8_t val = *(uint8_t *)src;
751 struct serial_port * com_port = NULL;
753 PrintDebug("Write to Status Port (val=%x)\n", val);
756 PrintDebug("Invalid Write length to status port %d\n", port);
760 com_port = get_com_from_port(state, port);
762 if (com_port == NULL) {
763 PrintError("Could not find serial port corresponding to IO port %d\n", port);
768 case COM1_LINE_STATUS_PORT:
769 case COM2_LINE_STATUS_PORT:
770 case COM3_LINE_STATUS_PORT:
771 case COM4_LINE_STATUS_PORT:
772 PrintDebug("UART:write to LSR");
773 com_port->lsr.val = val;
776 case COM1_MODEM_STATUS_PORT:
777 case COM2_MODEM_STATUS_PORT:
778 case COM3_MODEM_STATUS_PORT:
779 case COM4_MODEM_STATUS_PORT:
780 PrintDebug("UART:write to MSR");
781 com_port->msr.val = val;
785 PrintDebug("UART:write to NOBODY");
792 static int read_status_port(struct guest_info * core, uint16_t port, void * dst,
793 uint_t length, struct vm_device * dev) {
794 struct serial_state * state = (struct serial_state *)dev->private_data;
795 uint8_t * val = (uint8_t *)dst;
796 struct serial_port * com_port = NULL;
798 PrintDebug("Read from Status Port 0x%x\n", port);
801 PrintDebug("Invalid Read length to control port\n");
805 com_port = get_com_from_port(state, port);
807 if (com_port == NULL) {
808 PrintError("Could not find serial port corresponding to IO port %d\n", port);
813 case COM1_LINE_STATUS_PORT:
814 case COM2_LINE_STATUS_PORT:
815 case COM3_LINE_STATUS_PORT:
816 case COM4_LINE_STATUS_PORT:
817 PrintDebug("UART:read from LSR");
819 *val = com_port->lsr.val;
820 com_port->lsr.oe = 0; // Why do we clear this??
824 case COM1_MODEM_STATUS_PORT:
825 case COM2_MODEM_STATUS_PORT:
826 case COM3_MODEM_STATUS_PORT:
827 case COM4_MODEM_STATUS_PORT:
828 PrintDebug("UART:read from COM4 MSR");
829 *val = com_port->msr.val;
833 PrintDebug("UART:read from NOBODY");
840 static int serial_deinit(struct vm_device * dev) {
843 v3_dev_unhook_io(dev, COM1_DATA_PORT);
844 v3_dev_unhook_io(dev, COM1_IRQ_ENABLE_PORT);
845 v3_dev_unhook_io(dev, COM1_FIFO_CTRL_PORT);
846 v3_dev_unhook_io(dev, COM1_LINE_CTRL_PORT);
847 v3_dev_unhook_io(dev, COM1_MODEM_CTRL_PORT);
848 v3_dev_unhook_io(dev, COM1_LINE_STATUS_PORT);
849 v3_dev_unhook_io(dev, COM1_MODEM_STATUS_PORT);
850 v3_dev_unhook_io(dev, COM1_SCRATCH_PORT);
852 v3_dev_unhook_io(dev, COM2_DATA_PORT);
853 v3_dev_unhook_io(dev, COM2_IRQ_ENABLE_PORT);
854 v3_dev_unhook_io(dev, COM2_FIFO_CTRL_PORT);
855 v3_dev_unhook_io(dev, COM2_LINE_CTRL_PORT);
856 v3_dev_unhook_io(dev, COM2_MODEM_CTRL_PORT);
857 v3_dev_unhook_io(dev, COM2_LINE_STATUS_PORT);
858 v3_dev_unhook_io(dev, COM2_MODEM_STATUS_PORT);
859 v3_dev_unhook_io(dev, COM2_SCRATCH_PORT);
861 v3_dev_unhook_io(dev, COM3_DATA_PORT);
862 v3_dev_unhook_io(dev, COM3_IRQ_ENABLE_PORT);
863 v3_dev_unhook_io(dev, COM3_FIFO_CTRL_PORT);
864 v3_dev_unhook_io(dev, COM3_LINE_CTRL_PORT);
865 v3_dev_unhook_io(dev, COM3_MODEM_CTRL_PORT);
866 v3_dev_unhook_io(dev, COM3_LINE_STATUS_PORT);
867 v3_dev_unhook_io(dev, COM3_MODEM_STATUS_PORT);
868 v3_dev_unhook_io(dev, COM3_SCRATCH_PORT);
870 v3_dev_unhook_io(dev, COM4_DATA_PORT);
871 v3_dev_unhook_io(dev, COM4_IRQ_ENABLE_PORT);
872 v3_dev_unhook_io(dev, COM4_FIFO_CTRL_PORT);
873 v3_dev_unhook_io(dev, COM4_LINE_CTRL_PORT);
874 v3_dev_unhook_io(dev, COM4_MODEM_CTRL_PORT);
875 v3_dev_unhook_io(dev, COM4_LINE_STATUS_PORT);
876 v3_dev_unhook_io(dev, COM4_MODEM_STATUS_PORT);
877 v3_dev_unhook_io(dev, COM4_SCRATCH_PORT);
885 static struct v3_device_ops dev_ops = {
886 //.init = serial_init,
887 .free = serial_deinit,
895 static int init_serial_port(struct serial_port * com) {
897 com->ier.val = IER_INIT_VAL;
898 com->iir.val = IIR_INIT_VAL;
899 com->fcr.val = FCR_INIT_VAL;
900 com->lcr.val = LCR_INIT_VAL;
901 com->mcr.val = MCR_INIT_VAL;
902 com->lsr.val = LSR_INIT_VAL;
903 com->msr.val = MSR_INIT_VAL;
905 com->dll.data = DLL_INIT_VAL;
906 com->dlm.data = DLM_INIT_VAL;
908 com->tx_buffer.head = 0;
909 com->tx_buffer.tail = 0;
910 com->tx_buffer.full = 0;
911 memset(com->tx_buffer.buffer, 0, SERIAL_BUF_LEN);
913 com->rx_buffer.head = 0;
914 com->rx_buffer.tail = 0;
915 com->rx_buffer.full = 0;
916 memset(com->rx_buffer.buffer, 0, SERIAL_BUF_LEN);
921 static int serial_input(char *buf, uint_t len, void *front_data){
922 struct serial_port *com_port = (struct serial_port *)front_data;
925 for(i=0; i<len; i++){
926 queue_data(&(com_port->rx_buffer), buf[i], com_port, com_port->vm_dev);
932 static int serial_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
933 struct serial_state * state = (struct serial_state *)V3_Malloc(sizeof(struct serial_state));
934 char * dev_id = v3_cfg_val(cfg, "ID");
936 init_serial_port(&(state->com1));
937 init_serial_port(&(state->com2));
938 init_serial_port(&(state->com3));
939 init_serial_port(&(state->com4));
941 state->com1.irq_number = COM1_IRQ;
942 state->com2.irq_number = COM2_IRQ;
943 state->com3.irq_number = COM3_IRQ;
944 state->com4.irq_number = COM4_IRQ;
946 struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, state);
947 if (v3_attach_device(vm, dev) == -1) {
948 PrintError("Could not attach device %s\n", dev_id);
952 state->com1.vm_dev = dev;
953 state->com2.vm_dev = dev;
954 state->com3.vm_dev = dev;
955 state->com4.vm_dev = dev;
957 PrintDebug("Serial device attached\n");
959 v3_dev_hook_io(dev, COM1_DATA_PORT, &read_data_port, &write_data_port);
960 v3_dev_hook_io(dev, COM1_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
961 v3_dev_hook_io(dev, COM1_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
962 v3_dev_hook_io(dev, COM1_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
963 v3_dev_hook_io(dev, COM1_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
964 v3_dev_hook_io(dev, COM1_LINE_STATUS_PORT, &read_status_port, &write_status_port);
965 v3_dev_hook_io(dev, COM1_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
966 v3_dev_hook_io(dev, COM1_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
968 v3_dev_hook_io(dev, COM2_DATA_PORT, &read_data_port, &write_data_port);
969 v3_dev_hook_io(dev, COM2_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
970 v3_dev_hook_io(dev, COM2_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
971 v3_dev_hook_io(dev, COM2_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
972 v3_dev_hook_io(dev, COM2_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
973 v3_dev_hook_io(dev, COM2_LINE_STATUS_PORT, &read_status_port, &write_status_port);
974 v3_dev_hook_io(dev, COM2_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
975 v3_dev_hook_io(dev, COM2_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
977 v3_dev_hook_io(dev, COM3_DATA_PORT, &read_data_port, &write_data_port);
978 v3_dev_hook_io(dev, COM3_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
979 v3_dev_hook_io(dev, COM3_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
980 v3_dev_hook_io(dev, COM3_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
981 v3_dev_hook_io(dev, COM3_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
982 v3_dev_hook_io(dev, COM3_LINE_STATUS_PORT, &read_status_port, &write_status_port);
983 v3_dev_hook_io(dev, COM3_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
984 v3_dev_hook_io(dev, COM3_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
986 v3_dev_hook_io(dev, COM4_DATA_PORT, &read_data_port, &write_data_port);
987 v3_dev_hook_io(dev, COM4_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
988 v3_dev_hook_io(dev, COM4_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
989 v3_dev_hook_io(dev, COM4_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
990 v3_dev_hook_io(dev, COM4_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
991 v3_dev_hook_io(dev, COM4_LINE_STATUS_PORT, &read_status_port, &write_status_port);
992 v3_dev_hook_io(dev, COM4_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
993 v3_dev_hook_io(dev, COM4_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
995 PrintDebug("Serial ports hooked\n");
1000 int v3_stream_register_serial(struct vm_device * serial_dev, struct v3_stream_ops * ops, void * private_data)
1002 struct serial_state *state = (struct serial_state *)(serial_dev->private_data);
1004 state->com1.stream_ops = ops;
1005 state->com1.backend_data = private_data;
1006 /* bind to other ports here */
1008 ops->input = serial_input;
1009 ops->front_data = &(state->com1);
1015 device_register("SERIAL", serial_init)