upload tizen2.0 source
[framework/uifw/xorg/lib/libpciaccess.git] / src / common_io.c
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
31 static struct pci_io_handle *
32 new_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
43 static void
44 delete_io_handle(struct pci_io_handle *handle)
45 {
46     free(handle);
47     return;
48 }
49
50 _pci_hidden void
51 pci_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  */
63 struct pci_io_handle *
64 pci_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  */
105 struct pci_io_handle *
106 pci_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  */
128 void
129 pci_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  */
145 uint32_t
146 pci_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  */
162 uint16_t
163 pci_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  */
178 uint8_t
179 pci_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  */
192 void
193 pci_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  */
206 void
207 pci_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  */
219 void
220 pci_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 }