Skip to content

Commit 7687a3d

Browse files
xiaoguangwulijinxia
authored andcommitted
DM USB: xHCI: support bulk and interrupt transfer for port mapper
Support USB mouse, USB keyboard and USB flash drive by enabling the USB bulk and interrupt transfer for port mapper. Change-Id: Ia202729e0cfb26fb44a6b278cf4306f2b0b6fa36 Signed-off-by: Wu, Xiaoguang <xiaoguang.wu@intel.com> Reviewed-by: Shuo Liu <shuo.a.liu@intel.com> Reviewed-by: Yu Wang <yu1.wang@intel.com> Reviewed-by: Zhao Yakui <yakui.zhao@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
1 parent 3b63927 commit 7687a3d

File tree

5 files changed

+409
-24
lines changed

5 files changed

+409
-24
lines changed

devicemodel/hw/pci/xhci.c

Lines changed: 98 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,9 @@ static void pci_xhci_dev_destroy(struct pci_xhci_dev_emu *de);
322322
static int pci_xhci_port_chg(struct pci_xhci_vdev *xdev, int port, int conn);
323323
static void pci_xhci_set_evtrb(struct xhci_trb *evtrb, uint64_t port,
324324
uint32_t errcode, uint32_t evtype);
325+
static int pci_xhci_xfer_complete(struct pci_xhci_vdev *xdev,
326+
struct usb_data_xfer *xfer, uint32_t slot, uint32_t epid,
327+
int *do_intr);
325328

326329
static int
327330
pci_xhci_native_usb_dev_conn_cb(void *hci_data, void *dev_data)
@@ -417,6 +420,56 @@ pci_xhci_native_usb_dev_disconn_cb(void *hci_data, void *dev_data)
417420
return 0;
418421
}
419422

423+
/*
424+
* return value:
425+
* = 0: succeed without interrupt
426+
* > 0: succeed with interrupt
427+
* < 0: failure
428+
*/
429+
static int
430+
pci_xhci_usb_dev_notify_cb(void *hci_data, void *udev_data)
431+
{
432+
int slot, epid, intr, rc;
433+
struct usb_data_xfer *xfer;
434+
struct pci_xhci_dev_emu *edev;
435+
struct pci_xhci_vdev *xdev;
436+
437+
xfer = udev_data;
438+
if (!xfer)
439+
return -1;
440+
441+
epid = xfer->epid;
442+
edev = xfer->dev;
443+
if (!edev)
444+
return -1;
445+
446+
xdev = edev->xdev;
447+
if (!xdev)
448+
return -1;
449+
450+
slot = edev->hci.hci_address;
451+
rc = pci_xhci_xfer_complete(xdev, xfer, slot, epid, &intr);
452+
453+
if (rc)
454+
return -1;
455+
else if (intr)
456+
return 1;
457+
else
458+
return 0;
459+
}
460+
461+
static int
462+
pci_xhci_usb_dev_intr_cb(void *hci_data, void *udev_data)
463+
{
464+
struct pci_xhci_dev_emu *edev;
465+
466+
edev = hci_data;
467+
if (edev && edev->xdev)
468+
pci_xhci_assert_interrupt(edev->xdev);
469+
470+
return 0;
471+
}
472+
420473
static struct pci_xhci_dev_emu*
421474
pci_xhci_dev_create(struct pci_xhci_vdev *xdev, void *dev_data)
422475
{
@@ -432,15 +485,22 @@ pci_xhci_dev_create(struct pci_xhci_vdev *xdev, void *dev_data)
432485
if (!ue)
433486
return NULL;
434487

435-
/* TODO: following function pointers will be populated in future */
488+
/*
489+
* TODO: at present, the following functions are
490+
* enough. But for the purpose to be compatible with
491+
* usb_mouse.c, the high level design including the
492+
* function interface should be changed and refined
493+
* in future.
494+
*/
436495
ue->ue_init = usb_dev_init;
437496
ue->ue_request = usb_dev_request;
438-
ue->ue_data = NULL;
497+
ue->ue_data = usb_dev_data;
439498
ue->ue_info = usb_dev_info;
440499
ue->ue_reset = usb_dev_reset;
441500
ue->ue_remove = NULL;
442501
ue->ue_stop = NULL;
443502
ue->ue_deinit = usb_dev_deinit;
503+
ue->ue_devtype = USB_DEV_PORT_MAPPER;
444504

445505
ud = ue->ue_init(dev_data, NULL);
446506
if (!ud)
@@ -489,10 +549,16 @@ pci_xhci_dev_destroy(struct pci_xhci_dev_emu *de)
489549
ue = de->dev_ue;
490550
ud = de->dev_instance;
491551
if (ue) {
492-
assert(ue->ue_deinit);
493-
ue->ue_deinit(ud);
552+
if (ue->ue_devtype == USB_DEV_PORT_MAPPER) {
553+
assert(ue->ue_deinit);
554+
if (ue->ue_deinit)
555+
ue->ue_deinit(ud);
556+
}
494557
}
495-
free(ue);
558+
559+
if (ue->ue_devtype == USB_DEV_PORT_MAPPER)
560+
free(ue);
561+
496562
free(de);
497563
}
498564
}
@@ -879,9 +945,11 @@ pci_xhci_init_ep(struct pci_xhci_dev_emu *dev, int epid)
879945

880946
if (devep->ep_xfer == NULL) {
881947
devep->ep_xfer = malloc(sizeof(struct usb_data_xfer));
882-
if (devep->ep_xfer)
948+
if (devep->ep_xfer) {
883949
USB_DATA_XFER_INIT(devep->ep_xfer);
884-
else
950+
devep->ep_xfer->dev = (void *)dev;
951+
devep->ep_xfer->epid = epid;
952+
} else
885953
return -1;
886954
}
887955
return 0;
@@ -1821,6 +1889,7 @@ pci_xhci_xfer_complete(struct pci_xhci_vdev *xdev,
18211889
}
18221890

18231891
xfer->ndata--;
1892+
xfer->head = (xfer->head + 1) % USB_MAX_XFER_BLOCKS;
18241893
edtla += xfer->data[i].bdone;
18251894

18261895
trb->dwTrb3 = (trb->dwTrb3 & ~0x1) | (xfer->data[i].ccs);
@@ -1929,7 +1998,12 @@ pci_xhci_try_usb_xfer(struct pci_xhci_vdev *xdev,
19291998
if (USB_DATA_GET_ERRCODE(&xfer->data[xfer->head]) ==
19301999
USB_NAK)
19312000
err = XHCI_TRB_ERROR_SUCCESS;
1932-
} else {
2001+
}
2002+
/*
2003+
* Only for usb_mouse.c, emulation with port mapping will do it
2004+
* by the libusb callback function.
2005+
*/
2006+
else if (dev->dev_ue->ue_devtype == USB_DEV_STATIC) {
19332007
err = pci_xhci_xfer_complete(xdev, xfer, slot, epid,
19342008
&do_intr);
19352009
if (err == XHCI_TRB_ERROR_SUCCESS && do_intr)
@@ -2050,13 +2124,12 @@ pci_xhci_handle_transfer(struct pci_xhci_vdev *xdev,
20502124
/* fall through */
20512125

20522126
case XHCI_TRB_TYPE_DATA_STAGE:
2053-
xfer_block =
2054-
usb_data_xfer_append(xfer, (void *)(trbflags &
2055-
XHCI_TRB_3_IDT_BIT ?
2056-
&trb->qwTrb0 :
2057-
XHCI_GADDR(xdev,
2058-
trb->qwTrb0)),
2059-
trb->dwTrb2 & 0x1FFFF, (void *)addr, ccs);
2127+
xfer_block = usb_data_xfer_append(xfer,
2128+
(void *)(trbflags & XHCI_TRB_3_IDT_BIT ?
2129+
&trb->qwTrb0 :
2130+
XHCI_GADDR(xdev, trb->qwTrb0)),
2131+
trb->dwTrb2 & 0x1FFFF, (void *)addr,
2132+
ccs);
20602133
break;
20612134

20622135
case XHCI_TRB_TYPE_STATUS_STAGE:
@@ -2200,8 +2273,14 @@ pci_xhci_device_doorbell(struct pci_xhci_vdev *xdev,
22002273
if (ep_ctx->qwEpCtx2 == 0)
22012274
return;
22022275

2276+
/*
2277+
* In USB emulation with port mapping, the following transfer should
2278+
* NOT be called, or else the interrupt transfer will result
2279+
* of invalid and infinite loop. It is used by usb_mouse.c only.
2280+
*/
22032281
/* handle pending transfers */
2204-
if (devep->ep_xfer->ndata > 0) {
2282+
if (dev->dev_ue && dev->dev_ue->ue_devtype == USB_DEV_STATIC &&
2283+
devep->ep_xfer->ndata > 0) {
22052284
pci_xhci_try_usb_xfer(xdev, dev, devep, ep_ctx, slot, epid);
22062285
return;
22072286
}
@@ -3090,10 +3169,10 @@ pci_xhci_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
30903169
if (xdev->ndevices == 0)
30913170
if (usb_dev_sys_init(pci_xhci_native_usb_dev_conn_cb,
30923171
pci_xhci_native_usb_dev_disconn_cb,
3093-
NULL, NULL, xdev,
3094-
usb_get_log_level()) < 0) {
3172+
pci_xhci_usb_dev_notify_cb,
3173+
pci_xhci_usb_dev_intr_cb,
3174+
xdev, usb_get_log_level()) < 0)
30953175
goto done;
3096-
}
30973176

30983177
xdev->caplength = XHCI_SET_CAPLEN(XHCI_CAPLEN) |
30993178
XHCI_SET_HCIVERSION(0x0100);

devicemodel/hw/platform/usb_mouse.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,7 @@ struct usb_devemu ue_mouse = {
809809
.ue_emu = "tablet",
810810
.ue_usbver = 3,
811811
.ue_usbspeed = USB_SPEED_HIGH,
812+
.ue_devtype = USB_DEV_STATIC,
812813
.ue_init = umouse_init,
813814
.ue_request = umouse_request,
814815
.ue_data = umouse_data_handler,

0 commit comments

Comments
 (0)