From owner-p4-projects@FreeBSD.ORG Sun Sep 23 16:22:39 2007 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 603EE16A421; Sun, 23 Sep 2007 16:22:39 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2ECC816A420 for ; Sun, 23 Sep 2007 16:22:39 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 0B66D13C44B for ; Sun, 23 Sep 2007 16:22:39 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id l8NGMc8G096913 for ; Sun, 23 Sep 2007 16:22:38 GMT (envelope-from hselasky@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id l8NGMcxN096910 for perforce@freebsd.org; Sun, 23 Sep 2007 16:22:38 GMT (envelope-from hselasky@FreeBSD.org) Date: Sun, 23 Sep 2007 16:22:38 GMT Message-Id: <200709231622.l8NGMcxN096910@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky To: Perforce Change Reviews Cc: Subject: PERFORCE change 126744 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 23 Sep 2007 16:22:39 -0000 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; }