2 * Copyright 2009 Red Hat, Inc.
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:
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
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.
23 * Adam Jackson <ajax@redhat.com>
28 #include "pciaccess.h"
29 #include "pciaccess_private.h"
31 static struct pci_io_handle *ios;
32 static unsigned int num_ios;
34 static struct pci_io_handle *
37 struct pci_io_handle *new;
39 new = realloc(ios, sizeof(struct pci_io_handle) * (num_ios + 1));
46 return ios + num_ios - 1;
50 delete_io_handle(struct pci_io_handle *handle)
52 struct pci_io_handle *new;
55 if (!handle || !num_ios || (void *)handle < (void *)ios ||
56 (void *)handle > (void *)(ios + num_ios - 1))
59 for (i = 0; i < num_ios; i++) {
60 if (ios + i == handle) {
61 memmove(&ios[i], &ios[i+1], sizeof(struct pci_io_handle) *
67 new = realloc(ios, sizeof(struct pci_io_handle) * (num_ios - 1));
82 * Open a handle to a PCI device I/O range. The \c base and \c size
83 * requested must fit entirely within a single I/O BAR on the device.
84 * \c size is in bytes.
87 * An opaque handle to the I/O BAR, or \c NULL on error.
89 struct pci_io_handle *
90 pci_device_open_io(struct pci_device *dev, pciaddr_t base, pciaddr_t size)
92 struct pci_io_handle *ret;
95 if (!pci_sys->methods->open_device_io)
98 for (bar = 0; bar < 6; bar++) {
99 struct pci_mem_region *region = &(dev->regions[bar]);
103 if (base < region->base_addr || base > (region->base_addr+region->size))
106 if ((base + size) > (region->base_addr + region->size))
109 ret = new_io_handle();
113 if (!pci_sys->methods->open_device_io(ret, dev, bar, base, size)) {
114 delete_io_handle(ret);
125 * Open a handle to the legacy I/O space for the PCI domain containing
126 * \c dev. \c size is in bytes.
129 * An opaque handle to the requested range, or \c NULL on error.
131 struct pci_io_handle *
132 pci_legacy_open_io(struct pci_device *dev, pciaddr_t base, pciaddr_t size)
134 struct pci_io_handle *ret;
136 if (!pci_sys->methods->open_legacy_io)
139 ret = new_io_handle();
143 if (!pci_sys->methods->open_legacy_io(ret, dev, base, size)) {
144 delete_io_handle(ret);
152 * Close an I/O handle.
155 pci_device_close_io(struct pci_device *dev, struct pci_io_handle *handle)
157 if (dev && handle && pci_sys->methods->close_io)
158 pci_sys->methods->close_io(dev, handle);
160 delete_io_handle(handle);
164 * Read a 32-bit value from the I/O space. \c reg is relative to the
165 * \c base specified when the handle was opened. Some platforms may
166 * require that \c reg be 32-bit-aligned.
169 * The value read from the I/O port, or undefined on any error.
172 pci_io_read32(struct pci_io_handle *handle, uint32_t reg)
174 if (reg + 4 > handle->size)
177 return pci_sys->methods->read32(handle, reg);
181 * Read a 16-bit value from the I/O space. \c reg is relative to the
182 * \c base specified when the handle was opened. Some platforms may
183 * require that \c reg be 16-bit-aligned.
186 * The value read from the I/O port, or undefined on any error.
189 pci_io_read16(struct pci_io_handle *handle, uint32_t reg)
191 if (reg + 2 > handle->size)
194 return pci_sys->methods->read16(handle, reg);
198 * Read a 8-bit value from the I/O space. \c reg is relative to the
199 * \c base specified when the handle was opened.
202 * The value read from the I/O port, or undefined on any error.
205 pci_io_read8(struct pci_io_handle *handle, uint32_t reg)
207 if (reg + 1 > handle->size)
210 return pci_sys->methods->read8(handle, reg);
214 * Write a 32-bit value to the I/O space. \c reg is relative to the
215 * \c base specified when the handle was opened. Some platforms may
216 * require that \c reg be 32-bit-aligned.
219 pci_io_write32(struct pci_io_handle *handle, uint32_t reg, uint32_t data)
221 if (reg + 4 > handle->size)
224 pci_sys->methods->write32(handle, reg, data);
228 * Write a 16-bit value to the I/O space. \c reg is relative to the
229 * \c base specified when the handle was opened. Some platforms may
230 * require that \c reg be 16-bit-aligned.
233 pci_io_write16(struct pci_io_handle *handle, uint32_t reg, uint16_t data)
235 if (reg + 2 > handle->size)
238 pci_sys->methods->write16(handle, reg, data);
242 * Write a 8-bit value to the I/O space. \c reg is relative to the
243 * \c base specified when the handle was opened.
246 pci_io_write8(struct pci_io_handle *handle, uint32_t reg, uint8_t data)
248 if (reg + 1 > handle->size)
251 pci_sys->methods->write8(handle, reg, data);