1 #include <devices/serial.h>
2 #include <palacios/vmm.h>
5 #define COM1_DATA_PORT 0x3f8
6 #define COM1_IRQ_ENABLE_PORT 0x3f9
7 #define COM1_DIV_LATCH_LSB_PORT 0x3f8
8 #define COM1_DIV_LATCH_MSB_PORT 0x3f9
9 #define COM1_IIR_PORT 0x3fa
10 #define COM1_FIFO_CTRL_PORT 0x3fa
11 #define COM1_LINE_CTRL_PORT 0x3fb
12 #define COM1_MODEM_CTRL_PORT 0x3fc
13 #define COM1_LINE_STATUS_PORT 0x3fd
14 #define COM1_MODEM_STATUS_PORT 0x3fe
15 #define COM1_SCRATCH_PORT 0x3ff
17 #define COM2_DATA_PORT 0x2f8
18 #define COM2_IRQ_ENABLE_PORT 0x2f9
19 #define COM2_DIV_LATCH_LSB_PORT 0x2f8
20 #define COM2_DIV_LATCH_MSB_PORT 0x2f9
21 #define COM2_IIR_PORT 0x2fa
22 #define COM2_FIFO_CTRL_PORT 0x2fa
23 #define COM2_LINE_CTRL_PORT 0x2fb
24 #define COM2_MODEM_CTRL_PORT 0x2fc
25 #define COM2_LINE_STATUS_PORT 0x2fd
26 #define COM2_MODEM_STATUS_PORT 0x2fe
27 #define COM2_SCRATCH_PORT 0x2ff
29 #define COM3_DATA_PORT 0x3e8
30 #define COM3_IRQ_ENABLE_PORT 0x3e9
31 #define COM3_DIV_LATCH_LSB_PORT 0x3e8
32 #define COM3_DIV_LATCH_MSB_PORT 0x3e9
33 #define COM3_IIR_PORT 0x3ea
34 #define COM3_FIFO_CTRL_PORT 0x3ea
35 #define COM3_LINE_CTRL_PORT 0x3eb
36 #define COM3_MODEM_CTRL_PORT 0x3ec
37 #define COM3_LINE_STATUS_PORT 0x3ed
38 #define COM3_MODEM_STATUS_PORT 0x3ee
39 #define COM3_SCRATCH_PORT 0x3ef
41 #define COM4_DATA_PORT 0x2e8
42 #define COM4_IRQ_ENABLE_PORT 0x2e9
43 #define COM4_DIV_LATCH_LSB_PORT 0x2e8
44 #define COM4_DIV_LATCH_MSB_PORT 0x2e9
45 #define COM4_IIR_PORT 0x2ea
46 #define COM4_FIFO_CTRL_PORT 0x2ea
47 #define COM4_LINE_CTRL_PORT 0x2eb
48 #define COM4_MODEM_CTRL_PORT 0x2ec
49 #define COM4_LINE_STATUS_PORT 0x2ed
50 #define COM4_MODEM_STATUS_PORT 0x2ee
51 #define COM4_SCRATCH_PORT 0x2ef
55 struct irq_enable_reg {
56 uint_t erbfi : 1; // Enable Receiver Buffer full interrupt
57 uint_t etbei : 1; // Enable Transmit buffer empty interrupt
58 uint_t elsi : 1; // Enable Line Status Interrupt
59 uint_t edssi : 1; // Enable Delta Status signals interrupt
60 uint_t rsvd : 4; // MBZ
65 // Interrupt IDs (in priority order, highest is first)
66 #define STATUS_IRQ_LSR_OE_SET 0x3
67 #define STATUS_IRQ_LSR_PE_SET 0x3
68 #define STATUS_IRQ_LSR_FE_SET 0x3
69 #define STATUS_IRQ_LSR_BI_SET 0x3
71 #define RX_IRQ_TRIGGER_LEVEL 0x2
73 #define TX_IRQ_THRE 0x1
74 #define MODEL_IRQ_DELTA_SET 0x0
77 uint_t pending : 1; // Interrupt pending (0=interrupt pending)
78 uint_t iid : 3; // Interrupt Identification
79 uint_t rsvd : 2; // MBZ
80 uint_t fifo_en : 2; // FIFO enable
83 struct fifo_ctrl_reg {
84 uint_t enable : 1; // enable fifo
85 uint_t rfres : 1; // RX FIFO reset
86 uint_t xfres : 1; // TX FIFO reset
87 uint_t dma_sel : 1; // DMA mode select
88 uint_t rsvd : 2; // MBZ
89 uint_t rx_trigger: 2; // RX FIFO trigger level select
92 struct line_ctrl_reg {
93 uint_t word_len : 2; // word length select
94 uint_t stop_bits : 1; // Stop Bit select
95 uint_t parity_enable : 1; // Enable parity
96 uint_t even_sel : 1; // Even Parity Select
97 uint_t stick_parity : 1; // Stick Parity Select
98 uint_t sbr : 1; // Set Break
99 uint_t dlab : 1; // Divisor latch access bit
103 struct modem_ctrl_reg {
108 uint_t loop : 1; // loopback mode
109 uint_t rsvd : 3; // MBZ
113 struct line_status_reg {
114 uint_t rbf : 1; // Receiver Buffer Full
115 uint_t oe : 1; // Overrun error
116 uint_t pe : 1; // Parity Error
117 uint_t fe : 1; // Framing Error
118 uint_t brk : 1; // broken line detected
119 uint_t thre : 1; // Transmitter holding register empty
120 uint_t temt : 1; // Transmitter Empty
121 uint_t fifo_err : 1; // at least one error is pending in the RX FIFO chain
125 struct modem_status_reg {
126 uint_t dcts : 1; // Delta Clear To Send
127 uint_t ddsr : 1; // Delta Data Set Ready
128 uint_t teri : 1; // Trailing Edge Ring Indicator
129 uint_t ddcd : 1; // Delta Data Carrier Detect
130 uint_t cts : 1; // Clear to Send
131 uint_t dsr : 1; // Data Set Ready
132 uint_t ri : 1; // Ring Indicator
133 uint_t dcd : 1; // Data Carrier Detect
138 struct irq_enable_reg ier;
139 struct irq_id_reg iid;
140 struct fifo_ctrl_reg fcr;
141 struct line_ctrl_reg lcr;
142 struct modem_ctrl_reg mcr;
143 struct line_status_reg lsr;
144 struct modem_status_reg msr;
152 struct serial_state {
153 struct serial_port com1;
154 struct serial_port com2;
155 struct serial_port com3;
156 struct serial_port com4;
160 int write_data_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
161 PrintDebug("Write to Data Port\n");
166 int read_data_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
167 PrintDebug("Read from Data Port\n");
172 int write_ctrl_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
173 PrintDebug("Write to Control Port\n");
178 int read_ctrl_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
179 PrintDebug("Read from Control Port\n");
184 int write_status_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
185 PrintDebug("Write to Status Port\n");
190 int read_status_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
191 PrintDebug("Read from Status Port\n");
201 int serial_init(struct vm_device * dev) {
202 struct serial_state * state = (struct serial_state *)dev->private_data;
204 state->com1.ier.rsvd = 0;
205 state->com1.iid.rsvd = 0;
206 state->com1.fcr.rsvd = 0;
207 state->com1.mcr.rsvd = 0;
208 state->com1.iid.pending = 1;
210 state->com2.ier.rsvd = 0;
211 state->com2.iid.rsvd = 0;
212 state->com2.fcr.rsvd = 0;
213 state->com2.mcr.rsvd = 0;
214 state->com2.iid.pending = 1;
216 state->com3.ier.rsvd = 0;
217 state->com3.iid.rsvd = 0;
218 state->com3.fcr.rsvd = 0;
219 state->com3.mcr.rsvd = 0;
220 state->com3.iid.pending = 1;
222 state->com4.ier.rsvd = 0;
223 state->com4.iid.rsvd = 0;
224 state->com4.fcr.rsvd = 0;
225 state->com4.mcr.rsvd = 0;
226 state->com4.iid.pending = 1;
229 dev_hook_io(dev, COM1_DATA_PORT, &read_data_port, &write_data_port);
230 dev_hook_io(dev, COM1_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
231 dev_hook_io(dev, COM1_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
232 dev_hook_io(dev, COM1_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
233 dev_hook_io(dev, COM1_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
234 dev_hook_io(dev, COM1_LINE_STATUS_PORT, &read_status_port, &write_status_port);
235 dev_hook_io(dev, COM1_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
236 dev_hook_io(dev, COM1_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
238 dev_hook_io(dev, COM2_DATA_PORT, &read_data_port, &write_data_port);
239 dev_hook_io(dev, COM2_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
240 dev_hook_io(dev, COM2_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
241 dev_hook_io(dev, COM2_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
242 dev_hook_io(dev, COM2_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
243 dev_hook_io(dev, COM2_LINE_STATUS_PORT, &read_status_port, &write_status_port);
244 dev_hook_io(dev, COM2_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
245 dev_hook_io(dev, COM2_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
247 dev_hook_io(dev, COM3_DATA_PORT, &read_data_port, &write_data_port);
248 dev_hook_io(dev, COM3_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
249 dev_hook_io(dev, COM3_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
250 dev_hook_io(dev, COM3_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
251 dev_hook_io(dev, COM3_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
252 dev_hook_io(dev, COM3_LINE_STATUS_PORT, &read_status_port, &write_status_port);
253 dev_hook_io(dev, COM3_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
254 dev_hook_io(dev, COM3_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
256 dev_hook_io(dev, COM4_DATA_PORT, &read_data_port, &write_data_port);
257 dev_hook_io(dev, COM4_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
258 dev_hook_io(dev, COM4_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
259 dev_hook_io(dev, COM4_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
260 dev_hook_io(dev, COM4_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
261 dev_hook_io(dev, COM4_LINE_STATUS_PORT, &read_status_port, &write_status_port);
262 dev_hook_io(dev, COM4_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
263 dev_hook_io(dev, COM4_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
269 int serial_deinit(struct vm_device * dev) {
272 dev_unhook_io(dev, COM1_DATA_PORT);
273 dev_unhook_io(dev, COM1_IRQ_ENABLE_PORT);
274 dev_unhook_io(dev, COM1_FIFO_CTRL_PORT);
275 dev_unhook_io(dev, COM1_LINE_CTRL_PORT);
276 dev_unhook_io(dev, COM1_MODEM_CTRL_PORT);
277 dev_unhook_io(dev, COM1_LINE_STATUS_PORT);
278 dev_unhook_io(dev, COM1_MODEM_STATUS_PORT);
279 dev_unhook_io(dev, COM1_SCRATCH_PORT);
281 dev_unhook_io(dev, COM2_DATA_PORT);
282 dev_unhook_io(dev, COM2_IRQ_ENABLE_PORT);
283 dev_unhook_io(dev, COM2_FIFO_CTRL_PORT);
284 dev_unhook_io(dev, COM2_LINE_CTRL_PORT);
285 dev_unhook_io(dev, COM2_MODEM_CTRL_PORT);
286 dev_unhook_io(dev, COM2_LINE_STATUS_PORT);
287 dev_unhook_io(dev, COM2_MODEM_STATUS_PORT);
288 dev_unhook_io(dev, COM2_SCRATCH_PORT);
290 dev_unhook_io(dev, COM3_DATA_PORT);
291 dev_unhook_io(dev, COM3_IRQ_ENABLE_PORT);
292 dev_unhook_io(dev, COM3_FIFO_CTRL_PORT);
293 dev_unhook_io(dev, COM3_LINE_CTRL_PORT);
294 dev_unhook_io(dev, COM3_MODEM_CTRL_PORT);
295 dev_unhook_io(dev, COM3_LINE_STATUS_PORT);
296 dev_unhook_io(dev, COM3_MODEM_STATUS_PORT);
297 dev_unhook_io(dev, COM3_SCRATCH_PORT);
299 dev_unhook_io(dev, COM4_DATA_PORT);
300 dev_unhook_io(dev, COM4_IRQ_ENABLE_PORT);
301 dev_unhook_io(dev, COM4_FIFO_CTRL_PORT);
302 dev_unhook_io(dev, COM4_LINE_CTRL_PORT);
303 dev_unhook_io(dev, COM4_MODEM_CTRL_PORT);
304 dev_unhook_io(dev, COM4_LINE_STATUS_PORT);
305 dev_unhook_io(dev, COM4_MODEM_STATUS_PORT);
306 dev_unhook_io(dev, COM4_SCRATCH_PORT);
313 static struct vm_device_ops dev_ops = {
315 .deinit = serial_deinit,
322 struct vm_device * create_serial(int num_ports) {
323 struct serial_state * state = NULL;
324 state = (struct serial_state *)V3_Malloc(sizeof(struct serial_state));
325 V3_ASSERT(state != NULL);
327 struct vm_device * device = create_device("Serial UART", &dev_ops, state);