xref: /libpciaccess/src/common_interface.c (revision 5a04522a)
1 /*
2  * (C) Copyright IBM Corporation 2006
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * on the rights to use, copy, modify, merge, publish, distribute, sub
9  * license, and/or sell copies of the Software, and to permit persons to whom
10  * the Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
19  * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 
25 /**
26  * \file common_interface.c
27  * Platform independent interface glue.
28  *
29  * \author Ian Romanick <[email protected]>
30  */
31 
32 #include <stdlib.h>
33 #include <errno.h>
34 
35 #include "pciaccess.h"
36 #include "pciaccess_private.h"
37 
38 #include <byteswap.h>
39 
40 #if __BYTE_ORDER == __BIG_ENDIAN
41 # define LETOH_16(x)   bswap_16(x)
42 # define HTOLE_16(x)   bswap_16(x)
43 # define LETOH_32(x)   bswap_32(x)
44 # define HTOLE_32(x)   bswap_32(x)
45 #else
46 # define LETOH_16(x)   (x)
47 # define HTOLE_16(x)   (x)
48 # define LETOH_32(x)   (x)
49 # define HTOLE_32(x)   (x)
50 #endif
51 
52 /**
53  * Read a device's expansion ROM.
54  *
55  * Reads the device's expansion ROM and stores the data in the memory pointed
56  * to by \c buffer.  The buffer must be at least \c pci_device::rom_size
57  * bytes.
58  *
59  * \param dev    Device whose expansion ROM is to be read.
60  * \param buffer Memory in which to store the ROM.
61  *
62  * \return
63  * Zero on success or an \c errno value on failure.
64  */
65 int
66 pci_device_read_rom( struct pci_device * dev, void * buffer )
67 {
68     if ( (dev == NULL) || (buffer == NULL) ) {
69 	return EFAULT;
70     }
71 
72 
73     return (pci_sys->methods->read_rom)( dev, buffer );
74 }
75 
76 
77 /**
78  * Probe a PCI device to learn information about the device.
79  *
80  * Probes a PCI device to learn various information about the device.  Before
81  * calling this function, the only public fields in the \c pci_device
82  * structure that have valid values are \c pci_device::domain,
83  * \c pci_device::bus, \c pci_device::dev, and \c pci_device::func.
84  *
85  * \param dev  Device to be probed.
86  *
87  * \return
88  * Zero on succes or an \c errno value on failure.
89  */
90 int
91 pci_device_probe( struct pci_device * dev )
92 {
93     if ( dev == NULL ) {
94 	return EFAULT;
95     }
96 
97 
98     return (pci_sys->methods->probe)( dev );
99 }
100 
101 
102 /**
103  * Map the specified BAR so that it can be accessed by the CPU.
104  *
105  * Maps the specified BAR for acces by the processor.  The pointer to the
106  * mapped region is stored in the \c pci_mem_region::memory pointer for the
107  * BAR.
108  *
109  * \param dev          Device whose memory region is to be mapped.
110  * \param region       Region, on the range [0, 5], that is to be mapped.
111  * \param write_enable Map for writing (non-zero).
112  *
113  * \return
114  * Zero on success or an \c errno value on failure.
115  *
116  * \sa pci_device_unmap_region
117  */
118 int
119 pci_device_map_region( struct pci_device * dev, unsigned region,
120 		       int write_enable )
121 {
122     if ( dev == NULL ) {
123 	return EFAULT;
124     }
125 
126     if ( (region > 5) || (dev->regions[ region ].size == 0) ) {
127 	return ENOENT;
128     }
129 
130     if ( dev->regions[ region ].memory != NULL ) {
131 	return 0;
132     }
133 
134     return (pci_sys->methods->map)( dev, region, write_enable );
135 }
136 
137 
138 /**
139  * Unmap the specified BAR so that it can no longer be accessed by the CPU.
140  *
141  * Unmaps the specified BAR that was previously mapped via
142  * \c pci_device_map_region.
143  *
144  * \param dev          Device whose memory region is to be mapped.
145  * \param region       Region, on the range [0, 5], that is to be mapped.
146  *
147  * \return
148  * Zero on success or an \c errno value on failure.
149  *
150  * \sa pci_device_map_region
151  */
152 int
153 pci_device_unmap_region( struct pci_device * dev, unsigned region )
154 {
155     if ( dev == NULL ) {
156 	return EFAULT;
157     }
158 
159     if ( (region > 5) || (dev->regions[ region ].size == 0) ) {
160 	return ENOENT;
161     }
162 
163     if ( dev->regions[ region ].memory == NULL ) {
164 	return 0;
165     }
166 
167     return (pci_sys->methods->unmap)( dev, region );
168 }
169 
170 
171 /**
172  * Read arbitrary bytes from device's PCI config space
173  *
174  * Reads data from the device's PCI configuration space.  As with the system
175  * read command, less data may be returned, without an error, than was
176  * requested.  This is particuarly the case if a non-root user tries to read
177  * beyond the first 64-bytes of configuration space.
178  *
179  * \param dev         Device whose PCI configuration data is to be read.
180  * \param data        Location to store the data
181  * \param offset      Initial byte offset to read
182  * \param size        Total number of bytes to read
183  * \param bytes_read  Location to store the actual number of bytes read.  This
184  *                    pointer may be \c NULL.
185  *
186  * \returns
187  * Zero on success or an errno value on failure.
188  *
189  * \note
190  * Data read from PCI configuartion space using this routine is \b not
191  * byte-swapped to the host's byte order.  PCI configuration data is always
192  * stored in little-endian order, and that is what this routine returns.
193  */
194 int
195 pci_device_cfg_read( struct pci_device * dev, void * data,
196 		     pciaddr_t offset, pciaddr_t size,
197 		     pciaddr_t * bytes_read )
198 {
199     pciaddr_t  scratch;
200 
201     if ( (dev == NULL) || (data == NULL) ) {
202 	return EFAULT;
203     }
204 
205     return pci_sys->methods->read( dev, data, offset, size,
206 				   (bytes_read == NULL)
207 				   ? & scratch : bytes_read );
208 }
209 
210 
211 int
212 pci_device_cfg_read_u8( struct pci_device * dev, uint8_t * data,
213 			pciaddr_t offset )
214 {
215     pciaddr_t bytes;
216     int err = pci_device_cfg_read( dev, data, offset, 1, & bytes );
217 
218     if ( (err == 0) && (bytes != 1) ) {
219 	err = ENODATA;
220     }
221 
222     return err;
223 }
224 
225 
226 int
227 pci_device_cfg_read_u16( struct pci_device * dev, uint16_t * data,
228 			 pciaddr_t offset )
229 {
230     pciaddr_t bytes;
231     int err = pci_device_cfg_read( dev, data, offset, 2, & bytes );
232 
233     if ( (err == 0) && (bytes != 2) ) {
234 	err = ENODATA;
235     }
236 
237     *data = LETOH_16( *data );
238     return err;
239 }
240 
241 
242 int
243 pci_device_cfg_read_u32( struct pci_device * dev, uint32_t * data,
244 			 pciaddr_t offset )
245 {
246     pciaddr_t bytes;
247     int err = pci_device_cfg_read( dev, data, offset, 4, & bytes );
248 
249     if ( (err == 0) && (bytes != 4) ) {
250 	err = ENODATA;
251     }
252 
253     *data = LETOH_32( *data );
254     return err;
255 }
256 
257 
258 /**
259  * Write arbitrary bytes to device's PCI config space
260  *
261  * Writess data to the device's PCI configuration space.  As with the system
262  * write command, less data may be written, without an error, than was
263  * requested.
264  *
265  * \param dev         Device whose PCI configuration data is to be written.
266  * \param data        Location of the source data
267  * \param offset      Initial byte offset to write
268  * \param size        Total number of bytes to write
269  * \param bytes_read  Location to store the actual number of bytes written.
270  *                    This pointer may be \c NULL.
271  *
272  * \returns
273  * Zero on success or an errno value on failure.
274  *
275  * \note
276  * Data written to PCI configuartion space using this routine is \b not
277  * byte-swapped from the host's byte order.  PCI configuration data is always
278  * stored in little-endian order, so data written with this routine should be
279  * put in that order in advance.
280  */
281 int
282 pci_device_cfg_write( struct pci_device * dev, const void * data,
283 		      pciaddr_t offset, pciaddr_t size,
284 		      pciaddr_t * bytes_written )
285 {
286     pciaddr_t  scratch;
287 
288     if ( (dev == NULL) || (data == NULL) ) {
289 	return EFAULT;
290     }
291 
292     return pci_sys->methods->write( dev, data, offset, size,
293 				    (bytes_written == NULL)
294 				    ? & scratch : bytes_written );
295 }
296 
297 
298 int
299 pci_device_cfg_write_u8( struct pci_device * dev, const uint8_t * data,
300 			 pciaddr_t offset )
301 {
302     pciaddr_t bytes;
303     int err = pci_device_cfg_write( dev, data, offset, 1, & bytes );
304 
305     if ( (err == 0) && (bytes != 1) ) {
306 	err = ENOSPC;
307     }
308 
309 
310     return err;
311 }
312 
313 
314 int
315 pci_device_cfg_write_u16( struct pci_device * dev, const uint16_t * data,
316 			  pciaddr_t offset )
317 {
318     pciaddr_t bytes;
319     const uint16_t temp = HTOLE_16( *data );
320     int err = pci_device_cfg_write( dev, & temp, offset, 2, & bytes );
321 
322     if ( (err == 0) && (bytes != 2) ) {
323 	err = ENOSPC;
324     }
325 
326 
327     return err;
328 }
329 
330 
331 int
332 pci_device_cfg_write_u32( struct pci_device * dev, const uint32_t * data,
333 			  pciaddr_t offset )
334 {
335     pciaddr_t bytes;
336     const uint32_t temp = HTOLE_32( *data );
337     int err = pci_device_cfg_write( dev, & temp, offset, 4, & bytes );
338 
339     if ( (err == 0) && (bytes != 4) ) {
340 	err = ENOSPC;
341     }
342 
343 
344     return err;
345 }
346