mirror of https://github.com/ipxe/ipxe.git
[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>pull/41/head
parent
8baefad659
commit
f9e192605c
|
@ -530,6 +530,7 @@ int usb_stream ( struct usb_endpoint *ep, struct io_buffer *iobuf,
|
||||||
int terminate ) {
|
int terminate ) {
|
||||||
struct usb_device *usb = ep->usb;
|
struct usb_device *usb = ep->usb;
|
||||||
struct usb_port *port = usb->port;
|
struct usb_port *port = usb->port;
|
||||||
|
int zlp;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Fail immediately if device has been unplugged */
|
/* 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 ) )
|
( ( rc = usb_endpoint_reset ( ep ) ) != 0 ) )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
/* Append a zero-length packet if necessary */
|
||||||
|
zlp = terminate;
|
||||||
|
if ( iob_len ( iobuf ) & ( ep->mtu - 1 ) )
|
||||||
|
zlp = 0;
|
||||||
|
|
||||||
/* Enqueue stream transfer */
|
/* 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",
|
DBGC ( usb, "USB %s %s could not enqueue stream transfer: %s\n",
|
||||||
usb->name, usb_endpoint_name ( ep ), strerror ( rc ) );
|
usb->name, usb_endpoint_name ( ep ), strerror ( rc ) );
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -1223,11 +1223,11 @@ static int ehci_endpoint_message ( struct usb_endpoint *ep,
|
||||||
*
|
*
|
||||||
* @v ep USB endpoint
|
* @v ep USB endpoint
|
||||||
* @v iobuf I/O buffer
|
* @v iobuf I/O buffer
|
||||||
* @v terminate Terminate using a short packet
|
* @v zlp Append a zero-length packet
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
static int ehci_endpoint_stream ( struct usb_endpoint *ep,
|
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_endpoint *endpoint = usb_endpoint_get_hostdata ( ep );
|
||||||
struct ehci_device *ehci = endpoint->ehci;
|
struct ehci_device *ehci = endpoint->ehci;
|
||||||
unsigned int input = ( ep->address & USB_DIR_IN );
|
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 |
|
xfer->flags = ( EHCI_FL_IOC |
|
||||||
( input ? EHCI_FL_PID_IN : EHCI_FL_PID_OUT ) );
|
( input ? EHCI_FL_PID_IN : EHCI_FL_PID_OUT ) );
|
||||||
xfer++;
|
xfer++;
|
||||||
if ( terminate && ( ( len & ( ep->mtu - 1 ) ) == 0 ) ) {
|
if ( zlp ) {
|
||||||
xfer->data = NULL;
|
xfer->data = NULL;
|
||||||
xfer->len = 0;
|
xfer->len = 0;
|
||||||
assert ( ! input );
|
assert ( ! input );
|
||||||
|
|
|
@ -835,22 +835,20 @@ static int uhci_endpoint_message ( struct usb_endpoint *ep,
|
||||||
*
|
*
|
||||||
* @v ep USB endpoint
|
* @v ep USB endpoint
|
||||||
* @v iobuf I/O buffer
|
* @v iobuf I/O buffer
|
||||||
* @v terminate Terminate using a short packet
|
* @v zlp Append a zero-length packet
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
static int uhci_endpoint_stream ( struct usb_endpoint *ep,
|
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_endpoint *endpoint = usb_endpoint_get_hostdata ( ep );
|
||||||
struct uhci_ring *ring = &endpoint->ring;
|
struct uhci_ring *ring = &endpoint->ring;
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
size_t len;
|
size_t len;
|
||||||
int input;
|
int input;
|
||||||
int zlp;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Calculate number of descriptors */
|
/* Calculate number of descriptors */
|
||||||
len = iob_len ( iobuf );
|
len = iob_len ( iobuf );
|
||||||
zlp = ( terminate && ( ( len & ( ring->mtu - 1 ) ) == 0 ) );
|
|
||||||
count = ( ( ( len + ring->mtu - 1 ) / ring->mtu ) + ( zlp ? 1 : 0 ) );
|
count = ( ( ( len + ring->mtu - 1 ) / ring->mtu ) + ( zlp ? 1 : 0 ) );
|
||||||
|
|
||||||
/* Enqueue transfer */
|
/* Enqueue transfer */
|
||||||
|
|
|
@ -1005,17 +1005,14 @@ static int usbio_endpoint_message ( struct usb_endpoint *ep,
|
||||||
*
|
*
|
||||||
* @v ep USB endpoint
|
* @v ep USB endpoint
|
||||||
* @v iobuf I/O buffer
|
* @v iobuf I/O buffer
|
||||||
* @v terminate Terminate using a short packet
|
* @v zlp Append a zero-length packet
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
static int usbio_endpoint_stream ( struct usb_endpoint *ep,
|
static int usbio_endpoint_stream ( struct usb_endpoint *ep,
|
||||||
struct io_buffer *iobuf, int terminate ) {
|
struct io_buffer *iobuf, int zlp ) {
|
||||||
size_t len = iob_len ( iobuf );
|
|
||||||
int zlen;
|
|
||||||
|
|
||||||
/* Enqueue transfer */
|
/* Enqueue transfer */
|
||||||
zlen = ( terminate && ( ( len & ( ep->mtu - 1 ) ) == 0 ) );
|
return usbio_endpoint_enqueue ( ep, iobuf, ( zlp ? USBIO_ZLEN : 0 ) );
|
||||||
return usbio_endpoint_enqueue ( ep, iobuf, ( zlen ? USBIO_ZLEN : 0 ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2546,11 +2546,11 @@ static int xhci_endpoint_message ( struct usb_endpoint *ep,
|
||||||
*
|
*
|
||||||
* @v ep USB endpoint
|
* @v ep USB endpoint
|
||||||
* @v iobuf I/O buffer
|
* @v iobuf I/O buffer
|
||||||
* @v terminate Terminate using a short packet
|
* @v zlp Append a zero-length packet
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
static int xhci_endpoint_stream ( struct usb_endpoint *ep,
|
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 );
|
struct xhci_endpoint *endpoint = usb_endpoint_get_hostdata ( ep );
|
||||||
union xhci_trb trbs[ 1 /* Normal */ + 1 /* Possible zero-length */ ];
|
union xhci_trb trbs[ 1 /* Normal */ + 1 /* Possible zero-length */ ];
|
||||||
union xhci_trb *trb = trbs;
|
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->data = cpu_to_le64 ( virt_to_phys ( iobuf->data ) );
|
||||||
normal->len = cpu_to_le32 ( len );
|
normal->len = cpu_to_le32 ( len );
|
||||||
normal->type = XHCI_TRB_NORMAL;
|
normal->type = XHCI_TRB_NORMAL;
|
||||||
if ( terminate && ( ( len & ( ep->mtu - 1 ) ) == 0 ) ) {
|
if ( zlp ) {
|
||||||
normal->flags = XHCI_TRB_CH;
|
normal->flags = XHCI_TRB_CH;
|
||||||
normal = &(trb++)->normal;
|
normal = &(trb++)->normal;
|
||||||
normal->type = XHCI_TRB_NORMAL;
|
normal->type = XHCI_TRB_NORMAL;
|
||||||
|
|
|
@ -458,11 +458,11 @@ struct usb_endpoint_host_operations {
|
||||||
*
|
*
|
||||||
* @v ep USB endpoint
|
* @v ep USB endpoint
|
||||||
* @v iobuf I/O buffer
|
* @v iobuf I/O buffer
|
||||||
* @v terminate Terminate using a short packet
|
* @v zlp Append a zero-length packet
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
int ( * stream ) ( struct usb_endpoint *ep, struct io_buffer *iobuf,
|
int ( * stream ) ( struct usb_endpoint *ep, struct io_buffer *iobuf,
|
||||||
int terminate );
|
int zlp );
|
||||||
};
|
};
|
||||||
|
|
||||||
/** USB endpoint driver operations */
|
/** USB endpoint driver operations */
|
||||||
|
|
Loading…
Reference in New Issue