Blame SOURCES/0387-grub-core-bus-usb-uhci.c-Fix-DMA-handling-and-enable.patch

f96e0b
From f94f8f792c37fe2abd7db8d6eaf70929580bf62f Mon Sep 17 00:00:00 2001
f96e0b
From: Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>
f96e0b
Date: Mon, 29 Apr 2013 12:05:19 +0200
f96e0b
Subject: [PATCH 387/482] 	* grub-core/bus/usb/uhci.c: Fix DMA handling
f96e0b
 and enable on all PCI 	platforms.
f96e0b
f96e0b
---
f96e0b
 ChangeLog                   |  5 ++++
f96e0b
 grub-core/Makefile.core.def |  2 +-
f96e0b
 grub-core/bus/usb/uhci.c    | 70 ++++++++++++++++++++++++++++++++++-----------
f96e0b
 3 files changed, 59 insertions(+), 18 deletions(-)
f96e0b
f96e0b
diff --git a/ChangeLog b/ChangeLog
f96e0b
index 9dacb19..99a049a 100644
f96e0b
--- a/ChangeLog
f96e0b
+++ b/ChangeLog
f96e0b
@@ -1,5 +1,10 @@
f96e0b
 2013-04-29  Vladimir Serbinenko  <phcoder@gmail.com>
f96e0b
 
f96e0b
+	* grub-core/bus/usb/uhci.c: Fix DMA handling and enable on all PCI
f96e0b
+	platforms.
f96e0b
+
f96e0b
+2013-04-29  Vladimir Serbinenko  <phcoder@gmail.com>
f96e0b
+
f96e0b
 	* grub-core/script/execute.c (grub_script_arglist_to_argv): Fix
f96e0b
 	handling of variables containing backslash.
f96e0b
 
f96e0b
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
f96e0b
index 2e73d89..dcb92ef 100644
f96e0b
--- a/grub-core/Makefile.core.def
f96e0b
+++ b/grub-core/Makefile.core.def
f96e0b
@@ -482,7 +482,7 @@ module = {
f96e0b
 module = {
f96e0b
   name = uhci;
f96e0b
   common = bus/usb/uhci.c;
f96e0b
-  enable = x86;
f96e0b
+  enable = pci;
f96e0b
 };
f96e0b
 
f96e0b
 module = {
f96e0b
diff --git a/grub-core/bus/usb/uhci.c b/grub-core/bus/usb/uhci.c
f96e0b
index 3639c42..a314637 100644
f96e0b
--- a/grub-core/bus/usb/uhci.c
f96e0b
+++ b/grub-core/bus/usb/uhci.c
f96e0b
@@ -26,6 +26,7 @@
f96e0b
 #include <grub/cpu/io.h>
f96e0b
 #include <grub/time.h>
f96e0b
 #include <grub/cpu/pci.h>
f96e0b
+#include <grub/disk.h>
f96e0b
 
f96e0b
 GRUB_MOD_LICENSE ("GPLv3+");
f96e0b
 
f96e0b
@@ -44,12 +45,22 @@ typedef enum
f96e0b
     GRUB_UHCI_REG_USBLEGSUP = 0xc0
f96e0b
   } grub_uhci_reg_t;
f96e0b
 
f96e0b
+enum
f96e0b
+  {
f96e0b
+    GRUB_UHCI_DETECT_CHANGED = (1 << 1),
f96e0b
+    GRUB_UHCI_DETECT_HAVE_DEVICE = 1,
f96e0b
+    GRUB_UHCI_DETECT_LOW_SPEED = (1 << 8)
f96e0b
+  };
f96e0b
+
f96e0b
 /* R/WC legacy support bits */
f96e0b
-#define GRUB_UHCI_LEGSUP_END_A20GATE (1 << 15)
f96e0b
-#define GRUB_UHCI_TRAP_BY_64H_WSTAT  (1 << 11)
f96e0b
-#define GRUB_UHCI_TRAP_BY_64H_RSTAT  (1 << 10)
f96e0b
-#define GRUB_UHCI_TRAP_BY_60H_WSTAT  (1 <<  9)
f96e0b
-#define GRUB_UHCI_TRAP_BY_60H_RSTAT  (1 <<  8)
f96e0b
+enum
f96e0b
+  {
f96e0b
+    GRUB_UHCI_LEGSUP_END_A20GATE = (1 << 15),
f96e0b
+    GRUB_UHCI_TRAP_BY_64H_WSTAT = (1 << 11),
f96e0b
+    GRUB_UHCI_TRAP_BY_64H_RSTAT = (1 << 10),
f96e0b
+    GRUB_UHCI_TRAP_BY_60H_WSTAT = (1 <<  9),
f96e0b
+    GRUB_UHCI_TRAP_BY_60H_RSTAT = (1 <<  8)
f96e0b
+  };
f96e0b
 
f96e0b
 /* Reset all legacy support - clear all R/WC bits and all R/W bits */
f96e0b
 #define GRUB_UHCI_RESET_LEGSUP_SMI ( GRUB_UHCI_LEGSUP_END_A20GATE \
f96e0b
@@ -125,7 +136,7 @@ typedef volatile struct grub_uhci_qh *grub_uhci_qh_t;
f96e0b
 
f96e0b
 struct grub_uhci
f96e0b
 {
f96e0b
-  int iobase;
f96e0b
+  grub_port_t iobase;
f96e0b
   volatile grub_uint32_t *framelist_virt;
f96e0b
   grub_uint32_t framelist_phys;
f96e0b
   struct grub_pci_dma_chunk *framelist_chunk;
f96e0b
@@ -213,22 +224,36 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
f96e0b
 
f96e0b
   /* Set bus master - needed for coreboot or broken BIOSes */
f96e0b
   addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
f96e0b
-  grub_pci_write_word(addr,
f96e0b
-    GRUB_PCI_COMMAND_BUS_MASTER | grub_pci_read_word(addr));
f96e0b
+  grub_pci_write_word(addr, GRUB_PCI_COMMAND_IO_ENABLED
f96e0b
+		      | GRUB_PCI_COMMAND_BUS_MASTER
f96e0b
+		      | grub_pci_read_word (addr));
f96e0b
 
f96e0b
   /* Determine IO base address.  */
f96e0b
   addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG4);
f96e0b
   base = grub_pci_read (addr);
f96e0b
   /* Stop if there is no IO space base address defined.  */
f96e0b
-  if (! (base & 1))
f96e0b
+  if ((base & GRUB_PCI_ADDR_SPACE_MASK) != GRUB_PCI_ADDR_SPACE_IO)
f96e0b
     return 0;
f96e0b
 
f96e0b
+  if ((base & GRUB_UHCI_IOMASK) == 0)
f96e0b
+    {
f96e0b
+#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_QEMU)
f96e0b
+      static int ndevs = 0;
f96e0b
+      base = 0x1800 + ndevs++ * 0x100;
f96e0b
+      grub_pci_write (addr, base | GRUB_PCI_ADDR_SPACE_IO);
f96e0b
+#else
f96e0b
+      return 0;
f96e0b
+#endif
f96e0b
+    }
f96e0b
+
f96e0b
+  grub_dprintf ("uhci", "base = %x\n", base);
f96e0b
+
f96e0b
   /* Allocate memory for the controller and register it.  */
f96e0b
   u = grub_zalloc (sizeof (*u));
f96e0b
   if (! u)
f96e0b
     return 1;
f96e0b
 
f96e0b
-  u->iobase = base & GRUB_UHCI_IOMASK;
f96e0b
+  u->iobase = (base & GRUB_UHCI_IOMASK) + GRUB_MACHINE_PCI_IO_BASE;
f96e0b
 
f96e0b
   /* Reset PIRQ and SMI */
f96e0b
   addr = grub_pci_make_address (dev, GRUB_UHCI_REG_USBLEGSUP);       
f96e0b
@@ -392,6 +417,7 @@ grub_free_queue (struct grub_uhci *u, grub_uhci_qh_t qh, grub_uhci_td_t td,
f96e0b
     {
f96e0b
       grub_uhci_td_t tdprev;
f96e0b
 
f96e0b
+      grub_dprintf ("uhci", "Freeing %p\n", td);
f96e0b
       /* Check state of TD and possibly set last_trans */
f96e0b
       if (transfer && (td->linkptr & 1))
f96e0b
         transfer->last_trans = i;
f96e0b
@@ -400,7 +426,10 @@ grub_free_queue (struct grub_uhci *u, grub_uhci_qh_t qh, grub_uhci_td_t td,
f96e0b
       
f96e0b
       /* Unlink the queue.  */
f96e0b
       tdprev = td;
f96e0b
-      td = grub_dma_phys2virt (td->linkptr2, u->td_chunk);
f96e0b
+      if (!td->linkptr2)
f96e0b
+	td = 0;
f96e0b
+      else
f96e0b
+	td = grub_dma_phys2virt (td->linkptr2, u->td_chunk);
f96e0b
 
f96e0b
       /* Free the TD.  */
f96e0b
       grub_free_td (u, tdprev);
f96e0b
@@ -583,10 +612,17 @@ grub_uhci_check_transfer (grub_usb_controller_t dev,
f96e0b
 
f96e0b
   *actual = 0;
f96e0b
 
f96e0b
-  errtd = grub_dma_phys2virt (cdata->qh->elinkptr & ~0x0f, u->qh_chunk);
f96e0b
+  if (cdata->qh->elinkptr & ~0x0f)
f96e0b
+    errtd = grub_dma_phys2virt (cdata->qh->elinkptr & ~0x0f, u->qh_chunk);
f96e0b
+  else
f96e0b
+    errtd = 0;
f96e0b
   
f96e0b
-  grub_dprintf ("uhci", ">t status=0x%02x data=0x%02x td=%p\n",
f96e0b
-		errtd->ctrl_status, errtd->buffer & (~15), errtd);
f96e0b
+  if (errtd)
f96e0b
+    {
f96e0b
+      grub_dprintf ("uhci", ">t status=0x%02x data=0x%02x td=%p, %x\n",
f96e0b
+		    errtd->ctrl_status, errtd->buffer & (~15), errtd,
f96e0b
+		    cdata->qh->elinkptr);
f96e0b
+    }
f96e0b
 
f96e0b
   /* Check if the transaction completed.  */
f96e0b
   if (cdata->qh->elinkptr & 1)
f96e0b
@@ -788,7 +824,7 @@ grub_uhci_detect_dev (grub_usb_controller_t dev, int port, int *changed)
f96e0b
   grub_dprintf ("uhci", "detect=0x%02x port=%d\n", status, port);
f96e0b
 
f96e0b
   /* Connect Status Change bit - it detects change of connection */
f96e0b
-  if (status & (1 << 1))
f96e0b
+  if (status & GRUB_UHCI_DETECT_CHANGED)
f96e0b
     {
f96e0b
       *changed = 1;
f96e0b
       /* Reset bit Connect Status Change */
f96e0b
@@ -798,9 +834,9 @@ grub_uhci_detect_dev (grub_usb_controller_t dev, int port, int *changed)
f96e0b
   else
f96e0b
     *changed = 0;
f96e0b
     
f96e0b
-  if (! (status & 1))
f96e0b
+  if (! (status & GRUB_UHCI_DETECT_HAVE_DEVICE))
f96e0b
     return GRUB_USB_SPEED_NONE;
f96e0b
-  else if (status & (1 << 8))
f96e0b
+  else if (status & GRUB_UHCI_DETECT_LOW_SPEED)
f96e0b
     return GRUB_USB_SPEED_LOW;
f96e0b
   else
f96e0b
     return GRUB_USB_SPEED_FULL;
f96e0b
-- 
f96e0b
1.8.2.1
f96e0b