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@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 34static struct pci_io_handle * 35new_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 46static void 47delete_io_handle(struct pci_io_handle *handle) 48{ 49 free(handle); 50 return; 51} 52 53_pci_hidden void 54pci_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 */ 66struct pci_io_handle * 67pci_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 */ 108struct pci_io_handle * 109pci_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 */ 131void 132pci_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 */ 148uint32_t 149pci_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 */ 165uint16_t 166pci_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 */ 181uint8_t 182pci_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 */ 195void 196pci_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 */ 209void 210pci_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 */ 222void 223pci_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