Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  * Copyright 2009 Red Hat, Inc.
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software")
      6  * to deal in the software without restriction, including without limitation
      7  * on the rights to use, copy, modify, merge, publish, distribute, sub
      8  * license, and/or sell copies of the Software, and to permit persons to whom
      9  * them Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER
     19  * IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF OR IN
     20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     21  *
     22  * Author:
     23  *	Adam Jackson <ajax (at) redhat.com>
     24  */
     25 #ifdef HAVE_CONFIG_H
     26 #include "config.h"
     27 #endif
     28 
     29 #include <stdlib.h>
     30 #include <string.h>
     31 #include "pciaccess.h"
     32 #include "pciaccess_private.h"
     33 
     34 static struct pci_io_handle *
     35 new_io_handle(void)
     36 {
     37     struct pci_io_handle *new;
     38 
     39     new = malloc(sizeof(struct pci_io_handle));
     40     if (!new)
     41 	return NULL;
     42 
     43     return new;
     44 }
     45 
     46 static void
     47 delete_io_handle(struct pci_io_handle *handle)
     48 {
     49     free(handle);
     50     return;
     51 }
     52 
     53 _pci_hidden void
     54 pci_io_cleanup(void)
     55 {
     56 }
     57 
     58 /**
     59  * Open a handle to a PCI device I/O range.  The \c base and \c size
     60  * requested must fit entirely within a single I/O BAR on the device.
     61  * \c size is in bytes.
     62  *
     63  * \returns
     64  * An opaque handle to the I/O BAR, or \c NULL on error.
     65  */
     66 struct pci_io_handle *
     67 pci_device_open_io(struct pci_device *dev, pciaddr_t base, pciaddr_t size)
     68 {
     69     struct pci_io_handle *ret;
     70     int bar;
     71 
     72     if (!pci_sys->methods->open_device_io)
     73 	return NULL;
     74 
     75     for (bar = 0; bar < 6; bar++) {
     76 	struct pci_mem_region *region = &(dev->regions[bar]);
     77 	if (!region->is_IO)
     78 	    continue;
     79 
     80 	if (base < region->base_addr || base > (region->base_addr+region->size))
     81 	    continue;
     82 
     83 	if ((base + size) > (region->base_addr + region->size))
     84 	    continue;
     85 
     86 	ret = new_io_handle();
     87 	if (!ret)
     88 	    return NULL;
     89 
     90 	if (!pci_sys->methods->open_device_io(ret, dev, bar, base, size)) {
     91 	    delete_io_handle(ret);
     92 	    return NULL;
     93 	}
     94 
     95         return ret;
     96     }
     97 
     98     return NULL;
     99 }
    100 
    101 /**
    102  * Open a handle to the legacy I/O space for the PCI domain containing
    103  * \c dev. \c size is in bytes.
    104  *
    105  * \returns
    106  * An opaque handle to the requested range, or \c NULL on error.
    107  */
    108 struct pci_io_handle *
    109 pci_legacy_open_io(struct pci_device *dev, pciaddr_t base, pciaddr_t size)
    110 {
    111     struct pci_io_handle *ret;
    112 
    113     if (!pci_sys->methods->open_legacy_io)
    114 	return NULL;
    115 
    116     ret = new_io_handle();
    117     if (!ret)
    118 	return NULL;
    119 
    120     if (!pci_sys->methods->open_legacy_io(ret, dev, base, size)) {
    121 	delete_io_handle(ret);
    122 	return NULL;
    123     }
    124 
    125     return ret;
    126 }
    127 
    128 /**
    129  * Close an I/O handle.
    130  */
    131 void
    132 pci_device_close_io(struct pci_device *dev, struct pci_io_handle *handle)
    133 {
    134     if (dev && handle && pci_sys->methods->close_io)
    135 	pci_sys->methods->close_io(dev, handle);
    136 
    137     delete_io_handle(handle);
    138 }
    139 
    140 /**
    141  * Read a 32-bit value from the I/O space.  \c reg is relative to the
    142  * \c base specified when the handle was opened.  Some platforms may
    143  * require that \c reg be 32-bit-aligned.
    144  *
    145  * \returns
    146  * The value read from the I/O port, or undefined on any error.
    147  */
    148 uint32_t
    149 pci_io_read32(struct pci_io_handle *handle, uint32_t reg)
    150 {
    151     if (reg + 4 > handle->size)
    152 	return UINT32_MAX;
    153 
    154     return pci_sys->methods->read32(handle, reg);
    155 }
    156 
    157 /**
    158  * Read a 16-bit value from the I/O space.  \c reg is relative to the
    159  * \c base specified when the handle was opened.  Some platforms may
    160  * require that \c reg be 16-bit-aligned.
    161  *
    162  * \returns
    163  * The value read from the I/O port, or undefined on any error.
    164  */
    165 uint16_t
    166 pci_io_read16(struct pci_io_handle *handle, uint32_t reg)
    167 {
    168     if (reg + 2 > handle->size)
    169 	return UINT16_MAX;
    170 
    171     return pci_sys->methods->read16(handle, reg);
    172 }
    173 
    174 /**
    175  * Read a 8-bit value from the I/O space.  \c reg is relative to the
    176  * \c base specified when the handle was opened.
    177  *
    178  * \returns
    179  * The value read from the I/O port, or undefined on any error.
    180  */
    181 uint8_t
    182 pci_io_read8(struct pci_io_handle *handle, uint32_t reg)
    183 {
    184     if (reg + 1 > handle->size)
    185 	return UINT8_MAX;
    186 
    187     return pci_sys->methods->read8(handle, reg);
    188 }
    189 
    190 /**
    191  * Write a 32-bit value to the I/O space.  \c reg is relative to the
    192  * \c base specified when the handle was opened.  Some platforms may
    193  * require that \c reg be 32-bit-aligned.
    194  */
    195 void
    196 pci_io_write32(struct pci_io_handle *handle, uint32_t reg, uint32_t data)
    197 {
    198     if (reg + 4 > handle->size)
    199 	return;
    200 
    201     pci_sys->methods->write32(handle, reg, data);
    202 }
    203 
    204 /**
    205  * Write a 16-bit value to the I/O space.  \c reg is relative to the
    206  * \c base specified when the handle was opened.  Some platforms may
    207  * require that \c reg be 16-bit-aligned.
    208  */
    209 void
    210 pci_io_write16(struct pci_io_handle *handle, uint32_t reg, uint16_t data)
    211 {
    212     if (reg + 2 > handle->size)
    213 	return;
    214 
    215     pci_sys->methods->write16(handle, reg, data);
    216 }
    217 
    218 /**
    219  * Write a 8-bit value to the I/O space.  \c reg is relative to the
    220  * \c base specified when the handle was opened.
    221  */
    222 void
    223 pci_io_write8(struct pci_io_handle *handle, uint32_t reg, uint8_t data)
    224 {
    225     if (reg + 1 > handle->size)
    226 	return;
    227 
    228     pci_sys->methods->write8(handle, reg, data);
    229 }
    230