xref: /kvmtool/virtio/blk.c (revision fbc2fbf9b9cdbf265aa13a44cd3cc8a2bfaddfcd)
1b30d05adSPekka Enberg #include "kvm/blk-virtio.h"
2b30d05adSPekka Enberg 
3984b7ae0SPekka Enberg #include "kvm/virtio_pci.h"
4b30d05adSPekka Enberg #include "kvm/ioport.h"
5b30d05adSPekka Enberg #include "kvm/pci.h"
6b30d05adSPekka Enberg 
7984b7ae0SPekka Enberg #define VIRTIO_PCI_IOPORT_SIZE		24
8984b7ae0SPekka Enberg 
9*fbc2fbf9SPekka Enberg struct device {
10*fbc2fbf9SPekka Enberg 	uint32_t		guest_features;
11*fbc2fbf9SPekka Enberg 	uint8_t			status;
12*fbc2fbf9SPekka Enberg };
13*fbc2fbf9SPekka Enberg 
14*fbc2fbf9SPekka Enberg static struct device device;
15*fbc2fbf9SPekka Enberg 
16*fbc2fbf9SPekka Enberg static bool blk_virtio_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
17*fbc2fbf9SPekka Enberg {
18*fbc2fbf9SPekka Enberg 	unsigned long offset;
19*fbc2fbf9SPekka Enberg 
20*fbc2fbf9SPekka Enberg 	offset		= port - IOPORT_VIRTIO;
21*fbc2fbf9SPekka Enberg 
22*fbc2fbf9SPekka Enberg 	switch (offset) {
23*fbc2fbf9SPekka Enberg 	case VIRTIO_PCI_HOST_FEATURES:
24*fbc2fbf9SPekka Enberg 		ioport__write32(data, 0x00);
25*fbc2fbf9SPekka Enberg 		break;
26*fbc2fbf9SPekka Enberg 	case VIRTIO_PCI_GUEST_FEATURES:
27*fbc2fbf9SPekka Enberg 	case VIRTIO_PCI_QUEUE_PFN:
28*fbc2fbf9SPekka Enberg 	case VIRTIO_PCI_QUEUE_NUM:
29*fbc2fbf9SPekka Enberg 	case VIRTIO_PCI_QUEUE_SEL:
30*fbc2fbf9SPekka Enberg 	case VIRTIO_PCI_QUEUE_NOTIFY:
31*fbc2fbf9SPekka Enberg 		return false;
32*fbc2fbf9SPekka Enberg 	case VIRTIO_PCI_STATUS:
33*fbc2fbf9SPekka Enberg 		ioport__write8(data, device.status);
34*fbc2fbf9SPekka Enberg 		break;
35*fbc2fbf9SPekka Enberg 	case VIRTIO_PCI_ISR:
36*fbc2fbf9SPekka Enberg 	case VIRTIO_MSI_CONFIG_VECTOR:
37*fbc2fbf9SPekka Enberg 	default:
38*fbc2fbf9SPekka Enberg 		return false;
39*fbc2fbf9SPekka Enberg 	};
40*fbc2fbf9SPekka Enberg 
41*fbc2fbf9SPekka Enberg 	return true;
42*fbc2fbf9SPekka Enberg }
43*fbc2fbf9SPekka Enberg 
44*fbc2fbf9SPekka Enberg #include <stdio.h>
45*fbc2fbf9SPekka Enberg 
46*fbc2fbf9SPekka Enberg static bool blk_virtio_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
47*fbc2fbf9SPekka Enberg {
48*fbc2fbf9SPekka Enberg 	unsigned long offset;
49*fbc2fbf9SPekka Enberg 
50*fbc2fbf9SPekka Enberg 	offset		= port - IOPORT_VIRTIO;
51*fbc2fbf9SPekka Enberg 
52*fbc2fbf9SPekka Enberg 	switch (offset) {
53*fbc2fbf9SPekka Enberg 	case VIRTIO_PCI_GUEST_FEATURES:
54*fbc2fbf9SPekka Enberg 		device.guest_features	= ioport__read32(data);
55*fbc2fbf9SPekka Enberg 		break;
56*fbc2fbf9SPekka Enberg 	case VIRTIO_PCI_QUEUE_PFN:
57*fbc2fbf9SPekka Enberg 	case VIRTIO_PCI_QUEUE_SEL:
58*fbc2fbf9SPekka Enberg 	case VIRTIO_PCI_QUEUE_NOTIFY:
59*fbc2fbf9SPekka Enberg 		return false;
60*fbc2fbf9SPekka Enberg 	case VIRTIO_PCI_STATUS:
61*fbc2fbf9SPekka Enberg 		device.status		= ioport__read8(data);
62*fbc2fbf9SPekka Enberg 		break;
63*fbc2fbf9SPekka Enberg 	case VIRTIO_MSI_CONFIG_VECTOR:
64*fbc2fbf9SPekka Enberg 	case VIRTIO_MSI_QUEUE_VECTOR:
65*fbc2fbf9SPekka Enberg 	default:
66*fbc2fbf9SPekka Enberg 		return false;
67*fbc2fbf9SPekka Enberg 	};
68*fbc2fbf9SPekka Enberg 
69*fbc2fbf9SPekka Enberg 	return true;
70*fbc2fbf9SPekka Enberg }
71*fbc2fbf9SPekka Enberg 
72*fbc2fbf9SPekka Enberg static struct ioport_operations blk_virtio_io_ops = {
73*fbc2fbf9SPekka Enberg 	.io_in		= blk_virtio_in,
74*fbc2fbf9SPekka Enberg 	.io_out		= blk_virtio_out,
75*fbc2fbf9SPekka Enberg };
76*fbc2fbf9SPekka Enberg 
77b30d05adSPekka Enberg #define PCI_VENDOR_ID_REDHAT_QUMRANET		0x1af4
78b30d05adSPekka Enberg #define PCI_DEVICE_ID_VIRTIO_BLK		0x1001
79b30d05adSPekka Enberg #define PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET	0x1af4
80b30d05adSPekka Enberg #define PCI_SUBSYSTEM_ID_VIRTIO_BLK		0x0002
81b30d05adSPekka Enberg 
82*fbc2fbf9SPekka Enberg static struct pci_device_header blk_virtio_pci_device = {
83b30d05adSPekka Enberg 	.vendor_id		= PCI_VENDOR_ID_REDHAT_QUMRANET,
84b30d05adSPekka Enberg 	.device_id		= PCI_DEVICE_ID_VIRTIO_BLK,
85b30d05adSPekka Enberg 	.header_type		= PCI_HEADER_TYPE_NORMAL,
86b30d05adSPekka Enberg 	.revision_id		= 0,
87b30d05adSPekka Enberg 	.class			= 0x010000,
88b30d05adSPekka Enberg 	.subsys_vendor_id	= PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET,
89b30d05adSPekka Enberg 	.subsys_id		= PCI_SUBSYSTEM_ID_VIRTIO_BLK,
90b30d05adSPekka Enberg 	.bar[0]			= IOPORT_VIRTIO | PCI_BASE_ADDRESS_SPACE_IO,
91b30d05adSPekka Enberg };
92b30d05adSPekka Enberg 
93b30d05adSPekka Enberg void blk_virtio__init(void)
94b30d05adSPekka Enberg {
95*fbc2fbf9SPekka Enberg 	pci__register(&blk_virtio_pci_device, 1);
96b30d05adSPekka Enberg 
97984b7ae0SPekka Enberg 	ioport__register(IOPORT_VIRTIO, &blk_virtio_io_ops, VIRTIO_PCI_IOPORT_SIZE);
98b30d05adSPekka Enberg }
99