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