@ -278,6 +278,105 @@ static void pci_basic(void)
test_end ( ) ;
}
static void pci_indirect ( void )
{
QVirtioPCIDevice * dev ;
QPCIBus * bus ;
QVirtQueue * vq ;
QGuestAllocator * alloc ;
QVirtioBlkReq req ;
QVRingIndirectDesc * indirect ;
void * addr ;
uint64_t req_addr ;
uint64_t capacity ;
uint32_t features ;
uint32_t free_head ;
uint8_t status ;
char * data ;
bus = test_start ( ) ;
dev = virtio_blk_init ( bus ) ;
/* MSI-X is not enabled */
addr = dev - > addr + QVIRTIO_DEVICE_SPECIFIC_NO_MSIX ;
capacity = qvirtio_config_readq ( & qvirtio_pci , & dev - > vdev , addr ) ;
g_assert_cmpint ( capacity , = = , TEST_IMAGE_SIZE / 512 ) ;
features = qvirtio_get_features ( & qvirtio_pci , & dev - > vdev ) ;
g_assert_cmphex ( features & QVIRTIO_F_RING_INDIRECT_DESC , ! = , 0 ) ;
features = features & ~ ( QVIRTIO_F_BAD_FEATURE | QVIRTIO_F_RING_EVENT_IDX |
QVIRTIO_BLK_F_SCSI ) ;
qvirtio_set_features ( & qvirtio_pci , & dev - > vdev , features ) ;
alloc = pc_alloc_init ( ) ;
vq = qvirtqueue_setup ( & qvirtio_pci , & dev - > vdev , alloc , 0 ) ;
qvirtio_set_driver_ok ( & qvirtio_pci , & dev - > vdev ) ;
/* Write request */
req . type = QVIRTIO_BLK_T_OUT ;
req . ioprio = 1 ;
req . sector = 0 ;
req . data = g_malloc0 ( 512 ) ;
strcpy ( req . data , " TEST " ) ;
req_addr = virtio_blk_request ( alloc , & req , 512 ) ;
g_free ( req . data ) ;
indirect = qvring_indirect_desc_setup ( & dev - > vdev , alloc , 2 ) ;
qvring_indirect_desc_add ( indirect , req_addr , 528 , false ) ;
qvring_indirect_desc_add ( indirect , req_addr + 528 , 1 , true ) ;
free_head = qvirtqueue_add_indirect ( vq , indirect ) ;
qvirtqueue_kick ( & qvirtio_pci , & dev - > vdev , vq , free_head ) ;
g_assert ( qvirtio_wait_isr ( & qvirtio_pci , & dev - > vdev , 0x1 ,
QVIRTIO_BLK_TIMEOUT ) ) ;
status = readb ( req_addr + 528 ) ;
g_assert_cmpint ( status , = = , 0 ) ;
g_free ( indirect ) ;
guest_free ( alloc , req_addr ) ;
/* Read request */
req . type = QVIRTIO_BLK_T_IN ;
req . ioprio = 1 ;
req . sector = 0 ;
req . data = g_malloc0 ( 512 ) ;
strcpy ( req . data , " TEST " ) ;
req_addr = virtio_blk_request ( alloc , & req , 512 ) ;
g_free ( req . data ) ;
indirect = qvring_indirect_desc_setup ( & dev - > vdev , alloc , 2 ) ;
qvring_indirect_desc_add ( indirect , req_addr , 16 , false ) ;
qvring_indirect_desc_add ( indirect , req_addr + 16 , 513 , true ) ;
free_head = qvirtqueue_add_indirect ( vq , indirect ) ;
qvirtqueue_kick ( & qvirtio_pci , & dev - > vdev , vq , free_head ) ;
g_assert ( qvirtio_wait_isr ( & qvirtio_pci , & dev - > vdev , 0x1 ,
QVIRTIO_BLK_TIMEOUT ) ) ;
status = readb ( req_addr + 528 ) ;
g_assert_cmpint ( status , = = , 0 ) ;
data = g_malloc0 ( 512 ) ;
memread ( req_addr + 16 , data , 512 ) ;
g_assert_cmpstr ( data , = = , " TEST " ) ;
g_free ( data ) ;
g_free ( indirect ) ;
guest_free ( alloc , req_addr ) ;
/* End test */
guest_free ( alloc , vq - > desc ) ;
qvirtio_pci_device_disable ( dev ) ;
g_free ( dev ) ;
test_end ( ) ;
}
int main ( int argc , char * * argv )
{
int ret ;
@ -285,6 +384,7 @@ int main(int argc, char **argv)
g_test_init ( & argc , & argv , NULL ) ;
g_test_add_func ( " /virtio/blk/pci/basic " , pci_basic ) ;
g_test_add_func ( " /virtio/blk/pci/indirect " , pci_indirect ) ;
ret = g_test_run ( ) ;