]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Merge Aleš' latest patch
authorAleš Nesrsta <starous@volny.cz>
Tue, 1 Jun 2010 00:10:19 +0000 (02:10 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Tue, 1 Jun 2010 00:10:19 +0000 (02:10 +0200)
bus/usb/ohci.c
bus/usb/uhci.c
bus/usb/usbtrans.c
disk/scsi.c
disk/usbms.c
include/grub/usb.h
include/grub/usbtrans.h
term/usb_keyboard.c

index 03768d39e30ab3dbd6fb725e8f648c73b248bd2f..ac6f61ee8fd24d51a073302db873dee43b564ec5 100644 (file)
@@ -116,6 +116,11 @@ typedef enum
 #define GRUB_OHCI_PERIODIC_START 0x257f
 #define GRUB_OHCI_FRAME_INTERVAL 0x2edf
 
+#define GRUB_OHCI_SET_PORT_ENABLE (1 << 1)
+#define GRUB_OHCI_CLEAR_PORT_ENABLE (1 << 0)
+#define GRUB_OHCI_SET_PORT_RESET (1 << 4)
+#define GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE (1 << 20)
+
 static grub_uint32_t
 grub_ohci_readreg32 (struct grub_ohci *o, grub_ohci_reg_t reg)
 {
@@ -281,7 +286,7 @@ grub_ohci_pci_iter (grub_pci_device_t dev,
 
   /* Misc. pre-sets. */
   o->hcca->donehead = 0;
-  grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1)); /* Clears WDH */
+  grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, 0x7f); /* Clears everything */
   grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD, 0);
   grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLCURR, 0);
   grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, 0);
@@ -396,8 +401,10 @@ grub_ohci_transaction (grub_ohci_td_t td,
       break;
     }
 
+#if 0 /* Always generate interrupt */
   /* Generate no interrupts.  */
   token |= 7 << 21;
+#endif
 
   /* Set the token.  */
   token |= toggle << 24;
@@ -444,9 +451,12 @@ grub_ohci_transfer (grub_usb_controller_t dev,
   grub_uint32_t status;
   grub_uint32_t control;
   grub_usb_err_t err;
-  int i, j;
+  int i;
   grub_uint64_t maxtime;
   int err_timeout = 0;
+  int err_unrec = 0;
+  grub_uint32_t intstatus;
+  grub_uint32_t tderr_addr = 0;
 
   /* Allocate an Endpoint Descriptor.  */
   ed_chunk = grub_memalign_dma32 (256, sizeof (*ed));
@@ -479,11 +489,13 @@ grub_ohci_transfer (grub_usb_controller_t dev,
                                             + (i + 1) * sizeof (td_list[0]));
     }
 
+#if 0 /* Better will be enable interrupt on all TDs. */
   /* The last-1 TD token we should change to enable interrupt when TD finishes.
    * As OHCI interrupts are disabled, it does only setting of WDH bit in
    * HcInterruptStatus register - and that is what we want to safely detect
    * normal end of all transactions. */
   td_list[transfer->transcnt - 1].token &= ~(7 << 21);
+#endif
 
   td_list[transfer->transcnt].token = 0;
   td_list[transfer->transcnt].buffer = 0;
@@ -582,9 +594,11 @@ grub_ohci_transfer (grub_usb_controller_t dev,
     }
 
   grub_dprintf ("ohci", "wait for completion\n");
-  grub_dprintf ("ohci", "control=0x%02x status=0x%02x\n",
+  grub_dprintf ("ohci",
+               "begin: control=0x%02x status=0x%02x\n\t\t intstatus=0x%02x\n",
                grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL),
-               grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS));
+               grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS),
+               grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS));
 
   /* Safety measure to avoid a hang. */
   maxtime = grub_get_time_ms () + 1000;
@@ -592,30 +606,34 @@ grub_ohci_transfer (grub_usb_controller_t dev,
   /* Wait until the transfer is completed or STALLs.  */
   do
     {
-      grub_cpu_idle ();
+      /* Check transfer status */
+      intstatus = grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS);
+      if ((intstatus & 0x2) != 0)
+        {
+          grub_dprintf ("ohci", "Current HccaDoneHead=0x%08x\n",
+                       o->hcca->donehead);
+          /* Remember last successful TD */
+          tderr_addr = grub_le_to_cpu32 (o->hcca->donehead) & ~0xf;
+          /* Reset DoneHead */
+         o->hcca->donehead = 0;
+          grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1));
+          /* if TD is last, finish */
+          if (tderr_addr == td_list_addr
+             + sizeof (td_list[0]) * (transfer->transcnt - 1))
+            break;
+           continue;
+        }
+
+      if ((intstatus & 0x10) != 0)
+        { /* Unrecoverable error - only reset can help...! */
+          err_unrec = 1;
+          break;
+        }
 
       /* Detected a HALT.  */
       if (grub_le_to_cpu32 (ed->td_head) & 1)
         break;
-  
-      if ((grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS) & 0x2) != 0)
-        {
-          if ((grub_le_to_cpu32 (o->hcca->donehead) & ~0xf)
-             == td_list_addr + (transfer->transcnt - 1) * sizeof (td_list[0]))
-           break;
-
-          /* Done Head can be updated on some another place if ED is halted. */          
-          if (grub_le_to_cpu32 (ed->td_head) & 1)
-            break;
 
-          /* If there is not HALT in ED, it is not correct, so debug it, reset
-           * donehead and WDH and continue waiting. */
-          grub_dprintf ("ohci", "Incorrect HccaDoneHead=0x%08x\n",
-                        o->hcca->donehead);
-          o->hcca->donehead = 0;
-          grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1));
-          continue;
-        }
       /* Timeout ? */
       if (grub_get_time_ms () > maxtime)
        {
@@ -628,9 +646,45 @@ grub_ohci_transfer (grub_usb_controller_t dev,
 
       if ((ed->td_head & ~0xf) == (ed->td_tail & ~0xf))
        break;
+
+      grub_cpu_idle ();
     }
   while (1);
 
+  grub_dprintf ("ohci", "end: control=0x%02x status=0x%02x\n\t\t intstatus=0x%02x\n",
+               grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL),
+               grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS),
+               grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS));
+
+  if (!tderr_addr)
+    {
+      /* It means that something wrong happened,
+       * it could be:
+       * - timeout and no TD processed
+       * - some or unrecoverable error and no TD processed
+       * - something unexpected... :-( */
+      /* Try look into DONEHEAD reg., but there should be also zero */
+      grub_dprintf("ohci", "HCCA DoneHead is zero, something is bad!\n");
+      tderr_addr = grub_ohci_readreg32 (o, GRUB_OHCI_REG_DONEHEAD) & ~0xf;
+    }
+  
+  /* Remember last processed transaction (TD) - it is necessary for
+   * proper setting of toggle bit in next transaction. */
+  transfer->last_trans = (tderr_addr - td_list_addr) / sizeof (*td_list);
+  
+  /* Check correct value in last_trans */
+  /* It could happen if timeout happens and no TD was retired */
+  if (transfer->last_trans >= transfer->transcnt || !tderr_addr)
+    {
+      grub_dprintf("ohci", "tder==0 or out of TDs range!\n");
+      grub_dprintf("ohci", "tderr_addr=0x%x, td_list=%p,\n\t\t last_trans=%d, transcnt=%d\n",
+                   tderr_addr, td_list, transfer->last_trans, transfer->transcnt);
+      /* We should set something valid... */
+      transfer->last_trans = -1; /* Probably no TD done */
+      tderr_addr = td_list_addr;
+    }
+  /* In case of timeout do not detect error from TD */    
   if (err_timeout)
     {
       err = GRUB_ERR_TIMEOUT;
@@ -640,20 +694,25 @@ grub_ohci_transfer (grub_usb_controller_t dev,
       grub_le_to_cpu32(ed->td_tail),
       grub_le_to_cpu32(ed->next_ed));
     }
+  /* In case of unrecoverable error do not detect error from TD */    
+  else if (err_unrec)
+    {
+      err = GRUB_USB_ERR_UNRECOVERABLE;
+      grub_dprintf("ohci",
+                  "Unrecoverable error, target=%08x, head=%08x\n"
+                  "\t\ttail=%08x, next=%08x\n",
+                  grub_le_to_cpu32(ed->target),
+                  grub_le_to_cpu32(ed->td_head),
+                  grub_le_to_cpu32(ed->td_tail),
+                  grub_le_to_cpu32(ed->next_ed));
+    }
   else if (grub_le_to_cpu32 (ed->td_head) & 1)
     {
-      grub_uint32_t td_err_addr;
       grub_uint8_t errcode;
       grub_ohci_td_t tderr = NULL;
 
-      td_err_addr = (grub_ohci_readreg32 (o, GRUB_OHCI_REG_DONEHEAD) & ~0xf);
-      if (td_err_addr == 0)
-        /* If DONEHEAD==0 it means that correct address is in HCCA.
-         * It should be always now! */
-        td_err_addr = (grub_le_to_cpu32 (o->hcca->donehead) & ~0xf);
-
       tderr = (grub_ohci_td_t) ((char *) td_list
-                               + (td_err_addr - td_list_addr));
+                               + (tderr_addr - td_list_addr));
  
       errcode = grub_le_to_cpu32 (tderr->token) >> 28;      
       grub_dprintf ("ohci", "OHCI errcode=0x%02x\n", errcode);
@@ -702,17 +761,17 @@ grub_ohci_transfer (grub_usb_controller_t dev,
        case 8:
          /* XXX: Data overrun error.  */
          err = GRUB_USB_ERR_DATA;
-         j = ((grub_uint32_t)tderr - (grub_uint32_t)td_list) / sizeof (*td_list);
-         grub_dprintf ("ohci", "Overrun, failed TD address: %p, index: %d\n", tderr, j);
+         grub_dprintf ("ohci", "Overrun, failed TD address: %p, index: %d\n",
+                       tderr, transfer->last_trans);
          break;
 
        case 9:
          /* XXX: Data underrun error.  */
          err = GRUB_USB_ERR_DATA;
+         grub_dprintf ("ohci", "Underrun, failed TD address: %p, index: %d\n",
+                       tderr, transfer->last_trans);
          grub_dprintf ("ohci", "Underrun, number of not transferred bytes: %d\n",
                        1 + grub_le_to_cpu32 (tderr->buffer_end) - grub_le_to_cpu32 (tderr->buffer));
-         j = ((grub_uint32_t)tderr - (grub_uint32_t)td_list) / sizeof (*td_list);
-         grub_dprintf ("ohci", "Underrun, failed TD address: %p, index: %d\n", tderr, j);
          break;
 
        case 10:
@@ -764,7 +823,8 @@ grub_ohci_transfer (grub_usb_controller_t dev,
   /* SF bit reset. (SF bit indicates Start Of Frame (SOF) packet) */
   grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1<<2));
   /* Wait for new SOF */
-  while ((grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS) & 0x4) == 0);
+  while (((grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS) & 0x4) == 0)
+         && !err_unrec);
   /* Now it should be safe to change CONTROL and BULK lists. */
    
   /* Important cleaning. */
@@ -774,7 +834,29 @@ grub_ohci_transfer (grub_usb_controller_t dev,
   grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLCURR, 0);
   grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, 0);
   grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKCURR, 0);
+
+ if (err_unrec)
+   {
+     /* Do OHCI reset in case of unrecoverable error - maybe we will need
+      * do more - re-enumerate bus etc. (?) */
+
+     /* Suspend the OHCI by issuing a reset.  */
+     grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, 1); /* XXX: Magic.  */
+     grub_millisleep (1);
+     grub_dprintf ("ohci", "Unrecoverable error - OHCI reset\n");
+
+     /* Misc. resets. */
+     o->hcca->donehead = 0;
+     grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, 0x7f); /* Clears everything */
+     grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD, 0);
+     grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLCURR, 0);
+     grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, 0);
+     grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKCURR, 0);
+
+     /* Enable the OHCI.  */
+     grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, (2 << 6));
+   } 
+
   grub_dprintf ("ohci", "OHCI finished, freeing, err=0x%02x\n", err);
    
   grub_dma_free (td_list_chunk);
index eb533c926797447347f3e1162d8ab2c1d4186cc9..1510f98e84d39cd260bfab86ccb2ccd43a33f05f 100644 (file)
@@ -332,13 +332,20 @@ grub_free_td (struct grub_uhci *u, grub_uhci_td_t td)
 }
 
 static void
-grub_free_queue (struct grub_uhci *u, grub_uhci_td_t td)
+grub_free_queue (struct grub_uhci *u, grub_uhci_td_t td,
+                 grub_usb_transfer_t transfer)
 {
-  /* Free the TDs in this queue.  */
-  while (td)
+  int i; /* Index of TD in transfer */
+  
+  /* Free the TDs in this queue and set last_trans.  */
+  for (i=0; td; i++)
     {
       grub_uhci_td_t tdprev;
 
+      /* Check state of TD and possibly set last_trans */
+      if (transfer && (td->linkptr & 1))
+        transfer->last_trans = i;
+      
       /* Unlink the queue.  */
       tdprev = td;
       td = (grub_uhci_td_t) td->linkptr2;
@@ -461,7 +468,7 @@ grub_uhci_transfer (grub_usb_controller_t dev,
          td_prev->linkptr = 1;
 
          if (td_first)
-           grub_free_queue (u, td_first);
+           grub_free_queue (u, td_first, NULL);
 
          return GRUB_USB_ERR_INTERNAL;
        }
@@ -560,7 +567,7 @@ grub_uhci_transfer (grub_usb_controller_t dev,
   /* Place the QH back in the free list and deallocate the associated
      TDs.  */
   qh->elinkptr = 1;
-  grub_free_queue (u, td_first);
+  grub_free_queue (u, td_first, transfer);
 
   return err;
 }
@@ -609,7 +616,7 @@ grub_uhci_portstatus (grub_usb_controller_t dev,
   grub_uhci_writereg16 (u, reg, enable << 9);
 
   /* Wait for the reset to complete.  XXX: How long exactly?  */
-  grub_millisleep (10);
+  grub_millisleep (50); /* For root hub should be nominaly 50ms */
   status = grub_uhci_readreg16 (u, reg);
   grub_uhci_writereg16 (u, reg, status & ~(1 << 9));
   grub_dprintf ("uhci", "reset completed\n");
index 0bf5ee6de0100ef9397c6f4aab306785ad1ca5e9..b3ee167a1ec45493892d6cb397601eed656afa98 100644 (file)
@@ -213,6 +213,7 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev,
   transfer->type = GRUB_USB_TRANSACTION_TYPE_BULK;
   transfer->max = max;
   transfer->dev = dev;
+  transfer->last_trans = -1; /* Reset index of last processed transaction (TD) */
 
   /* Allocate an array of transfer data structures.  */
   transfer->transactions = grub_malloc (transfer->transcnt
@@ -240,6 +241,13 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev,
     }
 
   err = dev->controller.dev->transfer (&dev->controller, transfer);
+  /* We must remember proper toggle value even if some transactions
+   * were not processed - correct value should be inversion of last
+   * processed transaction (TD). */
+  if (transfer->last_trans >= 0)
+    toggle = transfer->transactions[transfer->last_trans].toggle ? 0 : 1;
+  else
+    toggle = dev->toggle[endpoint]; /* Nothing done, take original */
   grub_dprintf ("usb", "toggle=%d\n", toggle);
   dev->toggle[endpoint] = toggle;
 
index e8bfb6a3fc9b8c8ac9d04342bd504c7385c38ddc..dffabc26e6fed37c7e40e888e405fedfa01ed31c 100644 (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
index 7b719fb84bffa4407b4bb98db7e0eefe6e1750ab..a49b30e7ecf7fcb15c3dcfb5e11cd2e2a3816ef9 100644 (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;
 }
index cbbc39303981c79f48655c9da1cb9fcedf425b5a..64dc78d61b0651ca4780e17d2849965d7fe5662c 100644 (file)
@@ -35,7 +35,8 @@ typedef enum
     GRUB_USB_ERR_NAK,
     GRUB_USB_ERR_BABBLE,
     GRUB_USB_ERR_TIMEOUT,
-    GRUB_USB_ERR_BITSTUFF
+    GRUB_USB_ERR_BITSTUFF,
+    GRUB_USB_ERR_UNRECOVERABLE
   } grub_usb_err_t;
 
 typedef enum
index cd818e1fc70bdb408beaaecded1f0a7117f5bb92..40fc0dd5f3a51859b7cd58d6b077c4d5c7717e57 100644 (file)
@@ -58,6 +58,9 @@ struct grub_usb_transfer
   struct grub_usb_device *dev;
 
   struct grub_usb_transaction *transactions;
+  
+  int last_trans;
+  /* Index of last processed transaction in OHCI/UHCI driver. */
 };
 typedef struct grub_usb_transfer *grub_usb_transfer_t;
 
index 5d76c5e02a760ef7b3448dd8f0bea77b1d6dfcb6..69d5709b60630b0c18ee0176ac9573daa12e3379 100644 (file)
@@ -18,7 +18,6 @@
  */
 
 #include <grub/term.h>
-#include <grub/machine/console.h>
 #include <grub/time.h>
 #include <grub/cpu/io.h>
 #include <grub/misc.h>