diff -purB ./grub/grub-core/bus/usb/ehci.c ./grub_patched/grub-core/bus/usb/ehci.c
--- ./grub/grub-core/bus/usb/ehci.c	2012-12-07 21:11:42.000000000 +0100
+++ ./grub_patched/grub-core/bus/usb/ehci.c	2012-12-07 19:36:56.000000000 +0100
@@ -940,9 +940,9 @@ grub_ehci_setup_qh (grub_ehci_qh_t qh, g
    * SplitCompletionMask - AFAIK it is ignored in asynchronous list,
    * InterruptScheduleMask - AFAIK it should be zero in async. list */
   ep_cap |= GRUB_EHCI_MULT_THREE;
-  ep_cap |= (transfer->dev->port << GRUB_EHCI_DEVPORT_OFF)
+  ep_cap |= (transfer->dev->split_hubport << GRUB_EHCI_DEVPORT_OFF)
     & GRUB_EHCI_DEVPORT_MASK;
-  ep_cap |= (transfer->dev->hubaddr << GRUB_EHCI_HUBADDR_OFF)
+  ep_cap |= (transfer->dev->split_hubaddr << GRUB_EHCI_HUBADDR_OFF)
     & GRUB_EHCI_HUBADDR_MASK;
   if (transfer->dev->speed == GRUB_USB_SPEED_LOW
       && transfer->type != GRUB_USB_TRANSACTION_TYPE_CONTROL)
@@ -1259,16 +1259,6 @@ grub_ehci_setup_transfer (grub_usb_contr
     /* XXX: Fix it: Currently we don't do anything to restart EHCI */
     return GRUB_USB_ERR_INTERNAL;
 
-  /* Check if transfer is not high speed and connected to root hub.
-   * It should not happened but... */
-  if ((transfer->dev->speed != GRUB_USB_SPEED_HIGH)
-      && !transfer->dev->hubaddr)
-    {
-      grub_error (GRUB_USB_ERR_BADDEVICE,
-		  "FULL/LOW speed device on EHCI port!?!");
-      return GRUB_USB_ERR_BADDEVICE;
-    }
-
   /* Allocate memory for controller transfer data.  */
   cdata = grub_malloc (sizeof (*cdata));
   if (!cdata)
diff -purB ./grub/grub-core/bus/usb/usbhub.c ./grub_patched/grub-core/bus/usb/usbhub.c
--- ./grub/grub-core/bus/usb/usbhub.c	2012-12-07 21:11:42.000000000 +0100
+++ ./grub_patched/grub-core/bus/usb/usbhub.c	2012-12-07 20:40:11.000000000 +0100
@@ -46,7 +46,7 @@ static struct grub_usb_hub *hubs;
 static grub_usb_device_t
 grub_usb_hub_add_dev (grub_usb_controller_t controller,
                       grub_usb_speed_t speed,
-                      int port, int hubaddr)
+                      int split_hubport, int split_hubaddr)
 {
   grub_usb_device_t dev;
   int i;
@@ -58,8 +58,8 @@ grub_usb_hub_add_dev (grub_usb_controlle
 
   dev->controller = *controller;
   dev->speed = speed;
-  dev->port = port;
-  dev->hubaddr = hubaddr;
+  dev->split_hubport = split_hubport;
+  dev->split_hubaddr = split_hubaddr;
 
   err = grub_usb_device_initialize (dev);
   if (err)
@@ -103,8 +103,8 @@ grub_usb_hub_add_dev (grub_usb_controlle
 
   grub_dprintf ("usb", "Added new usb device: %p, addr=%d\n",
 		dev, i);
-  grub_dprintf ("usb", "speed=%d, port=%d, hubaddr=%d\n",
-		speed, port, hubaddr);
+  grub_dprintf ("usb", "speed=%d, split_hubport=%d, split_hubaddr=%d\n",
+		speed, split_hubport, split_hubaddr);
 
   /* Wait "recovery interval", spec. says 2ms */
   grub_millisleep (2);
@@ -229,7 +229,12 @@ attach_root_port (struct grub_usb_hub *h
   grub_millisleep (10);
 
   /* Enable the port and create a device.  */
-  dev = grub_usb_hub_add_dev (hub->controller, speed, portno, 0);
+  /* High speed device needs not transaction translation
+     and full/low speed device cannot be connected to EHCI root hub
+     and full/low speed device connected to OHCI/UHCI needs not
+     transaction translation - e.g. hubport and hubaddr should be
+     always none (zero) for any device connected to any root hub. */
+  dev = grub_usb_hub_add_dev (hub->controller, speed, 0, 0);
   hub->controller->dev->pending_reset = 0;
   if (! dev)
     return;
@@ -353,7 +358,9 @@ poll_nonroot_hub (grub_usb_device_t dev)
     {
       grub_uint32_t status;
       grub_uint32_t current_status = 0;
-
+      int split_hubport = 0;
+      int split_hubaddr = 0;
+      
       if (!(changed & (1 << i)))
 	continue;
 
@@ -483,8 +490,37 @@ poll_nonroot_hub (grub_usb_device_t dev)
 	      /* Wait a recovery time after reset, spec. says 10ms */
 	      grub_millisleep (10);
 
+              /* Find correct values for SPLIT hubport and hubaddr */
+	      if (speed == GRUB_USB_SPEED_HIGH)
+	        {
+		  /* HIGH speed device needs not transaction translation */
+		  split_hubport = 0;
+		  split_hubaddr = 0;
+		}
+	      else
+	        /* FULL/LOW device needs hub port and hub address
+		   for transaction translation (if connected to EHCI) */
+	        if (dev->speed == GRUB_USB_SPEED_HIGH)
+	          {
+		    /* This port is the first FULL/LOW speed port
+		       in the chain from root hub. Attached device
+		       should use its port number and hub address */
+		    split_hubport = i;
+		    split_hubaddr = dev->addr;
+		  }
+	        else
+	          {
+		    /* This port is NOT the first FULL/LOW speed port
+		       in the chain from root hub. Attached device
+		       should use inherited from some parent HIGH speed
+		       hub - if any. */
+		    split_hubport = dev->split_hubport;
+		    split_hubaddr = dev->split_hubaddr;
+		  }
+		
 	      /* Add the device and assign a device address to it.  */
-	      next_dev = grub_usb_hub_add_dev (&dev->controller, speed, i, dev->addr);
+	      next_dev = grub_usb_hub_add_dev (&dev->controller, speed,
+	                   split_hubport, split_hubaddr);
 	      dev->controller.dev->pending_reset = 0;
 	      if (! next_dev)
 		continue;
diff -purB ./grub/grub-core/bus/usb/usbtrans.c ./grub_patched/grub-core/bus/usb/usbtrans.c
--- ./grub/grub-core/bus/usb/usbtrans.c	2012-12-07 21:11:42.000000000 +0100
+++ ./grub_patched/grub-core/bus/usb/usbtrans.c	2012-12-07 20:42:46.000000000 +0100
@@ -351,11 +351,23 @@ 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;
+  grub_size_t actual, transferred;
   grub_usb_err_t err;
-  err = grub_usb_bulk_readwrite (dev, endpoint, size, data,
-				 GRUB_USB_TRANSFER_TYPE_IN, 1000, &actual);
-  if (!err && actual != size)
+  grub_size_t current_size, position;
+
+  for (position = 0, transferred = 0;
+       position < size; position += GRUB_MAX_USB_TRANSFER_LEN)
+    {
+      current_size = size - position;
+      if (current_size >= GRUB_MAX_USB_TRANSFER_LEN)
+	current_size = GRUB_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;
 }
diff -purB ./grub/include/grub/usb.h ./grub_patched/include/grub/usb.h
--- ./grub/include/grub/usb.h	2012-12-07 21:11:42.000000000 +0100
+++ ./grub_patched/include/grub/usb.h	2012-12-07 19:10:50.000000000 +0100
@@ -200,9 +200,9 @@ struct grub_usb_device
   struct grub_usb_desc_endp *hub_endpoint;
 
   /* EHCI Split Transfer information */
-  int port;
+  int split_hubport;
 
-  int hubaddr;
+  int split_hubaddr;
 };
 
 
diff -purB ./grub/include/grub/usbtrans.h ./grub_patched/include/grub/usbtrans.h
--- ./grub/include/grub/usbtrans.h	2012-12-07 21:11:42.000000000 +0100
+++ ./grub_patched/include/grub/usbtrans.h	2012-12-07 20:42:46.000000000 +0100
@@ -19,6 +19,8 @@
 #ifndef	GRUB_USBTRANS_H
 #define	GRUB_USBTRANS_H	1
 
+#define GRUB_MAX_USB_TRANSFER_LEN 0x0800
+
 typedef enum
   {
     GRUB_USB_TRANSFER_TYPE_IN,
