aboutsummaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2015-09-13 00:49:56 +0100
committerMichael Brown <mcb30@ipxe.org>2015-09-13 12:54:30 +0100
commitf9e192605c7095497438398c2653ede3c78ebe1b (patch)
tree10ee45b16836a8e4bebbce1eb0d506bb98d29620 /src/drivers
parent8baefad65915defc493f28c6d8ac313b1152c858 (diff)
downloadipxe-f9e192605c7095497438398c2653ede3c78ebe1b.zip
ipxe-f9e192605c7095497438398c2653ede3c78ebe1b.tar.gz
ipxe-f9e192605c7095497438398c2653ede3c78ebe1b.tar.bz2
[usb] Generalise zero-length packet generation logic
The decision on whether or not a zero-length packet needs to be transmitted is independent of the host controller and belongs in the USB core. Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/bus/usb.c8
-rw-r--r--src/drivers/usb/ehci.c6
-rw-r--r--src/drivers/usb/uhci.c6
-rw-r--r--src/drivers/usb/usbio.c9
-rw-r--r--src/drivers/usb/xhci.c6
5 files changed, 18 insertions, 17 deletions
diff --git a/src/drivers/bus/usb.c b/src/drivers/bus/usb.c
index c0cd54b..cd80c32 100644
--- a/src/drivers/bus/usb.c
+++ b/src/drivers/bus/usb.c
@@ -530,6 +530,7 @@ int usb_stream ( struct usb_endpoint *ep, struct io_buffer *iobuf,
int terminate ) {
struct usb_device *usb = ep->usb;
struct usb_port *port = usb->port;
+ int zlp;
int rc;
/* Fail immediately if device has been unplugged */
@@ -541,8 +542,13 @@ int usb_stream ( struct usb_endpoint *ep, struct io_buffer *iobuf,
( ( rc = usb_endpoint_reset ( ep ) ) != 0 ) )
return rc;
+ /* Append a zero-length packet if necessary */
+ zlp = terminate;
+ if ( iob_len ( iobuf ) & ( ep->mtu - 1 ) )
+ zlp = 0;
+
/* Enqueue stream transfer */
- if ( ( rc = ep->host->stream ( ep, iobuf, terminate ) ) != 0 ) {
+ if ( ( rc = ep->host->stream ( ep, iobuf, zlp ) ) != 0 ) {
DBGC ( usb, "USB %s %s could not enqueue stream transfer: %s\n",
usb->name, usb_endpoint_name ( ep ), strerror ( rc ) );
return rc;
diff --git a/src/drivers/usb/ehci.c b/src/drivers/usb/ehci.c
index 4124692..0a89ec1 100644
--- a/src/drivers/usb/ehci.c
+++ b/src/drivers/usb/ehci.c
@@ -1223,11 +1223,11 @@ static int ehci_endpoint_message ( struct usb_endpoint *ep,
*
* @v ep USB endpoint
* @v iobuf I/O buffer
- * @v terminate Terminate using a short packet
+ * @v zlp Append a zero-length packet
* @ret rc Return status code
*/
static int ehci_endpoint_stream ( struct usb_endpoint *ep,
- struct io_buffer *iobuf, int terminate ) {
+ struct io_buffer *iobuf, int zlp ) {
struct ehci_endpoint *endpoint = usb_endpoint_get_hostdata ( ep );
struct ehci_device *ehci = endpoint->ehci;
unsigned int input = ( ep->address & USB_DIR_IN );
@@ -1242,7 +1242,7 @@ static int ehci_endpoint_stream ( struct usb_endpoint *ep,
xfer->flags = ( EHCI_FL_IOC |
( input ? EHCI_FL_PID_IN : EHCI_FL_PID_OUT ) );
xfer++;
- if ( terminate && ( ( len & ( ep->mtu - 1 ) ) == 0 ) ) {
+ if ( zlp ) {
xfer->data = NULL;
xfer->len = 0;
assert ( ! input );
diff --git a/src/drivers/usb/uhci.c b/src/drivers/usb/uhci.c
index b6bb925..4220bef 100644
--- a/src/drivers/usb/uhci.c
+++ b/src/drivers/usb/uhci.c
@@ -835,22 +835,20 @@ static int uhci_endpoint_message ( struct usb_endpoint *ep,
*
* @v ep USB endpoint
* @v iobuf I/O buffer
- * @v terminate Terminate using a short packet
+ * @v zlp Append a zero-length packet
* @ret rc Return status code
*/
static int uhci_endpoint_stream ( struct usb_endpoint *ep,
- struct io_buffer *iobuf, int terminate ) {
+ struct io_buffer *iobuf, int zlp ) {
struct uhci_endpoint *endpoint = usb_endpoint_get_hostdata ( ep );
struct uhci_ring *ring = &endpoint->ring;
unsigned int count;
size_t len;
int input;
- int zlp;
int rc;
/* Calculate number of descriptors */
len = iob_len ( iobuf );
- zlp = ( terminate && ( ( len & ( ring->mtu - 1 ) ) == 0 ) );
count = ( ( ( len + ring->mtu - 1 ) / ring->mtu ) + ( zlp ? 1 : 0 ) );
/* Enqueue transfer */
diff --git a/src/drivers/usb/usbio.c b/src/drivers/usb/usbio.c
index 70aa509..a80f7c8 100644
--- a/src/drivers/usb/usbio.c
+++ b/src/drivers/usb/usbio.c
@@ -1005,17 +1005,14 @@ static int usbio_endpoint_message ( struct usb_endpoint *ep,
*
* @v ep USB endpoint
* @v iobuf I/O buffer
- * @v terminate Terminate using a short packet
+ * @v zlp Append a zero-length packet
* @ret rc Return status code
*/
static int usbio_endpoint_stream ( struct usb_endpoint *ep,
- struct io_buffer *iobuf, int terminate ) {
- size_t len = iob_len ( iobuf );
- int zlen;
+ struct io_buffer *iobuf, int zlp ) {
/* Enqueue transfer */
- zlen = ( terminate && ( ( len & ( ep->mtu - 1 ) ) == 0 ) );
- return usbio_endpoint_enqueue ( ep, iobuf, ( zlen ? USBIO_ZLEN : 0 ) );
+ return usbio_endpoint_enqueue ( ep, iobuf, ( zlp ? USBIO_ZLEN : 0 ) );
}
/**
diff --git a/src/drivers/usb/xhci.c b/src/drivers/usb/xhci.c
index 49e6731..f0f8eb1 100644
--- a/src/drivers/usb/xhci.c
+++ b/src/drivers/usb/xhci.c
@@ -2546,11 +2546,11 @@ static int xhci_endpoint_message ( struct usb_endpoint *ep,
*
* @v ep USB endpoint
* @v iobuf I/O buffer
- * @v terminate Terminate using a short packet
+ * @v zlp Append a zero-length packet
* @ret rc Return status code
*/
static int xhci_endpoint_stream ( struct usb_endpoint *ep,
- struct io_buffer *iobuf, int terminate ) {
+ struct io_buffer *iobuf, int zlp ) {
struct xhci_endpoint *endpoint = usb_endpoint_get_hostdata ( ep );
union xhci_trb trbs[ 1 /* Normal */ + 1 /* Possible zero-length */ ];
union xhci_trb *trb = trbs;
@@ -2567,7 +2567,7 @@ static int xhci_endpoint_stream ( struct usb_endpoint *ep,
normal->data = cpu_to_le64 ( virt_to_phys ( iobuf->data ) );
normal->len = cpu_to_le32 ( len );
normal->type = XHCI_TRB_NORMAL;
- if ( terminate && ( ( len & ( ep->mtu - 1 ) ) == 0 ) ) {
+ if ( zlp ) {
normal->flags = XHCI_TRB_CH;
normal = &(trb++)->normal;
normal->type = XHCI_TRB_NORMAL;