]> mj.ucw.cz Git - pciutils.git/blobdiff - lib/mmio-ports.c
libpci: ecam: Fix detect sequence when addresses are not specified
[pciutils.git] / lib / mmio-ports.c
index 9a9b48dd10d65bbf1f21730447aa40dea21fefb7..cac8a7e35ad138269d11d3e7db1d74db6959b25d 100644 (file)
@@ -8,64 +8,58 @@
  *     SPDX-License-Identifier: GPL-2.0-or-later
  */
 
-/*
- * Tell 32-bit platforms that we are interested in 64-bit variant of off_t type
- * as 32-bit variant of off_t type is signed and so it cannot represent all
- * possible 32-bit offsets. It is required because off_t type is used by mmap().
- */
-#define _FILE_OFFSET_BITS 64
-
 #include "internal.h"
+#include "physmem.h"
+#include "physmem-access.h"
 
 #include <ctype.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
-#include <limits.h>
-
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
 
-#ifndef OFF_MAX
-#define OFF_MAX (off_t)((1ULL << (sizeof(off_t) * CHAR_BIT - 1)) - 1)
-#endif
-
-struct mmio_cache
-{
-  off_t addr_page;
-  off_t data_page;
+struct mmio_cache {
+  u64 addr_page;
+  u64 data_page;
   void *addr_map;
   void *data_map;
 };
 
-static long pagesize;
+struct mmio_access {
+  struct mmio_cache *cache;
+  struct physmem *physmem;
+  long pagesize;
+};
 
 static void
 munmap_regs(struct pci_access *a)
 {
-  struct mmio_cache *cache = a->backend_data;
+  struct mmio_access *macc = a->backend_data;
+  struct mmio_cache *cache = macc->cache;
+  struct physmem *physmem = macc->physmem;
+  long pagesize = macc->pagesize;
 
   if (!cache)
     return;
 
-  munmap(cache->addr_map, pagesize);
+  physmem_unmap(physmem, cache->addr_map, pagesize);
   if (cache->addr_page != cache->data_page)
-    munmap(cache->data_map, pagesize);
+    physmem_unmap(physmem, cache->data_map, pagesize);
 
-  pci_mfree(a->backend_data);
-  a->backend_data = NULL;
+  pci_mfree(macc->cache);
+  macc->cache = NULL;
 }
 
 static int
-mmap_regs(struct pci_access *a, off_t addr_reg, off_t data_reg, int data_off, volatile void **addr, volatile void **data)
+mmap_regs(struct pci_access *a, u64 addr_reg, u64 data_reg, int data_off, volatile void **addr, volatile void **data)
 {
-  struct mmio_cache *cache = a->backend_data;
-  off_t addr_page = addr_reg & ~(pagesize-1);
-  off_t data_page = data_reg & ~(pagesize-1);
-  void *addr_map = MAP_FAILED;
-  void *data_map = MAP_FAILED;
+  struct mmio_access *macc = a->backend_data;
+  struct mmio_cache *cache = macc->cache;
+  struct physmem *physmem = macc->physmem;
+  long pagesize = macc->pagesize;
+  u64 addr_page = addr_reg & ~(pagesize-1);
+  u64 data_page = data_reg & ~(pagesize-1);
+  void *addr_map = (void *)-1;
+  void *data_map = (void *)-1;
 
   if (cache && cache->addr_page == addr_page)
     addr_map = cache->addr_map;
@@ -73,35 +67,35 @@ mmap_regs(struct pci_access *a, off_t addr_reg, off_t data_reg, int data_off, vo
   if (cache && cache->data_page == data_page)
     data_map = cache->data_map;
 
-  if (addr_map == MAP_FAILED)
-    addr_map = mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, a->fd, addr_page);
+  if (addr_map == (void *)-1)
+    addr_map = physmem_map(physmem, addr_page, pagesize, 1);
 
-  if (addr_map == MAP_FAILED)
+  if (addr_map == (void *)-1)
     return 0;
 
-  if (data_map == MAP_FAILED)
+  if (data_map == (void *)-1)
     {
       if (data_page == addr_page)
         data_map = addr_map;
       else
-        data_map = mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, a->fd, data_page);
+        data_map = physmem_map(physmem, data_page, pagesize, 1);
     }
 
-  if (data_map == MAP_FAILED)
+  if (data_map == (void *)-1)
     {
       if (!cache || cache->addr_map != addr_map)
-        munmap(addr_map, pagesize);
+        physmem_unmap(physmem, addr_map, pagesize);
       return 0;
     }
 
   if (cache && cache->addr_page != addr_page)
-    munmap(cache->addr_map, pagesize);
+    physmem_unmap(physmem, cache->addr_map, pagesize);
 
   if (cache && cache->data_page != data_page && cache->data_page != cache->addr_page)
-    munmap(cache->data_map, pagesize);
+    physmem_unmap(physmem, cache->data_map, pagesize);
 
   if (!cache)
-    cache = a->backend_data = pci_malloc(a, sizeof(*cache));
+    cache = macc->cache = pci_malloc(a, sizeof(*cache));
 
   cache->addr_page = addr_page;
   cache->data_page = data_page;
@@ -113,47 +107,11 @@ mmap_regs(struct pci_access *a, off_t addr_reg, off_t data_reg, int data_off, vo
   return 1;
 }
 
-static void
-writeb(unsigned char value, volatile void *addr)
-{
-  *(volatile unsigned char *)addr = value;
-}
-
-static void
-writew(unsigned short value, volatile void *addr)
-{
-  *(volatile unsigned short *)addr = value;
-}
-
-static void
-writel(u32 value, volatile void *addr)
-{
-  *(volatile u32 *)addr = value;
-}
-
-static unsigned char
-readb(volatile void *addr)
-{
-  return *(volatile unsigned char *)addr;
-}
-
-static unsigned short
-readw(volatile void *addr)
-{
-  return *(volatile unsigned short *)addr;
-}
-
-static u32
-readl(volatile void *addr)
-{
-  return *(volatile u32 *)addr;
-}
-
 static int
 validate_addrs(const char *addrs)
 {
   const char *sep, *next;
-  unsigned long long num;
+  u64 num;
   char *endptr;
 
   if (!*addrs)
@@ -174,12 +132,12 @@ validate_addrs(const char *addrs)
 
       errno = 0;
       num = strtoull(addrs, &endptr, 16);
-      if (errno || endptr != sep || (num & 3) || num > OFF_MAX)
+      if (errno || endptr != sep || (num & 3))
         return 0;
 
       errno = 0;
       num = strtoull(sep+1, &endptr, 16);
-      if (errno || endptr != next || (num & 3) || num > OFF_MAX)
+      if (errno || endptr != next || (num & 3))
         return 0;
 
       if (!*next)
@@ -202,7 +160,7 @@ get_domain_count(const char *addrs)
 }
 
 static int
-get_domain_addr(const char *addrs, int domain, off_t *addr_reg, off_t *data_reg)
+get_domain_addr(const char *addrs, int domain, u64 *addr_reg, u64 *data_reg)
 {
   char *endptr;
 
@@ -223,14 +181,14 @@ get_domain_addr(const char *addrs, int domain, off_t *addr_reg, off_t *data_reg)
 static void
 conf1_config(struct pci_access *a)
 {
-  pci_define_param(a, "devmem.path", PCI_PATH_DEVMEM_DEVICE, "Path to the /dev/mem device");
+  physmem_init_config(a);
   pci_define_param(a, "mmio-conf1.addrs", "", "Physical addresses of memory mapped Intel conf1 interface"); /* format: 0xaddr1/0xdata1,0xaddr2/0xdata2,... */
 }
 
 static void
 conf1_ext_config(struct pci_access *a)
 {
-  pci_define_param(a, "devmem.path", PCI_PATH_DEVMEM_DEVICE, "Path to the /dev/mem device");
+  physmem_init_config(a);
   pci_define_param(a, "mmio-conf1-ext.addrs", "", "Physical addresses of memory mapped Intel conf1 extended interface"); /* format: 0xaddr1/0xdata1,0xaddr2/0xdata2,... */
 }
 
@@ -238,7 +196,6 @@ static int
 detect(struct pci_access *a, char *addrs_param_name)
 {
   char *addrs = pci_get_param(a, addrs_param_name);
-  char *devmem = pci_get_param(a, "devmem.path");
 
   if (!*addrs)
     {
@@ -252,13 +209,13 @@ detect(struct pci_access *a, char *addrs_param_name)
       return 0;
     }
 
-  if (access(devmem, R_OK | W_OK))
+  if (physmem_access(a, 1))
     {
-      a->debug("cannot access %s: %s", devmem, strerror(errno));
+      a->debug("cannot access physical memory: %s", strerror(errno));
       return 0;
     }
 
-  a->debug("using %s with %s", devmem, addrs);
+  a->debug("using with %s", addrs);
   return 1;
 }
 
@@ -288,11 +245,9 @@ conf1_init(struct pci_access *a)
 {
   char *addrs_param_name = get_addrs_param_name(a);
   char *addrs = pci_get_param(a, addrs_param_name);
-  char *devmem = pci_get_param(a, "devmem.path");
-
-  pagesize = sysconf(_SC_PAGESIZE);
-  if (pagesize < 0)
-    a->error("Cannot get page size: %s", strerror(errno));
+  struct mmio_access *macc;
+  struct physmem *physmem;
+  long pagesize;
 
   if (!*addrs)
     a->error("Option %s was not specified.", addrs_param_name);
@@ -300,20 +255,29 @@ conf1_init(struct pci_access *a)
   if (!validate_addrs(addrs))
     a->error("Option %s has invalid address format \"%s\".", addrs_param_name, addrs);
 
-  a->fd = open(devmem, O_RDWR | O_DSYNC); /* O_DSYNC bypass CPU cache for mmap() on Linux */
-  if (a->fd < 0)
-    a->error("Cannot open %s: %s.", devmem, strerror(errno));
+  physmem = physmem_open(a, 1);
+  if (!physmem)
+    a->error("Cannot open physcal memory: %s.", strerror(errno));
+
+  pagesize = physmem_get_pagesize(physmem);
+  if (pagesize <= 0)
+    a->error("Cannot get page size: %s.", strerror(errno));
+
+  macc = pci_malloc(a, sizeof(*macc));
+  macc->cache = NULL;
+  macc->physmem = physmem;
+  macc->pagesize = pagesize;
+  a->backend_data = macc;
 }
 
 static void
 conf1_cleanup(struct pci_access *a)
 {
-  if (a->fd < 0)
-    return;
+  struct mmio_access *macc = a->backend_data;
 
   munmap_regs(a);
-  close(a->fd);
-  a->fd = -1;
+  physmem_close(macc->physmem);
+  pci_mfree(macc);
 }
 
 static void
@@ -334,7 +298,7 @@ conf1_ext_read(struct pci_dev *d, int pos, byte *buf, int len)
   char *addrs_param_name = get_addrs_param_name(d->access);
   char *addrs = pci_get_param(d->access, addrs_param_name);
   volatile void *addr, *data;
-  off_t addr_reg, data_reg;
+  u64 addr_reg, data_reg;
 
   if (pos >= 4096)
     return 0;
@@ -348,19 +312,19 @@ conf1_ext_read(struct pci_dev *d, int pos, byte *buf, int len)
   if (!mmap_regs(d->access, addr_reg, data_reg, pos&3, &addr, &data))
     return 0;
 
-  writel(0x80000000 | ((pos & 0xf00) << 16) | ((d->bus & 0xff) << 16) | (PCI_DEVFN(d->dev, d->func) << 8) | (pos & 0xfc), addr);
-  readl(addr); /* write barrier for address */
+  physmem_writel(0x80000000 | ((pos & 0xf00) << 16) | ((d->bus & 0xff) << 16) | (PCI_DEVFN(d->dev, d->func) << 8) | (pos & 0xfc), addr);
+  physmem_readl(addr); /* write barrier for address */
 
   switch (len)
     {
     case 1:
-      buf[0] = readb(data);
+      buf[0] = physmem_readb(data);
       break;
     case 2:
-      ((u16 *) buf)[0] = readw(data);
+      ((u16 *) buf)[0] = physmem_readw(data);
       break;
     case 4:
-      ((u32 *) buf)[0] = readl(data);
+      ((u32 *) buf)[0] = physmem_readl(data);
       break;
     }
 
@@ -382,7 +346,7 @@ conf1_ext_write(struct pci_dev *d, int pos, byte *buf, int len)
   char *addrs_param_name = get_addrs_param_name(d->access);
   char *addrs = pci_get_param(d->access, addrs_param_name);
   volatile void *addr, *data;
-  off_t addr_reg, data_reg;
+  u64 addr_reg, data_reg;
 
   if (pos >= 4096)
     return 0;
@@ -396,19 +360,19 @@ conf1_ext_write(struct pci_dev *d, int pos, byte *buf, int len)
   if (!mmap_regs(d->access, addr_reg, data_reg, pos&3, &addr, &data))
     return 0;
 
-  writel(0x80000000 | ((pos & 0xf00) << 16) | ((d->bus & 0xff) << 16) | (PCI_DEVFN(d->dev, d->func) << 8) | (pos & 0xfc), addr);
-  readl(addr); /* write barrier for address */
+  physmem_writel(0x80000000 | ((pos & 0xf00) << 16) | ((d->bus & 0xff) << 16) | (PCI_DEVFN(d->dev, d->func) << 8) | (pos & 0xfc), addr);
+  physmem_readl(addr); /* write barrier for address */
 
   switch (len)
     {
     case 1:
-      writeb(buf[0], data);
+      physmem_writeb(buf[0], data);
       break;
     case 2:
-      writew(((u16 *) buf)[0], data);
+      physmem_writew(((u16 *) buf)[0], data);
       break;
     case 4:
-      writel(((u32 *) buf)[0], data);
+      physmem_writel(((u32 *) buf)[0], data);
       break;
     }
 
@@ -421,7 +385,7 @@ conf1_ext_write(struct pci_dev *d, int pos, byte *buf, int len)
    * Correct way is to issue CPU instruction for full hw sync barrier but gcc
    * does not provide any (builtin) function yet.
    */
-  readl(addr);
+  physmem_readl(addr);
 
   return 1;
 }