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>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
21 #include <palacios/vmm.h>
22 #include <palacios/vmm_dev_mgr.h>
23 #include <palacios/vmm_types.h>
25 #include <palacios/vmm_ringbuffer.h>
26 #include <palacios/vmm_lock.h>
27 #include <palacios/vmm_intr.h>
28 #include <palacios/vmm_host_events.h>
29 #include <palacios/vm_guest.h>
32 #define COM1_DATA_PORT 0x3f8
33 #define COM1_IRQ_ENABLE_PORT 0x3f9
34 #define COM1_DIV_LATCH_LSB_PORT 0x3f8
35 #define COM1_DIV_LATCH_MSB_PORT 0x3f9
36 #define COM1_IIR_PORT 0x3fa
37 #define COM1_FIFO_CTRL_PORT 0x3fa
38 #define COM1_LINE_CTRL_PORT 0x3fb
39 #define COM1_MODEM_CTRL_PORT 0x3fc
40 #define COM1_LINE_STATUS_PORT 0x3fd
41 #define COM1_MODEM_STATUS_PORT 0x3fe
42 #define COM1_SCRATCH_PORT 0x3ff
44 #define COM2_DATA_PORT 0x2f8
45 #define COM2_IRQ_ENABLE_PORT 0x2f9
46 #define COM2_DIV_LATCH_LSB_PORT 0x2f8
47 #define COM2_DIV_LATCH_MSB_PORT 0x2f9
48 #define COM2_IIR_PORT 0x2fa
49 #define COM2_FIFO_CTRL_PORT 0x2fa
50 #define COM2_LINE_CTRL_PORT 0x2fb
51 #define COM2_MODEM_CTRL_PORT 0x2fc
52 #define COM2_LINE_STATUS_PORT 0x2fd
53 #define COM2_MODEM_STATUS_PORT 0x2fe
54 #define COM2_SCRATCH_PORT 0x2ff
56 #define COM3_DATA_PORT 0x3e8
57 #define COM3_IRQ_ENABLE_PORT 0x3e9
58 #define COM3_DIV_LATCH_LSB_PORT 0x3e8
59 #define COM3_DIV_LATCH_MSB_PORT 0x3e9
60 #define COM3_IIR_PORT 0x3ea
61 #define COM3_FIFO_CTRL_PORT 0x3ea
62 #define COM3_LINE_CTRL_PORT 0x3eb
63 #define COM3_MODEM_CTRL_PORT 0x3ec
64 #define COM3_LINE_STATUS_PORT 0x3ed
65 #define COM3_MODEM_STATUS_PORT 0x3ee
66 #define COM3_SCRATCH_PORT 0x3ef
68 #define COM4_DATA_PORT 0x2e8
69 #define COM4_IRQ_ENABLE_PORT 0x2e9
70 #define COM4_DIV_LATCH_LSB_PORT 0x2e8
71 #define COM4_DIV_LATCH_MSB_PORT 0x2e9
72 #define COM4_IIR_PORT 0x2ea
73 #define COM4_FIFO_CTRL_PORT 0x2ea
74 #define COM4_LINE_CTRL_PORT 0x2eb
75 #define COM4_MODEM_CTRL_PORT 0x2ec
76 #define COM4_LINE_STATUS_PORT 0x2ed
77 #define COM4_MODEM_STATUS_PORT 0x2ee
78 #define COM4_SCRATCH_PORT 0x2ef
81 // Interrupt IDs (in priority order, highest is first)
82 #define STATUS_IRQ_LSR_OE_SET 0x3
83 #define STATUS_IRQ_LSR_PE_SET 0x3
84 #define STATUS_IRQ_LSR_FE_SET 0x3
85 #define STATUS_IRQ_LSR_BI_SET 0x3
87 #define RX_IRQ_TRIGGER_LEVEL 0x2
89 #define TX_IRQ_THRE 0x1
90 #define MODEL_IRQ_DELTA_SET 0x0
101 //initial value for registers
103 #define IER_INIT_VAL 0x3
104 //receive data available interrupt and THRE interrupt are enabled
105 #define IIR_INIT_VAL 0x1
106 //No Pending Interrupt bit is set.
107 #define FCR_INIT_VAL 0xc0
108 //fifo control register is set to 0
109 #define LCR_INIT_VAL 0x3
110 #define MCR_INIT_VAL 0x0
111 #define LSR_INIT_VAL 0x60
112 #define MSR_INIT_VAL 0x0
113 #define DLL_INIT_VAL 0x1
114 #define DLM_INIT_VAL 0x0
118 //receiver buffer register
119 struct rbr_register {
123 // transmitter holding register
124 struct thr_register {
128 //interrupt enable register
129 struct ier_register {
133 uint8_t erbfi : 1; // Enable Receiver Buffer full interrupt
134 uint8_t etbei : 1; // Enable Transmit buffer empty interrupt
135 uint8_t elsi : 1; // Enable Line Status Interrupt
136 uint8_t edssi : 1; // Enable Delta Status signals interrupt
137 uint8_t rsvd : 4; // MBZ
138 } __attribute__((packed));
139 } __attribute__((packed));
140 } __attribute__((packed));
143 //interrupt identification register
144 struct iir_register {
148 uint8_t pending : 1; // Interrupt pending (0=interrupt pending)
149 uint8_t iid : 3; // Interrupt Identification
150 uint8_t rsvd : 2; // MBZ
151 uint8_t fifo_en : 2; // FIFO enable
152 } __attribute__((packed));
153 } __attribute__((packed));
154 } __attribute__((packed));
156 //FIFO control register
157 struct fcr_register {
161 uint8_t enable : 1; // enable fifo
162 uint8_t rfres : 1; // RX FIFO reset
163 uint8_t xfres : 1; // TX FIFO reset
164 uint8_t dma_sel : 1; // DMA mode select
165 uint8_t rsvd : 2; // MBZ
166 uint8_t rx_trigger: 2; // RX FIFO trigger level select
167 } __attribute__((packed));
168 } __attribute__((packed));
169 } __attribute__((packed));
172 //line control register
173 struct lcr_register {
177 uint8_t word_len : 2; // word length select
178 uint8_t stop_bits : 1; // Stop Bit select
179 uint8_t parity_enable : 1; // Enable parity
180 uint8_t even_sel : 1; // Even Parity Select
181 uint8_t stick_parity : 1; // Stick Parity Select
182 uint8_t sbr : 1; // Set Break
183 uint8_t dlab : 1; // Divisor latch access bit
184 } __attribute__((packed));
185 } __attribute__((packed));
186 } __attribute__((packed));
189 //modem control register
190 struct mcr_register {
198 uint8_t loop : 1; // loopback mode
199 uint8_t rsvd : 3; // MBZ
200 } __attribute__((packed));
201 } __attribute__((packed));
202 } __attribute__((packed));
205 //line status register
206 struct lsr_register {
210 uint8_t dr : 1; // data ready
211 uint8_t oe : 1; // Overrun error
212 uint8_t pe : 1; // Parity Error
213 uint8_t fe : 1; // Framing Error
214 uint8_t brk : 1; // broken line detected
215 uint8_t thre : 1; // Transmitter holding register empty
216 uint8_t temt : 1; // Transmitter Empty
217 uint8_t fifo_err : 1; // at least one error is pending in the RX FIFO chain
218 } __attribute__((packed));
219 } __attribute__((packed));
220 } __attribute__((packed));
223 struct msr_register {
227 uint8_t dcts : 1; // Delta Clear To Send
228 uint8_t ddsr : 1; // Delta Data Set Ready
229 uint8_t teri : 1; // Trailing Edge Ring Indicator
230 uint8_t ddcd : 1; // Delta Data Carrier Detect
231 uint8_t cts : 1; // Clear to Send
232 uint8_t dsr : 1; // Data Set Ready
233 uint8_t ri : 1; // Ring Indicator
234 uint8_t dcd : 1; // Data Carrier Detect
235 } __attribute__((packed));
236 } __attribute__((packed));
237 } __attribute__((packed));
240 struct scr_register {
245 struct dll_register {
250 struct dlm_register {
253 #define SERIAL_BUF_LEN 16
255 struct serial_buffer {
256 int head; // most recent data
257 int tail; // oldest char
259 uint8_t buffer[SERIAL_BUF_LEN];
263 struct rbr_register rbr;
264 struct thr_register thr;
265 struct ier_register ier;
266 struct iir_register iir;
267 struct fcr_register fcr;
268 struct lcr_register lcr;
269 struct mcr_register mcr;
270 struct lsr_register lsr;
271 struct msr_register msr;
272 struct scr_register scr;
273 struct dll_register dll;
274 struct dlm_register dlm;
277 struct serial_buffer tx_buffer;
278 struct serial_buffer rx_buffer;
283 struct serial_state {
284 struct serial_port com1;
285 struct serial_port com2;
286 struct serial_port com3;
287 struct serial_port com4;
292 static struct serial_port * get_com_from_port(struct serial_state * serial, uint16_t port) {
293 if ((port >= COM1_DATA_PORT) && (port <= COM1_SCRATCH_PORT)) {
294 return &(serial->com1);
295 } else if ((port >= COM2_DATA_PORT) && (port <= COM2_SCRATCH_PORT)) {
296 return &(serial->com2);
297 } else if ((port >= COM3_DATA_PORT) && (port <= COM3_SCRATCH_PORT)) {
298 return &(serial->com3);
299 } else if ((port >= COM4_DATA_PORT) && (port <= COM4_SCRATCH_PORT)) {
300 return &(serial->com4);
302 PrintError("Error: Could not find serial port associated with IO port %d\n", port);
307 static inline bool receive_buffer_trigger(int number, int trigger_number) {
309 switch (trigger_number) {
311 return (number >= 1);
313 return (number >= 4);
315 return (number >= 8);
317 return (number >= 14);
323 static int getNumber(struct serial_buffer * buf) {
324 int number = buf->head - buf->tail;
326 if (buf->full == 1) {
327 return SERIAL_BUF_LEN;
328 } else if (number >= 0) {
331 return SERIAL_BUF_LEN + number;
335 static int updateIRQ(struct serial_port * com, struct vm_device * dev) {
337 if ( (com->ier.erbfi == 0x1) &&
338 (receive_buffer_trigger( getNumber(&(com->rx_buffer)), com->fcr.rx_trigger)) ) {
340 PrintDebug("UART: receive buffer interrupt(trigger level reached)");
342 com->iir.iid = RX_IRQ_TRIGGER_LEVEL;
343 v3_raise_irq(dev->vm, com->irq_number);
346 if ( (com->iir.iid == RX_IRQ_TRIGGER_LEVEL) &&
347 (!(receive_buffer_trigger( getNumber(&(com->rx_buffer)), com->fcr.rx_trigger))) ) {
349 com->iir.iid = 0x0; //reset interrupt identification register
350 com->iir.pending = 0x1;
353 if ( (com->iir.iid == TX_IRQ_THRE) &&
354 (getNumber(&(com->tx_buffer)) == SERIAL_BUF_LEN)) {
356 com->iir.iid = 0x0; //reset interrupt identification register
357 com->iir.pending = 0x1;
359 } else if ( (com->ier.etbei == 0x1) &&
360 (getNumber(&(com->tx_buffer)) != SERIAL_BUF_LEN )) {
362 PrintDebug("UART: transmit buffer interrupt(buffer not full)");
364 com->iir.iid = TX_IRQ_THRE;
365 com->iir.pending = 0;
367 v3_raise_irq(dev->vm, com->irq_number);
374 static int queue_data(struct serial_buffer * buf, uint8_t data,
375 struct serial_port * com, struct vm_device * dev) {
377 int next_loc = (buf->head + 1) % SERIAL_BUF_LEN;
379 if (buf->full == 1) {
380 PrintDebug("Buffer is full!\n");
382 if (buf == &(com->rx_buffer)) {
383 com->lsr.oe = 1; //overrun error bit set
389 buf->buffer[next_loc] = data;
390 buf->head = next_loc;
392 if (buf->head == buf->tail) {
396 if (buf == &(com->rx_buffer)) {
397 com->lsr.dr = 1; //as soon as new data arrives at receive buffer, set data ready bit in lsr.
400 if (buf == &(com->tx_buffer)) {
401 com->lsr.thre = 0; //reset thre and temt bits.
410 static int dequeue_data(struct serial_buffer * buf, uint8_t * data,
411 struct serial_port * com, struct vm_device * dev) {
413 int next_tail = (buf->tail + 1) % SERIAL_BUF_LEN;
416 if ( (buf->head == buf->tail) && (buf->full != 1) ) {
417 PrintDebug("no data to delete!\n");
421 if (buf->full == 1) {
426 *data = buf->buffer[next_tail];
427 buf->buffer[next_tail] = 0;
428 buf->tail = next_tail;
430 if ( (buf == &(com->rx_buffer)) && (getNumber(&(com->rx_buffer)) == 0) ) {
434 if ((buf == &(com->tx_buffer)) && (getNumber(&(com->tx_buffer)) == 0)) {
445 static void printBuffer(struct serial_buffer * buf) {
448 for (i = 0; i < SERIAL_BUF_LEN; i++) {
449 PrintDebug(" %d ", buf->buffer[i]);
452 PrintDebug("\n the number of elements is %d \n", getNumber(buf));
456 //note: write to data port is NOT implemented and corresponding codes are commented out
457 static int write_data_port(struct guest_info * core, uint16_t port,
458 void * src, uint_t length, struct vm_device * dev) {
459 struct serial_state * state = (struct serial_state *)dev->private_data;
460 uint8_t * val = (uint8_t *)src;
461 struct serial_port * com_port = NULL;
463 PrintDebug("Write to Data Port 0x%x (val=%x)\n", port, *val);
466 PrintDebug("Invalid length(%d) in write to 0x%x\n", length, port);
470 if ((port != COM1_DATA_PORT) && (port != COM2_DATA_PORT) &&
471 (port != COM3_DATA_PORT) && (port != COM4_DATA_PORT)) {
472 PrintError("Serial Read data port for illegal port Number (%d)\n", port);
476 com_port = get_com_from_port(state, port);
478 if (com_port == NULL) {
479 PrintDebug("UART:read from NOBODY");
484 // dlab is always checked first
485 if (com_port->lcr.dlab == 1) {
486 com_port->dll.data = *val;
488 queue_data(&(com_port->tx_buffer), *val, com_port, dev);
497 static int read_data_port(struct guest_info * core, uint16_t port,
498 void * dst, uint_t length, struct vm_device * dev) {
499 struct serial_state * state = (struct serial_state *)dev->private_data;
500 uint8_t * val = (uint8_t *)dst;
501 struct serial_port * com_port = NULL;
503 PrintDebug("Read from Data Port 0x%x\n", port);
506 PrintDebug("Invalid length(%d) in write to 0x%x\n", length, port);
510 if ((port != COM1_DATA_PORT) && (port != COM2_DATA_PORT) &&
511 (port != COM3_DATA_PORT) && (port != COM4_DATA_PORT)) {
512 PrintError("Serial Read data port for illegal port Number (%d)\n", port);
516 com_port = get_com_from_port(state, port);
518 if (com_port == NULL) {
519 PrintDebug("UART:read from NOBODY");
523 if (com_port->lcr.dlab == 1) {
524 *val = com_port->dll.data;
526 dequeue_data(&(com_port->rx_buffer), val, com_port, dev);
534 static int handle_fcr_write(struct serial_port * com, uint8_t value) {
536 com->fcr.enable = value & 0x1;
538 if (com->fcr.enable == 0x1) {
539 com->fcr.val = value;
541 com->fcr.enable = 1; // Do we need to set this??
543 //if rfres set, clear receive buffer.
544 if (com->fcr.rfres == 0x1) {
545 com->rx_buffer.head = 0;
546 com->rx_buffer.tail = 0;
547 com->rx_buffer.full = 0;
548 memset(com->rx_buffer.buffer, 0, SERIAL_BUF_LEN);
552 //if xfres set, clear transmit buffer.
553 if (com->fcr.xfres == 0x1) {
554 com->tx_buffer.head = 0;
555 com->tx_buffer.tail = 0;
556 com->tx_buffer.full = 0;
557 memset(com->tx_buffer.buffer, 0, SERIAL_BUF_LEN);
561 //clear both buffers.
562 com->tx_buffer.head = 0;
563 com->tx_buffer.tail = 0;
564 com->tx_buffer.full = 0;
565 com->rx_buffer.head = 0;
566 com->rx_buffer.tail = 0;
567 com->rx_buffer.full = 0;
569 memset(com->rx_buffer.buffer, 0, SERIAL_BUF_LEN);
570 memset(com->tx_buffer.buffer, 0, SERIAL_BUF_LEN);
580 static int write_ctrl_port(struct guest_info * core, uint16_t port, void * src,
581 uint_t length, struct vm_device * dev) {
582 struct serial_state * state = (struct serial_state *)dev->private_data;
583 uint8_t val = *(uint8_t *)src;
584 struct serial_port * com_port = NULL;
586 PrintDebug("UART:Write to Control Port (val=%x)\n", val);
589 PrintDebug("UART:Invalid Write length to control port%d\n", port);
593 com_port = get_com_from_port(state, port);
595 if (com_port == NULL) {
596 PrintError("Could not find serial port corresponding to IO port %d\n", port);
600 //always check dlab first
602 case COM1_IRQ_ENABLE_PORT:
603 case COM2_IRQ_ENABLE_PORT:
604 case COM3_IRQ_ENABLE_PORT:
605 case COM4_IRQ_ENABLE_PORT: {
606 PrintDebug("UART:Write to IER/LATCH port: dlab is %x\n", com_port->lcr.dlab);
608 if (com_port->lcr.dlab == 1) {
609 com_port->dlm.data = val;
611 com_port->ier.val = val;
616 case COM1_FIFO_CTRL_PORT:
617 case COM2_FIFO_CTRL_PORT:
618 case COM3_FIFO_CTRL_PORT:
619 case COM4_FIFO_CTRL_PORT: {
620 PrintDebug("UART:Write to FCR");
622 if (handle_fcr_write(com_port, val) == -1) {
628 case COM1_LINE_CTRL_PORT:
629 case COM2_LINE_CTRL_PORT:
630 case COM3_LINE_CTRL_PORT:
631 case COM4_LINE_CTRL_PORT: {
632 PrintDebug("UART:Write to LCR");
633 com_port->lcr.val = val;
636 case COM1_MODEM_CTRL_PORT:
637 case COM2_MODEM_CTRL_PORT:
638 case COM3_MODEM_CTRL_PORT:
639 case COM4_MODEM_CTRL_PORT: {
640 PrintDebug("UART:Write to MCR");
641 com_port->mcr.val = val;
644 case COM1_SCRATCH_PORT:
645 case COM2_SCRATCH_PORT:
646 case COM3_SCRATCH_PORT:
647 case COM4_SCRATCH_PORT: {
648 PrintDebug("UART:Write to SCRATCH");
649 com_port->scr.data = val;
653 PrintDebug("UART:Write to NOBODY, ERROR");
664 static int read_ctrl_port(struct guest_info * core, uint16_t port, void * dst,
665 uint_t length, struct vm_device * dev) {
666 struct serial_state * state = (struct serial_state *)dev->private_data;
667 uint8_t * val = (uint8_t *)dst;
668 struct serial_port * com_port = NULL;
670 PrintDebug("Read from Control Port\n");
673 PrintDebug("Invalid Read length to control port\n");
677 com_port = get_com_from_port(state, port);
679 if (com_port == NULL) {
680 PrintError("Could not find serial port corresponding to IO port %d\n", port);
684 //always check dlab first
686 case COM1_IRQ_ENABLE_PORT:
687 case COM2_IRQ_ENABLE_PORT:
688 case COM3_IRQ_ENABLE_PORT:
689 case COM4_IRQ_ENABLE_PORT: {
690 PrintDebug("UART:read from IER");
692 if (com_port->lcr.dlab == 1) {
693 *val = com_port->dlm.data;
695 *val = com_port->ier.val;
700 case COM1_FIFO_CTRL_PORT:
701 case COM2_FIFO_CTRL_PORT:
702 case COM3_FIFO_CTRL_PORT:
703 case COM4_FIFO_CTRL_PORT:
704 PrintDebug("UART:read from FCR");
705 *val = com_port->fcr.val;
708 case COM1_LINE_CTRL_PORT:
709 case COM2_LINE_CTRL_PORT:
710 case COM3_LINE_CTRL_PORT:
711 case COM4_LINE_CTRL_PORT:
712 PrintDebug("UART:read from LCR");
713 *val = com_port->lcr.val;
716 case COM1_MODEM_CTRL_PORT:
717 case COM2_MODEM_CTRL_PORT:
718 case COM3_MODEM_CTRL_PORT:
719 case COM4_MODEM_CTRL_PORT:
720 PrintDebug("UART:read from MCR");
721 *val = com_port->mcr.val;
724 case COM1_SCRATCH_PORT:
725 case COM2_SCRATCH_PORT:
726 case COM3_SCRATCH_PORT:
727 case COM4_SCRATCH_PORT:
728 PrintDebug("UART:read from SCRATCH");
729 *val = com_port->scr.data;
733 PrintDebug("UART:read from NOBODY");
741 static int write_status_port(struct guest_info * core, uint16_t port, void * src,
742 uint_t length, struct vm_device * dev) {
743 struct serial_state * state = (struct serial_state *)dev->private_data;
744 uint8_t val = *(uint8_t *)src;
745 struct serial_port * com_port = NULL;
747 PrintDebug("Write to Status Port (val=%x)\n", val);
750 PrintDebug("Invalid Write length to status port %d\n", port);
754 com_port = get_com_from_port(state, port);
756 if (com_port == NULL) {
757 PrintError("Could not find serial port corresponding to IO port %d\n", port);
762 case COM1_LINE_STATUS_PORT:
763 case COM2_LINE_STATUS_PORT:
764 case COM3_LINE_STATUS_PORT:
765 case COM4_LINE_STATUS_PORT:
766 PrintDebug("UART:write to LSR");
767 com_port->lsr.val = val;
770 case COM1_MODEM_STATUS_PORT:
771 case COM2_MODEM_STATUS_PORT:
772 case COM3_MODEM_STATUS_PORT:
773 case COM4_MODEM_STATUS_PORT:
774 PrintDebug("UART:write to MSR");
775 com_port->msr.val = val;
779 PrintDebug("UART:write to NOBODY");
786 static int read_status_port(struct guest_info * core, uint16_t port, void * dst,
787 uint_t length, struct vm_device * dev) {
788 struct serial_state * state = (struct serial_state *)dev->private_data;
789 uint8_t * val = (uint8_t *)dst;
790 struct serial_port * com_port = NULL;
792 PrintDebug("Read from Status Port 0x%x\n", port);
795 PrintDebug("Invalid Read length to control port\n");
799 com_port = get_com_from_port(state, port);
801 if (com_port == NULL) {
802 PrintError("Could not find serial port corresponding to IO port %d\n", port);
807 case COM1_LINE_STATUS_PORT:
808 case COM2_LINE_STATUS_PORT:
809 case COM3_LINE_STATUS_PORT:
810 case COM4_LINE_STATUS_PORT:
811 PrintDebug("UART:read from LSR");
813 *val = com_port->lsr.val;
814 com_port->lsr.oe = 0; // Why do we clear this??
818 case COM1_MODEM_STATUS_PORT:
819 case COM2_MODEM_STATUS_PORT:
820 case COM3_MODEM_STATUS_PORT:
821 case COM4_MODEM_STATUS_PORT:
822 PrintDebug("UART:read from COM4 MSR");
823 *val = com_port->msr.val;
827 PrintDebug("UART:read from NOBODY");
834 static int serial_deinit(struct vm_device * dev) {
837 v3_dev_unhook_io(dev, COM1_DATA_PORT);
838 v3_dev_unhook_io(dev, COM1_IRQ_ENABLE_PORT);
839 v3_dev_unhook_io(dev, COM1_FIFO_CTRL_PORT);
840 v3_dev_unhook_io(dev, COM1_LINE_CTRL_PORT);
841 v3_dev_unhook_io(dev, COM1_MODEM_CTRL_PORT);
842 v3_dev_unhook_io(dev, COM1_LINE_STATUS_PORT);
843 v3_dev_unhook_io(dev, COM1_MODEM_STATUS_PORT);
844 v3_dev_unhook_io(dev, COM1_SCRATCH_PORT);
846 v3_dev_unhook_io(dev, COM2_DATA_PORT);
847 v3_dev_unhook_io(dev, COM2_IRQ_ENABLE_PORT);
848 v3_dev_unhook_io(dev, COM2_FIFO_CTRL_PORT);
849 v3_dev_unhook_io(dev, COM2_LINE_CTRL_PORT);
850 v3_dev_unhook_io(dev, COM2_MODEM_CTRL_PORT);
851 v3_dev_unhook_io(dev, COM2_LINE_STATUS_PORT);
852 v3_dev_unhook_io(dev, COM2_MODEM_STATUS_PORT);
853 v3_dev_unhook_io(dev, COM2_SCRATCH_PORT);
855 v3_dev_unhook_io(dev, COM3_DATA_PORT);
856 v3_dev_unhook_io(dev, COM3_IRQ_ENABLE_PORT);
857 v3_dev_unhook_io(dev, COM3_FIFO_CTRL_PORT);
858 v3_dev_unhook_io(dev, COM3_LINE_CTRL_PORT);
859 v3_dev_unhook_io(dev, COM3_MODEM_CTRL_PORT);
860 v3_dev_unhook_io(dev, COM3_LINE_STATUS_PORT);
861 v3_dev_unhook_io(dev, COM3_MODEM_STATUS_PORT);
862 v3_dev_unhook_io(dev, COM3_SCRATCH_PORT);
864 v3_dev_unhook_io(dev, COM4_DATA_PORT);
865 v3_dev_unhook_io(dev, COM4_IRQ_ENABLE_PORT);
866 v3_dev_unhook_io(dev, COM4_FIFO_CTRL_PORT);
867 v3_dev_unhook_io(dev, COM4_LINE_CTRL_PORT);
868 v3_dev_unhook_io(dev, COM4_MODEM_CTRL_PORT);
869 v3_dev_unhook_io(dev, COM4_LINE_STATUS_PORT);
870 v3_dev_unhook_io(dev, COM4_MODEM_STATUS_PORT);
871 v3_dev_unhook_io(dev, COM4_SCRATCH_PORT);
879 static struct v3_device_ops dev_ops = {
880 //.init = serial_init,
881 .free = serial_deinit,
889 static int init_serial_port(struct serial_port * com) {
891 com->ier.val = IER_INIT_VAL;
892 com->iir.val = IIR_INIT_VAL;
893 com->fcr.val = FCR_INIT_VAL;
894 com->lcr.val = LCR_INIT_VAL;
895 com->mcr.val = MCR_INIT_VAL;
896 com->lsr.val = LSR_INIT_VAL;
897 com->msr.val = MSR_INIT_VAL;
899 com->dll.data = DLL_INIT_VAL;
900 com->dlm.data = DLM_INIT_VAL;
902 com->tx_buffer.head = 0;
903 com->tx_buffer.tail = 0;
904 com->tx_buffer.full = 0;
905 memset(com->tx_buffer.buffer, 0, SERIAL_BUF_LEN);
907 com->rx_buffer.head = 0;
908 com->rx_buffer.tail = 0;
909 com->rx_buffer.full = 0;
910 memset(com->rx_buffer.buffer, 0, SERIAL_BUF_LEN);
915 static int serial_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
916 struct serial_state * state = (struct serial_state *)V3_Malloc(sizeof(struct serial_state));
917 char * dev_id = v3_cfg_val(cfg, "ID");
919 PrintDebug("UART: init_device\n");
920 init_serial_port(&(state->com1));
921 init_serial_port(&(state->com2));
922 init_serial_port(&(state->com3));
923 init_serial_port(&(state->com4));
925 state->com1.irq_number = COM1_IRQ;
926 state->com2.irq_number = COM2_IRQ;
927 state->com3.irq_number = COM3_IRQ;
928 state->com4.irq_number = COM4_IRQ;
931 struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, state);
933 if (v3_attach_device(vm, dev) == -1) {
934 PrintError("Could not attach device %s\n", dev_id);
938 v3_dev_hook_io(dev, COM1_DATA_PORT, &read_data_port, &write_data_port);
939 v3_dev_hook_io(dev, COM1_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
940 v3_dev_hook_io(dev, COM1_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
941 v3_dev_hook_io(dev, COM1_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
942 v3_dev_hook_io(dev, COM1_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
943 v3_dev_hook_io(dev, COM1_LINE_STATUS_PORT, &read_status_port, &write_status_port);
944 v3_dev_hook_io(dev, COM1_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
945 v3_dev_hook_io(dev, COM1_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
947 v3_dev_hook_io(dev, COM2_DATA_PORT, &read_data_port, &write_data_port);
948 v3_dev_hook_io(dev, COM2_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
949 v3_dev_hook_io(dev, COM2_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
950 v3_dev_hook_io(dev, COM2_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
951 v3_dev_hook_io(dev, COM2_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
952 v3_dev_hook_io(dev, COM2_LINE_STATUS_PORT, &read_status_port, &write_status_port);
953 v3_dev_hook_io(dev, COM2_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
954 v3_dev_hook_io(dev, COM2_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
956 v3_dev_hook_io(dev, COM3_DATA_PORT, &read_data_port, &write_data_port);
957 v3_dev_hook_io(dev, COM3_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
958 v3_dev_hook_io(dev, COM3_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
959 v3_dev_hook_io(dev, COM3_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
960 v3_dev_hook_io(dev, COM3_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
961 v3_dev_hook_io(dev, COM3_LINE_STATUS_PORT, &read_status_port, &write_status_port);
962 v3_dev_hook_io(dev, COM3_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
963 v3_dev_hook_io(dev, COM3_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
965 v3_dev_hook_io(dev, COM4_DATA_PORT, &read_data_port, &write_data_port);
966 v3_dev_hook_io(dev, COM4_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
967 v3_dev_hook_io(dev, COM4_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
968 v3_dev_hook_io(dev, COM4_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
969 v3_dev_hook_io(dev, COM4_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
970 v3_dev_hook_io(dev, COM4_LINE_STATUS_PORT, &read_status_port, &write_status_port);
971 v3_dev_hook_io(dev, COM4_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
972 v3_dev_hook_io(dev, COM4_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
978 device_register("SERIAL", serial_init)