1 /* virtio-pci.c - pci interface for virtio interface
3 * (c) Copyright 2008 Bull S.A.S.
5 * Author: Laurent Vivier <Laurent.Vivier@bull.net>
7 * some parts from Linux Virtio PCI driver
9 * Copyright IBM Corp. 2007
10 * Authors: Anthony Liguori <aliguori@us.ibm.com>
12 * Adopted for Seabios: Gleb Natapov <gleb@redhat.com>
14 * This work is licensed under the terms of the GNU LGPLv3
15 * See the COPYING file in the top-level directory.
18 #include "config.h" // CONFIG_DEBUG_LEVEL
19 #include "malloc.h" // free
20 #include "output.h" // dprintf
21 #include "pci.h" // pci_config_readl
22 #include "pci_regs.h" // PCI_BASE_ADDRESS_0
23 #include "string.h" // memset
24 #include "virtio-pci.h"
25 #include "virtio-ring.h"
27 u64 vp_get_features(struct vp_device *vp)
32 vp_write(&vp->common, virtio_pci_common_cfg, device_feature_select, 0);
33 f0 = vp_read(&vp->common, virtio_pci_common_cfg, device_feature);
34 vp_write(&vp->common, virtio_pci_common_cfg, device_feature_select, 1);
35 f1 = vp_read(&vp->common, virtio_pci_common_cfg, device_feature);
37 f0 = vp_read(&vp->legacy, virtio_pci_legacy, host_features);
40 return ((u64)f1 << 32) | f0;
43 void vp_set_features(struct vp_device *vp, u64 features)
51 vp_write(&vp->common, virtio_pci_common_cfg, guest_feature_select, 0);
52 vp_write(&vp->common, virtio_pci_common_cfg, guest_feature, f0);
53 vp_write(&vp->common, virtio_pci_common_cfg, guest_feature_select, 1);
54 vp_write(&vp->common, virtio_pci_common_cfg, guest_feature, f1);
56 vp_write(&vp->legacy, virtio_pci_legacy, guest_features, f0);
60 u8 vp_get_status(struct vp_device *vp)
63 return vp_read(&vp->common, virtio_pci_common_cfg, device_status);
65 return vp_read(&vp->legacy, virtio_pci_legacy, status);
69 void vp_set_status(struct vp_device *vp, u8 status)
71 if (status == 0) /* reset */
74 vp_write(&vp->common, virtio_pci_common_cfg, device_status, status);
76 vp_write(&vp->legacy, virtio_pci_legacy, status, status);
80 u8 vp_get_isr(struct vp_device *vp)
83 return vp_read(&vp->isr, virtio_pci_isr, isr);
85 return vp_read(&vp->legacy, virtio_pci_legacy, isr);
89 void vp_reset(struct vp_device *vp)
92 vp_write(&vp->common, virtio_pci_common_cfg, device_status, 0);
93 vp_read(&vp->isr, virtio_pci_isr, isr);
95 vp_write(&vp->legacy, virtio_pci_legacy, status, 0);
96 vp_read(&vp->legacy, virtio_pci_legacy, isr);
100 void vp_notify(struct vp_device *vp, struct vring_virtqueue *vq)
102 if (vp->use_modern) {
103 u32 addr = vp->notify.addr +
104 vq->queue_notify_off *
105 vp->notify_off_multiplier;
106 if (vp->notify.is_io) {
107 outw(vq->queue_index, addr);
109 writew((void*)addr, vq->queue_index);
111 dprintf(9, "vp notify %x (%d) -- 0x%x\n",
112 addr, 2, vq->queue_index);
114 vp_write(&vp->legacy, virtio_pci_legacy, queue_notify, vq->queue_index);
118 int vp_find_vq(struct vp_device *vp, int queue_index,
119 struct vring_virtqueue **p_vq)
124 struct vring_virtqueue *vq = *p_vq = memalign_high(PAGE_SIZE, sizeof(*vq));
129 memset(vq, 0, sizeof(*vq));
132 /* select the queue */
133 if (vp->use_modern) {
134 vp_write(&vp->common, virtio_pci_common_cfg, queue_select, queue_index);
136 vp_write(&vp->legacy, virtio_pci_legacy, queue_sel, queue_index);
139 /* check if the queue is available */
140 if (vp->use_modern) {
141 num = vp_read(&vp->common, virtio_pci_common_cfg, queue_size);
142 if (num > MAX_QUEUE_NUM) {
143 vp_write(&vp->common, virtio_pci_common_cfg, queue_size,
145 num = vp_read(&vp->common, virtio_pci_common_cfg, queue_size);
148 num = vp_read(&vp->legacy, virtio_pci_legacy, queue_num);
151 dprintf(1, "ERROR: queue size is 0\n");
154 if (num > MAX_QUEUE_NUM) {
155 dprintf(1, "ERROR: queue size %d > %d\n", num, MAX_QUEUE_NUM);
159 /* check if the queue is already active */
160 if (vp->use_modern) {
161 if (vp_read(&vp->common, virtio_pci_common_cfg, queue_enable)) {
162 dprintf(1, "ERROR: queue already active\n");
166 if (vp_read(&vp->legacy, virtio_pci_legacy, queue_pfn)) {
167 dprintf(1, "ERROR: queue already active\n");
171 vq->queue_index = queue_index;
173 /* initialize the queue */
174 struct vring * vr = &vq->vring;
175 vring_init(vr, num, (unsigned char*)&vq->queue);
177 /* activate the queue
179 * NOTE: vr->desc is initialized by vring_init()
182 if (vp->use_modern) {
183 vp_write(&vp->common, virtio_pci_common_cfg, queue_desc_lo,
184 (unsigned long)virt_to_phys(vr->desc));
185 vp_write(&vp->common, virtio_pci_common_cfg, queue_desc_hi, 0);
186 vp_write(&vp->common, virtio_pci_common_cfg, queue_avail_lo,
187 (unsigned long)virt_to_phys(vr->avail));
188 vp_write(&vp->common, virtio_pci_common_cfg, queue_avail_hi, 0);
189 vp_write(&vp->common, virtio_pci_common_cfg, queue_used_lo,
190 (unsigned long)virt_to_phys(vr->used));
191 vp_write(&vp->common, virtio_pci_common_cfg, queue_used_hi, 0);
192 vp_write(&vp->common, virtio_pci_common_cfg, queue_enable, 1);
193 vq->queue_notify_off = vp_read(&vp->common, virtio_pci_common_cfg,
196 vp_write(&vp->legacy, virtio_pci_legacy, queue_pfn,
197 (unsigned long)virt_to_phys(vr->desc) >> PAGE_SHIFT);
207 void vp_init_simple(struct vp_device *vp, struct pci_device *pci)
209 u8 cap = pci_find_capability(pci, PCI_CAP_ID_VNDR, 0);
210 struct vp_cap *vp_cap;
211 u32 addr, offset, mul;
214 memset(vp, 0, sizeof(*vp));
216 type = pci_config_readb(pci->bdf, cap +
217 offsetof(struct virtio_pci_cap, cfg_type));
219 case VIRTIO_PCI_CAP_COMMON_CFG:
220 vp_cap = &vp->common;
222 case VIRTIO_PCI_CAP_NOTIFY_CFG:
223 vp_cap = &vp->notify;
224 mul = offsetof(struct virtio_pci_notify_cap, notify_off_multiplier);
225 vp->notify_off_multiplier = pci_config_readl(pci->bdf, cap + mul);
227 case VIRTIO_PCI_CAP_ISR_CFG:
230 case VIRTIO_PCI_CAP_DEVICE_CFG:
231 vp_cap = &vp->device;
237 if (vp_cap && !vp_cap->cap) {
239 vp_cap->bar = pci_config_readb(pci->bdf, cap +
240 offsetof(struct virtio_pci_cap, bar));
241 offset = pci_config_readl(pci->bdf, cap +
242 offsetof(struct virtio_pci_cap, offset));
243 addr = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0 + 4 * vp_cap->bar);
244 if (addr & PCI_BASE_ADDRESS_SPACE_IO) {
246 addr &= PCI_BASE_ADDRESS_IO_MASK;
249 addr &= PCI_BASE_ADDRESS_MEM_MASK;
251 vp_cap->addr = addr + offset;
252 dprintf(3, "pci dev %x:%x virtio cap at 0x%x type %d "
253 "bar %d at 0x%08x off +0x%04x [%s]\n",
254 pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf),
255 vp_cap->cap, type, vp_cap->bar, addr, offset,
256 vp_cap->is_io ? "io" : "mmio");
259 cap = pci_find_capability(pci, PCI_CAP_ID_VNDR, cap);
262 if (vp->common.cap && vp->notify.cap && vp->isr.cap && vp->device.cap) {
263 dprintf(1, "pci dev %x:%x using modern (1.0) virtio mode\n",
264 pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf));
267 dprintf(1, "pci dev %x:%x using legacy (0.9.5) virtio mode\n",
268 pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf));
270 vp->legacy.addr = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0) &
271 PCI_BASE_ADDRESS_IO_MASK;
272 vp->legacy.is_io = 1;
276 pci_config_maskw(pci->bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER);
277 vp_set_status(vp, VIRTIO_CONFIG_S_ACKNOWLEDGE |
278 VIRTIO_CONFIG_S_DRIVER );