common_io.c revision cad31331
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 MERCHANTIBILITY, 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 26#include <stdlib.h> 27#include <string.h> 28#include "pciaccess.h" 29#include "pciaccess_private.h" 30 31static struct pci_io_handle * 32new_io_handle(void) 33{ 34 struct pci_io_handle *new; 35 36 new = malloc(sizeof(struct pci_io_handle)); 37 if (!new) 38 return NULL; 39 40 return new; 41} 42 43static void 44delete_io_handle(struct pci_io_handle *handle) 45{ 46 free(handle); 47 return; 48} 49 50_pci_hidden void 51pci_io_cleanup(void) 52{ 53} 54 55/** 56 * Open a handle to a PCI device I/O range. The \c base and \c size 57 * requested must fit entirely within a single I/O BAR on the device. 58 * \c size is in bytes. 59 * 60 * \returns 61 * An opaque handle to the I/O BAR, or \c NULL on error. 62 */ 63struct pci_io_handle * 64pci_device_open_io(struct pci_device *dev, pciaddr_t base, pciaddr_t size) 65{ 66 struct pci_io_handle *ret; 67 int bar; 68 69 if (!pci_sys->methods->open_device_io) 70 return NULL; 71 72 for (bar = 0; bar < 6; bar++) { 73 struct pci_mem_region *region = &(dev->regions[bar]); 74 if (!region->is_IO) 75 continue; 76 77 if (base < region->base_addr || base > (region->base_addr+region->size)) 78 continue; 79 80 if ((base + size) > (region->base_addr + region->size)) 81 continue; 82 83 ret = new_io_handle(); 84 if (!ret) 85 return NULL; 86 87 if (!pci_sys->methods->open_device_io(ret, dev, bar, base, size)) { 88 delete_io_handle(ret); 89 return NULL; 90 } 91 92 return ret; 93 } 94 95 return NULL; 96} 97 98/** 99 * Open a handle to the legacy I/O space for the PCI domain containing 100 * \c dev. \c size is in bytes. 101 * 102 * \returns 103 * An opaque handle to the requested range, or \c NULL on error. 104 */ 105struct pci_io_handle * 106pci_legacy_open_io(struct pci_device *dev, pciaddr_t base, pciaddr_t size) 107{ 108 struct pci_io_handle *ret; 109 110 if (!pci_sys->methods->open_legacy_io) 111 return NULL; 112 113 ret = new_io_handle(); 114 if (!ret) 115 return NULL; 116 117 if (!pci_sys->methods->open_legacy_io(ret, dev, base, size)) { 118 delete_io_handle(ret); 119 return NULL; 120 } 121 122 return ret; 123} 124 125/** 126 * Close an I/O handle. 127 */ 128void 129pci_device_close_io(struct pci_device *dev, struct pci_io_handle *handle) 130{ 131 if (dev && handle && pci_sys->methods->close_io) 132 pci_sys->methods->close_io(dev, handle); 133 134 delete_io_handle(handle); 135} 136 137/** 138 * Read a 32-bit value from the I/O space. \c reg is relative to the 139 * \c base specified when the handle was opened. Some platforms may 140 * require that \c reg be 32-bit-aligned. 141 * 142 * \returns 143 * The value read from the I/O port, or undefined on any error. 144 */ 145uint32_t 146pci_io_read32(struct pci_io_handle *handle, uint32_t reg) 147{ 148 if (reg + 4 > handle->size) 149 return UINT32_MAX; 150 151 return pci_sys->methods->read32(handle, reg); 152} 153 154/** 155 * Read a 16-bit value from the I/O space. \c reg is relative to the 156 * \c base specified when the handle was opened. Some platforms may 157 * require that \c reg be 16-bit-aligned. 158 * 159 * \returns 160 * The value read from the I/O port, or undefined on any error. 161 */ 162uint16_t 163pci_io_read16(struct pci_io_handle *handle, uint32_t reg) 164{ 165 if (reg + 2 > handle->size) 166 return UINT16_MAX; 167 168 return pci_sys->methods->read16(handle, reg); 169} 170 171/** 172 * Read a 8-bit value from the I/O space. \c reg is relative to the 173 * \c base specified when the handle was opened. 174 * 175 * \returns 176 * The value read from the I/O port, or undefined on any error. 177 */ 178uint8_t 179pci_io_read8(struct pci_io_handle *handle, uint32_t reg) 180{ 181 if (reg + 1 > handle->size) 182 return UINT8_MAX; 183 184 return pci_sys->methods->read8(handle, reg); 185} 186 187/** 188 * Write a 32-bit value to the I/O space. \c reg is relative to the 189 * \c base specified when the handle was opened. Some platforms may 190 * require that \c reg be 32-bit-aligned. 191 */ 192void 193pci_io_write32(struct pci_io_handle *handle, uint32_t reg, uint32_t data) 194{ 195 if (reg + 4 > handle->size) 196 return; 197 198 pci_sys->methods->write32(handle, reg, data); 199} 200 201/** 202 * Write a 16-bit value to the I/O space. \c reg is relative to the 203 * \c base specified when the handle was opened. Some platforms may 204 * require that \c reg be 16-bit-aligned. 205 */ 206void 207pci_io_write16(struct pci_io_handle *handle, uint32_t reg, uint16_t data) 208{ 209 if (reg + 2 > handle->size) 210 return; 211 212 pci_sys->methods->write16(handle, reg, data); 213} 214 215/** 216 * Write a 8-bit value to the I/O space. \c reg is relative to the 217 * \c base specified when the handle was opened. 218 */ 219void 220pci_io_write8(struct pci_io_handle *handle, uint32_t reg, uint8_t data) 221{ 222 if (reg + 1 > handle->size) 223 return; 224 225 pci_sys->methods->write8(handle, reg, data); 226} 227