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