Merge Aleš' latest patch

This commit is contained in:
Aleš Nesrsta 2010-06-01 02:10:19 +02:00 committed by Vladimir 'phcoder' Serbinenko
parent 778ff32476
commit 7d4873c26a
8 changed files with 206 additions and 57 deletions

View file

@ -421,7 +421,7 @@ grub_scsi_open (const char *name, grub_disk_t disk)
/* According to USB MS tests specification, issue Test Unit Ready
* until OK */
maxtime = grub_get_time_ms () + 1000;
maxtime = grub_get_time_ms () + 5000; /* It is safer value */
do
{
/* Timeout is necessary - for example in case when we have
@ -519,6 +519,37 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector,
/* XXX: Never reached. */
return GRUB_ERR_NONE;
#if 0 /* Workaround - it works - but very slowly, from some reason
* unknown to me (specially on OHCI). Do not use it. */
/* Split transfer requests to device sector size because */
/* some devices are not able to transfer more than 512-1024 bytes */
grub_err_t err = GRUB_ERR_NONE;
for ( ; size; size--)
{
/* Depending on the type, select a read function. */
switch (scsi->devtype)
{
case grub_scsi_devtype_direct:
err = grub_scsi_read10 (disk, sector, 1, buf);
break;
case grub_scsi_devtype_cdrom:
err = grub_scsi_read12 (disk, sector, 1, buf);
break;
default: /* This should not happen */
return GRUB_ERR_READ_ERROR;
}
if (err)
return err;
sector++;
buf += scsi->blocksize;
}
return err;
#endif
}
static grub_err_t

View file

@ -253,6 +253,7 @@ grub_usbms_transfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
struct grub_usbms_csw status;
static grub_uint32_t tag = 0;
grub_usb_err_t err = GRUB_USB_ERR_NONE;
grub_usb_err_t errCSW = GRUB_USB_ERR_NONE;
int retrycnt = 3 + 1;
grub_size_t i;
@ -290,9 +291,8 @@ grub_usbms_transfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
{
if (err == GRUB_USB_ERR_STALL)
{
grub_usb_clear_halt (dev->dev, dev->in->endp_addr);
grub_usb_clear_halt (dev->dev, dev->out->endp_addr);
goto retry;
goto CheckCSW;
}
return grub_error (GRUB_ERR_IO, "USB Mass Storage request failed");
}
@ -302,7 +302,12 @@ grub_usbms_transfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
{
err = grub_usb_bulk_read (dev->dev, dev->in->endp_addr, size, buf);
grub_dprintf ("usb", "read: %d %d\n", err, GRUB_USB_ERR_STALL);
if (err) goto CheckCSW;
if (err)
{
if (err == GRUB_USB_ERR_STALL)
grub_usb_clear_halt (dev->dev, dev->in->endp_addr);
goto CheckCSW;
}
/* Debug print of received data. */
grub_dprintf ("usb", "buf:\n");
if (size <= 64)
@ -316,6 +321,12 @@ grub_usbms_transfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
err = grub_usb_bulk_write (dev->dev, dev->out->endp_addr, size, buf);
grub_dprintf ("usb", "write: %d %d\n", err, GRUB_USB_ERR_STALL);
grub_dprintf ("usb", "buf:\n");
if (err)
{
if (err == GRUB_USB_ERR_STALL)
grub_usb_clear_halt (dev->dev, dev->out->endp_addr);
goto CheckCSW;
}
/* Debug print of sent data. */
if (size <= 256)
for (i=0; i<size; i++)
@ -326,15 +337,16 @@ grub_usbms_transfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
/* Read the status - (maybe) according to specification. */
CheckCSW:
err = grub_usb_bulk_read (dev->dev, dev->in->endp_addr,
errCSW = grub_usb_bulk_read (dev->dev, dev->in->endp_addr,
sizeof (status), (char *) &status);
if (err)
if (errCSW)
{
grub_usb_clear_halt (dev->dev, dev->in->endp_addr);
err = grub_usb_bulk_read (dev->dev, dev->in->endp_addr,
errCSW = grub_usb_bulk_read (dev->dev, dev->in->endp_addr,
sizeof (status), (char *) &status);
if (err)
if (errCSW)
{ /* Bulk-only reset device. */
grub_dprintf ("usb", "Bulk-only reset device - errCSW\n");
grub_usbms_reset (dev->dev, dev->interface);
grub_usb_clear_halt (dev->dev, dev->in->endp_addr);
grub_usb_clear_halt (dev->dev, dev->out->endp_addr);
@ -347,9 +359,11 @@ CheckCSW:
status.signature, status.tag, status.residue);
grub_dprintf ("usb", "CSW: status=0x%02x\n", status.status);
/* If phase error, do bulk-only reset device. */
if (status.status == 2)
{
/* If phase error or not valid signature, do bulk-only reset device. */
if ((status.status == 2) ||
(status.signature != grub_cpu_to_le32(0x53425355)))
{ /* Bulk-only reset device. */
grub_dprintf ("usb", "Bulk-only reset device - bad status\n");
grub_usbms_reset (dev->dev, dev->interface);
grub_usb_clear_halt (dev->dev, dev->in->endp_addr);
grub_usb_clear_halt (dev->dev, dev->out->endp_addr);
@ -357,9 +371,13 @@ CheckCSW:
goto retry;
}
if (status.status)
/* If "command failed" status or data transfer failed -> error */
if ((status.status || err) && !read_write)
return grub_error (GRUB_ERR_READ_ERROR,
"error communication with USB Mass Storage device");
else if ((status.status || err) && read_write)
return grub_error (GRUB_ERR_WRITE_ERROR,
"error communication with USB Mass Storage device");
return GRUB_ERR_NONE;
}