1/* virtio-pci.c - pci interface for virtio interface
2 *
3 * (c) Copyright 2008 Bull S.A.S.
4 *
5 *  Author: Laurent Vivier <Laurent.Vivier@bull.net>
6 *
7 * some parts from Linux Virtio PCI driver
8 *
9 *  Copyright IBM Corp. 2007
10 *  Authors: Anthony Liguori  <aliguori@us.ibm.com>
11 *
12 */
13
14#include "etherboot.h"
15#include "gpxe/io.h"
16#include "gpxe/virtio-ring.h"
17#include "gpxe/virtio-pci.h"
18
19int vp_find_vq(unsigned int ioaddr, int queue_index,
20               struct vring_virtqueue *vq)
21{
22   struct vring * vr = &vq->vring;
23   u16 num;
24
25   /* select the queue */
26
27   outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_SEL);
28
29   /* check if the queue is available */
30
31   num = inw(ioaddr + VIRTIO_PCI_QUEUE_NUM);
32   if (!num) {
33           printf("ERROR: queue size is 0\n");
34           return -1;
35   }
36
37   if (num > MAX_QUEUE_NUM) {
38           printf("ERROR: queue size %d > %d\n", num, MAX_QUEUE_NUM);
39           return -1;
40   }
41
42   /* check if the queue is already active */
43
44   if (inl(ioaddr + VIRTIO_PCI_QUEUE_PFN)) {
45           printf("ERROR: queue already active\n");
46           return -1;
47   }
48
49   vq->queue_index = queue_index;
50
51   /* initialize the queue */
52
53   vring_init(vr, num, (unsigned char*)&vq->queue);
54
55   /* activate the queue
56    *
57    * NOTE: vr->desc is initialized by vring_init()
58    */
59
60   outl((unsigned long)virt_to_phys(vr->desc) >> PAGE_SHIFT,
61        ioaddr + VIRTIO_PCI_QUEUE_PFN);
62
63   return num;
64}
65