Better estimate the maximum USB transfer size.
This commit is contained in:
parent
2f1071d57e
commit
5dd6f58789
6 changed files with 85 additions and 44 deletions
|
@ -1,3 +1,7 @@
|
|||
2013-03-19 Aleš Nesrsta <starous@volny.cz>
|
||||
|
||||
Better estimate the maximum USB transfer size.
|
||||
|
||||
2013-03-17 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
Resend a packet if we got the wrong buffer in status.
|
||||
|
|
|
@ -1902,7 +1902,9 @@ static struct grub_usb_controller_dev usb_controller = {
|
|||
.cancel_transfer = grub_ehci_cancel_transfer,
|
||||
.hubports = grub_ehci_hubports,
|
||||
.portstatus = grub_ehci_portstatus,
|
||||
.detect_dev = grub_ehci_detect_dev
|
||||
.detect_dev = grub_ehci_detect_dev,
|
||||
/* estimated max. count of TDs for one bulk transfer */
|
||||
.max_bulk_tds = GRUB_EHCI_N_TD * 3 / 4
|
||||
};
|
||||
|
||||
GRUB_MOD_INIT (ehci)
|
||||
|
|
|
@ -1431,7 +1431,9 @@ static struct grub_usb_controller_dev usb_controller =
|
|||
.cancel_transfer = grub_ohci_cancel_transfer,
|
||||
.hubports = grub_ohci_hubports,
|
||||
.portstatus = grub_ohci_portstatus,
|
||||
.detect_dev = grub_ohci_detect_dev
|
||||
.detect_dev = grub_ohci_detect_dev,
|
||||
/* estimated max. count of TDs for one bulk transfer */
|
||||
.max_bulk_tds = GRUB_OHCI_TDS * 3 / 4
|
||||
};
|
||||
|
||||
static struct grub_preboot *fini_hnd;
|
||||
|
|
|
@ -823,7 +823,9 @@ static struct grub_usb_controller_dev usb_controller =
|
|||
.cancel_transfer = grub_uhci_cancel_transfer,
|
||||
.hubports = grub_uhci_hubports,
|
||||
.portstatus = grub_uhci_portstatus,
|
||||
.detect_dev = grub_uhci_detect_dev
|
||||
.detect_dev = grub_uhci_detect_dev,
|
||||
/* estimated max. count of TDs for one bulk transfer */
|
||||
.max_bulk_tds = N_TD * 3 / 4
|
||||
};
|
||||
|
||||
GRUB_MOD_INIT(uhci)
|
||||
|
|
|
@ -25,6 +25,26 @@
|
|||
#include <grub/usbtrans.h>
|
||||
#include <grub/time.h>
|
||||
|
||||
|
||||
static inline unsigned int
|
||||
grub_usb_bulk_maxpacket (grub_usb_device_t dev, int endpoint)
|
||||
{
|
||||
unsigned int max = 64;
|
||||
|
||||
/* Use the maximum packet size given in the endpoint descriptor. */
|
||||
if (dev->initialized)
|
||||
{
|
||||
struct grub_usb_desc_endp *endpdesc;
|
||||
endpdesc = grub_usb_get_endpdescriptor (dev, endpoint);
|
||||
|
||||
if (endpdesc)
|
||||
max = endpdesc->maxpacket;
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
|
||||
static grub_usb_err_t
|
||||
grub_usb_execute_and_wait_transfer (grub_usb_device_t dev,
|
||||
grub_usb_transfer_t transfer,
|
||||
|
@ -224,20 +244,6 @@ grub_usb_bulk_setup_readwrite (grub_usb_device_t dev,
|
|||
if (type == GRUB_USB_TRANSFER_TYPE_OUT)
|
||||
grub_memcpy ((char *) data, data_in, size);
|
||||
|
||||
/* Use the maximum packet size given in the endpoint descriptor. */
|
||||
if (dev->initialized)
|
||||
{
|
||||
struct grub_usb_desc_endp *endpdesc;
|
||||
endpdesc = grub_usb_get_endpdescriptor (dev, endpoint);
|
||||
|
||||
if (endpdesc)
|
||||
max = endpdesc->maxpacket;
|
||||
else
|
||||
max = 64;
|
||||
}
|
||||
else
|
||||
max = 64;
|
||||
|
||||
/* Create a transfer. */
|
||||
transfer = grub_malloc (sizeof (struct grub_usb_transfer));
|
||||
if (! transfer)
|
||||
|
@ -246,6 +252,8 @@ grub_usb_bulk_setup_readwrite (grub_usb_device_t dev,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
max = grub_usb_bulk_maxpacket (dev, endpoint);
|
||||
|
||||
datablocks = ((size + max - 1) / max);
|
||||
transfer->transcnt = datablocks;
|
||||
transfer->size = size - 1;
|
||||
|
@ -333,43 +341,59 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev,
|
|||
return err;
|
||||
}
|
||||
|
||||
static grub_usb_err_t
|
||||
grub_usb_bulk_readwrite_packetize (grub_usb_device_t dev,
|
||||
int endpoint,
|
||||
grub_transfer_type_t type,
|
||||
grub_size_t size, char *data)
|
||||
{
|
||||
grub_size_t actual, transferred;
|
||||
grub_usb_err_t err;
|
||||
grub_size_t current_size, position;
|
||||
grub_size_t max_bulk_transfer_len = MAX_USB_TRANSFER_LEN;
|
||||
grub_size_t max;
|
||||
|
||||
if (dev->controller.dev->max_bulk_tds)
|
||||
{
|
||||
max = grub_usb_bulk_maxpacket (dev, endpoint);
|
||||
|
||||
/* Calculate max. possible length of bulk transfer */
|
||||
max_bulk_transfer_len = dev->controller.dev->max_bulk_tds * max;
|
||||
}
|
||||
|
||||
for (position = 0, transferred = 0;
|
||||
position < size; position += max_bulk_transfer_len)
|
||||
{
|
||||
current_size = size - position;
|
||||
if (current_size >= max_bulk_transfer_len)
|
||||
current_size = max_bulk_transfer_len;
|
||||
err = grub_usb_bulk_readwrite (dev, endpoint, current_size,
|
||||
&data[position], type, 1000, &actual);
|
||||
transferred += actual;
|
||||
if (err || (current_size != actual)) break;
|
||||
}
|
||||
|
||||
if (!err && transferred != size)
|
||||
err = GRUB_USB_ERR_DATA;
|
||||
return err;
|
||||
}
|
||||
|
||||
grub_usb_err_t
|
||||
grub_usb_bulk_write (grub_usb_device_t dev,
|
||||
int endpoint, grub_size_t size, char *data)
|
||||
{
|
||||
grub_size_t actual;
|
||||
grub_usb_err_t err;
|
||||
|
||||
err = grub_usb_bulk_readwrite (dev, endpoint, size, data,
|
||||
GRUB_USB_TRANSFER_TYPE_OUT, 1000, &actual);
|
||||
if (!err && actual != size)
|
||||
err = GRUB_USB_ERR_DATA;
|
||||
return err;
|
||||
return grub_usb_bulk_readwrite_packetize (dev, endpoint,
|
||||
GRUB_USB_TRANSFER_TYPE_OUT,
|
||||
size, data);
|
||||
}
|
||||
|
||||
grub_usb_err_t
|
||||
grub_usb_bulk_read (grub_usb_device_t dev,
|
||||
int endpoint, grub_size_t size, char *data)
|
||||
{
|
||||
grub_size_t actual, transferred;
|
||||
grub_usb_err_t err;
|
||||
grub_size_t current_size, position;
|
||||
|
||||
for (position = 0, transferred = 0;
|
||||
position < size; position += MAX_USB_TRANSFER_LEN)
|
||||
{
|
||||
current_size = size - position;
|
||||
if (current_size >= MAX_USB_TRANSFER_LEN)
|
||||
current_size = MAX_USB_TRANSFER_LEN;
|
||||
err = grub_usb_bulk_readwrite (dev, endpoint, current_size,
|
||||
&data[position], GRUB_USB_TRANSFER_TYPE_IN, 1000, &actual);
|
||||
transferred += actual;
|
||||
if (err || (current_size != actual) ) break;
|
||||
}
|
||||
|
||||
if (!err && transferred != size)
|
||||
err = GRUB_USB_ERR_DATA;
|
||||
return err;
|
||||
return grub_usb_bulk_readwrite_packetize (dev, endpoint,
|
||||
GRUB_USB_TRANSFER_TYPE_IN,
|
||||
size, data);
|
||||
}
|
||||
|
||||
grub_usb_err_t
|
||||
|
|
|
@ -124,6 +124,13 @@ struct grub_usb_controller_dev
|
|||
|
||||
/* Per controller flag - port reset pending, don't do another reset */
|
||||
grub_uint64_t pending_reset;
|
||||
|
||||
/* Max. number of transfer descriptors used per one bulk transfer */
|
||||
/* The reason is to prevent "exhausting" of TD by large bulk */
|
||||
/* transfer - number of TD is limited in USB host driver */
|
||||
/* Value is calculated/estimated in driver - some TDs should be */
|
||||
/* reserved for posible concurrent control or "interrupt" transfers */
|
||||
grub_size_t max_bulk_tds;
|
||||
|
||||
/* The next host controller. */
|
||||
struct grub_usb_controller_dev *next;
|
||||
|
|
Loading…
Reference in a new issue