@@ -373,7 +373,10 @@ struct pci_xhci_vdev {
373
373
int (* excap_write )(struct pci_xhci_vdev * , uint64_t , uint64_t );
374
374
int usb2_port_start ;
375
375
int usb3_port_start ;
376
- uint8_t port_map_tbl [USB_NATIVE_NUM_BUS ][USB_NATIVE_NUM_PORT ];
376
+
377
+ uint16_t port_map_tbl [USB_NATIVE_NUM_BUS ][USB_NATIVE_NUM_PORT ];
378
+ struct usb_native_devinfo
379
+ native_dev_info [USB_NATIVE_NUM_BUS ][USB_NATIVE_NUM_PORT ];
377
380
struct timespec mf_prev_time ; /* previous time of accessing MFINDEX */
378
381
};
379
382
@@ -385,8 +388,16 @@ struct pci_xhci_vdev {
385
388
#define XHCI_GADDR (xdev , a ) paddr_guest2host((xdev)->dev->vmctx, (a), \
386
389
XHCI_PADDR_SZ - ((a) & (XHCI_PADDR_SZ-1)))
387
390
391
+ /* port mapping status */
388
392
#define VPORT_FREE (0)
389
- #define VPORT_ASSIGNED (-1)
393
+ #define VPORT_ASSIGNED (1)
394
+ #define VPORT_CONNECTED (2)
395
+ #define VPORT_EMULATED (3)
396
+
397
+ /* helpers for get port mapping information */
398
+ #define VPORT_NUM (state ) (state & 0xFF)
399
+ #define VPORT_STATE (state ) ((state >> 8) & 0xFF)
400
+ #define VPORT_NUM_STATE (status , num ) (((status & 0xFF) << 8) | (num & 0xFF))
390
401
391
402
struct pci_xhci_option_elem {
392
403
char * parse_opt ;
@@ -470,91 +481,65 @@ static struct pci_xhci_option_elem xhci_option_table[] = {
470
481
static int
471
482
pci_xhci_native_usb_dev_conn_cb (void * hci_data , void * dev_data )
472
483
{
473
- struct pci_xhci_dev_emu * de ;
474
484
struct pci_xhci_vdev * xdev ;
475
- struct usb_devemu * ue ;
476
485
struct usb_native_devinfo * di ;
477
- int port_start , port_end ;
478
- int slot_start , slot_end ;
479
- int port , slot ;
480
- void * ud ;
486
+ int vport_start , vport_end ;
487
+ int port ;
481
488
482
489
xdev = hci_data ;
483
- di = dev_data ;
484
490
485
491
assert (xdev );
486
492
assert (dev_data );
487
493
assert (xdev -> devices );
488
494
assert (xdev -> slots );
489
495
490
- de = pci_xhci_dev_create (xdev , di );
491
- if (!de ) {
492
- UPRINTF (LFTL , "fail to create device\r\n" );
493
- return -1 ;
494
- }
495
-
496
- /* find free port and slot for the new usb device */
497
- ud = de -> dev_instance ;
498
- ue = de -> dev_ue ;
499
-
500
- assert (ud );
501
- assert (ue );
496
+ di = dev_data ;
502
497
503
498
/* print physical information about new device */
504
499
UPRINTF (LDBG , "%04x:%04x %d-%d connecting.\r\n" ,
505
500
di -> vid , di -> pid , di -> bus , di -> port );
506
501
507
- if (xdev -> port_map_tbl [di -> bus ][di -> port ] == VPORT_FREE ) {
502
+ if (VPORT_STATE (xdev -> port_map_tbl [di -> bus ][di -> port ]) ==
503
+ VPORT_FREE ) {
508
504
UPRINTF (LDBG , "%04x:%04x %d-%d doesn't belong to this vm, bye."
509
505
"\r\n" , di -> vid , di -> pid , di -> bus , di -> port );
510
506
goto errout ;
511
507
}
512
-
513
508
UPRINTF (LDBG , "%04x:%04x %d-%d belong to this vm.\r\n" , di -> vid ,
514
509
di -> pid , di -> bus , di -> port );
515
510
516
- if (di -> bcd < 0x300 )
517
- port_start = xdev -> usb2_port_start ;
518
- else
519
- port_start = xdev -> usb3_port_start ;
520
-
521
- slot_start = 1 ;
522
- port_end = port_start + (XHCI_MAX_DEVS / 2 );
523
- slot_end = XHCI_MAX_SLOTS ;
511
+ if (di -> bcd < 0x300 ) {
512
+ vport_start = xdev -> usb2_port_start ;
513
+ vport_end = vport_start + (XHCI_MAX_DEVS / 2 );
514
+ } else {
515
+ vport_start = xdev -> usb3_port_start ;
516
+ vport_end = vport_start + (XHCI_MAX_DEVS / 2 );
517
+ }
524
518
525
519
/* find free port */
526
- for (port = port_start ; port < port_end ; port ++ )
520
+ for (port = vport_start ; port < vport_end ; port ++ )
527
521
if (!xdev -> devices [port ])
528
522
break ;
529
523
530
- /* find free slot */
531
- for (slot = slot_start ; slot < slot_end ; slot ++ )
532
- if (!xdev -> slots [slot ])
533
- break ;
534
-
535
- if (port >= port_end || slot >= slot_end ) {
536
- UPRINTF (LFTL , "no free resource: port %d slot %d\r\n" ,
537
- port , slot );
524
+ if (port >= vport_end ) {
525
+ UPRINTF (LFTL , "no free virtual port for native device %d-%d"
526
+ "\r\n" , di -> bus , di -> port );
538
527
goto errout ;
539
528
}
540
529
541
- /* use index of devices as port number */
542
- xdev -> devices [port ] = de ;
543
- xdev -> slots [slot ] = de ;
544
- xdev -> ndevices ++ ;
530
+ UPRINTF (LDBG , "%04X:%04X %d-%d is attached to virtual port %d.\r\n" ,
531
+ di -> vid , di -> pid , di -> bus , di -> port , port );
545
532
546
- pci_xhci_reset_slot (xdev , slot );
547
- UPRINTF (LDBG , "%X:%X %d-%d locates in slot %d port %d.\r\n" ,
548
- di -> vid , di -> pid , di -> bus , di -> port ,
549
- slot , port );
533
+ xdev -> native_dev_info [di -> bus ][di -> port ] = * di ;
534
+ xdev -> port_map_tbl [di -> bus ][di -> port ] =
535
+ VPORT_NUM_STATE (VPORT_CONNECTED , port );
550
536
551
537
/* Trigger port change event for the arriving device */
552
538
if (pci_xhci_connect_port (xdev , port , di -> speed , 1 ))
553
539
UPRINTF (LFTL , "fail to report port event\n" );
554
540
555
541
return 0 ;
556
542
errout :
557
- pci_xhci_dev_destroy (de );
558
543
return -1 ;
559
544
}
560
545
@@ -563,8 +548,10 @@ pci_xhci_native_usb_dev_disconn_cb(void *hci_data, void *dev_data)
563
548
{
564
549
struct pci_xhci_vdev * xdev ;
565
550
struct pci_xhci_dev_emu * edev ;
551
+ struct usb_native_devinfo di ;
566
552
struct usb_dev * udev ;
567
- uint8_t port , native_port ;
553
+ uint8_t port , slot , native_port ;
554
+ uint8_t status ;
568
555
569
556
assert (hci_data );
570
557
assert (dev_data );
@@ -584,15 +571,28 @@ pci_xhci_native_usb_dev_disconn_cb(void *hci_data, void *dev_data)
584
571
continue ;
585
572
586
573
udev = edev -> dev_instance ;
587
- if (udev -> info .port == native_port )
574
+ if (udev -> info .port == native_port ) {
575
+ di = udev -> info ;
588
576
break ;
577
+ }
589
578
}
590
579
591
580
if (port == XHCI_MAX_DEVS + 1 ) {
592
581
UPRINTF (LFTL , "fail to find physical port %d\r\n" , native_port );
593
582
return -1 ;
594
583
}
595
584
585
+ for (slot = 1 ; slot < XHCI_MAX_SLOTS ; ++ slot )
586
+ if (xdev -> slots [slot ] == edev )
587
+ break ;
588
+
589
+ assert (slot < USB_NATIVE_NUM_BUS );
590
+
591
+ status = VPORT_STATE (xdev -> port_map_tbl [di .bus ][di .port ]);
592
+ assert (status == VPORT_EMULATED || status == VPORT_CONNECTED );
593
+ xdev -> port_map_tbl [di .bus ][di .port ] = VPORT_NUM_STATE (VPORT_ASSIGNED ,
594
+ 0 );
595
+
596
596
UPRINTF (LDBG , "report virtual port %d status\r\n" , port );
597
597
if (pci_xhci_disconnect_port (xdev , port , 1 )) {
598
598
UPRINTF (LFTL , "fail to report event\r\n" );
@@ -1393,28 +1393,67 @@ pci_xhci_insert_event(struct pci_xhci_vdev *xdev,
1393
1393
return err ;
1394
1394
}
1395
1395
1396
+ static struct usb_native_devinfo *
1397
+ pci_xhci_find_native_devinfo (struct pci_xhci_vdev * xdev )
1398
+ {
1399
+ int i , j ;
1400
+
1401
+ assert (xdev );
1402
+ for (i = 0 ; i < USB_NATIVE_NUM_BUS ; ++ i )
1403
+ for (j = 0 ; j < USB_NATIVE_NUM_PORT ; ++ j )
1404
+ if (VPORT_STATE (xdev -> port_map_tbl [i ][j ]) ==
1405
+ VPORT_CONNECTED )
1406
+ return & xdev -> native_dev_info [i ][j ];
1407
+
1408
+ return NULL ;
1409
+ }
1410
+
1396
1411
static uint32_t
1397
1412
pci_xhci_cmd_enable_slot (struct pci_xhci_vdev * xdev , uint32_t * slot )
1398
1413
{
1399
1414
struct pci_xhci_dev_emu * dev ;
1400
- uint32_t cmderr ;
1401
- int i ;
1415
+ uint32_t cmderr ;
1416
+ struct usb_native_devinfo * di ;
1417
+ int i , vport ;
1402
1418
1403
1419
cmderr = XHCI_TRB_ERROR_NO_SLOTS ;
1404
- if (xdev -> portregs != NULL )
1405
- for (i = 1 ; i <= XHCI_MAX_SLOTS ; i ++ ) {
1406
- dev = XHCI_SLOTDEV_PTR (xdev , i );
1407
- if (dev && dev -> dev_slotstate == XHCI_ST_DISABLED ) {
1408
- * slot = i ;
1409
- dev -> dev_slotstate = XHCI_ST_ENABLED ;
1410
- cmderr = XHCI_TRB_ERROR_SUCCESS ;
1411
- dev -> hci .hci_address = i ;
1412
- break ;
1413
- }
1420
+
1421
+ di = pci_xhci_find_native_devinfo (xdev );
1422
+ if (!di ) {
1423
+ UPRINTF (LWRN , "unexpected Enable Slot commnad\r\n" );
1424
+ return -1 ;
1425
+ }
1426
+
1427
+ assert (di -> priv_data );
1428
+ dev = pci_xhci_dev_create (xdev , di );
1429
+ if (!dev ) {
1430
+ UPRINTF (LFTL , "fail to create device\r\n" );
1431
+ return -1 ;
1432
+ }
1433
+
1434
+ vport = VPORT_NUM (xdev -> port_map_tbl [di -> bus ][di -> port ]);
1435
+ assert (vport > 0 );
1436
+ assert (!xdev -> devices [vport ]);
1437
+
1438
+ xdev -> devices [vport ] = dev ;
1439
+ xdev -> ndevices ++ ;
1440
+
1441
+ for (i = 1 ; i <= XHCI_MAX_SLOTS ; i ++ ) {
1442
+ if (XHCI_SLOTDEV_PTR (xdev , i ) == NULL ) {
1443
+ xdev -> slots [i ] = dev ;
1444
+ * slot = i ;
1445
+ dev -> dev_slotstate = XHCI_ST_ENABLED ;
1446
+ cmderr = XHCI_TRB_ERROR_SUCCESS ;
1447
+ dev -> hci .hci_address = i ;
1448
+ xdev -> port_map_tbl [di -> bus ][di -> port ] =
1449
+ VPORT_NUM_STATE (VPORT_EMULATED , vport );
1450
+ break ;
1414
1451
}
1452
+ }
1415
1453
1416
- UPRINTF (LDBG , "enable slot (error=%d) slot %u\r\n" ,
1417
- cmderr != XHCI_TRB_ERROR_SUCCESS , * slot );
1454
+ UPRINTF (LDBG , "enable slot (error=%d) slot %u for native device "
1455
+ "%d-%d\r\n" , cmderr != XHCI_TRB_ERROR_SUCCESS , * slot ,
1456
+ di -> bus , di -> port );
1418
1457
1419
1458
return cmderr ;
1420
1459
}
@@ -1423,6 +1462,8 @@ static uint32_t
1423
1462
pci_xhci_cmd_disable_slot (struct pci_xhci_vdev * xdev , uint32_t slot )
1424
1463
{
1425
1464
struct pci_xhci_dev_emu * dev ;
1465
+ struct usb_dev * udev ;
1466
+ struct usb_native_devinfo * di ;
1426
1467
uint32_t cmderr ;
1427
1468
int i ;
1428
1469
@@ -1446,6 +1487,9 @@ pci_xhci_cmd_disable_slot(struct pci_xhci_vdev *xdev, uint32_t slot)
1446
1487
cmderr = XHCI_TRB_ERROR_SUCCESS ;
1447
1488
/* TODO: reset events and endpoints */
1448
1489
}
1490
+ } else {
1491
+ UPRINTF (LDBG , "disable NULL device, slot %d\r\n" , slot );
1492
+ goto done ;
1449
1493
}
1450
1494
1451
1495
for (i = 1 ; i <= XHCI_MAX_DEVS ; ++ i )
@@ -1455,8 +1499,20 @@ pci_xhci_cmd_disable_slot(struct pci_xhci_vdev *xdev, uint32_t slot)
1455
1499
if (i <= XHCI_MAX_DEVS && XHCI_PORTREG_PTR (xdev , i )) {
1456
1500
XHCI_PORTREG_PTR (xdev , i )-> portsc &= ~(XHCI_PS_CSC |
1457
1501
XHCI_PS_CCS | XHCI_PS_PED | XHCI_PS_PP );
1502
+
1503
+ udev = dev -> dev_instance ;
1504
+ assert (udev );
1505
+
1458
1506
xdev -> devices [i ] = NULL ;
1459
1507
xdev -> slots [slot ] = NULL ;
1508
+
1509
+ di = & udev -> info ;
1510
+ xdev -> port_map_tbl [di -> bus ][di -> port ] =
1511
+ VPORT_NUM_STATE (VPORT_ASSIGNED , 0 );
1512
+
1513
+ UPRINTF (LINF , "disable slot %d for native device %d-%d"
1514
+ "\r\n" , slot , di -> bus , di -> port );
1515
+
1460
1516
pci_xhci_dev_destroy (dev );
1461
1517
} else
1462
1518
UPRINTF (LWRN , "invalid slot %d\r\n" , slot );
@@ -1624,7 +1680,10 @@ pci_xhci_cmd_config_ep(struct pci_xhci_vdev *xdev,
1624
1680
UPRINTF (LDBG , "config_ep slot %u\r\n" , slot );
1625
1681
1626
1682
dev = XHCI_SLOTDEV_PTR (xdev , slot );
1627
- assert (dev != NULL );
1683
+ if (dev == NULL ) {
1684
+ cmderr = XHCI_TRB_ERROR_SLOT_NOT_ON ;
1685
+ goto done ;
1686
+ }
1628
1687
1629
1688
if ((trb -> dwTrb3 & XHCI_TRB_3_DCEP_BIT ) != 0 ) {
1630
1689
UPRINTF (LDBG , "config_ep - deconfigure ep slot %u\r\n" , slot );
@@ -3364,7 +3423,10 @@ pci_xhci_parse_bus_port(struct pci_xhci_vdev *xdev, char *opts)
3364
3423
goto errout ;
3365
3424
}
3366
3425
3367
- xdev -> port_map_tbl [bus ][port ] = VPORT_ASSIGNED ;
3426
+ xdev -> port_map_tbl [bus ][port ] =
3427
+ VPORT_NUM_STATE (VPORT_ASSIGNED , 0 );
3428
+ return 0 ;
3429
+
3368
3430
errout :
3369
3431
if (rc )
3370
3432
UPRINTF (LWRN , "%s fails, rc=%d\r\n" , __func__ , rc );
0 commit comments