Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 23 Sep 2007 16:22:38 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 126744 for review
Message-ID:  <200709231622.l8NGMcxN096910@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=126744

Change 126744 by hselasky@hselasky_laptop001 on 2007/09/23 16:22:02

	
	FYI; The comments follow the P4 diff from top to bottom.
	
	- "usb_cdev_read_wakeup()"; factored out code
	
	- "usb_cdev_write_wakeup()"; factored out code
	
	- new mechanism to force frame synchronsation: To every data
	  packet a last packet bit is added, like in Wireless USB. When
	  this is set the "usb_cdev_read()" function will stop reading
	  and return data to the caller. Else it will continue reading
	  more data.
	
	- add missing start of read transfer in "usb_cdev_poll()".
	
	- new global function "usb_cdev_put_bytes_max()" to get the
	  maximum receive buffer size. Might be useful when setting up
	  USB read transfer.
	
	- "usb_cdev_put_data()" and "usb_cdev_get_data()" now
	  transfers data directly to/from USB DMA memory.
	
	- "usb_cdev_put_data_linear()" provides the same functionality
	  as "usb_cdev_put_data()" only operating on a linear buffer.
	
	- "usb_cdev_get_data_linear()" provides the same functionality
	  as "usb_cdev_get_data()" only operating on a linear buffer.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/usb_cdev.c#14 edit

Differences ...

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

@@ -219,6 +219,49 @@
 	return;
 }
 
+static void
+usb_cdev_read_wakeup(struct usb_cdev *sc)
+{
+	if (sc->sc_flags &   USB_CDEV_FLAG_WAKEUP_READ) {
+	    sc->sc_flags &= ~USB_CDEV_FLAG_WAKEUP_READ;
+	    wakeup(&(sc->sc_wakeup_read));
+	}
+
+	if (sc->sc_flags &   USB_CDEV_FLAG_SELECT_READ) {
+	    sc->sc_flags &= ~USB_CDEV_FLAG_SELECT_READ;
+	    selwakeup(&(sc->sc_read_sel));
+	}
+
+	if (sc->sc_async_rd != NULL) {
+	    PROC_LOCK(sc->sc_async_rd);
+	    psignal(sc->sc_async_rd, SIGIO);
+	    PROC_UNLOCK(sc->sc_async_rd);
+	}
+
+	return;
+}
+
+static void
+usb_cdev_write_wakeup(struct usb_cdev *sc)
+{
+	if (sc->sc_flags &   USB_CDEV_FLAG_WAKEUP_WRITE) {
+	    sc->sc_flags &= ~USB_CDEV_FLAG_WAKEUP_WRITE;
+	    wakeup(&(sc->sc_wakeup_write));
+	}
+
+	if (sc->sc_flags &   USB_CDEV_FLAG_SELECT_WRITE) {
+	    sc->sc_flags &= ~USB_CDEV_FLAG_SELECT_WRITE;
+	    selwakeup(&(sc->sc_write_sel));
+	}
+
+	if (sc->sc_async_wr != NULL) {
+	    PROC_LOCK(sc->sc_async_wr);
+	    psignal(sc->sc_async_wr, SIGIO);
+	    PROC_UNLOCK(sc->sc_async_wr);
+	}
+	return;
+}
+
 void
 usb_cdev_unlock(struct usb_cdev *sc, int32_t fflags)
 {
@@ -775,14 +818,16 @@
 	    m->cur_data_ptr += io_len;
 
 	    if (m->cur_data_len == 0) {
+
+	        uint8_t last_packet;
+
+		last_packet = m->last_packet;
+
 	        USBD_IF_ENQUEUE(&(sc->sc_rdq_free), m);
 
-		if (sc->sc_flags & USB_CDEV_FLAG_FWD_SHORT) {
-		    /* forward short transfers to userland */
-		    if ((m->cur_data_ptr - m->min_data_ptr) < m->max_data_len) {
-		        /* short transfer */
-		        break;
-		    }
+		if (last_packet) {
+		    /* keep framing */
+		    break;
 		}
 
 	    } else {
@@ -943,6 +988,9 @@
 	    } else {
 	        sc->sc_flags |= USB_CDEV_FLAG_SELECT_READ;
 		selrecord(td, &(sc->sc_read_sel));
+
+		/* start reading data */
+		(sc->sc_start_read)(sc);
 	    }
 	}
 
@@ -1204,14 +1252,32 @@
 	return;
 }
 
-/*
+uint32_t
+usb_cdev_put_bytes_max(struct usb_cdev *sc)
+{
+	struct usbd_mbuf *m;
+	uint32_t len;
+
+	USBD_IF_POLL(&(sc->sc_rdq_free), m);
+
+	if (m) {
+	  len = m->max_data_len;
+	} else {
+	  len = 0;
+	}
+	return len;
+}
+
+/*------------------------------------------------------------------------*
+ *	usb_cdev_put_data
+ *
  * what: 
  *  0 - normal operation
- *  1 - force short packet
- */
+ *  1 - set last packet flag to enforce framing
+ *------------------------------------------------------------------------*/
 void
-usb_cdev_put_data(struct usb_cdev *sc, u_int8_t *buf, u_int32_t len, 
-		  u_int8_t what)
+usb_cdev_put_data(struct usb_cdev *sc, struct usbd_page_cache *pc,
+		  uint32_t offset, uint32_t len, uint8_t what)
 {
 	struct usbd_mbuf *m;
 	u_int32_t io_len;
@@ -1225,35 +1291,73 @@
 
 		io_len = min(len, m->cur_data_len);
 
-		bcopy(buf, m->cur_data_ptr, io_len);
+		usbd_copy_out(pc, offset, m->cur_data_ptr, io_len);
 
 		m->cur_data_len = io_len;
-		buf += io_len;
+		offset += io_len;
 		len -= io_len;
 
+		if ((len == 0) && (what == 1)) {
+		    m->last_packet = 1;
+		}
+
 		USBD_IF_ENQUEUE(&(sc->sc_rdq_used), m);
 
+		/* check if we should do a wakeup */
+
 		if ((sc->sc_rdq_used.ifq_len >= 
 		     ((sc->sc_rdq_used.ifq_maxlen+1)/2)) ||
 		    (sc->sc_flags & USB_CDEV_FLAG_WAKEUP_RD_IMMED)) {
 
-		    /* buffer is half full */
+		    usb_cdev_read_wakeup(sc);
+		}
+
+		if ((len == 0) || (what == 1)) {
+		    break;
+		}
+
+	    } else {
+		break;
+	    }
+	}
+	return;
+}
+
+void
+usb_cdev_put_data_linear(struct usb_cdev *sc, void *ptr, 
+			 uint32_t len, uint8_t what)
+{
+	struct usbd_mbuf *m;
+	u_int32_t io_len;
+
+	while (len || (what == 1)) {
+
+	    USBD_IF_DEQUEUE(&(sc->sc_rdq_free), m);
+
+	    if (m) {
+	        USBD_MBUF_RESET(m);
+
+		io_len = min(len, m->cur_data_len);
+
+		bcopy(ptr, m->cur_data_ptr, io_len);
+
+		m->cur_data_len = io_len;
+		ptr = USBD_ADD_BYTES(ptr, io_len);
+		len -= io_len;
+
+		if ((len == 0) && (what == 1)) {
+		    m->last_packet = 1;
+		}
+
+		USBD_IF_ENQUEUE(&(sc->sc_rdq_used), m);
 
-		    if (sc->sc_flags &   USB_CDEV_FLAG_WAKEUP_READ) {
-		        sc->sc_flags &= ~USB_CDEV_FLAG_WAKEUP_READ;
-			wakeup(&(sc->sc_wakeup_read));
-		    }
+		/* check if we should do a wakeup */
 
-		    if (sc->sc_flags &   USB_CDEV_FLAG_SELECT_READ) {
-		        sc->sc_flags &= ~USB_CDEV_FLAG_SELECT_READ;
-			selwakeup(&(sc->sc_read_sel));
-		    }
+		if ((sc->sc_rdq_used.ifq_len >= 
+		     ((sc->sc_rdq_used.ifq_maxlen+1)/2)) ||
+		    (sc->sc_flags & USB_CDEV_FLAG_WAKEUP_RD_IMMED)) {
 
-		    if (sc->sc_async_rd != NULL) {
-		        PROC_LOCK(sc->sc_async_rd);
-			psignal(sc->sc_async_rd, SIGIO);
-			PROC_UNLOCK(sc->sc_async_rd);
-		    }
+		    usb_cdev_read_wakeup(sc);
 		}
 
 		if ((len == 0) || (what == 1)) {
@@ -1272,36 +1376,25 @@
 {
 	sc->sc_flags |= USB_CDEV_FLAG_ERROR_READ;
 
-	if (sc->sc_flags &   USB_CDEV_FLAG_WAKEUP_READ) {
-	    sc->sc_flags &= ~USB_CDEV_FLAG_WAKEUP_READ;
-	    wakeup(&(sc->sc_wakeup_read));
-	}
-
-	if (sc->sc_flags &   USB_CDEV_FLAG_SELECT_READ) {
-	    sc->sc_flags &= ~USB_CDEV_FLAG_SELECT_READ;
-	    selwakeup(&(sc->sc_read_sel));
-	}
-
-	if (sc->sc_async_rd != NULL) {
-	    PROC_LOCK(sc->sc_async_rd);
-	    psignal(sc->sc_async_rd, SIGIO);
-	    PROC_UNLOCK(sc->sc_async_rd);
-	}
+	usb_cdev_read_wakeup(sc);
 	return;
 }
 
-/*
+/*------------------------------------------------------------------------*
+ *	usb_cdev_get_data
+ *
  * what: 
  *  0 - normal operation
- *  1 - force only one packet
+ *  1 - only get one "usbd_mbuf"
  *
  * returns:
  *  0 - no more data
  *  1 - data in buffer
- */
-u_int8_t
-usb_cdev_get_data(struct usb_cdev *sc, u_int8_t *buf, u_int32_t len, 
-		  u_int32_t *actlen, u_int8_t what)
+ *------------------------------------------------------------------------*/
+uint8_t
+usb_cdev_get_data(struct usb_cdev *sc, struct usbd_page_cache *pc, 
+		  uint32_t offset, uint32_t len, uint32_t *actlen,
+		  uint8_t what)
 {
 	struct usbd_mbuf *m;
 	u_int32_t io_len;
@@ -1319,10 +1412,10 @@
 
 	        io_len = min(len, m->cur_data_len);
 
-		bcopy(m->cur_data_ptr, buf, io_len);
+		usbd_copy_in(pc, offset, m->cur_data_ptr, io_len);
 
 		len -= io_len;
-		buf += io_len;
+		offset += io_len;
 		actlen[0] += io_len;
 		m->cur_data_ptr += io_len;
 		m->cur_data_len -= io_len;
@@ -1334,23 +1427,72 @@
 			 ((sc->sc_wrq_free.ifq_maxlen+1)/2)) ||
 			(sc->sc_flags & USB_CDEV_FLAG_WAKEUP_WR_IMMED)) {
 
-		        /* buffer is half full */
+			usb_cdev_write_wakeup(sc);
+		    }
+
+		    if (what == 1) {
+		        break;
+		    }
+
+		} else {
+	            USBD_IF_PREPEND(&(sc->sc_wrq_used), m);
+		}
+	    } else {
+
+		if (tr_data) {
+		   /* wait for data to be written out */
+		   break;
+		}
+
+	        if (sc->sc_flags &   USB_CDEV_FLAG_FLUSHING_WRITE) {
+		    sc->sc_flags &= ~USB_CDEV_FLAG_FLUSHING_WRITE;
+		    wakeup(&(sc->sc_wakeup_flush));
+		}
+		break;
+	    }
+	    if (len == 0) {
+	        break;
+	    }
+	}
+	return tr_data;
+}
+
+uint8_t
+usb_cdev_get_data_linear(struct usb_cdev *sc, void *ptr,
+			 uint32_t len, uint32_t *actlen, uint8_t what)
+{
+	struct usbd_mbuf *m;
+	u_int32_t io_len;
+	u_int8_t tr_data = 0;
+
+	actlen[0] = 0;
+
+	while(1) {
+
+	    USBD_IF_DEQUEUE(&(sc->sc_wrq_used), m);
+
+	    if (m) {
+
+	        tr_data = 1;
+
+	        io_len = min(len, m->cur_data_len);
+
+		bcopy(m->cur_data_ptr, ptr, io_len);
+
+		len -= io_len;
+		ptr = USBD_ADD_BYTES(ptr, io_len);
+		actlen[0] += io_len;
+		m->cur_data_ptr += io_len;
+		m->cur_data_len -= io_len;
 
-		        if (sc->sc_flags &   USB_CDEV_FLAG_WAKEUP_WRITE) {
-			    sc->sc_flags &= ~USB_CDEV_FLAG_WAKEUP_WRITE;
-			    wakeup(&(sc->sc_wakeup_write));
-			}
+		if ((m->cur_data_len == 0) || (what == 1)) {
+		    USBD_IF_ENQUEUE(&(sc->sc_wrq_free), m);
 
-			if (sc->sc_flags &   USB_CDEV_FLAG_SELECT_WRITE) {
-			    sc->sc_flags &= ~USB_CDEV_FLAG_SELECT_WRITE;
-			    selwakeup(&(sc->sc_write_sel));
-			}
+		    if ((sc->sc_wrq_free.ifq_len >= 
+			 ((sc->sc_wrq_free.ifq_maxlen+1)/2)) ||
+			(sc->sc_flags & USB_CDEV_FLAG_WAKEUP_WR_IMMED)) {
 
-			if (sc->sc_async_wr != NULL) {
-			    PROC_LOCK(sc->sc_async_wr);
-			    psignal(sc->sc_async_wr, SIGIO);
-			    PROC_UNLOCK(sc->sc_async_wr);
-			}
+			usb_cdev_write_wakeup(sc);
 		    }
 
 		    if (what == 1) {
@@ -1385,26 +1527,8 @@
 {
 	sc->sc_flags |= USB_CDEV_FLAG_ERROR_WRITE;
 
-	if (sc->sc_flags &   USB_CDEV_FLAG_WAKEUP_WRITE) {
-	    sc->sc_flags &= ~USB_CDEV_FLAG_WAKEUP_WRITE;
-	    wakeup(&(sc->sc_wakeup_write));
-	}
-
-	if (sc->sc_flags &   USB_CDEV_FLAG_SELECT_WRITE) {
-	    sc->sc_flags &= ~USB_CDEV_FLAG_SELECT_WRITE;
-	    selwakeup(&(sc->sc_write_sel));
-	}
-
-	if (sc->sc_flags &   USB_CDEV_FLAG_FLUSHING_WRITE) {
-	    sc->sc_flags &= ~USB_CDEV_FLAG_FLUSHING_WRITE;
-	    wakeup(&(sc->sc_wakeup_flush));
-	}
+	usb_cdev_write_wakeup(sc);
 
-	if (sc->sc_async_wr != NULL) {
-	    PROC_LOCK(sc->sc_async_wr);
-	    psignal(sc->sc_async_wr, SIGIO);
-	    PROC_UNLOCK(sc->sc_async_wr);
-	}
 	return;
 }
 



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