Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 27 Sep 2013 10:47:22 GMT
From:      bguan@FreeBSD.org
To:        svn-soc-all@FreeBSD.org
Subject:   socsvn commit: r257755 - soc2013/bguan/head/sys/dev/xen/usbfront
Message-ID:  <201309271047.r8RAlM5W091038@socsvn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201309271047.r8RAlM5W091038>