summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Romanick <idr@us.ibm.com>2007-01-11 21:40:57 -0800
committerIan Romanick <idr@us.ibm.com>2007-01-11 21:40:57 -0800
commitc65aa7630802c8dfcc06a20e515ace31ab0d0e48 (patch)
treea277e8355848652b6ef3785c5c0c9e65c4e2c617
parentdb4a12d09fba381f39af024418e913fb99c34935 (diff)
Add interfaces to map / unmap specific memory ranges, bump lib version to 0.7.0.
Add pci_device_map_memory_range and pci_device_unmap_memory_range to map and unmap specific memory ranges. The unmap bit is still a bit hinkey (unmaps the whole BAR). Works so far for initial conversion of VESA driver. Will need to be revisited.
-rw-r--r--configure.ac2
-rw-r--r--include/pciaccess.h6
-rw-r--r--src/Makefile.am2
-rw-r--r--src/common_interface.c117
4 files changed, 125 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac
index 99ea0cf..1c99739 100644
--- a/configure.ac
+++ b/configure.ac
@@ -41,7 +41,7 @@ dnl refers to ${prefix}. Thus we have to use `eval' twice.
AC_PREREQ([2.57])
-AC_INIT(libpciaccess, 0.6.0, [none yet], libpciaccess)
+AC_INIT(libpciaccess, 0.7.0, [none yet], libpciaccess)
AM_INIT_AUTOMAKE([dist-bzip2])
AM_MAINTAINER_MODE
diff --git a/include/pciaccess.h b/include/pciaccess.h
index 4078f0f..a0cf067 100644
--- a/include/pciaccess.h
+++ b/include/pciaccess.h
@@ -47,6 +47,12 @@ int pci_device_map_region( struct pci_device * dev, unsigned region,
int pci_device_unmap_region( struct pci_device * dev, unsigned region );
+int pci_device_map_memory_range(struct pci_device *dev, pciaddr_t base,
+ pciaddr_t size, int write_enable, void **addr);
+
+int pci_device_unmap_memory_range(struct pci_device *dev, void *memory,
+ pciaddr_t size);
+
int pci_device_probe( struct pci_device * dev );
const struct pci_agp_info * pci_device_get_agp_info( struct pci_device * dev );
diff --git a/src/Makefile.am b/src/Makefile.am
index da20076..de4e52a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -43,7 +43,7 @@ INCLUDES = -I$(top_srcdir)/include
libpciaccess_la_LIBADD = @PCIACCESS_LIBS@
-libpciaccess_la_LDFLAGS = -version-number 0:6:0 -no-undefined
+libpciaccess_la_LDFLAGS = -version-number 0:7:0 -no-undefined
libpciaccessincludedir = $(includedir)
libpciaccessinclude_HEADERS = \
diff --git a/src/common_interface.c b/src/common_interface.c
index 67e8e9a..54c8b26 100644
--- a/src/common_interface.c
+++ b/src/common_interface.c
@@ -148,6 +148,72 @@ pci_device_map_region( struct pci_device * dev, unsigned region,
/**
+ * Map the specified memory range so that it can be accessed by the CPU.
+ *
+ * Maps the specified memory range for access by the processor. The pointer
+ * to the mapped region is stored in \c addr. In addtion, the
+ * \c pci_mem_region::memory pointer for the BAR will be updated.
+ *
+ * \param dev Device whose memory region is to be mapped.
+ * \param base Base address of the range to be mapped.
+ * \param size Size of the range to be mapped.
+ * \param write_enable Map for writing (non-zero).
+ * \param addr Location to store the mapped address.
+ *
+ * \return
+ * Zero on success or an \c errno value on failure.
+ *
+ * \sa pci_device_unmap_memory_range, pci_device_map_region
+ */
+int
+pci_device_map_memory_range(struct pci_device *dev, pciaddr_t base,
+ pciaddr_t size, int write_enable,
+ void **addr)
+{
+ unsigned region;
+ int err = 0;
+
+
+ *addr = NULL;
+
+ if (dev == NULL) {
+ return EFAULT;
+ }
+
+
+ for (region = 0; region < 6; region++) {
+ const struct pci_mem_region const* r = &dev->regions[region];
+
+ if (r->size != 0) {
+ if ((r->base_addr <= base) && ((r->base_addr + r->size) > base)) {
+ if ((base + size) > (r->base_addr + r->size)) {
+ return E2BIG;
+ }
+
+ break;
+ }
+ }
+ }
+
+ if (region > 5) {
+ return ENOENT;
+ }
+
+ if (dev->regions[region].memory == NULL) {
+ err = (*pci_sys->methods->map)(dev, region, write_enable);
+ }
+
+ if (err == 0) {
+ const pciaddr_t offset = base - dev->regions[region].base_addr;
+
+ *addr = ((uint8_t *)dev->regions[region].memory) + offset;
+ }
+
+ return err;
+}
+
+
+/**
* Unmap the specified BAR so that it can no longer be accessed by the CPU.
*
* Unmaps the specified BAR that was previously mapped via
@@ -181,6 +247,57 @@ pci_device_unmap_region( struct pci_device * dev, unsigned region )
/**
+ * Unmap the specified memory range so that it can no longer be accessed by the CPU.
+ *
+ * Unmaps the specified memory range that was previously mapped via
+ * \c pci_device_map_memory_range.
+ *
+ * \param dev Device whose memory is to be unmapped.
+ * \param memory Pointer to the base of the mapped range.
+ * \param size Size, in bytes, of the range to be unmapped.
+ *
+ * \return
+ * Zero on success or an \c errno value on failure.
+ *
+ * \sa pci_device_map_memory_range, pci_device_unmap_region
+ */
+int
+pci_device_unmap_memory_range(struct pci_device *dev, void *memory,
+ pciaddr_t size)
+{
+ unsigned region;
+
+
+ if (dev == NULL) {
+ return EFAULT;
+ }
+
+ for (region = 0; region < 6; region++) {
+ const struct pci_mem_region const* r = &dev->regions[region];
+ const uint8_t *const mem = r->memory;
+
+ if (r->size != 0) {
+ if ((mem <= memory) && ((mem + r->size) > memory)) {
+ if ((memory + size) > (mem + r->size)) {
+ return E2BIG;
+ }
+
+ break;
+ }
+ }
+ }
+
+ if (region > 5) {
+ return ENOENT;
+ }
+
+ return (dev->regions[region].memory != NULL)
+ ? (*pci_sys->methods->unmap)(dev, region)
+ : 0;
+}
+
+
+/**
* Read arbitrary bytes from device's PCI config space
*
* Reads data from the device's PCI configuration space. As with the system