PERFORCE change 100971 for review

Hans Petter Selasky hselasky at FreeBSD.org
Sat Jul 8 09:09:16 UTC 2006


http://perforce.freebsd.org/chv.cgi?CH=100971

Change 100971 by hselasky at hselasky_mini_itx on 2006/07/08 09:09:13

	All USB hosts controllers now allocate DMA-able memory in
	chunks of PAGE_SIZE bytes. This should allow the USB system
	to operate also when then host memory becomes fragmented.
	There are alot of changes. Please test.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/ehci.c#6 edit
.. //depot/projects/usb/src/sys/dev/usb/ehci.h#3 edit
.. //depot/projects/usb/src/sys/dev/usb/ehci_pci.c#5 edit
.. //depot/projects/usb/src/sys/dev/usb/ohci.c#6 edit
.. //depot/projects/usb/src/sys/dev/usb/ohci.h#3 edit
.. //depot/projects/usb/src/sys/dev/usb/ohci_pci.c#5 edit
.. //depot/projects/usb/src/sys/dev/usb/uhci.c#6 edit
.. //depot/projects/usb/src/sys/dev/usb/uhci.h#3 edit
.. //depot/projects/usb/src/sys/dev/usb/uhci_pci.c#5 edit
.. //depot/projects/usb/src/sys/dev/usb/usb.c#5 edit
.. //depot/projects/usb/src/sys/dev/usb/usb.h#4 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_port.h#5 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_subr.c#7 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_subr.h#11 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#6 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb/ehci.c#6 (text+ko) ====

@@ -60,8 +60,6 @@
 #include <sys/lock.h>
 #include <sys/malloc.h>
 
-#include <machine/bus.h> /* bus_space_xxx() */
-
 #define INCLUDE_PCIXXX_H
 
 #include <dev/usb/usb_port.h>
@@ -671,11 +669,11 @@
 static void
 ehci_dump_sqtds(ehci_qtd_t *sqtd)
 {
-	int i;
+	u_int16_t i;
 	u_int32_t stop;
 
 	stop = 0;
-	for(i = 0; sqtd && (i < 20) && !stop; sqtd = sqtd->next, i++)
+	for(i = 0; sqtd && (i < 20) && !stop; sqtd = sqtd->obj_next, i++)
 	{
 		ehci_dump_sqtd(sqtd);
 		stop = sqtd->qtd_next & htole32(EHCI_LINK_TERMINATE);
@@ -987,7 +985,7 @@
 	/* the transfer is done, compute actual length and status */
 	for (;
 	     td != NULL;
-	     td = td->next)
+	     td = ((td == xfer->td_transfer_last) ? NULL : td->obj_next))
 	{
 		if(td->qtd_status & htole32(EHCI_QTD_ACTIVE))
 		{
@@ -1123,7 +1121,7 @@
 
 			for(td = xfer->td_transfer_first;
 			    td != NULL;
-			    td = td->next)
+			    td = ((td == xfer->td_transfer_last) ? NULL : td->obj_next))
 			{
 				u_int32_t status;
 
@@ -1403,7 +1401,7 @@
 	if((xfer)->interrupt_list.le_prev)
 	{
 		LIST_REMOVE((xfer), interrupt_list);
-		(xfer)->interrupt_list.le_prev = 0;
+		(xfer)->interrupt_list.le_prev = NULL;
 	}
 	return;
 }
@@ -1411,19 +1409,20 @@
 static void
 ehci_setup_standard_chain(struct usbd_xfer *xfer, ehci_qh_t **qh_last)
 {
+	struct usbd_page_search buf_res;
 	/* the EHCI hardware can handle at most five 4k crossing per TD */
-	u_int32_t average = ((unsigned)(EHCI_PAGE_SIZE / xfer->max_packet_size))
-	  * xfer->max_packet_size;
+	u_int32_t average = (EHCI_PAGE_SIZE - (EHCI_PAGE_SIZE % 
+					       xfer->max_packet_size));
 	u_int32_t qtd_status;
-	u_int32_t physbuffer = xfer->physbuffer;
+	u_int32_t buf_offset;
 	u_int32_t len = xfer->length;
 	u_int32_t c_error = 
 	  (xfer->udev->speed == USB_SPEED_HIGH) ? 0 : 
 	  htole32(EHCI_QTD_SET_CERR(3));
 	u_int8_t isread;
 	u_int8_t shortpkt = 0;
-
 	ehci_qtd_t *td;
+	ehci_qtd_t *td_last = NULL;
 	ehci_qh_t *qh;
 
 	DPRINTFN(8, ("addr=%d endpt=%d len=%d speed=%d\n", 
@@ -1432,41 +1431,43 @@
 
 	td = (xfer->td_transfer_first = xfer->td_start);
 
+	buf_offset = 0;
+	usbd_get_page(&(xfer->buf_data), buf_offset, &buf_res);
+
 	if(xfer->pipe->methods == &ehci_device_ctrl_methods)
 	{
-		isread = ((usb_device_request_t *)(xfer->buffer))->
-		  bmRequestType & UT_READ;
+		/* the first byte is "bmRequestType" */
+
+		isread = *((u_int8_t *)(buf_res.buffer));
+		isread &= UT_READ;
 
-		/* xfer->length = sizeof(usb_device_request_t) + 
-		 *                UGETW(req->wLength)
-		 * check length ??
+		/*
+		 * check length ?
 		 */
 		xfer->pipe->toggle_next = 1;
 
 		/* SETUP message */
 
-		td->next = (td+1);
-		td->qtd_next = (td+1)->qtd_self;
-		td->qtd_altnext = htole32(EHCI_LINK_TERMINATE);
-
 		td->qtd_status = c_error | htole32
 		  (EHCI_QTD_ACTIVE |
 		   EHCI_QTD_SET_PID(EHCI_QTD_PID_SETUP) |
 		   EHCI_QTD_SET_TOGGLE(0) |
 		   EHCI_QTD_SET_BYTES(sizeof(usb_device_request_t)));
 
-		td->qtd_buffer[0] = htole32(physbuffer);
+		td->qtd_buffer[0] = htole32(buf_res.physaddr);
 		td->qtd_buffer_hi[0] = 0;
+
+		buf_offset += sizeof(usb_device_request_t);
+		usbd_get_page(&(xfer->buf_data), buf_offset, &buf_res);
+
 		td->qtd_buffer[1] = 
-		  htole32(physbuffer + sizeof(usb_device_request_t)) & 
-		  htole32(~0xfff);
+		  htole32(buf_res.physaddr & (~0xFFF));
 		td->qtd_buffer_hi[1] = 0;
 
 		td->len = sizeof(usb_device_request_t);
-
-		physbuffer += sizeof(usb_device_request_t);
 		len -= sizeof(usb_device_request_t);
-		td++;
+		td_last = td;
+		td = td->obj_next;
 	}
 	else
 	{
@@ -1474,8 +1475,8 @@
 
 		if(xfer->length == 0)
 		{
-			/* must allow access to (td-1),
-			 * so xfer->length cannot be zero
+			/* must allow access to "td_last",
+			 * so xfer->length cannot be zero!
 			 */
 			printf("%s: setting USBD_FORCE_SHORT_XFER!\n",
 			       __FUNCTION__);
@@ -1524,27 +1525,33 @@
 			average = len;
 		}
 
-		if(((void *)td) >= xfer->td_end)
+		if(td == NULL)
 		{
 			panic("%s: software wants to write more data "
 			      "than there is in the buffer!", __FUNCTION__);
 		}
 
-		/* fill out TD */
+		/* link in last TD */
 
-		td->next = (td+1);
-		td->qtd_next = (td+1)->qtd_self;
+		if (td_last) {
+		    td_last->qtd_next = td->qtd_self;
+		    /* short transfers should terminate the transfer: */
+		    td_last->qtd_altnext = htole32(EHCI_LINK_TERMINATE);
+		}
 
-		/* short transfers should terminate the transfer: */
-		td->qtd_altnext = htole32(EHCI_LINK_TERMINATE);
+		/* fill out current TD */
 
 		td->qtd_status = 
 		  qtd_status | htole32(EHCI_QTD_SET_BYTES(average));
 
-		td->qtd_buffer[0] = htole32(physbuffer);
+		td->qtd_buffer[0] = htole32(buf_res.physaddr);
 		td->qtd_buffer_hi[0] = 0;
+
+		buf_offset += average;
+		usbd_get_page(&(xfer->buf_data), buf_offset, &buf_res);
+
 		td->qtd_buffer[1] = 
-		  htole32(physbuffer + average) & htole32(~0xfff);
+		  htole32(buf_res.physaddr & (~0xFFF));
 		td->qtd_buffer_hi[1] = 0;
 
 		td->len = average;
@@ -1562,13 +1569,19 @@
 		    qtd_status ^= htole32(EHCI_QTD_TOGGLE_MASK);
 		}
 
-		physbuffer += average;
 		len -= average;
-		td++;
+		td_last = td;
+		td = td->obj_next;
 	}
 
 	if(xfer->pipe->methods == &ehci_device_ctrl_methods)
 	{
+		/* link in last TD */
+
+		td_last->qtd_next = td->qtd_self;
+		/* short transfers should terminate the transfer: */
+		td_last->qtd_altnext = htole32(EHCI_LINK_TERMINATE);
+
 		/* STATUS message */
 
 		td->qtd_status = c_error | (isread ?
@@ -1586,26 +1599,17 @@
 		td->qtd_buffer[0] = 0; 
 		td->qtd_buffer_hi[0] = 0;
 
-		td->next = NULL;
-		td->qtd_next = htole32(EHCI_LINK_TERMINATE);
-		td->qtd_altnext = htole32(EHCI_LINK_TERMINATE);
 		td->len = 0;
+		td_last = td;
+	}
 
-		physbuffer += 0;
-		len -= 0;
-		td++;
-	}
-	else
-	{
-		(td-1)->next = NULL;
-		(td-1)->qtd_next = htole32(EHCI_LINK_TERMINATE);
-		(td-1)->qtd_altnext = htole32(EHCI_LINK_TERMINATE);
-		(td-1)->qtd_status |= htole32(EHCI_QTD_IOC);
-	}
+	td_last->qtd_next = htole32(EHCI_LINK_TERMINATE);
+	td_last->qtd_altnext = htole32(EHCI_LINK_TERMINATE);
+	td_last->qtd_status |= htole32(EHCI_QTD_IOC);
 
 	/* must have at least one frame! */
 
-	xfer->td_transfer_last = (td-1);
+	xfer->td_transfer_last = td_last;
 
 #ifdef USB_DEBUG
 	if(ehcidebug > 8)
@@ -1615,9 +1619,11 @@
 		ehci_dump_sqtds(xfer->td_start);
 	}
 #endif
+
 	qh = xfer->qh_start;
 
-	/* qh_link filled when the QH is added */
+	/* the "qh_link" field is filled when the QH is added */
+
 	qh->qh_endp = htole32
 	  (EHCI_QH_SET_ADDR(xfer->address) |
 	   EHCI_QH_SET_ENDPT(UE_GET_ADDR(xfer->endpoint)) |
@@ -1626,8 +1632,6 @@
 	   EHCI_QH_SET_NRL(8) /* XXX */ 
 	   );
 
-	/* XXX have data toogle in qh */
-
 	switch (xfer->udev->speed) {
 	case USB_SPEED_LOW:  
 	  qh->qh_endp |= htole32(EHCI_QH_SET_EPS(EHCI_QH_SPEED_LOW)|
@@ -1683,26 +1687,35 @@
 static void
 ehci_root_intr_done(ehci_softc_t *sc, struct usbd_xfer *xfer)
 {
+	struct usbd_page_search buf_res;
 	u_int8_t *p;
-	int i, m;
+	u_int16_t i;
+	u_int16_t m;
 
 	if(sc->sc_intrxfer)
 	{
 		/* disable further interrupts */
 		sc->sc_intrxfer = NULL;
 
-		p = xfer->buffer;
-		m = min(sc->sc_noport, (xfer->length * 8) - 1);
-		memset(p, 0, xfer->length);
-		for(i = 1; i <= m; i++)
+		/* clear all bits */
+		usbd_bzero(&(xfer->buf_data), 0, xfer->length);
+
+		/* set bits */
+		m = (xfer->length * 8);
+		i = (sc->sc_noport + 1);
+		m = min(m,i);
+		for(i = 1; i < m; i++)
 		{
 			/* pick out CHANGE bits from the status register */
 			if(EOREAD4(sc, EHCI_PORTSC(i)) & EHCI_PS_CLEAR)
 			{
-				p[i/8] |= 1 << (i%8);
+				usbd_get_page(&(xfer->buf_data), i/8, &buf_res);
+				p = buf_res.buffer;
+				*p |= 1 << (i % 8);
+
+				DPRINTF(("port %d changed\n", i));
 			}
 		}
-		DPRINTF(("change=0x%02x\n", *p));
 		xfer->actlen = xfer->length;
 	}
 	return;
@@ -1724,9 +1737,10 @@
 
 	while(nframes--)
 	{
-	  if(((void *)td) >= xfer->td_end)
+	  if(td == NULL)
 	  {
-		td = xfer->td_start;
+		panic("%s:%d: out of TD's\n",
+		      __FUNCTION__, __LINE__);
 	  }
 
 	  if(pp_last >= &sc->sc_isoc_fs_p_last[EHCI_VIRTUAL_FRAMELIST_COUNT])
@@ -1766,7 +1780,7 @@
 
 	  pp_last++;
 	  plen++;
-	  td++;
+	  td = td->obj_next;
 	}
 	xfer->actlen = actlen;
 
@@ -1790,9 +1804,10 @@
 
 	while(nframes--)
 	{
-	  if(((void *)td) >= xfer->td_end)
+	  if(td == NULL)
 	  {
-		td = xfer->td_start;
+		panic("%s:%d: out of TD's\n",
+		      __FUNCTION__, __LINE__);
 	  }
 
 	  if(pp_last >= &sc->sc_isoc_hs_p_last[EHCI_VIRTUAL_FRAMELIST_COUNT])
@@ -1836,7 +1851,7 @@
 		pp_last++;
 
 		td_no = 0;
-		td++;
+		td = td->obj_next;
 	  }
 	}
 	xfer->actlen = actlen;
@@ -1915,8 +1930,8 @@
 			}
 		}
 
-		xfer->td_transfer_first = 0;
-		xfer->td_transfer_last = 0;
+		xfer->td_transfer_first = NULL;
+		xfer->td_transfer_last = NULL;
 	}
 
 	/* finish root interrupt transfer
@@ -2044,6 +2059,8 @@
   .close = ehci_device_bulk_close,
   .enter = ehci_device_bulk_enter,
   .start = ehci_device_bulk_start,
+  .copy_in = usbd_std_bulk_intr_copy_in,
+  .copy_out = usbd_std_bulk_intr_copy_out,
 };
 
 /*---------------------------------------------------------------------------*
@@ -2075,15 +2092,6 @@
 {
 	ehci_softc_t *sc = xfer->usb_sc;
 
-	DPRINTFN(3,("type=0x%02x, request=0x%02x, "
-		    "wValue=0x%04x, wIndex=0x%04x len=%d, addr=%d, endpt=%d\n",
-		    ((usb_device_request_t *)(xfer->buffer))->bmRequestType,
-		    ((usb_device_request_t *)(xfer->buffer))->bRequest,
-		    UGETW(((usb_device_request_t *)(xfer->buffer))->wValue),
-		    UGETW(((usb_device_request_t *)(xfer->buffer))->wIndex), 
-		    UGETW(((usb_device_request_t *)(xfer->buffer))->wLength),
-		    xfer->address, xfer->endpoint));
-
 	/* setup TD's and QH */
 	ehci_setup_standard_chain(xfer, &sc->sc_async_p_last);
 
@@ -2104,6 +2112,8 @@
   .close = ehci_device_ctrl_close,
   .enter = ehci_device_ctrl_enter,
   .start = ehci_device_ctrl_start,
+  .copy_in = usbd_std_ctrl_copy_in,
+  .copy_out = usbd_std_ctrl_copy_out,
 };
 
 /*---------------------------------------------------------------------------*
@@ -2194,6 +2204,8 @@
   .close = ehci_device_intr_close,
   .enter = ehci_device_intr_enter,
   .start = ehci_device_intr_start,
+  .copy_in = usbd_std_bulk_intr_copy_in,
+  .copy_out = usbd_std_bulk_intr_copy_out,
 };
 
 /*---------------------------------------------------------------------------*
@@ -2225,9 +2237,7 @@
 
 	/* initialize all TD's */
 
-	for(td = xfer->td_start;
-	    ((void *)td) < xfer->td_end;
-	    td++)
+	for(td = xfer->td_start; td; td = td->obj_next)
 	{
 		td->sitd_portaddr = sitd_portaddr;
 
@@ -2269,14 +2279,16 @@
 static void
 ehci_device_isoc_fs_enter(struct usbd_xfer *xfer)
 {
+	struct usbd_page_search buf_res;
 	ehci_softc_t *sc = xfer->usb_sc;
-	u_int32_t physbuffer;
+	u_int32_t buf_offset;
 	u_int32_t nframes;
 	u_int16_t *plen;
 #ifdef USB_DEBUG
 	u_int8_t once = 1;
 #endif
 	ehci_sitd_t *td;
+	ehci_sitd_t *td_last = NULL;
 	ehci_sitd_t **pp_last;
 
 	DPRINTFN(5,("xfer=%p next=%d nframes=%d\n",
@@ -2307,7 +2319,8 @@
 		return;
 	}
 
-	physbuffer = xfer->physbuffer;
+	buf_offset = 0;
+	usbd_get_page(&(xfer->buf_data), buf_offset, &buf_res);
 
 	plen = xfer->frlengths;
 
@@ -2321,9 +2334,10 @@
 
 	while(nframes--)
 	{
-		if(((void *)td) >= xfer->td_end)
+		if(td == NULL)
 		{
-			td = xfer->td_start;
+			panic("%s:%d: out of TD's\n",
+			      __FUNCTION__, __LINE__);
 		}
 
 		if(pp_last >= &sc->sc_isoc_fs_p_last[EHCI_VIRTUAL_FRAMELIST_COUNT])
@@ -2334,28 +2348,27 @@
 		/* reuse sitd_portaddr and sitd_back from last transfer */
 
 		/* TODO: implement support for multiple transactions */
-		if(*plen > 188)
+		if(*plen > xfer->max_frame_size)
 		{
 #ifdef USB_DEBUG
 			if(once)
 			{
 				once = 0;
-				printf("%s: frame length(%d) exceeds %d bytes "
-				       "(frame truncated)\n", 
-				       __FUNCTION__, *plen, 188);
+				printf("%s: frame length(%d) exceeds %d "
+				       "bytes (frame truncated)\n", 
+				       __FUNCTION__, *plen, 
+				       xfer->max_frame_size);
 			}
 #endif
+			*plen = xfer->max_frame_size;
+		}
 
-			/* set new frame length, so that
-			 * a valid transfer can be setup,
-			 * even if synchronization with
-			 * physbuffer is lost
-			 */
-			*plen = 188;
-		}
+		td->sitd_bp[0] = htole32(buf_res.physaddr);
+
+		buf_offset += *plen;
+		usbd_get_page(&(xfer->buf_data), buf_offset, &buf_res);
 
-		td->sitd_bp[0] = htole32(physbuffer);
-		td->sitd_bp[1] = htole32((physbuffer + *plen) & ~0xFFF);
+		td->sitd_bp[1] = htole32(buf_res.physaddr & (~0xFFF));
 
 		if(UE_GET_DIR(xfer->endpoint) == UE_DIR_OUT)
 		{
@@ -2386,12 +2399,12 @@
 		EHCI_APPEND_FS_TD(td, *pp_last);
 		pp_last++;
 
-		physbuffer += *plen;
 		plen++;
-		td++;
+		td_last = td;
+		td = td->obj_next;
 	}
 
-	xfer->td_transfer_last = (td-1);
+	xfer->td_transfer_last = td_last;
 
 	/* update isoc_next */
 	xfer->pipe->isoc_next = (pp_last - &sc->sc_isoc_fs_p_last[0]) &
@@ -2426,6 +2439,8 @@
   .close = ehci_device_isoc_fs_close,
   .enter = ehci_device_isoc_fs_enter,
   .start = ehci_device_isoc_fs_start,
+  .copy_in = usbd_std_isoc_copy_in,
+  .copy_out = usbd_std_isoc_copy_out,
 };
 
 /*---------------------------------------------------------------------------*
@@ -2438,9 +2453,7 @@
 
 	/* initialize all TD's */
 
-	for(td = xfer->td_start;
-	    ((void *)td) < xfer->td_end;
-	    td++)
+	for(td = xfer->td_start; td; td = td->obj_next)
 	{
 		/* set TD inactive */
 		td->itd_status[0] = 0;
@@ -2483,10 +2496,11 @@
 static void
 ehci_device_isoc_hs_enter(struct usbd_xfer *xfer)
 {
+	struct usbd_page_search buf_res;
 	ehci_softc_t *sc = xfer->usb_sc;
 	u_int32_t status;
 	u_int32_t page_addr;
-	u_int32_t physbuffer;
+	u_int32_t buf_offset;
 	u_int32_t nframes;
 	u_int16_t *plen;
 	u_int8_t page_no;
@@ -2495,6 +2509,7 @@
 	u_int8_t once = 1;
 #endif
 	ehci_itd_t *td;
+	ehci_itd_t *td_last = NULL;
 	ehci_itd_t **pp_last;
 
 	DPRINTFN(5,("xfer=%p next=%d nframes=%d\n",
@@ -2525,9 +2540,10 @@
 		return;
 	}
 
-	physbuffer = xfer->physbuffer;
+	buf_offset = 0;
+	usbd_get_page(&(xfer->buf_data), buf_offset, &buf_res);
 
-	page_addr = physbuffer & ~0xFFF;
+	page_addr = buf_res.physaddr & ~0xFFF;
 	page_no = 0;
 	td_no = 0;
 
@@ -2543,9 +2559,10 @@
 
 	while(nframes--)
 	{
-		if(((void *)td) >= xfer->td_end)
+		if(td == NULL)
 		{
-			td = xfer->td_start;
+			panic("%s:%d: out of TD's\n",
+			      __FUNCTION__, __LINE__);
 		}
 
 		if(pp_last >= &sc->sc_isoc_hs_p_last[EHCI_VIRTUAL_FRAMELIST_COUNT])
@@ -2554,7 +2571,7 @@
 		}
 
 		/* range check */
-		if(*plen > 0xC00)
+		if(*plen > xfer->max_frame_size)
 		{
 #ifdef USB_DEBUG
 			if(once)
@@ -2562,15 +2579,10 @@
 				once = 0;
 				printf("%s: frame length(%d) exceeds %d bytes "
 				       "(frame truncated)\n", 
-				       __FUNCTION__, *plen, 0xC00);
+				       __FUNCTION__, *plen, xfer->max_frame_size);
 			}
 #endif
-			/* set new frame length, so that
-			 * a valid transfer can be setup,
-			 * even if synchronization with
-			 * physbuffer is lost
-			 */
-			*plen = 0xC00;
+			*plen = xfer->max_frame_size;
 		}
 
 		if(td_no == 0)
@@ -2603,7 +2615,7 @@
 			   EHCI_ITD_ACTIVE|
 			   EHCI_ITD_IOC|
 			   EHCI_ITD_SET_PG(page_no)|
-			   (physbuffer & 0xFFF));
+			   (buf_res.physaddr & 0xFFF));
 		}
 		else
 		{
@@ -2611,15 +2623,16 @@
 			  (EHCI_ITD_SET_LEN(*plen)|
 			   EHCI_ITD_ACTIVE|
 			   EHCI_ITD_SET_PG(page_no)|
-			   (physbuffer & 0xFFF));
+			   (buf_res.physaddr & 0xFFF));
 		}
 
-		physbuffer += *plen;
+		buf_offset += *plen;
+		usbd_get_page(&(xfer->buf_data), buf_offset, &buf_res);
 
-		if((physbuffer ^ page_addr) & ~0xFFF)
+		if((buf_res.physaddr ^ page_addr) & ~0xFFF)
 		{
 			/* new page needed */
-			page_addr = physbuffer & ~0xFFF;
+			page_addr = buf_res.physaddr & ~0xFFF;
 			page_no++;
 
 			if(page_no < 7)
@@ -2669,11 +2682,12 @@
 
 			page_no = 0;
 			td_no = 0;
-			td++;
+			td_last = td;
+			td = td->obj_next;
 		}
 	}
 
-	xfer->td_transfer_last = (td-1);
+	xfer->td_transfer_last = td_last;
 
 	/* update isoc_next */
 	xfer->pipe->isoc_next = (pp_last - &sc->sc_isoc_hs_p_last[0]) &
@@ -2708,6 +2722,8 @@
   .close = ehci_device_isoc_hs_close,
   .enter = ehci_device_isoc_hs_enter,
   .start = ehci_device_isoc_hs_start,
+  .copy_in = usbd_std_isoc_copy_in,
+  .copy_out = usbd_std_isoc_copy_out,
 };
 
 /*---------------------------------------------------------------------------*
@@ -2737,7 +2753,7 @@
 static const
 usb_device_descriptor_t ehci_devd = 
 {
-	USB_DEVICE_DESCRIPTOR_SIZE,
+	sizeof(usb_device_descriptor_t),
 	UDESC_DEVICE,		/* type */
 	{0x00, 0x02},		/* USB version */
 	UDCLASS_HUB,		/* class */
@@ -2752,7 +2768,7 @@
 static const
 usb_device_qualifier_t ehci_odevd = 
 {
-	USB_DEVICE_DESCRIPTOR_SIZE,
+	sizeof(usb_device_qualifier_t), 
 	UDESC_DEVICE_QUALIFIER,	/* type */
 	{0x00, 0x02},		/* USB version */
 	UDCLASS_HUB,		/* class */
@@ -2766,7 +2782,7 @@
 static const
 usb_config_descriptor_t ehci_confd = 
 {
-	USB_CONFIG_DESCRIPTOR_SIZE,
+	sizeof(usb_config_descriptor_t),
 	UDESC_CONFIG,
 	{USB_CONFIG_DESCRIPTOR_SIZE +
 	 USB_INTERFACE_DESCRIPTOR_SIZE +
@@ -2781,7 +2797,7 @@
 static const
 usb_interface_descriptor_t ehci_ifcd = 
 {
-	USB_INTERFACE_DESCRIPTOR_SIZE,
+	sizeof(usb_interface_descriptor_t),
 	UDESC_INTERFACE,
 	0,
 	0,
@@ -2795,7 +2811,7 @@
 static const
 usb_endpoint_descriptor_t ehci_endpd =
 {
-	USB_ENDPOINT_DESCRIPTOR_SIZE,
+	sizeof(usb_endpoint_descriptor_t),
 	UDESC_ENDPOINT,
 	UE_DIR_IN | EHCI_INTR_ENDPT,
 	UE_INTERRUPT,
@@ -2806,7 +2822,7 @@
 static const
 usb_hub_descriptor_t ehci_hubd =
 {
-	USB_HUB_DESCRIPTOR_SIZE,
+	0, /* dynamic length */
 	UDESC_HUB,
 	0,
 	{0,0},
@@ -2815,28 +2831,6 @@
 	{0},
 };
 
-static int
-ehci_str(usb_string_descriptor_t *p, int l, char *s)
-{
-	int i;
-
-	if(l == 0)
-	{
-		return (0);
-	}
-	p->bLength = (2 * strlen(s)) + 2;
-	if(l == 1)
-	{
-		return (1);
-	}
-	p->bDescriptorType = UDESC_STRING;
-	l -= 2;
-	for(i = 0; s[i] && (l > 1); i++, l -= 2)
-	{
-		USETW2(p->bString[i], 0, s[i]);
-	}
-	return ((2 * i) + 2);
-}
 
 static void
 ehci_disown(ehci_softc_t *sc, int index, int lowspeed)
@@ -2855,38 +2849,59 @@
 ehci_root_ctrl_enter(struct usbd_xfer *xfer)
 {
 	ehci_softc_t *sc = xfer->usb_sc;
-	usb_device_request_t *req = xfer->buffer;
-	void *buf;
-	int port, i;
-	int len, value, index, l, totlen = 0;
-	usb_port_status_t ps;
-	usb_hub_descriptor_t hubd;
+	u_int32_t port;
+	u_int32_t v;
+	u_int16_t i;
+	u_int16_t len;
+	u_int16_t value;
+	u_int16_t index;
+	u_int16_t l;
+	u_int16_t totlen = 0;
+	union {
+	  usb_status_t stat;
+	  usb_port_status_t ps;
+	  usb_device_request_t req;
+	  usb_hub_descriptor_t hubd;
+	  usb_device_descriptor_t devd;
+	  usb_device_qualifier_t odevd;
+	  usb_config_descriptor_t confd;
+	  usb_interface_descriptor_t ifcd;
+	  usb_endpoint_descriptor_t endpd;
+	  u_int8_t str_temp[128];
+	  u_int8_t byte_temp;
+	} u;
 	usbd_status err;
-	u_int32_t v;
 
-	DPRINTFN(2,("type=0x%02x request=0x%02x\n",
-		    req->bmRequestType, req->bRequest));
+	mtx_assert(&sc->sc_bus.mtx, MA_OWNED);
 
-	mtx_assert(&sc->sc_bus.mtx, MA_OWNED);
+	if (xfer->length < sizeof(u.req)) {
+	    err = USBD_INVAL;
+	    goto done;
+	}
 
 	/* set default actual length */
-	xfer->actlen = sizeof(*req);
+	xfer->actlen = sizeof(u.req);
+
+	/* copy out "request" */
+	usbd_copy_out(&(xfer->buf_data), 0, &u.req, sizeof(u.req));
 
-	len = UGETW(req->wLength);
-	value = UGETW(req->wValue);
-	index = UGETW(req->wIndex);
+	len = (xfer->length - sizeof(u.req));
 
-	if(len != 0)
-	{
-		buf = (req+1);
+	if (len != UGETW(u.req.wLength)) {
+	    err = USBD_INVAL;
+	    goto done;
 	}
-	else
-	{
-		buf = NULL;
-	}
+
+	value = UGETW(u.req.wValue);
+	index = UGETW(u.req.wIndex);
+
+	DPRINTFN(2,("type=0x%02x request=0x%02x wLen=0x%04x "
+		    "wValue=0x%04x wIndex=0x%04x\n",
+		    u.req.bmRequestType, u.req.bRequest,
+		    len, value, index));
 
 #define C(x,y) ((x) | ((y) << 8))
-	switch(C(req->bRequest, req->bmRequestType)) {
+	switch(C(u.req.bRequest, u.req.bmRequestType)) {
 	case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE):
 	case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE):
 	case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
@@ -2898,12 +2913,13 @@
 	case C(UR_GET_CONFIG, UT_READ_DEVICE):
 		if(len > 0)
 		{
-			*(u_int8_t *)buf = sc->sc_conf;
-			totlen = 1;
+		    u.byte_temp = sc->sc_conf;
+		    totlen = 1;
+		    usbd_copy_in(&(xfer->buf_data), sizeof(u.req),
+				 &u, totlen);
 		}
 		break;
 	case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
-		DPRINTFN(8,("wValue=0x%04x\n", value));
 		switch(value >> 8) {
 		case UDESC_DEVICE:
 			if((value & 0xff) != 0)
@@ -2911,19 +2927,20 @@
 				err = USBD_IOERROR;
 				goto done;
 			}
-			totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE);
-			memcpy(buf, &ehci_devd, l);
+			totlen = min(len, sizeof(u.devd));
+
+			u.devd = ehci_devd;
 #if 0
-			if(len >= 12)
-			{
-			  USETW(((usb_device_descriptor_t *)buf)->idVendor,
-				sc->sc_id_vendor);
-			}
+			USETW(u.devd.idVendor,
+			      sc->sc_id_vendor);
 #endif
+			usbd_copy_in(&(xfer->buf_data), sizeof(u.req),
+				     &u, totlen);
 			break;
 		/*
-		 * We can't really operate at another speed, but the spec says
-		 * we need this descriptor.
+		 * We can't really operate at another speed, 
+		 * but the specification says we need this
+		 * descriptor:
 		 */
 		case UDESC_DEVICE_QUALIFIER:
 			if((value & 0xff) != 0)
@@ -2931,12 +2948,14 @@
 				err = USBD_IOERROR;
 				goto done;
 			}
-			totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE);
-			memcpy(buf, &ehci_odevd, l);
+			totlen = min(len, sizeof(ehci_odevd));
+			usbd_copy_in(&(xfer->buf_data), sizeof(u.req),
+				     &ehci_odevd, totlen);
 			break;
 		/*
-		 * We can't really operate at another speed, but the spec says
-		 * we need this descriptor.
+		 * We can't really operate at another speed, 
+		 * but the specification says we need this 
+		 * descriptor:
 		 */
 		case UDESC_OTHER_SPEED_CONFIGURATION:
 		case UDESC_CONFIG:
@@ -2945,40 +2964,67 @@
 				err = USBD_IOERROR;
 				goto done;
 			}
-			totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE);
-			memcpy(buf, &ehci_confd, l);
-			((usb_config_descriptor_t *)buf)->bDescriptorType =
-				value >> 8;
-			buf = ((u_int8_t *)buf) + l;
+			totlen = l = min(len, sizeof(u.confd));
 			len -= l;
-			l = min(len, USB_INTERFACE_DESCRIPTOR_SIZE);
+
+			u.confd = ehci_confd;
+			u.confd.bDescriptorType = (value >> 8);
+
+			usbd_copy_in(&(xfer->buf_data), sizeof(u.req),
+				     &u, l);
+
+			l = min(len, sizeof(ehci_ifcd));
 			totlen += l;
-			memcpy(buf, &ehci_ifcd, l);
-			buf = ((u_int8_t *)buf) + l;
 			len -= l;
-			l = min(len, USB_ENDPOINT_DESCRIPTOR_SIZE);
+
+			usbd_copy_in(&(xfer->buf_data), sizeof(u.req) +
+				     sizeof(u.confd), &ehci_ifcd, l);
+
+			l = min(len, sizeof(ehci_endpd));
 			totlen += l;
-			memcpy(buf, &ehci_endpd, l);
+			len -= l;
+
+			usbd_copy_in(&(xfer->buf_data), sizeof(u.req) +
+				     sizeof(u.confd) + sizeof(u.ifcd),
+				     &ehci_endpd, l);
 			break;
+
 		case UDESC_STRING:
 			if(len == 0)
 			{
 				break;
 			}
-			*(u_int8_t *)buf = 0;
-			totlen = 1;
+
 			switch (value & 0xff) {
 			case 0: /* Language table */
-				totlen = ehci_str(buf, len, "\001");
-				break;
+			    totlen = usbd_make_str_desc
+			      (u.str_temp, sizeof(u.str_temp), 
+			       "\001");
+			    break;
+
 			case 1: /* Vendor */
-				totlen = ehci_str(buf, len, sc->sc_vendor);
-				break;
+			    totlen = usbd_make_str_desc
+			      (u.str_temp, sizeof(u.str_temp), 
+			       sc->sc_vendor);
+			    break;
+
 			case 2: /* Product */
-				totlen = ehci_str(buf, len, "EHCI root hub");
-				break;
+			    totlen = usbd_make_str_desc
+			      (u.str_temp, sizeof(u.str_temp), 
+			       "EHCI root hub");
+			    break;
 
+			default:
+			    totlen = usbd_make_str_desc
+			      (u.str_temp, sizeof(u.str_temp),
+			       "");
+			    break;
 			}

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list