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