From owner-svn-soc-all@FreeBSD.ORG Fri Sep 27 10:47:22 2013 Return-Path: Delivered-To: svn-soc-all@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTP id D1753AA8 for ; Fri, 27 Sep 2013 10:47:22 +0000 (UTC) (envelope-from bguan@FreeBSD.org) Received: from socsvn.freebsd.org (socsvn.freebsd.org [IPv6:2001:1900:2254:206a::50:2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id B04EE227D for ; Fri, 27 Sep 2013 10:47:22 +0000 (UTC) Received: from socsvn.freebsd.org ([127.0.1.124]) by socsvn.freebsd.org (8.14.7/8.14.7) with ESMTP id r8RAlMGs091040 for ; Fri, 27 Sep 2013 10:47:22 GMT (envelope-from bguan@FreeBSD.org) Received: (from www@localhost) by socsvn.freebsd.org (8.14.7/8.14.6/Submit) id r8RAlM5W091038 for svn-soc-all@FreeBSD.org; Fri, 27 Sep 2013 10:47:22 GMT (envelope-from bguan@FreeBSD.org) Date: Fri, 27 Sep 2013 10:47:22 GMT Message-Id: <201309271047.r8RAlM5W091038@socsvn.freebsd.org> X-Authentication-Warning: socsvn.freebsd.org: www set sender to bguan@FreeBSD.org using -f From: bguan@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r257755 - soc2013/bguan/head/sys/dev/xen/usbfront MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 27 Sep 2013 10:47:22 -0000 Author: bguan Date: Fri Sep 27 10:47:22 2013 New Revision: 257755 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=257755 Log: set the pipe methods for xen usb host controller Modified: soc2013/bguan/head/sys/dev/xen/usbfront/xenhci.c Modified: soc2013/bguan/head/sys/dev/xen/usbfront/xenhci.c ============================================================================== --- soc2013/bguan/head/sys/dev/xen/usbfront/xenhci.c Fri Sep 27 10:06:14 2013 (r257754) +++ soc2013/bguan/head/sys/dev/xen/usbfront/xenhci.c Fri Sep 27 10:47:22 2013 (r257755) @@ -83,7 +83,7 @@ &xenhcidebug, 0, "Debug level"); TUNABLE_INT("hw.usb.xenhci.debug", &xenhcidebug); SYSCTL_INT(_hw_usb_xenhci, OID_AUTO, xenhci_port_route, CTLFLAG_RW | CTLFLAG_TUN, - &xenhciroute, 0, "Routing bitmap for switching EHCI ports to XENHCI controller"); + &xenhciroute, 0, "Routing bitmap for switching XENHCI ports to XENHCI controller"); TUNABLE_INT("hw.usb.xenhci.xenhci_port_route", &xenhciroute); SYSCTL_INT(_hw_usb_xenhci, OID_AUTO, use_polling, CTLFLAG_RW | CTLFLAG_TUN, &xenhcipolling, 0, "Set to enable software interrupt polling for XENHCI controller"); @@ -92,19 +92,98 @@ #define XENHCI_INTR_ENDPT 1 +struct xenhci_std_temp { + struct xenhci_softc *sc; + struct usb_page_cache *pc; + xenhci_qtd_t *td; + xenhci_qtd_t *td_next; + + uint32_t average; + uint32_t qtd_status; + uint32_t len; + uint16_t max_frame_size; + uint8_t shortpkt; + uint8_t auto_data_toggle; + uint8_t setup_alt_next; + uint8_t last_frame; +}; + + extern struct usb_bus_methods xenhci_bus_methods; extern struct usb_pipe_methods xenhci_device_generic_methods; +usb_error_t xenhci_start_controller(struct xenhci_softc *); +usb_error_t xenhci_halt_controller(struct xenhci_softc *); +static void xenhci_do_poll(struct usb_bus *); static void xenhci_timeout(void *); static void xenhci_device_done(struct usb_xfer *, usb_error_t); -/* + + static void -xenhci_iterate_hw_softc(struct usb_bus *bus, usb_bus_mem_sub_cb_t *cb) +xenhci_dump_itd(struct xenhci_softc *sc, xenhci_itd_t *itd) +{ +} + +#define XENHCI_APPEND_QH(sqh,last) (last) = _xenhci_append_qh(sqh,last) +static xenhci_qh_t * +_xenhci_append_qh(xenhci_qh_t *sqh, xenhci_qh_t *last) +{ + DPRINTFN(11, "%p to %p\n", sqh, last); + + if (sqh->prev != NULL) { + /* should not happen */ + DPRINTFN(0, "QH already linked!\n"); + return (last); + } + /* (sc->sc_bus.mtx) must be locked */ + + sqh->next = last->next; + sqh->qh_link = last->qh_link; + + sqh->prev = last; + + usb_pc_cpu_flush(sqh->page_cache); + + /* + * the last->next->prev is never followed: sqh->next->prev = sqh; + */ + + last->next = sqh; + last->qh_link = sqh->qh_self; + + usb_pc_cpu_flush(last->page_cache); + + return (sqh); +} + +#define XENHCI_APPEND_HS_TD(std,last) (last) = _xenhci_append_hs_td(std,last) +static xenhci_itd_t * +_xenhci_append_hs_td(xenhci_itd_t *std, xenhci_itd_t *last) { - //TODO need this method()? -}*/ + DPRINTFN(11, "%p to %p\n", std, last); + + /* (sc->sc_bus.mtx) must be locked */ + + std->next = last->next; + std->itd_next = last->itd_next; + + std->prev = last; + + usb_pc_cpu_flush(std->page_cache); + + /* + * the last->next->prev is never followed: std->next->prev = std; + */ + last->next = std; + last->itd_next = std->itd_self; + + usb_pc_cpu_flush(last->page_cache); + + return (std); +} +/***************************************************************/ usb_error_t xenhci_start_controller(struct xenhci_softc *sc) @@ -142,6 +221,9 @@ sc->sc_bus.devices = sc->sc_devices; sc->sc_bus.devices_max = XENHCI_MAX_DEVICES; + /* setup command queue mutex and condition varible */ + sx_init(&sc->sc_cmd_sx, "CMDQ lock"); + /* get all DMA memory */ //if (usb_bus_mem_alloc_all(&sc->sc_bus, // USB_GET_DMA_TAG(dev), &xenhci_iterate_hw_softc)) { @@ -163,6 +245,8 @@ * needed. */ usb_bus_mem_free_all(&sc->sc_bus, NULL); + + sx_destroy(&sc->sc_cmd_sx); } static void @@ -192,206 +276,6 @@ } } -static usb_error_t -xenhci_generic_done_sub(struct usb_xfer *xfer) -{ - #ifdef XENUSB_BEBUG - printf("[xenusb_debug]xenhci.c: xenhci_generic_done_sub()\n"); - #endif - - struct xenhci_td *td; - struct xenhci_td *td_alt_next; - uint32_t len; - uint8_t status; - - td = xfer->td_transfer_cache; - td_alt_next = td->alt_next; - - if (xfer->aframes != xfer->nframes) - usbd_xfer_set_frame_len(xfer, xfer->aframes, 0); - - while (1) { - - usb_pc_cpu_invalidate(td->page_cache); - - status = td->status; - len = td->remainder; - - DPRINTFN(4, "xfer=%p[%u/%u] rem=%u/%u status=%u\n", - xfer, (unsigned int)xfer->aframes, - (unsigned int)xfer->nframes, - (unsigned int)len, (unsigned int)td->len, - (unsigned int)status); - #ifdef XENUSB_BEBUG - printf("[xenusb_debug]xfer=%p[%u/%u] rem=%u/%u status=%u\n", - xfer, (unsigned int)xfer->aframes, - (unsigned int)xfer->nframes, - (unsigned int)len, (unsigned int)td->len, - (unsigned int)status); - #endif - - /* - * Verify the status length and - * add the length to "frlengths[]": - */ - if (len > td->len) { - /* should not happen */ - DPRINTF("Invalid status length, " - "0x%04x/0x%04x bytes\n", len, td->len); - - #ifdef XENUSB_BEBUG - printf("[xenusb_debug]Invalid status length, " - "0x%04x/0x%04x bytes\n", len, td->len); - #endif - - status = XENHCI_TRB_ERROR_LENGTH; - } else if (xfer->aframes != xfer->nframes) { - xfer->frlengths[xfer->aframes] += td->len - len; - } - /* Check for last transfer */ - if (((void *)td) == xfer->td_transfer_last) { - td = NULL; - break; - } - /* Check for transfer error */ - if (status != XENHCI_TRB_ERROR_SHORT_PKT && - status != XENHCI_TRB_ERROR_SUCCESS) { - /* the transfer is finished */ - td = NULL; - break; - } - /* Check for short transfer */ - if (len > 0) { - if (xfer->flags_int.short_frames_ok || - xfer->flags_int.isochronous_xfr || - xfer->flags_int.control_xfr) { - /* follow alt next */ - td = td->alt_next; - } else { - /* the transfer is finished */ - td = NULL; - } - break; - } - td = td->obj_next; - - if (td->alt_next != td_alt_next) { - /* this USB frame is complete */ - break; - } - } - - /* update transfer cache */ - - xfer->td_transfer_cache = td; - - return ((status == XENHCI_TRB_ERROR_STALL) ? USB_ERR_STALLED : - (status != XENHCI_TRB_ERROR_SHORT_PKT && - status != XENHCI_TRB_ERROR_SUCCESS) ? USB_ERR_IOERROR : - USB_ERR_NORMAL_COMPLETION); -} - -static void -xenhci_generic_done(struct usb_xfer *xfer) -{ - #ifdef XENUSB_BEBUG - printf("[xenusb_debug]xenhci.c: xenhci_generic_done()\n"); - #endif - - usb_error_t err = 0; - - DPRINTFN(13, "xfer=%p endpoint=%p transfer done\n", - xfer, xfer->endpoint); - #ifdef XENUSB_BEBUG - printf("[xenusb_debug]xfer=%p endpoint=%p transfer done\n", - xfer, xfer->endpoint); - #endif - - /* reset scanner */ - xfer->td_transfer_cache = xfer->td_transfer_first; - - if (xfer->flags_int.control_xfr) { - if (xfer->flags_int.control_hdr) - err = xenhci_generic_done_sub(xfer); - - xfer->aframes = 1; - - if (xfer->td_transfer_cache == NULL) - goto done; - } - - while (xfer->aframes != xfer->nframes) { - - err = xenhci_generic_done_sub(xfer); - xfer->aframes++; - - if (xfer->td_transfer_cache == NULL) - goto done; - } - - if (xfer->flags_int.control_xfr && - !xfer->flags_int.control_act) - err = xenhci_generic_done_sub(xfer); -done: - /* transfer is complete */ - //xhci_device_done(xfer, err); -} - -static void -xenhci_activate_transfer(struct usb_xfer *xfer) -{ - #ifdef XENUSB_BEBUG - printf("[xenusb_debug]xenhci.c: xenhci_activate_transfer()\n"); - #endif - - struct xenhci_td *td; - - td = xfer->td_transfer_cache; - - usb_pc_cpu_invalidate(td->page_cache); - - if (!(td->td_trb[0].dwTrb3 & htole32(XENHCI_TRB_3_CYCLE_BIT))) { - - /* activate the transfer */ - td->td_trb[0].dwTrb3 |= htole32(XENHCI_TRB_3_CYCLE_BIT); - usb_pc_cpu_flush(td->page_cache); - - //xhci_endpoint_doorbell(xfer);//? - } -} - -static void -xenhci_skip_transfer(struct usb_xfer *xfer) -{ - #ifdef XENUSB_BEBUG - printf("[xenusb_debug]xenhci.c: xenhci_skip_transfer()\n"); - #endif - - struct xenhci_td *td; - struct xenhci_td *td_last; - - td = xfer->td_transfer_cache; - td_last = xfer->td_transfer_last; - - td = td->alt_next; - - usb_pc_cpu_invalidate(td->page_cache); - - if (!(td->td_trb[0].dwTrb3 & htole32(XENHCI_TRB_3_CYCLE_BIT))) { - - usb_pc_cpu_invalidate(td_last->page_cache); - - /* copy LINK TRB to current waiting location */ - td->td_trb[0].qwTrb0 = td_last->td_trb[td_last->ntrb].qwTrb0; - td->td_trb[0].dwTrb2 = td_last->td_trb[td_last->ntrb].dwTrb2; - usb_pc_cpu_flush(td->page_cache); - - td->td_trb[0].dwTrb3 = td_last->td_trb[td_last->ntrb].dwTrb3; - usb_pc_cpu_flush(td->page_cache); - - //xhci_endpoint_doorbell(xfer);//? - } -} /*------------------------------------------------------------------------* * xenhci_check_transfer @@ -403,8 +287,8 @@ printf("[xenusb_debug]xenhci.c: xenhci_check_transfer()\n"); #endif - struct xenhci_endpoint_ext *pepext; - int64_t offset; +// struct xenhci_endpoint_ext *pepext; +// int64_t offset; uint64_t td_event; uint32_t temp; uint32_t remainder; @@ -449,131 +333,19 @@ return; } - pepext = &sc->sc_hw.devs[index].endp[epno]; + //pepext = &sc->sc_hw.devs[index].endp[epno]; - if (pepext->trb_ep_mode != USB_EP_MODE_STREAMS) { - stream_id = 0; - DPRINTF("stream_id=0\n"); - } else if (stream_id >= XENHCI_MAX_STREAMS) { - DPRINTF("Invalid stream ID.\n"); - return; - } + //if (pepext->trb_ep_mode != USB_EP_MODE_STREAMS) { + // stream_id = 0; + // DPRINTF("stream_id=0\n"); + //} else if (stream_id >= XENHCI_MAX_STREAMS) { + // DPRINTF("Invalid stream ID.\n"); + // return; + //} /* try to find the USB transfer that generated the event */ for (i = 0; i != (XENHCI_MAX_TRANSFERS - 1); i++) { - struct usb_xfer *xfer; - struct xenhci_td *td; - - xfer = pepext->xfer[i + (XENHCI_MAX_TRANSFERS * stream_id)]; - if (xfer == NULL) - continue; - - td = xfer->td_transfer_cache; - - DPRINTFN(5, "Checking if 0x%016llx == (0x%016llx .. 0x%016llx)\n", - (long long)td_event, - (long long)td->td_self, - (long long)td->td_self + sizeof(td->td_trb)); - #ifdef XENUSB_BEBUG - printf("[gbtest]Checking if 0x%016llx == (0x%016llx .. 0x%016llx)\n", - (long long)td_event, - (long long)td->td_self, - (long long)td->td_self + sizeof(td->td_trb)); - #endif - - /* - * NOTE: Some XENHCI implementations might not trigger - * an event on the last LINK TRB so we need to - * consider both the last and second last event - * address as conditions for a successful transfer. - * - * NOTE: We assume that the XENHCI will only trigger one - * event per chain of TRBs. - */ - - offset = td_event - td->td_self; - - if (offset >= 0 && - offset < (int64_t)sizeof(td->td_trb)) { - - usb_pc_cpu_invalidate(td->page_cache); - - /* compute rest of remainder, if any */ - for (i = (offset / 16) + 1; i < td->ntrb; i++) { - temp = le32toh(td->td_trb[i].dwTrb2); - remainder += XENHCI_TRB_2_BYTES_GET(temp); - } - - DPRINTFN(5, "New remainder: %u\n", remainder); - - /* clear isochronous transfer errors */ - if (xfer->flags_int.isochronous_xfr) { - if (halted) { - halted = 0; - status = XENHCI_TRB_ERROR_SUCCESS; - remainder = td->len; - } - } - - /* "td->remainder" is verified later */ - td->remainder = remainder; - td->status = status; - - usb_pc_cpu_flush(td->page_cache); - - /* - * 1) Last transfer descriptor makes the - * transfer done - */ - if (((void *)td) == xfer->td_transfer_last) { - DPRINTF("TD is last\n"); - xenhci_generic_done(xfer); - break; - } - - /* - * 2) Any kind of error makes the transfer - * done - */ - if (halted) { - DPRINTF("TD has I/O error\n"); - xenhci_generic_done(xfer); - break; - } - - /* - * 3) If there is no alternate next transfer, - * a short packet also makes the transfer done - */ - if (td->remainder > 0) { - if (td->alt_next == NULL) { - DPRINTF( - "short TD has no alternate next\n"); - xenhci_generic_done(xfer); - break; - } - DPRINTF("TD has short pkt\n"); - if (xfer->flags_int.short_frames_ok || - xfer->flags_int.isochronous_xfr || - xfer->flags_int.control_xfr) { - /* follow the alt next */ - xfer->td_transfer_cache = td->alt_next; - xenhci_activate_transfer(xfer); - break; - } - xenhci_skip_transfer(xfer); - xenhci_generic_done(xfer); - break; - } - - /* - * 4) Transfer complete - go to next TD - */ - DPRINTF("Following next TD\n"); - xfer->td_transfer_cache = td->obj_next; - xenhci_activate_transfer(xfer); - break; /* there should only be one match */ - } + //TODO } } @@ -584,12 +356,13 @@ printf("[xenusb_debug]xenhci.c: xenhci_check_command()\n"); #endif - if (sc->sc_cmd_addr == trb->qwTrb0) { - DPRINTF("Received command event\n"); - sc->sc_cmd_result[0] = trb->dwTrb2; - sc->sc_cmd_result[1] = trb->dwTrb3; - cv_signal(&sc->sc_cmd_cv); - } +//TODO?? +// if (sc->sc_cmd_addr == trb->qwTrb0) { +// DPRINTF("Received command event\n"); +// sc->sc_cmd_result[0] = trb->dwTrb2; +// sc->sc_cmd_result[1] = trb->dwTrb3; +// cv_signal(&sc->sc_cmd_cv); +// } } static void @@ -609,16 +382,18 @@ uint8_t k; uint8_t t; - usbd_get_page(&sc->sc_hw.root_pc, 0, &buf_res); + //usbd_get_page(&sc->sc_hw.root_pc, 0, &buf_res); phwr = buf_res.buffer; /* Receive any events */ - usb_pc_cpu_invalidate(&sc->sc_hw.root_pc); + //usb_pc_cpu_invalidate(&sc->sc_hw.root_pc); - i = sc->sc_event_idx; - j = sc->sc_event_ccs; +// i = sc->sc_event_idx; +// j = sc->sc_event_ccs; +i=0; +j=0; t = 2; while (1) { @@ -673,8 +448,8 @@ } } - sc->sc_event_idx = i; - sc->sc_event_ccs = j; +// sc->sc_event_idx = i; +// sc->sc_event_ccs = j; /* * NOTE: The Event Ring Dequeue Pointer Register is 64-bit @@ -739,328 +514,40 @@ } - - - /*------------------------------------------------------------------------* * */ static void xenhci_setup_generic_chain_sub(struct xenhci_std_temp *temp) -{ - struct usb_page_search buf_res; - struct xenhci_td *td; - struct xenhci_td *td_next; - struct xenhci_td *td_alt_next; - struct xenhci_td *td_first; - uint32_t buf_offset; - uint32_t average; - uint32_t len_old; - uint32_t npkt_off; - uint32_t dword; - uint8_t shortpkt_old; - uint8_t precompute; - uint8_t x; - - td_alt_next = NULL; - buf_offset = 0; - shortpkt_old = temp->shortpkt; - len_old = temp->len; - npkt_off = 0; - precompute = 1; - -restart: - - td = temp->td; - td_next = td_first = temp->td_next; - - while (1) { - - if (temp->len == 0) { - - if (temp->shortpkt) - break; - - /* send a Zero Length Packet, ZLP, last */ - - temp->shortpkt = 1; - average = 0; - - } else { - - average = temp->average; - - if (temp->len < average) { - if (temp->len % temp->max_packet_size) { - temp->shortpkt = 1; - } - average = temp->len; - } - } - - if (td_next == NULL) - panic("%s: out of XHCI transfer descriptors!", __FUNCTION__); - - /* get next TD */ - - td = td_next; - td_next = td->obj_next; - - /* check if we are pre-computing */ - - if (precompute) { - - /* update remaining length */ - - temp->len -= average; - - continue; - } - /* fill out current TD */ - - td->len = average; - td->remainder = 0; - td->status = 0; - - /* update remaining length */ - - temp->len -= average; - - /* reset TRB index */ - - x = 0; - - if (temp->trb_type == XENHCI_TRB_TYPE_SETUP_STAGE) { - /* immediate data */ - - if (average > 8) - average = 8; - - td->td_trb[0].qwTrb0 = 0; - - usbd_copy_out(temp->pc, temp->offset + buf_offset, - (uint8_t *)(uintptr_t)&td->td_trb[0].qwTrb0, - average); - - dword = XENHCI_TRB_2_BYTES_SET(8) | - XENHCI_TRB_2_TDSZ_SET(0) | - XENHCI_TRB_2_IRQ_SET(0); - - td->td_trb[0].dwTrb2 = htole32(dword); - - dword = XENHCI_TRB_3_TYPE_SET(XENHCI_TRB_TYPE_SETUP_STAGE) | - XENHCI_TRB_3_IDT_BIT | XENHCI_TRB_3_CYCLE_BIT; - - /* check wLength */ - if (td->td_trb[0].qwTrb0 & - htole64(XENHCI_TRB_0_WLENGTH_MASK)) { - if (td->td_trb[0].qwTrb0 & htole64(1)) - dword |= XENHCI_TRB_3_TRT_IN; - else - dword |= XENHCI_TRB_3_TRT_OUT; - } - - td->td_trb[0].dwTrb3 = htole32(dword); -#ifdef USB_DEBUG - xhci_dump_trb(&td->td_trb[x]); -#endif - x++; - - } else do { - - uint32_t npkt; - - /* fill out buffer pointers */ - - if (average == 0) { - npkt = 0; - memset(&buf_res, 0, sizeof(buf_res)); - } else { - usbd_get_page(temp->pc, temp->offset + - buf_offset, &buf_res); - - /* get length to end of page */ - if (buf_res.length > average) - buf_res.length = average; - - /* check for maximum length */ - if (buf_res.length > XENHCI_TD_PAGE_SIZE) - buf_res.length = XENHCI_TD_PAGE_SIZE; - - npkt_off += buf_res.length; - - /* setup npkt */ - npkt = (len_old - npkt_off + temp->max_packet_size - 1) / - temp->max_packet_size; - - if (npkt > 31) - npkt = 31; - } - - /* fill out TRB's */ - td->td_trb[x].qwTrb0 = - htole64((uint64_t)buf_res.physaddr); - - dword = - XENHCI_TRB_2_BYTES_SET(buf_res.length) | - XENHCI_TRB_2_TDSZ_SET(npkt) | - XENHCI_TRB_2_IRQ_SET(0); - - td->td_trb[x].dwTrb2 = htole32(dword); - - switch (temp->trb_type) { - case XENHCI_TRB_TYPE_ISOCH: - /* BEI: Interrupts are inhibited until EOT */ - dword = XENHCI_TRB_3_CHAIN_BIT | XENHCI_TRB_3_CYCLE_BIT | - XENHCI_TRB_3_BEI_BIT | - XENHCI_TRB_3_TBC_SET(temp->tbc) | - XENHCI_TRB_3_TLBPC_SET(temp->tlbpc); - if (td != td_first) { - dword |= XENHCI_TRB_3_TYPE_SET(XENHCI_TRB_TYPE_NORMAL); - } else if (temp->do_isoc_sync != 0) { - temp->do_isoc_sync = 0; - /* wait until "isoc_frame" */ - dword |= XENHCI_TRB_3_TYPE_SET(XENHCI_TRB_TYPE_ISOCH) | - XENHCI_TRB_3_FRID_SET(temp->isoc_frame / 8); - } else { - /* start data transfer at next interval */ - dword |= XENHCI_TRB_3_TYPE_SET(XENHCI_TRB_TYPE_ISOCH) | - XENHCI_TRB_3_ISO_SIA_BIT; - } - if (temp->direction == UE_DIR_IN) - dword |= XENHCI_TRB_3_DIR_IN | XENHCI_TRB_3_ISP_BIT; - break; - case XENHCI_TRB_TYPE_DATA_STAGE: - dword = XENHCI_TRB_3_CHAIN_BIT | XENHCI_TRB_3_CYCLE_BIT | - XENHCI_TRB_3_TYPE_SET(XENHCI_TRB_TYPE_DATA_STAGE) | - XENHCI_TRB_3_TBC_SET(temp->tbc) | - XENHCI_TRB_3_TLBPC_SET(temp->tlbpc); - if (temp->direction == UE_DIR_IN) - dword |= XENHCI_TRB_3_DIR_IN | XENHCI_TRB_3_ISP_BIT; - break; - case XENHCI_TRB_TYPE_STATUS_STAGE: - dword = XENHCI_TRB_3_CHAIN_BIT | XENHCI_TRB_3_CYCLE_BIT | - XENHCI_TRB_3_TYPE_SET(XENHCI_TRB_TYPE_STATUS_STAGE) | - XENHCI_TRB_3_TBC_SET(temp->tbc) | - XENHCI_TRB_3_TLBPC_SET(temp->tlbpc); - if (temp->direction == UE_DIR_IN) - dword |= XHCI_TRB_3_DIR_IN; - break; - default: /* XENHCI_TRB_TYPE_NORMAL */ - /* BEI: Interrupts are inhibited until EOT */ - dword = XENHCI_TRB_3_CHAIN_BIT | XENHCI_TRB_3_CYCLE_BIT | - XENHCI_TRB_3_TYPE_SET(XENHCI_TRB_TYPE_NORMAL) | - XENHCI_TRB_3_BEI_BIT | - XENHCI_TRB_3_TBC_SET(temp->tbc) | - XENHCI_TRB_3_TLBPC_SET(temp->tlbpc); - if (temp->direction == UE_DIR_IN) - dword |= XENHCI_TRB_3_DIR_IN | XENHCI_TRB_3_ISP_BIT; - break; - } - td->td_trb[x].dwTrb3 = htole32(dword); - - average -= buf_res.length; - buf_offset += buf_res.length; -#ifdef USB_DEBUG - xhci_dump_trb(&td->td_trb[x]); -#endif - x++; - - } while (average != 0); - - td->td_trb[x-1].dwTrb3 |= htole32(XENHCI_TRB_3_IOC_BIT); - - /* store number of data TRB's */ - - td->ntrb = x; - - DPRINTF("NTRB=%u\n", x); - - /* fill out link TRB */ - - if (td_next != NULL) { - /* link the current TD with the next one */ - td->td_trb[x].qwTrb0 = htole64((uint64_t)td_next->td_self); - DPRINTF("LINK=0x%08llx\n", (long long)td_next->td_self); - } else { - /* this field will get updated later */ - DPRINTF("NOLINK\n"); - } - - dword = XENHCI_TRB_2_IRQ_SET(0); - - td->td_trb[x].dwTrb2 = htole32(dword); - - dword = XENHCI_TRB_3_TYPE_SET(XENHCI_TRB_TYPE_LINK) | - XENHCI_TRB_3_CYCLE_BIT | XENHCI_TRB_3_IOC_BIT; - - td->td_trb[x].dwTrb3 = htole32(dword); - - td->alt_next = td_alt_next; -#ifdef USB_DEBUG - xhci_dump_trb(&td->td_trb[x]); -#endif - usb_pc_cpu_flush(td->page_cache); - } - - if (precompute) { - precompute = 0; - - /* setup alt next pointer, if any */ - if (temp->last_frame) { - td_alt_next = NULL; - } else { - /* we use this field internally */ - td_alt_next = td_next; - } - - /* restore */ - temp->shortpkt = shortpkt_old; - temp->len = len_old; - goto restart; - } - - /* - * Remove cycle bit from the first TRB if we are - * stepping them: - */ - if (temp->step_td != 0) { - td_first->td_trb[0].dwTrb3 &= ~htole32(XENHCI_TRB_3_CYCLE_BIT); - usb_pc_cpu_flush(td_first->page_cache); - } - - /* remove chain bit because this is the last TRB in the chain */ - td->td_trb[td->ntrb - 1].dwTrb2 &= ~htole32(XENHCI_TRB_2_TDSZ_SET(15)); - td->td_trb[td->ntrb - 1].dwTrb3 &= ~htole32(XENHCI_TRB_3_CHAIN_BIT); - - usb_pc_cpu_flush(td->page_cache); +{//TODO + #ifdef XENUSB_BEBUG + printf("[xenusb_debug]xenhci.c: xenhci_setup_generic_chain_sub()\n"); + #endif - temp->td = td; - temp->td_next = td_next; } static void -xenhci_setup_generic_chain(struct usb_xfer *xfer) -{ - //struct xhci_std_temp temp; - struct xenhci_td *td; +xenhci_setup_generic_chain(struct usb_xfer *xfer, xenhci_qh_t **qh_last) +{//TODO + #ifdef XENUSB_BEBUG + printf("[xenusb_debug]xenhci.c: xenhci_setup_generic_chain()\n"); + #endif + + struct xenhci_std_temp temp; + struct usb_pipe_methods *methods; + xenhci_qh_t *qh; + xenhci_qtd_t *td; + uint32_t qh_endp; + uint32_t qh_endphub; uint32_t x; - uint32_t y; - uint8_t mult; - temp.do_isoc_sync = 0; - temp.step_td = 0; - temp.tbc = 0; - temp.tlbpc = 0; + DPRINTFN(9, "addr=%d endpt=%d sumlen=%d speed=%d\n", + xfer->address, UE_GET_ADDR(xfer->endpointno), + xfer->sumlen, usbd_get_speed(xfer->xroot->udev)); + temp.average = xfer->max_hc_frame_size; - temp.max_packet_size = xfer->max_packet_size; - temp.sc = XHCI_BUS2SC(xfer->xroot->bus); - temp.pc = NULL; - temp.last_frame = 0; - temp.offset = 0; - temp.multishort = xfer->flags_int.isochronous_xfr || - xfer->flags_int.control_xfr || - xfer->flags_int.short_frames_ok; + temp.max_frame_size = xfer->max_frame_size; + temp.sc = XENHCI_BUS2SC(xfer->xroot->bus); /* toggle the DMA set we are using */ xfer->flags_int.curr_dma_set ^= 1; @@ -1068,124 +555,62 @@ /* get next DMA set */ td = xfer->td_start[xfer->flags_int.curr_dma_set]; - temp.td = NULL; - temp.td_next = td; - xfer->td_transfer_first = td; xfer->td_transfer_cache = td; - if (xfer->flags_int.isochronous_xfr) { - uint8_t shift; - - /* compute multiplier for ISOCHRONOUS transfers */ - mult = xfer->endpoint->ecomp ? - UE_GET_SS_ISO_MULT(xfer->endpoint->ecomp->bmAttributes) - : 0; - /* check for USB 2.0 multiplier */ - if (mult == 0) { - mult = (xfer->endpoint->edesc-> - wMaxPacketSize[1] >> 3) & 3; - } - /* range check */ - if (mult > 2) - mult = 3; - else - mult++; - - //x = XREAD4(temp.sc, runt, XENHCI_MFINDEX); - x = 0; - - DPRINTF("MFINDEX=0x%08x\n", x); - - switch (usbd_get_speed(xfer->xroot->udev)) { - case USB_SPEED_FULL: - shift = 3; - temp.isoc_delta = 8; /* 1ms */ - x += temp.isoc_delta - 1; - x &= ~(temp.isoc_delta - 1); - break; - default: - shift = usbd_xfer_get_fps_shift(xfer); - temp.isoc_delta = 1U << shift; - x += temp.isoc_delta - 1; - x &= ~(temp.isoc_delta - 1); - /* simple frame load balancing */ - x += xfer->endpoint->usb_uframe; - break; - } - - y = XENHCI_MFINDEX_GET(x - xfer->endpoint->isoc_next); - - if ((xfer->endpoint->is_synced == 0) || - (y < (xfer->nframes << shift)) || - (XENHCI_MFINDEX_GET(-y) >= (128 * 8))) { - /* - * If there is data underflow or the pipe - * queue is empty we schedule the transfer a - * few frames ahead of the current frame - * position. Else two isochronous transfers - * might overlap. - */ - xfer->endpoint->isoc_next = XENHCI_MFINDEX_GET(x + (3 * 8)); - xfer->endpoint->is_synced = 1; - temp.do_isoc_sync = 1; + temp.td = NULL; + temp.td_next = td; + temp.qtd_status = 0; + temp.last_frame = 0; + temp.setup_alt_next = xfer->flags_int.short_frames_ok; - DPRINTFN(3, "start next=%d\n", xfer->endpoint->isoc_next); + if (xfer->flags_int.control_xfr) { + if (xfer->endpoint->toggle_next) { + /* DATA1 is next */ + temp.qtd_status |= + htohc32(temp.sc, XENHCI_QTD_SET_TOGGLE(1)); } + temp.auto_data_toggle = 0; + } else { + temp.auto_data_toggle = 1; + } - /* compute isochronous completion time */ - - y = XENHCI_MFINDEX_GET(xfer->endpoint->isoc_next - (x & ~7)); - - xfer->isoc_time_complete = - usb_isoc_time_expand(&temp.sc->sc_bus, x / 8) + - (y / 8) + (((xfer->nframes << shift) + 7) / 8); - - x = 0; - temp.isoc_frame = xfer->endpoint->isoc_next; - temp.trb_type = XENHCI_TRB_TYPE_ISOCH; - - xfer->endpoint->isoc_next += xfer->nframes << shift; + if ((xfer->xroot->udev->parent_hs_hub != NULL) || + (xfer->xroot->udev->address != 0)) { + /* max 3 retries */ + temp.qtd_status |= + htohc32(temp.sc, XENHCI_QTD_SET_CERR(3)); + } + /* check if we should prepend a setup message */ *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***