8250-serial.c 5.28 KB
Newer Older
1
#include "kvm/8250-serial.h"
2
3

#include "kvm/ioport.h"
4
#include "kvm/util.h"
5
#include "kvm/kvm.h"
6

7
8
#include <linux/serial_reg.h>

9
#include <stdbool.h>
10
#include <poll.h>
11

12
13
struct serial8250_device {
	uint16_t		iobase;
14
	uint8_t			irq;
15

16
	uint8_t			rbr;		/* receive buffer */
17
18
	uint8_t			dll;
	uint8_t			dlm;
19
	uint8_t			iir;
20
21
22
23
	uint8_t			ier;
	uint8_t			fcr;
	uint8_t			lcr;
	uint8_t			mcr;
24
	uint8_t			lsr;
25
	uint8_t			msr;
26
	uint8_t			scr;
27
28
};

29
static struct serial8250_device devices[] = {
30
31
32
33
34
	/* ttyS0 */
	[0]	= {
		.iobase			= 0x3f8,
		.irq			= 4,

35
		.iir			= UART_IIR_NO_INT,
36
37
38
		.lsr			= UART_LSR_TEMT | UART_LSR_THRE,
		.msr			= UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS,
		.mcr			= UART_MCR_OUT2,
39
	},
40
41
42
43
	/* ttyS1 */
	[1]	= {
		.iobase			= 0x2f8,
		.irq			= 3,
44
45

		.iir			= UART_IIR_NO_INT,
46
47
48
49
50
	},
	/* ttyS2 */
	[2]	= {
		.iobase			= 0x3e8,
		.irq			= 4,
51
52

		.iir			= UART_IIR_NO_INT,
53
	},
54
55
};

56
57
58
59
60
61
62
63
64
65
66
67
static int read_char(int fd)
{
	int c;

	if (read(fd, &c, 1) < 0)
		return -1;

	return c;
}

static bool is_readable(int fd)
{
68
69
70
	struct pollfd pollfd = (struct pollfd) {
		.fd	= fd,
		.events	= POLLIN,
71
72
	};

73
	return poll(&pollfd, 1, 0) > 0;
74
75
}

76
77
78
79
static void serial8250__receive(struct kvm *self, struct serial8250_device *dev)
{
	int c;

80
81
82
	if (dev->lsr & UART_LSR_DR)
		return;

83
84
85
86
87
88
89
90
91
92
93
	if (!is_readable(fileno(stdin)))
		return;

	c		= read_char(fileno(stdin));
	if (c < 0)
		return;

	dev->rbr	= c;
	dev->lsr	|= UART_LSR_DR;
}

94
95
96
/*
 * Interrupts are injected for ttyS0 only.
 */
97
98
void serial8250__interrupt(struct kvm *self)
{
99
	struct serial8250_device *dev = &devices[0];
100

101
102
	serial8250__receive(self, dev);

103
104
	if (dev->ier & UART_IER_RDI && dev->lsr & UART_LSR_DR)
		dev->iir		= UART_IIR_RDI;
105
	else if (dev->ier & UART_IER_THRI)
106
107
108
		dev->iir		= UART_IIR_THRI;
	else
		dev->iir		= UART_IIR_NO_INT;
109

110
	if (dev->iir != UART_IIR_NO_INT) {
111
112
113
114
115
116
117
118
119
120
121
122
123
124
		kvm__irq_line(self, dev->irq, 0);
		kvm__irq_line(self, dev->irq, 1);
	}
}

static struct serial8250_device *find_device(uint16_t port)
{
	unsigned int i;

	for (i = 0; i < ARRAY_SIZE(devices); i++) {
		struct serial8250_device *dev = &devices[i];

		if (dev->iobase == (port & ~0x7))
			return dev;
125
	}
126
	return NULL;
127
128
}

129
130
static bool serial8250_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
{
131
132
133
134
135
136
137
138
	struct serial8250_device *dev;
	uint16_t offset;

	dev		= find_device(port);
	if (!dev)
		return false;

	offset		= port - dev->iobase;
139

140
	if (dev->lcr & UART_LCR_DLAB) {
141
		switch (offset) {
142
		case UART_DLL:
143
			dev->dll	= ioport__read8(data);
144
			break;
145
		case UART_DLM:
146
147
148
149
150
151
152
			dev->dlm	= ioport__read8(data);
			break;
		case UART_FCR:
			dev->fcr	= ioport__read8(data);
			break;
		case UART_LCR:
			dev->lcr	= ioport__read8(data);
153
			break;
154
155
156
157
158
159
160
161
162
163
164
165
166
167
		case UART_MCR:
			dev->mcr	= ioport__read8(data);
			break;
		case UART_LSR:
			/* Factory test */
			break;
		case UART_MSR:
			/* Not used */
			break;
		case UART_SCR:
			dev->scr	= ioport__read8(data);
			break;
		default:
			return false;
168
169
170
		}
	} else {
		switch (offset) {
171
		case UART_TX: {
172
173
174
			char *p = data;
			int i;

175
176
177
178
179
180
			if (!(dev->mcr & UART_MCR_LOOP)) {
				while (count--) {
					for (i = 0; i < size; i++)
						fprintf(stdout, "%c", *p++);
				}
				fflush(stdout);
181
			}
182
			dev->iir		= UART_IIR_NO_INT;
183
184
			break;
		}
185
186
187
		case UART_FCR:
			dev->fcr	= ioport__read8(data);
			break;
188
		case UART_IER:
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
			dev->ier	= ioport__read8(data) & 0x3f;
			break;
		case UART_LCR:
			dev->lcr	= ioport__read8(data);
			break;
		case UART_MCR:
			dev->mcr	= ioport__read8(data);
			break;
		case UART_LSR:
			/* Factory test */
			break;
		case UART_MSR:
			/* Not used */
			break;
		case UART_SCR:
			dev->scr	= ioport__read8(data);
205
			break;
206
207
		default:
			return false;
208
209
210
211
212
213
		}
	}
	return true;
}

static bool serial8250_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
214
{
215
216
217
218
219
220
	struct serial8250_device *dev;
	uint16_t offset;

	dev		= find_device(port);
	if (!dev)
		return false;
221

222
223
	offset		= port - dev->iobase;

224
225
226
227
228
229
230
231
	if (dev->lcr & UART_LCR_DLAB) {
		switch (offset) {
		case UART_DLL:
			ioport__write8(data, dev->dll);
			return true;
		case UART_DLM:
			ioport__write8(data, dev->dlm);
			return true;
232
233
		default:
			break;
234
235
236
237
		}
	} else {
		switch (offset) {
		case UART_RX:
238
239
240
			ioport__write8(data, dev->rbr);
			dev->lsr		&= ~UART_LSR_DR;
			dev->iir		= UART_IIR_NO_INT;
241
242
243
244
			return true;
		case UART_IER:
			ioport__write8(data, dev->ier);
			return true;
245
246
		default:
			break;
247
		}
248
249
250
	}

	switch (offset) {
251
252
253
254
255
256
257
	case UART_IIR: {
		uint8_t iir = dev->iir;

		if (dev->fcr & UART_FCR_ENABLE_FIFO)
			iir		|= 0xc0;

		ioport__write8(data, iir);
258
		break;
259
	}
260
	case UART_LCR:
261
		ioport__write8(data, dev->lcr);
262
		break;
263
	case UART_MCR:
264
		ioport__write8(data, dev->mcr);
265
		break;
266
	case UART_LSR:
267
		ioport__write8(data, dev->lsr);
268
		dev->lsr		&= ~(UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI);
269
		break;
270
	case UART_MSR:
271
		ioport__write8(data, dev->msr);
272
		break;
273
	case UART_SCR:
274
		ioport__write8(data, dev->scr);
275
		break;
276
277
	default:
		return false;
278
	}
279
280
281
	return true;
}

282
283
284
static struct ioport_operations serial8250_ops = {
	.io_in		= serial8250_in,
	.io_out		= serial8250_out,
285
286
};

287
288
289
290
291
292
293
static void serial8250__device_init(struct kvm *kvm, struct serial8250_device *dev)
{
	ioport__register(dev->iobase, &serial8250_ops, 8);
	kvm__irq_line(kvm, dev->irq, 0);
}

void serial8250__init(struct kvm *kvm)
294
{
295
296
297
298
299
	unsigned int i;

	for (i = 0; i < ARRAY_SIZE(devices); i++) {
		struct serial8250_device *dev = &devices[i];

300
		serial8250__device_init(kvm, dev);
301
	}
302
}