| 
									
										
										
										
											2018-07-31 11:17:38 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * libqos driver framework | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This library is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU Lesser General Public | 
					
						
							| 
									
										
										
										
											2020-06-05 12:02:42 +02:00
										 |  |  |  * License version 2.1 as published by the Free Software Foundation. | 
					
						
							| 
									
										
										
										
											2018-07-31 11:17:38 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
					
						
							|  |  |  |  * Lesser General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License along with this library; if not, see <http://www.gnu.org/licenses/>
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "qemu/osdep.h"
 | 
					
						
							| 
									
										
										
										
											2022-03-30 13:39:05 +04:00
										 |  |  | #include "../libqtest.h"
 | 
					
						
							| 
									
										
										
										
											2019-05-23 16:35:07 +02:00
										 |  |  | #include "qemu/module.h"
 | 
					
						
							| 
									
										
										
										
											2018-07-31 11:17:38 +02:00
										 |  |  | #include "standard-headers/linux/virtio_ids.h"
 | 
					
						
							| 
									
										
										
										
											2020-08-04 20:00:40 +02:00
										 |  |  | #include "qgraph.h"
 | 
					
						
							|  |  |  | #include "virtio-scsi.h"
 | 
					
						
							| 
									
										
										
										
											2018-07-31 11:17:38 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* virtio-scsi-device */ | 
					
						
							|  |  |  | static void *qvirtio_scsi_get_driver(QVirtioSCSI *v_scsi, | 
					
						
							|  |  |  |                                      const char *interface) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!g_strcmp0(interface, "virtio-scsi")) { | 
					
						
							|  |  |  |         return v_scsi; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!g_strcmp0(interface, "virtio")) { | 
					
						
							|  |  |  |         return v_scsi->vdev; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fprintf(stderr, "%s not present in virtio-scsi-device\n", interface); | 
					
						
							|  |  |  |     g_assert_not_reached(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void *qvirtio_scsi_device_get_driver(void *object, | 
					
						
							|  |  |  |                                             const char *interface) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QVirtioSCSIDevice *v_scsi = object; | 
					
						
							|  |  |  |     return qvirtio_scsi_get_driver(&v_scsi->scsi, interface); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void *virtio_scsi_device_create(void *virtio_dev, | 
					
						
							|  |  |  |                                           QGuestAllocator *t_alloc, | 
					
						
							|  |  |  |                                           void *addr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QVirtioSCSIDevice *virtio_bdevice = g_new0(QVirtioSCSIDevice, 1); | 
					
						
							|  |  |  |     QVirtioSCSI *interface = &virtio_bdevice->scsi; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     interface->vdev = virtio_dev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtio_bdevice->obj.get_driver = qvirtio_scsi_device_get_driver; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return &virtio_bdevice->obj; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* virtio-scsi-pci */ | 
					
						
							|  |  |  | static void *qvirtio_scsi_pci_get_driver(void *object, | 
					
						
							|  |  |  |                                          const char *interface) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QVirtioSCSIPCI *v_scsi = object; | 
					
						
							|  |  |  |     if (!g_strcmp0(interface, "pci-device")) { | 
					
						
							|  |  |  |         return v_scsi->pci_vdev.pdev; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return qvirtio_scsi_get_driver(&v_scsi->scsi, interface); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void *virtio_scsi_pci_create(void *pci_bus, | 
					
						
							|  |  |  |                                     QGuestAllocator *t_alloc, | 
					
						
							|  |  |  |                                     void *addr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QVirtioSCSIPCI *virtio_spci = g_new0(QVirtioSCSIPCI, 1); | 
					
						
							|  |  |  |     QVirtioSCSI *interface = &virtio_spci->scsi; | 
					
						
							|  |  |  |     QOSGraphObject *obj = &virtio_spci->pci_vdev.obj; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtio_pci_init(&virtio_spci->pci_vdev, pci_bus, addr); | 
					
						
							|  |  |  |     interface->vdev = &virtio_spci->pci_vdev.vdev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     g_assert_cmphex(interface->vdev->device_type, ==, VIRTIO_ID_SCSI); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     obj->get_driver = qvirtio_scsi_pci_get_driver; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return obj; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void virtio_scsi_register_nodes(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QPCIAddress addr = { | 
					
						
							|  |  |  |         .devfn = QPCI_DEVFN(4, 0), | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QOSGraphEdgeOptions opts = { | 
					
						
							| 
									
										
										
										
											2019-07-29 15:46:00 +03:00
										 |  |  |         .before_cmd_line = "-drive id=drv0,if=none,file=null-co://," | 
					
						
							|  |  |  |                            "file.read-zeroes=on,format=raw", | 
					
						
							| 
									
										
										
										
											2018-07-31 11:17:38 +02:00
										 |  |  |         .after_cmd_line = "-device scsi-hd,bus=vs0.0,drive=drv0", | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* virtio-scsi-device */ | 
					
						
							|  |  |  |     opts.extra_device_opts = "id=vs0"; | 
					
						
							|  |  |  |     qos_node_create_driver("virtio-scsi-device", | 
					
						
							|  |  |  |                             virtio_scsi_device_create); | 
					
						
							|  |  |  |     qos_node_consumes("virtio-scsi-device", "virtio-bus", &opts); | 
					
						
							|  |  |  |     qos_node_produces("virtio-scsi-device", "virtio-scsi"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* virtio-scsi-pci */ | 
					
						
							|  |  |  |     opts.extra_device_opts = "id=vs0,addr=04.0"; | 
					
						
							|  |  |  |     add_qpci_address(&opts, &addr); | 
					
						
							|  |  |  |     qos_node_create_driver("virtio-scsi-pci", virtio_scsi_pci_create); | 
					
						
							|  |  |  |     qos_node_consumes("virtio-scsi-pci", "pci-bus", &opts); | 
					
						
							|  |  |  |     qos_node_produces("virtio-scsi-pci", "pci-device"); | 
					
						
							|  |  |  |     qos_node_produces("virtio-scsi-pci", "virtio-scsi"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | libqos_init(virtio_scsi_register_nodes); |