xref: /kvmtool/hw/serial.c (revision e557eef9b67c7782a80a4639c637207d933495f3)
1 #include "kvm/8250-serial.h"
2 
3 #include "kvm/ioport.h"
4 #include "kvm/util.h"
5 #include "kvm/kvm.h"
6 
7 #include <stdbool.h>
8 
9 /* Transmitter holding register */
10 #define THR             0
11 
12 /* Receive buffer register */
13 #define RBR             0
14 
15 /* Divisor latch low byte */
16 #define DLL		0
17 
18 /* Divisor latch high byte */
19 #define DLM		1
20 
21 /* Interrupt enable register */
22 #define IER		1
23 
24 #define UART_IER_THRI		0x02
25 
26 /* Interrupt identification register */
27 #define IIR		2
28 
29 #define UART_IIR_NO_INT		0x01
30 #define UART_IIR_THRI		0x02
31 
32 /* 16550 FIFO Control Register */
33 #define FCR		2
34 
35 /* Line control register */
36 #define LCR		3
37 
38 #define UART_LCR_DLAB		0x80
39 
40 /* Modem control register */
41 #define MCR		4
42 
43 /* Line status register */
44 #define LSR		5
45 
46 #define UART_LSR_THRE		0x20
47 
48 /* Modem status register */
49 #define MSR		6
50 
51 #define UART_MSR_CTS		0x10
52 
53 /* Scratch register */
54 #define SCR		7
55 
56 struct serial8250_device {
57 	uint16_t		iobase;
58 	uint8_t			irq;
59 	uint8_t			dll;
60 	uint8_t			dlm;
61 	uint8_t			iir;
62 	uint8_t			ier;
63 	uint8_t			fcr;
64 	uint8_t			lcr;
65 	uint8_t			mcr;
66 	uint8_t			scr;
67 };
68 
69 static struct serial8250_device device = {
70 	.iobase			= 0x3f8,	/* ttyS0 */
71 	.irq			= 4,
72 
73 	.iir			= UART_IIR_NO_INT | UART_IIR_THRI,
74 };
75 
76 void serial8250__interrupt(struct kvm *self)
77 {
78 	if (device.ier & UART_IER_THRI) {
79 		device.iir		&= ~UART_IIR_NO_INT;
80 		kvm__irq_line(self, device.irq, 1);
81 	}
82 }
83 
84 static bool serial8250_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
85 {
86 	uint16_t offset = port - device.iobase;
87 
88 	if (device.lcr & UART_LCR_DLAB) {
89 		switch (offset) {
90 		case DLL:
91 			device.dll		= ioport__read8(data);
92 			break;
93 		case DLM:
94 			device.dlm		= ioport__read8(data);
95 			break;
96 		case FCR:
97 			device.fcr		= ioport__read8(data);
98 			break;
99 		case LCR:
100 			device.lcr		= ioport__read8(data);
101 			break;
102 		default:
103 			return false;
104 		}
105 	} else {
106 		switch (offset) {
107 		case THR: {
108 			char *p = data;
109 			int i;
110 
111 			while (count--) {
112 				for (i = 0; i < size; i++)
113 					fprintf(stdout, "%c", *p++);
114 			}
115 			fflush(stdout);
116 
117 			device.iir		|= UART_IIR_NO_INT;
118 			kvm__irq_line(self, device.irq, 0);
119 
120 			break;
121 		}
122 		case IER:
123 			device.ier		= ioport__read8(data);
124 			break;
125 		case FCR:
126 			device.fcr		= ioport__read8(data);
127 			break;
128 		case LCR:
129 			device.lcr		= ioport__read8(data);
130 			break;
131 		case MCR:
132 			device.mcr		= ioport__read8(data);
133 			break;
134 		case SCR:
135 			device.scr		= ioport__read8(data);
136 			break;
137 		default:
138 			return false;
139 		}
140 	}
141 
142 	return true;
143 }
144 
145 static bool serial8250_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
146 {
147 	uint16_t offset = port - device.iobase;
148 
149 	if (device.lcr & UART_LCR_DLAB)
150 		return false;
151 
152 	switch (offset) {
153 	case THR:
154 		/* TODO: input support */
155 		break;
156 	case IER:
157 		ioport__write8(data, device.ier);
158 		break;
159 	case IIR:
160 		ioport__write8(data, device.iir);
161 		break;
162 	case LCR:
163 		ioport__write8(data, device.lcr);
164 		break;
165 	case MCR:
166 		ioport__write8(data, device.mcr);
167 		break;
168 	case LSR:
169 		ioport__write8(data, UART_LSR_THRE);
170 		break;
171 	case MSR:
172 		ioport__write8(data, UART_MSR_CTS);
173 		break;
174 	case SCR:
175 		ioport__write8(data, device.scr);
176 		break;
177 	default:
178 		return false;
179 	}
180 
181 	return true;
182 }
183 
184 static struct ioport_operations serial8250_ops = {
185 	.io_in		= serial8250_in,
186 	.io_out		= serial8250_out,
187 };
188 
189 void serial8250__init(void)
190 {
191 	ioport__register(device.iobase, &serial8250_ops, 8);
192 }
193