xref: /openbmc/qemu/tests/qtest/libqos/virtio-blk.c (revision 1cf4323ecd03235984e43a416a42f10c975cf785)
1*1cf4323eSThomas Huth /*
2*1cf4323eSThomas Huth  * libqos driver framework
3*1cf4323eSThomas Huth  *
4*1cf4323eSThomas Huth  * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
5*1cf4323eSThomas Huth  *
6*1cf4323eSThomas Huth  * This library is free software; you can redistribute it and/or
7*1cf4323eSThomas Huth  * modify it under the terms of the GNU Lesser General Public
8*1cf4323eSThomas Huth  * License version 2 as published by the Free Software Foundation.
9*1cf4323eSThomas Huth  *
10*1cf4323eSThomas Huth  * This library is distributed in the hope that it will be useful,
11*1cf4323eSThomas Huth  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*1cf4323eSThomas Huth  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13*1cf4323eSThomas Huth  * Lesser General Public License for more details.
14*1cf4323eSThomas Huth  *
15*1cf4323eSThomas Huth  * You should have received a copy of the GNU Lesser General Public
16*1cf4323eSThomas Huth  * License along with this library; if not, see <http://www.gnu.org/licenses/>
17*1cf4323eSThomas Huth  */
18*1cf4323eSThomas Huth 
19*1cf4323eSThomas Huth #include "qemu/osdep.h"
20*1cf4323eSThomas Huth #include "libqtest.h"
21*1cf4323eSThomas Huth #include "qemu/module.h"
22*1cf4323eSThomas Huth #include "standard-headers/linux/virtio_blk.h"
23*1cf4323eSThomas Huth #include "libqos/qgraph.h"
24*1cf4323eSThomas Huth #include "libqos/virtio-blk.h"
25*1cf4323eSThomas Huth 
26*1cf4323eSThomas Huth #define PCI_SLOT                0x04
27*1cf4323eSThomas Huth #define PCI_FN                  0x00
28*1cf4323eSThomas Huth 
29*1cf4323eSThomas Huth /* virtio-blk-device */
30*1cf4323eSThomas Huth static void *qvirtio_blk_get_driver(QVirtioBlk *v_blk,
31*1cf4323eSThomas Huth                                     const char *interface)
32*1cf4323eSThomas Huth {
33*1cf4323eSThomas Huth     if (!g_strcmp0(interface, "virtio-blk")) {
34*1cf4323eSThomas Huth         return v_blk;
35*1cf4323eSThomas Huth     }
36*1cf4323eSThomas Huth     if (!g_strcmp0(interface, "virtio")) {
37*1cf4323eSThomas Huth         return v_blk->vdev;
38*1cf4323eSThomas Huth     }
39*1cf4323eSThomas Huth 
40*1cf4323eSThomas Huth     fprintf(stderr, "%s not present in virtio-blk-device\n", interface);
41*1cf4323eSThomas Huth     g_assert_not_reached();
42*1cf4323eSThomas Huth }
43*1cf4323eSThomas Huth 
44*1cf4323eSThomas Huth static void *qvirtio_blk_device_get_driver(void *object,
45*1cf4323eSThomas Huth                                            const char *interface)
46*1cf4323eSThomas Huth {
47*1cf4323eSThomas Huth     QVirtioBlkDevice *v_blk = object;
48*1cf4323eSThomas Huth     return qvirtio_blk_get_driver(&v_blk->blk, interface);
49*1cf4323eSThomas Huth }
50*1cf4323eSThomas Huth 
51*1cf4323eSThomas Huth static void *virtio_blk_device_create(void *virtio_dev,
52*1cf4323eSThomas Huth                                       QGuestAllocator *t_alloc,
53*1cf4323eSThomas Huth                                       void *addr)
54*1cf4323eSThomas Huth {
55*1cf4323eSThomas Huth     QVirtioBlkDevice *virtio_blk = g_new0(QVirtioBlkDevice, 1);
56*1cf4323eSThomas Huth     QVirtioBlk *interface = &virtio_blk->blk;
57*1cf4323eSThomas Huth 
58*1cf4323eSThomas Huth     interface->vdev = virtio_dev;
59*1cf4323eSThomas Huth 
60*1cf4323eSThomas Huth     virtio_blk->obj.get_driver = qvirtio_blk_device_get_driver;
61*1cf4323eSThomas Huth 
62*1cf4323eSThomas Huth     return &virtio_blk->obj;
63*1cf4323eSThomas Huth }
64*1cf4323eSThomas Huth 
65*1cf4323eSThomas Huth /* virtio-blk-pci */
66*1cf4323eSThomas Huth static void *qvirtio_blk_pci_get_driver(void *object, const char *interface)
67*1cf4323eSThomas Huth {
68*1cf4323eSThomas Huth     QVirtioBlkPCI *v_blk = object;
69*1cf4323eSThomas Huth     if (!g_strcmp0(interface, "pci-device")) {
70*1cf4323eSThomas Huth         return v_blk->pci_vdev.pdev;
71*1cf4323eSThomas Huth     }
72*1cf4323eSThomas Huth     return qvirtio_blk_get_driver(&v_blk->blk, interface);
73*1cf4323eSThomas Huth }
74*1cf4323eSThomas Huth 
75*1cf4323eSThomas Huth static void *virtio_blk_pci_create(void *pci_bus, QGuestAllocator *t_alloc,
76*1cf4323eSThomas Huth                                       void *addr)
77*1cf4323eSThomas Huth {
78*1cf4323eSThomas Huth     QVirtioBlkPCI *virtio_blk = g_new0(QVirtioBlkPCI, 1);
79*1cf4323eSThomas Huth     QVirtioBlk *interface = &virtio_blk->blk;
80*1cf4323eSThomas Huth     QOSGraphObject *obj = &virtio_blk->pci_vdev.obj;
81*1cf4323eSThomas Huth 
82*1cf4323eSThomas Huth     virtio_pci_init(&virtio_blk->pci_vdev, pci_bus, addr);
83*1cf4323eSThomas Huth     interface->vdev = &virtio_blk->pci_vdev.vdev;
84*1cf4323eSThomas Huth 
85*1cf4323eSThomas Huth     g_assert_cmphex(interface->vdev->device_type, ==, VIRTIO_ID_BLOCK);
86*1cf4323eSThomas Huth 
87*1cf4323eSThomas Huth     obj->get_driver = qvirtio_blk_pci_get_driver;
88*1cf4323eSThomas Huth 
89*1cf4323eSThomas Huth     return obj;
90*1cf4323eSThomas Huth }
91*1cf4323eSThomas Huth 
92*1cf4323eSThomas Huth static void virtio_blk_register_nodes(void)
93*1cf4323eSThomas Huth {
94*1cf4323eSThomas Huth     /* FIXME: every test using these two nodes needs to setup a
95*1cf4323eSThomas Huth      * -drive,id=drive0 otherwise QEMU is not going to start.
96*1cf4323eSThomas Huth      * Therefore, we do not include "produces" edge for virtio
97*1cf4323eSThomas Huth      * and pci-device yet.
98*1cf4323eSThomas Huth     */
99*1cf4323eSThomas Huth 
100*1cf4323eSThomas Huth     char *arg = g_strdup_printf("id=drv0,drive=drive0,addr=%x.%x",
101*1cf4323eSThomas Huth                                 PCI_SLOT, PCI_FN);
102*1cf4323eSThomas Huth 
103*1cf4323eSThomas Huth     QPCIAddress addr = {
104*1cf4323eSThomas Huth         .devfn = QPCI_DEVFN(PCI_SLOT, PCI_FN),
105*1cf4323eSThomas Huth     };
106*1cf4323eSThomas Huth 
107*1cf4323eSThomas Huth     QOSGraphEdgeOptions opts = { };
108*1cf4323eSThomas Huth 
109*1cf4323eSThomas Huth     /* virtio-blk-device */
110*1cf4323eSThomas Huth     opts.extra_device_opts = "drive=drive0";
111*1cf4323eSThomas Huth     qos_node_create_driver("virtio-blk-device", virtio_blk_device_create);
112*1cf4323eSThomas Huth     qos_node_consumes("virtio-blk-device", "virtio-bus", &opts);
113*1cf4323eSThomas Huth     qos_node_produces("virtio-blk-device", "virtio-blk");
114*1cf4323eSThomas Huth 
115*1cf4323eSThomas Huth     /* virtio-blk-pci */
116*1cf4323eSThomas Huth     opts.extra_device_opts = arg;
117*1cf4323eSThomas Huth     add_qpci_address(&opts, &addr);
118*1cf4323eSThomas Huth     qos_node_create_driver("virtio-blk-pci", virtio_blk_pci_create);
119*1cf4323eSThomas Huth     qos_node_consumes("virtio-blk-pci", "pci-bus", &opts);
120*1cf4323eSThomas Huth     qos_node_produces("virtio-blk-pci", "virtio-blk");
121*1cf4323eSThomas Huth 
122*1cf4323eSThomas Huth     g_free(arg);
123*1cf4323eSThomas Huth }
124*1cf4323eSThomas Huth 
125*1cf4323eSThomas Huth libqos_init(virtio_blk_register_nodes);
126