You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2024/09/06 02:01:19 UTC

(nuttx) 02/13: Changed the x86 64 pci driver

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 7cbb7d36d8a7ecc61e9a7afe4d393da22237189a
Author: yangshuyong <ya...@xiaomi.com>
AuthorDate: Tue Mar 5 14:25:08 2024 +0800

    Changed the x86 64 pci driver
    
    Signed-off-by: yangshuyong <ya...@xiaomi.com>
    Signed-off-by: lipengfei28 <li...@xiaomi.com>
---
 arch/x86_64/src/common/x86_64_pci.c | 228 ++++++++++++++++++++++++------------
 drivers/pci/pci.c                   |  36 ++++++
 include/nuttx/pci/pci.h             |  22 ++++
 3 files changed, 209 insertions(+), 77 deletions(-)

diff --git a/arch/x86_64/src/common/x86_64_pci.c b/arch/x86_64/src/common/x86_64_pci.c
index d603d8999b..a84bc73898 100644
--- a/arch/x86_64/src/common/x86_64_pci.c
+++ b/arch/x86_64/src/common/x86_64_pci.c
@@ -35,39 +35,41 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
-#define PCI_CFG_ADDR       0xcf8
-#define PCI_DATA_ADDR      0xcfc
-#define PCI_CFG_EN         (1 << 31)
+#define PCI_CFG_ADDR      0xcf8
+#define PCI_DATA_ADDR     0xcfc
+#define PCI_CFG_EN        (1 << 31)
 
 /****************************************************************************
  * Private Functions Definitions
  ****************************************************************************/
 
-static void x86_64_pci_cfg_write(struct pci_dev_s *dev, int reg,
-                               uint32_t val, int width);
-static uint32_t x86_64_pci_cfg_read(struct pci_dev_s *dev, int reg,
-                                  int width);
-static int x86_64_pci_map_bar(uint64_t addr, uint64_t len);
-static uint32_t x86_64_pci_io_read(const volatile void *addr, int width);
-static void x86_64_pci_io_write(const volatile void *addr, uint32_t val,
-                              int width);
+static int x86_64_pci_write(struct pci_bus_s *bus, unsigned int devfn,
+                            int where, int size, uint32_t val);
+static int x86_64_pci_read(struct pci_bus_s *bus, unsigned int devfn,
+                           int where, int size, uint32_t *val);
+static uintptr_t x86_64_pci_map(struct pci_bus_s *bus, uintptr_t start,
+                                uintptr_t end);
+static int x86_64_pci_read_io(struct pci_bus_s *bus, uintptr_t addr,
+                              int size, uint32_t *val);
+static int x86_64_pci_write_io(struct pci_bus_s *bus, uintptr_t addr,
+                               int size, uint32_t val);
 
 /****************************************************************************
  * Private Data
  ****************************************************************************/
 
-static const struct pci_bus_ops_s g_x86_64_pci_bus_ops =
+static const struct pci_ops_s g_x86_64_pci_ops =
 {
-  .pci_cfg_write = x86_64_pci_cfg_write,
-  .pci_cfg_read  = x86_64_pci_cfg_read,
-  .pci_map_bar   = x86_64_pci_map_bar,
-  .pci_io_read   = x86_64_pci_io_read,
-  .pci_io_write  = x86_64_pci_io_write,
+  .write    = x86_64_pci_write,
+  .read     = x86_64_pci_read,
+  .map      = x86_64_pci_map,
+  .read_io  = x86_64_pci_read_io,
+  .write_io = x86_64_pci_write_io,
 };
 
-static struct pci_bus_s g_x86_64_pci_bus =
+static struct pci_controller_s g_x86_64_pci =
 {
-  .ops = &g_x86_64_pci_bus_ops,
+  .ops = &g_x86_64_pci_ops
 };
 
 /****************************************************************************
@@ -75,135 +77,208 @@ static struct pci_bus_s g_x86_64_pci_bus =
  ****************************************************************************/
 
 /****************************************************************************
- * Name: x86_64_pci_cfg_write
+ * Name: x86_64_pci_write
  *
  * Description:
- *  Write 8, 16, 32, 64 bits data to PCI-E configuration space of device
+ *  Write 8, 16, 32, 64 bits data to PCI configuration space of device
  *  specified by dev
  *
  * Input Parameters:
- *   bdf  - Device private data
- *   reg  - A pointer to the read-only buffer of data to be written
- *   size - The number of bytes to send from the buffer
+ *   bus   - Bus that PCI device resides
+ *   devfn - The device and function bit field of bdf
+ *   where - Offset in the specify PCI device cfg address space
+ *   size  - The number of bytes to send from the buffer
+ *   val   - The value to write
  *
  * Returned Value:
  *   0: success, <0: A negated errno
  *
  ****************************************************************************/
 
-static void x86_64_pci_cfg_write(struct pci_dev_s *dev, int reg,
-                               uint32_t val, int width)
+static int x86_64_pci_write(struct pci_bus_s *bus, unsigned int devfn,
+                            int where, int size, uint32_t val)
 {
-  uint8_t offset_mask = (4 - width);
+  uint8_t offset_mask = (4 - size);
 
-  outl(PCI_CFG_EN | (dev->bdf << 8) | reg, PCI_CFG_ADDR);
-  switch (width)
+  outl(PCI_CFG_EN | (bus->number << 16) | (devfn << 8) | where,
+       PCI_CFG_ADDR);
+
+  switch (size)
     {
       case 1:
-        outb(val, PCI_DATA_ADDR + (reg & offset_mask));
-        return;
+        outb(val, PCI_DATA_ADDR + (where & offset_mask));
+        break;
       case 2:
-        outw(val, PCI_DATA_ADDR + (reg & offset_mask));
-        return;
+        outw(val, PCI_DATA_ADDR + (where & offset_mask));
+        break;
       case 4:
         outl(val, PCI_DATA_ADDR);
-        return;
+        break;
       default:
-        pcierr("Invalid cfg write width %d\n", width);
+        pcierr("Invalid cfg write size %d\n", size);
+        return -EINVAL;
     }
+
+  return 0;
 }
 
 /****************************************************************************
- * Name: x86_64_pci_cfg_read
+ * Name: x86_64_pci_read
  *
  * Description:
- *  Read 8, 16, 32, 64 bits data from PCI-E configuration space of device
+ *  Read 8, 16, 32, 64 bits data from PCI configuration space of device
  *  specified by dev
  *
  * Input Parameters:
- *   dev    - Device private data
- *   buffer - A pointer to a buffer to receive the data from the device
+ *   bus    - Bus that PCI device resides
+ *   devfn  - The device and function bit field of bdf
+ *   where  - Offset in the specify PCI device cfg address space
  *   size   - The requested number of bytes to be read
+ *   val    - A pointer to a buffer to receive the data from the device
  *
  * Returned Value:
  *   0: success, <0: A negated errno
  *
  ****************************************************************************/
 
-static uint32_t x86_64_pci_cfg_read(struct pci_dev_s *dev, int reg,
-                                  int width)
+static int x86_64_pci_read(struct pci_bus_s *bus, unsigned int devfn,
+                           int where, int size, uint32_t *val)
 {
-  uint32_t ret;
-  uint8_t  offset_mask = 4 - width;
+  uint8_t offset_mask = 4 - size;
 
-  outl(PCI_CFG_EN | (dev->bdf << 8) | reg, PCI_CFG_ADDR);
+  outl(PCI_CFG_EN | (bus->number << 16) | (devfn << 8) | where,
+       PCI_CFG_ADDR);
 
-  switch (width)
+  switch (size)
     {
       case 1:
-        ret = inb(PCI_DATA_ADDR + (reg & offset_mask));
-        return ret;
-
+        *val = inb(PCI_DATA_ADDR + (where & offset_mask));
+        break;
       case 2:
-        ret = inw(PCI_DATA_ADDR + (reg & offset_mask));
-        return ret;
+        *val = inw(PCI_DATA_ADDR + (where & offset_mask));
+        break;
       case 4:
-        ret = inl(PCI_DATA_ADDR);
-        return ret;
+        *val = inl(PCI_DATA_ADDR);
+        break;
       default:
-        pcierr("Invalid cfg read width %d\n", width);
+        *val = 0;
+        pcierr("Invalid cfg read size %d\n", size);
+        return -EINVAL;
     }
 
-  return 0;
+  return OK;
 }
 
-static uint32_t x86_64_pci_io_read(const volatile void *addr, int width)
+/****************************************************************************
+ * Name: x86_64_pci_read_io
+ *
+ * Description:
+ *  Read 8, 16, 32, 64 bits data from PCI io address space of x86 64 device
+ *
+ * Input Parameters:
+ *   bus    - Bus that PCI device resides
+ *   addr   - The address to received data
+ *   size   - The requested number of bytes to be read
+ *   val    - A pointer to a buffer to receive the data from the device
+ *
+ * Returned Value:
+ *   0: success, <0: A negated errno
+ *
+ ****************************************************************************/
+
+static int x86_64_pci_read_io(struct pci_bus_s *bus, uintptr_t addr,
+                              int size, uint32_t *val)
 {
-  uint16_t portaddr = (uint16_t)(intptr_t)addr;
+  uint16_t portaddr = (uint16_t)addr;
 
-  switch (width)
+  switch (size)
   {
     case 1:
-      return (uint32_t)inb(portaddr);
+      *val = (uint32_t)inb(portaddr);
+      break;
     case 2:
-      return (uint32_t)inw(portaddr);
+      *val = (uint32_t)inw(portaddr);
+      break;
     case 4:
-      return (uint32_t)inl(portaddr);
+      *val = (uint32_t)inl(portaddr);
+      break;
     default:
-      pcierr("Invalid read width %d\n", width);
+      *val = 0;
+      pcierr("Invalid read size %d\n", size);
       DEBUGPANIC();
+      return -EINVAL;
   }
 
-  return 0;
+  return OK;
 }
 
-static void x86_64_pci_io_write(const volatile void *addr, uint32_t val,
-                              int width)
+/****************************************************************************
+ * Name: x86_64_pci_write_io
+ *
+ * Description:
+ *  Write 8, 16, 32, 64 bits data to PCI io address space of x86 64 device
+ *
+ * Input Parameters:
+ *   bus    - Bus that PCI device resides
+ *   addr   - The address to write data
+ *   size   - The requested number of bytes to be write
+ *   val    - The value to write
+ *
+ * Returned Value:
+ *   0: success, <0: A negated errno
+ *
+ ****************************************************************************/
+
+static int x86_64_pci_write_io(struct pci_bus_s *bus, uintptr_t addr,
+                               int size, uint32_t val)
 {
-  uint16_t portaddr = (uint16_t)(intptr_t)addr;
+  uint16_t portaddr = (uint16_t)addr;
 
-  switch (width)
+  switch (size)
   {
     case 1:
       outb((uint8_t)val, portaddr);
-      return;
+      break;
     case 2:
       outw((uint16_t)val, portaddr);
-      return;
+      break;
     case 4:
       outl((uint32_t)val, portaddr);
-      return;
+      break;
     default:
-      pcierr("Invalid write width %d\n", width);
+      pcierr("Invalid write size %d\n", size);
       DEBUGPANIC();
+      return -EINVAL;
   }
+
+  return OK;
 }
 
-static int x86_64_pci_map_bar(uint64_t addr, uint64_t len)
+/****************************************************************************
+ * Name: x86_64_pci_map
+ *
+ * Description:
+ *  Map a memory region
+ *
+ * Input Parameters:
+ *   bus   - Bus that PCI device resides
+ *   start - The start address to map
+ *   end   - The end address to map
+ *
+ * Returned Value:
+ *   >0: success, 0: A positive value errno
+ *
+ ****************************************************************************/
+
+static uintptr_t x86_64_pci_map(struct pci_bus_s *bus, uintptr_t start,
+                                uintptr_t end)
 {
-  up_map_region((void *)(uintptr_t)addr, len,
-      X86_PAGE_WR | X86_PAGE_PRESENT | X86_PAGE_NOCACHE | X86_PAGE_GLOBAL);
-  return OK;
+  int ret;
+
+  ret = up_map_region((void *)start, end - start + 1, X86_PAGE_WR |
+                 X86_PAGE_PRESENT | X86_PAGE_NOCACHE | X86_PAGE_GLOBAL);
+
+  return ret < 0 ? 0 : start;
 }
 
 /****************************************************************************
@@ -214,12 +289,11 @@ static int x86_64_pci_map_bar(uint64_t addr, uint64_t len)
  * Name: x86_64_pci_init
  *
  * Description:
- *  Initialize the PCI-E bus
+ *  Initialize the PCI bus
  *
  ****************************************************************************/
 
 void x86_64_pci_init(void)
 {
-  pciinfo("Initializing PCI Bus\n");
-  pci_initialize(&g_x86_64_pci_bus);
+  pci_register_controller(&g_x86_64_pci);
 }
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index adcb05da3c..35b4ac0056 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -74,6 +74,36 @@
     return ret;                                                                 \
   }
 
+#define PCI_BUS_READ_IO(len, type, size)                                        \
+  int pci_bus_read_io_##len(FAR struct pci_bus_s *bus, uintptr_t where,         \
+                            FAR type *value)                                    \
+  {                                                                             \
+    int ret = -EINVAL;                                                          \
+    uint32_t data = 0;                                                          \
+                                                                                \
+    if (!PCI_##len##_BAD)                                                       \
+      {                                                                         \
+        ret = bus->ctrl->ops->read_io(bus, where, size, &data);                  \
+      }                                                                         \
+                                                                                \
+    *value = (type)data;                                                        \
+    return ret;                                                                 \
+  }
+
+#define PCI_BUS_WRITE_IO(len, type, size)                                       \
+  int pci_bus_write_io_##len(FAR struct pci_bus_s *bus, uintptr_t where,        \
+                             type value)                                        \
+  {                                                                             \
+    int ret = -EINVAL;                                                          \
+                                                                                \
+    if (!PCI_##len##_BAD)                                                       \
+      {                                                                         \
+        ret = bus->ctrl->ops->write_io(bus, where, size, value);                \
+      }                                                                         \
+                                                                                \
+    return ret;                                                                 \
+  }
+
 #define pci_match_one_device(id, dev)                               \
   (((id)->vendor == PCI_ANY_ID || (id)->vendor == (dev)->vendor) && \
    ((id)->device == PCI_ANY_ID || (id)->device == (dev)->device) && \
@@ -1171,3 +1201,9 @@ PCI_BUS_READ_CONFIG(dword, uint32_t, 4)
 PCI_BUS_WRITE_CONFIG(byte, uint8_t, 1)
 PCI_BUS_WRITE_CONFIG(word, uint16_t, 2)
 PCI_BUS_WRITE_CONFIG(dword, uint32_t, 4)
+PCI_BUS_READ_IO(byte, uint8_t, 1)
+PCI_BUS_READ_IO(word, uint16_t, 2)
+PCI_BUS_READ_IO(dword, uint32_t, 4)
+PCI_BUS_WRITE_IO(byte, uint8_t, 1)
+PCI_BUS_WRITE_IO(word, uint16_t, 2)
+PCI_BUS_WRITE_IO(dword, uint32_t, 4)
\ No newline at end of file
diff --git a/include/nuttx/pci/pci.h b/include/nuttx/pci/pci.h
index 917ea81d92..f6835e8c81 100644
--- a/include/nuttx/pci/pci.h
+++ b/include/nuttx/pci/pci.h
@@ -152,6 +152,24 @@
 #define pci_write_config_dword(dev, where, val) \
   pci_bus_write_config_dword((dev)->bus, (dev)->devfn, where, val)
 
+#define pci_read_io_byte(dev, addr, val) \
+  pci_bus_read_io_byte((dev)->bus, addr, val)
+
+#define pci_read_io_word(dev, addr, val) \
+  pci_bus_read_io_word((dev)->bus, addr, val)
+
+#define pci_read_io_dword(dev, addr, val) \
+  pci_bus_read_io_dword((dev)->bus, addr, val)
+
+#define pci_write_io_byte(dev, addr, val) \
+  pci_bus_write_io_byte((dev)->bus, addr, val)
+
+#define pci_write_io_word(dev, addr, val) \
+  pci_bus_write_io_word((dev)->bus, addr, val)
+
+#define pci_write_io_dword(dev, addr, val) \
+  pci_bus_write_io_dword((dev)->bus, addr, val)
+
 /****************************************************************************
  * Public Types
  ****************************************************************************/
@@ -232,6 +250,10 @@ struct pci_ops_s
 
   CODE uintptr_t (*map)(FAR struct pci_bus_s *bus, uintptr_t start,
                         uintptr_t end);
+  CODE int (*read_io)(FAR struct pci_bus_s *bus, uintptr_t addr,
+                      int size, FAR uint32_t *val);
+  CODE int (*write_io)(FAR struct pci_bus_s *bus, uintptr_t addr,
+                       int size, uint32_t val);
 };
 
 /* Each pci channel is a top-level PCI bus seem by CPU.  A machine with