#include "kvm/ioport.h"
#include "kvm/util.h"
+#include "kvm/kvm.h"
#include <stdbool.h>
/* Interrupt enable register */
#define IER 1
+#define UART_IER_THRI 0x02
+
/* Interrupt identification register */
#define IIR 2
struct serial8250_device {
uint16_t iobase;
+ uint8_t irq;
uint8_t dll;
uint8_t dlm;
+ uint8_t iir;
uint8_t ier;
uint8_t fcr;
uint8_t lcr;
static struct serial8250_device device = {
.iobase = 0x3f8, /* ttyS0 */
+ .irq = 4,
+
+ .iir = UART_IIR_NO_INT | UART_IIR_THRI,
};
void serial8250__interrupt(struct kvm *self)
{
- /* TODO: inject 8250 interrupt for the guest */
+ if (device.ier & UART_IER_THRI) {
+ device.iir &= ~UART_IIR_NO_INT;
+ kvm__irq_line(self, device.irq, 1);
+ }
}
static bool serial8250_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
fprintf(stdout, "%c", *p++);
}
fflush(stdout);
+
+ device.iir |= UART_IIR_NO_INT;
+ kvm__irq_line(self, device.irq, 0);
+
break;
}
case IER:
ioport__write8(data, device.ier);
break;
case IIR:
- ioport__write8(data, UART_IIR_NO_INT | UART_IIR_THRI);
+ ioport__write8(data, device.iir);
break;
case LCR:
ioport__write8(data, device.lcr);
return !strncmp(arg, option, strlen(option));
}
-#define TIMER_INTERVAL_NS 1000000000
+#define TIMER_INTERVAL_NS 1000000 /* 1 msec */
static void alarm_handler(int sig)
{