PERFORCE change 126744 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Sun Sep 23 09:22:39 PDT 2007
http://perforce.freebsd.org/chv.cgi?CH=126744
Change 126744 by hselasky at 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;
}
More information about the p4-projects
mailing list