From 5e829d5da058462782b59d7ecbc7c760407b3dc4 Mon Sep 17 00:00:00 2001 From: songyanguang <345810377@qq.com> Date: Tue, 6 Aug 2024 14:44:05 +0800 Subject: [PATCH] Modify Transfer TRB code in xHCI to apply to XiZi AIOT. --- .../usb/components/port/xhci/usb_hc_xhci.c | 77 ++++++++++++++++++- .../drivers/usb/components/port/xhci/xhci.c | 36 +++++---- .../drivers/usb/components/port/xhci/xhci.h | 4 + 3 files changed, 102 insertions(+), 15 deletions(-) diff --git a/Ubiquitous/XiZi_AIoT/services/drivers/usb/components/port/xhci/usb_hc_xhci.c b/Ubiquitous/XiZi_AIoT/services/drivers/usb/components/port/xhci/usb_hc_xhci.c index 57fea8451..f3f081016 100644 --- a/Ubiquitous/XiZi_AIoT/services/drivers/usb/components/port/xhci/usb_hc_xhci.c +++ b/Ubiquitous/XiZi_AIoT/services/drivers/usb/components/port/xhci/usb_hc_xhci.c @@ -859,6 +859,9 @@ int xhci_usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_c struct usbh_hubport *hport = ep_cfg->hport; struct xhci_endpoint *ppipe = usb_align(XHCI_RING_SIZE, sizeof(struct xhci_endpoint)); struct xhci_slot *slot; + uintptr_t ring_vir; + uintptr_t ring_phy; + size_t len; if (NULL == ppipe) { return -ENOMEM; @@ -877,6 +880,19 @@ int xhci_usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_c ppipe->ep_type = ep_cfg->ep_type; ppipe->burst = 0U; + /* Allocate xHCI ring */ + len = sizeof(*ppipe->ep_reqs); + rc = naive_mmap(&ring_vir, &ring_phy, len, false); + if(rc != 0){ + USB_LOG_ERR("XHCI %s could not allocate xhci device context\n", xhci->name ); + rc = -ENOMEM; + goto failed; + } + ppipe->ep_reqs_vir = ring_vir; + ppipe->ep_reqs_phy = ring_phy; + ppipe->ep_reqs = (struct xhci_ring *)ring_vir; + memset ( ppipe->ep_reqs, 0, len ); + if (ppipe->address == 0) { /* if try to allocate ctrl ep, open device first */ USB_LOG_DBG("allocate device for port-%d \r\n", hport->port); rc = xhci_device_open(xhci, ppipe, &slot_id); @@ -943,7 +959,66 @@ int xhci_usbh_pipe_free(usbh_pipe_t pipe){ int xhci_usbh_submit_urb(struct usbh_urb *urb){ - return 0; + int ret = 0; + if (!urb || !urb->pipe) { + return -EINVAL; + } + + struct xhci_endpoint *ppipe = (struct xhci_endpoint *)urb->pipe; + struct xhci_host *xhci = ppipe->xhci; + struct usb_setup_packet *setup = urb->setup; + size_t flags = usb_osal_enter_critical_section(); + + urb->errorcode = -EBUSY; + urb->actual_length = 0U; + + ppipe->urb = urb; + ppipe->timeout = urb->timeout; + if (ppipe->timeout > 0) { + ppipe->waiter = true; + } else { + ppipe->waiter = false; + } + + usb_osal_leave_critical_section(flags); + switch (ppipe->ep_type) { + case USB_ENDPOINT_TYPE_CONTROL: + USB_ASSERT(setup); + if (setup->bRequest == USB_REQUEST_SET_ADDRESS) { + /* Set address command sent during xhci_alloc_pipe. */ + goto skip_req; + } + + USB_LOG_DBG("%s request-%d.\n", __func__, setup->bRequest); + xhci_endpoint_message(ppipe, setup, urb->transfer_buffer, urb->transfer_buffer_length); + break; + case USB_ENDPOINT_TYPE_INTERRUPT: + case USB_ENDPOINT_TYPE_BULK: + xhci_endpoint_stream(ppipe, urb->transfer_buffer, urb->transfer_buffer_length); + break; + default: + USB_ASSERT(0U); + break; + } + + /* wait all ring handled by xHc */ +// int cc = xhci_event_wait(xhci, ppipe, &ppipe->reqs); + int cc = xhci_event_wait(xhci, ppipe, ppipe->ep_reqs); + if ((cc != XHCI_CMPLT_SUCCESS) && + !((cc == XHCI_CMPLT_TIMEOUT) && (ppipe->ep_type == USB_ENDPOINT_TYPE_INTERRUPT))) + { + /* ignore transfer timeout for interrupt type */ + USB_LOG_ERR("%s: xfer failed (cc %d).\n", __func__, cc); + ret = -1; + urb->errorcode = cc; + goto errout_timeout; + } + +skip_req: +errout_timeout: + /* Timeout will run here */ + usbh_kill_urb(urb); + return ret; } diff --git a/Ubiquitous/XiZi_AIoT/services/drivers/usb/components/port/xhci/xhci.c b/Ubiquitous/XiZi_AIoT/services/drivers/usb/components/port/xhci/xhci.c index 408275d9a..fae28bd33 100644 --- a/Ubiquitous/XiZi_AIoT/services/drivers/usb/components/port/xhci/xhci.c +++ b/Ubiquitous/XiZi_AIoT/services/drivers/usb/components/port/xhci/xhci.c @@ -32,7 +32,7 @@ Modification: replant and redefine some xhci data structure, so that the cherryU 2. Date: 2024-08-05 Author: AIIT XUOS Lab -Modification: Modify Command TRB code to apply to XiZi AIOT. +Modification: Modify Command TRB and Transfer TRB code to apply to XiZi AIOT. *************************************************/ #include "usbh_core.h" @@ -1884,7 +1884,8 @@ static void xhci_address_device_input ( struct xhci_host *xhci, bit[63:4] tr dequeue pointer bit[0] dequeue cycle state */ - ep_ctx->dequeue = CPU_TO_LE64 ( (uint64_t)( (uintptr_t)&endpoint->reqs.ring[0] ) | XHCI_EP_DCS ); +// ep_ctx->dequeue = CPU_TO_LE64 ( (uint64_t)( (uintptr_t)&endpoint->reqs.ring[0] ) | XHCI_EP_DCS ); + ep_ctx->dequeue = CPU_TO_LE64 ( (uint64_t)( (uintptr_t)endpoint->ep_reqs_phy ) | XHCI_EP_DCS ); ep_ctx->trb_len = CPU_TO_LE16 ( XHCI_EP0_TRB_LEN ); /* bit[15:0] average trb length */ } @@ -2229,8 +2230,9 @@ static void xhci_configure_endpoint_input ( struct xhci_host *xhci, ep_ctx->type = endpoint->ctx_type; ep_ctx->burst = endpoint->burst; ep_ctx->mtu = CPU_TO_LE16 ( endpoint->mtu ); /* bit[31:16] max packet size */ - ep_ctx->dequeue = CPU_TO_LE64 ( (uint64_t)( (uintptr_t)&(endpoint->reqs.ring[0]) ) | XHCI_EP_DCS ); - +// ep_ctx->dequeue = CPU_TO_LE64 ( (uint64_t)( (uintptr_t)&(endpoint->reqs.ring[0]) ) | XHCI_EP_DCS ); + ep_ctx->dequeue = CPU_TO_LE64 ( (uint64_t)( (uintptr_t)endpoint->ep_reqs_phy ) | XHCI_EP_DCS ); + /* TODO: endpoint attached on hub may need different setting here */ if (endpoint->ep_type == USB_ENDPOINT_TYPE_BULK) { ep_ctx->trb_len = CPU_TO_LE16 ( 256U ); /* bit[15:0] average trb length */ @@ -2359,15 +2361,16 @@ int xhci_ctrl_endpoint_open ( struct xhci_host *xhci, struct xhci_slot *slot, st ep->ctx_type = XHCI_EP_TYPE_CONTROL; ep->context = ( ( ( void * ) slot->context ) + xhci_device_context_offset ( xhci, ctx ) ); - ep->reqs.cs = 1; /* cycle state = 1 */ +// ep->reqs.cs = 1; /* cycle state = 1 */ + ep->ep_reqs->cs = 1; /* cycle state = 1 */ USB_LOG_DBG("XHCI %s slot %d endpoint 0x%x ep type %d xhci ep type 0x%x\n", xhci->name, slot->id, ep->address, ep->ep_type, (ep->ctx_type >> 3) ); USB_LOG_DBG("XHCI %s slot %d ctx %d ring [%08lx,%08lx)\n", - xhci->name, slot->id, ctx, ( ep->reqs.ring ), - ( ( ep->reqs.ring ) + sizeof(ep->reqs.ring) ) ); + xhci->name, slot->id, ctx, ( ep->ep_reqs->ring ), + ( ( ep->ep_reqs->ring ) + sizeof(ep->ep_reqs->ring) ) ); return 0; } @@ -2427,7 +2430,8 @@ int xhci_work_endpoint_open ( struct xhci_host *xhci, struct xhci_slot *slot, st ep->ctx_type = ctx_type; ep->context = ( ( ( void * ) slot->context ) + xhci_device_context_offset ( xhci, ctx ) ); - ep->reqs.cs = 1; /* cycle state = 1 */ +// ep->reqs.cs = 1; /* cycle state = 1 */ + ep->ep_reqs->cs = 1; /* cycle state = 1 */ USB_LOG_DBG("XHCI %s slot %d endpoint 0x%x ep type %d xhci ep type 0x%x\n", xhci->name, slot->id, ep->address, ep->ep_type, @@ -2439,8 +2443,8 @@ int xhci_work_endpoint_open ( struct xhci_host *xhci, struct xhci_slot *slot, st } USB_LOG_DBG("XHCI %s slot %d ctx %d ring [%08lx,%08lx)\n", - xhci->name, slot->id, ctx, ( ep->reqs.ring ), - ( ( ep->reqs.ring ) + sizeof(ep->reqs.ring) ) ); + xhci->name, slot->id, ctx, ( ep->ep_reqs->ring ), + ( ( ep->ep_reqs->ring ) + sizeof(ep->ep_reqs->ring) ) ); return 0; err_configure_endpoint: @@ -2504,7 +2508,8 @@ void xhci_endpoint_message ( struct xhci_endpoint *ep, setup->direction = ( input ? XHCI_SETUP_IN : XHCI_SETUP_OUT ); } - xhci_trb_queue(&(ep->reqs), &trb); +// xhci_trb_queue(&(ep->reqs), &trb); + xhci_trb_queue(ep->ep_reqs, &trb); /* Construct data stage TRB, if applicable */ if (datalen > 0) { @@ -2516,7 +2521,8 @@ void xhci_endpoint_message ( struct xhci_endpoint *ep, data->type = XHCI_TRB_DATA; /* bit[15:10] trb type */ data->direction = ( input ? XHCI_DATA_IN : XHCI_DATA_OUT ); /* bit[16] Direction, 0 = OUT, 1 = IN */ - xhci_trb_queue(&(ep->reqs), &trb); +// xhci_trb_queue(&(ep->reqs), &trb); + xhci_trb_queue(ep->ep_reqs, &trb); } status = &(trb.status); @@ -2526,7 +2532,8 @@ void xhci_endpoint_message ( struct xhci_endpoint *ep, status->direction = ( ( datalen && input ) ? XHCI_STATUS_OUT : XHCI_STATUS_IN ); - xhci_trb_queue(&(ep->reqs), &trb); +// xhci_trb_queue(&(ep->reqs), &trb); + xhci_trb_queue(ep->ep_reqs, &trb); /* pass command trb to hardware */ // DSB(); @@ -2575,7 +2582,8 @@ void xhci_endpoint_stream ( struct xhci_endpoint *ep, normal->type = XHCI_TRB_NORMAL; normal->flags = XHCI_TRB_IOC; - xhci_trb_queue(&(ep->reqs), trb); +// xhci_trb_queue(&(ep->reqs), trb); + xhci_trb_queue(ep->ep_reqs, trb); /* pass command trb to hardware */ // DSB(); diff --git a/Ubiquitous/XiZi_AIoT/services/drivers/usb/components/port/xhci/xhci.h b/Ubiquitous/XiZi_AIoT/services/drivers/usb/components/port/xhci/xhci.h index 400ceef0d..2a43d8856 100644 --- a/Ubiquitous/XiZi_AIoT/services/drivers/usb/components/port/xhci/xhci.h +++ b/Ubiquitous/XiZi_AIoT/services/drivers/usb/components/port/xhci/xhci.h @@ -758,6 +758,10 @@ struct xhci_er_seg { /** An xHCI endpoint */ struct xhci_endpoint { struct xhci_ring reqs; /* DO NOT MOVE reqs from structure beg */ + /** xHCI ring */ + struct xhci_ring *ep_reqs; + uintptr_t ep_reqs_vir; + uintptr_t ep_reqs_phy; /** xHCI device */ struct xhci_host *xhci; /** xHCI slot */