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