Bug Summary

File:common_interface.c
Location:line 444, column 26
Description:Call to 'realloc' has an allocation size of 0 bytes

Annotated Source Code

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 <idr@us.ibm.com>
30 */
31
32#include <stdlib.h>
33#include <string.h>
34#include <errno(*__errno_location ()).h>
35
36#include "pciaccess.h"
37#include "pciaccess_private.h"
38
39#if defined(__linux__1) || defined(__GLIBC__2)
40#include <byteswap.h>
41
42#if __BYTE_ORDER4321 == __BIG_ENDIAN4321
43# define LETOH_16(x)(__extension__ ({ unsigned short int __bsx = (x); ((((__bsx) >>
8) & 0xffu) | (((__bsx) & 0xffu) << 8)); }))
bswap_16(x)(__extension__ ({ unsigned short int __bsx = (x); ((((__bsx) >>
8) & 0xffu) | (((__bsx) & 0xffu) << 8)); }))
44# define HTOLE_16(x)(__extension__ ({ unsigned short int __bsx = (x); ((((__bsx) >>
8) & 0xffu) | (((__bsx) & 0xffu) << 8)); }))
bswap_16(x)(__extension__ ({ unsigned short int __bsx = (x); ((((__bsx) >>
8) & 0xffu) | (((__bsx) & 0xffu) << 8)); }))
45# define LETOH_32(x)(__extension__ ({ register unsigned int __bsx = (x); ((((__bsx
) & 0xff000000u) >> 24) | (((__bsx) & 0x00ff0000u
) >> 8) | (((__bsx) & 0x0000ff00u) << 8) | ((
(__bsx) & 0x000000ffu) << 24)); }))
bswap_32(x)(__extension__ ({ register unsigned int __bsx = (x); ((((__bsx
) & 0xff000000u) >> 24) | (((__bsx) & 0x00ff0000u
) >> 8) | (((__bsx) & 0x0000ff00u) << 8) | ((
(__bsx) & 0x000000ffu) << 24)); }))
46# define HTOLE_32(x)(__extension__ ({ register unsigned int __bsx = (x); ((((__bsx
) & 0xff000000u) >> 24) | (((__bsx) & 0x00ff0000u
) >> 8) | (((__bsx) & 0x0000ff00u) << 8) | ((
(__bsx) & 0x000000ffu) << 24)); }))
bswap_32(x)(__extension__ ({ register unsigned int __bsx = (x); ((((__bsx
) & 0xff000000u) >> 24) | (((__bsx) & 0x00ff0000u
) >> 8) | (((__bsx) & 0x0000ff00u) << 8) | ((
(__bsx) & 0x000000ffu) << 24)); }))
47#else
48# define LETOH_16(x)(__extension__ ({ unsigned short int __bsx = (x); ((((__bsx) >>
8) & 0xffu) | (((__bsx) & 0xffu) << 8)); }))
(x)
49# define HTOLE_16(x)(__extension__ ({ unsigned short int __bsx = (x); ((((__bsx) >>
8) & 0xffu) | (((__bsx) & 0xffu) << 8)); }))
(x)
50# define LETOH_32(x)(__extension__ ({ register unsigned int __bsx = (x); ((((__bsx
) & 0xff000000u) >> 24) | (((__bsx) & 0x00ff0000u
) >> 8) | (((__bsx) & 0x0000ff00u) << 8) | ((
(__bsx) & 0x000000ffu) << 24)); }))
(x)
51# define HTOLE_32(x)(__extension__ ({ register unsigned int __bsx = (x); ((((__bsx
) & 0xff000000u) >> 24) | (((__bsx) & 0x00ff0000u
) >> 8) | (((__bsx) & 0x0000ff00u) << 8) | ((
(__bsx) & 0x000000ffu) << 24)); }))
(x)
52#endif /* linux */
53
54#elif defined(__sun)
55
56#include <sys/byteorder.h>
57
58#ifdef _BIG_ENDIAN1
59# define LETOH_16(x)(__extension__ ({ unsigned short int __bsx = (x); ((((__bsx) >>
8) & 0xffu) | (((__bsx) & 0xffu) << 8)); }))
BSWAP_16(x)
60# define HTOLE_16(x)(__extension__ ({ unsigned short int __bsx = (x); ((((__bsx) >>
8) & 0xffu) | (((__bsx) & 0xffu) << 8)); }))
BSWAP_16(x)
61# define LETOH_32(x)(__extension__ ({ register unsigned int __bsx = (x); ((((__bsx
) & 0xff000000u) >> 24) | (((__bsx) & 0x00ff0000u
) >> 8) | (((__bsx) & 0x0000ff00u) << 8) | ((
(__bsx) & 0x000000ffu) << 24)); }))
BSWAP_32(x)
62# define HTOLE_32(x)(__extension__ ({ register unsigned int __bsx = (x); ((((__bsx
) & 0xff000000u) >> 24) | (((__bsx) & 0x00ff0000u
) >> 8) | (((__bsx) & 0x0000ff00u) << 8) | ((
(__bsx) & 0x000000ffu) << 24)); }))
BSWAP_32(x)
63#else
64# define LETOH_16(x)(__extension__ ({ unsigned short int __bsx = (x); ((((__bsx) >>
8) & 0xffu) | (((__bsx) & 0xffu) << 8)); }))
(x)
65# define HTOLE_16(x)(__extension__ ({ unsigned short int __bsx = (x); ((((__bsx) >>
8) & 0xffu) | (((__bsx) & 0xffu) << 8)); }))
(x)
66# define LETOH_32(x)(__extension__ ({ register unsigned int __bsx = (x); ((((__bsx
) & 0xff000000u) >> 24) | (((__bsx) & 0x00ff0000u
) >> 8) | (((__bsx) & 0x0000ff00u) << 8) | ((
(__bsx) & 0x000000ffu) << 24)); }))
(x)
67# define HTOLE_32(x)(__extension__ ({ register unsigned int __bsx = (x); ((((__bsx
) & 0xff000000u) >> 24) | (((__bsx) & 0x00ff0000u
) >> 8) | (((__bsx) & 0x0000ff00u) << 8) | ((
(__bsx) & 0x000000ffu) << 24)); }))
(x)
68#endif /* Solaris */
69
70#else
71
72#include <sys/endian.h>
73
74#define HTOLE_16(x)(__extension__ ({ unsigned short int __bsx = (x); ((((__bsx) >>
8) & 0xffu) | (((__bsx) & 0xffu) << 8)); }))
htole16(x)(__extension__ ({ unsigned short int __bsx = (x); ((((__bsx) >>
8) & 0xffu) | (((__bsx) & 0xffu) << 8)); }))
75#define HTOLE_32(x)(__extension__ ({ register unsigned int __bsx = (x); ((((__bsx
) & 0xff000000u) >> 24) | (((__bsx) & 0x00ff0000u
) >> 8) | (((__bsx) & 0x0000ff00u) << 8) | ((
(__bsx) & 0x000000ffu) << 24)); }))
htole32(x)(__extension__ ({ register unsigned int __bsx = (x); ((((__bsx
) & 0xff000000u) >> 24) | (((__bsx) & 0x00ff0000u
) >> 8) | (((__bsx) & 0x0000ff00u) << 8) | ((
(__bsx) & 0x000000ffu) << 24)); }))
76
77#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__)
78#define LETOH_16(x)(__extension__ ({ unsigned short int __bsx = (x); ((((__bsx) >>
8) & 0xffu) | (((__bsx) & 0xffu) << 8)); }))
le16toh(x)(__extension__ ({ unsigned short int __bsx = (x); ((((__bsx) >>
8) & 0xffu) | (((__bsx) & 0xffu) << 8)); }))
79#define LETOH_32(x)(__extension__ ({ register unsigned int __bsx = (x); ((((__bsx
) & 0xff000000u) >> 24) | (((__bsx) & 0x00ff0000u
) >> 8) | (((__bsx) & 0x0000ff00u) << 8) | ((
(__bsx) & 0x000000ffu) << 24)); }))
le32toh(x)(__extension__ ({ register unsigned int __bsx = (x); ((((__bsx
) & 0xff000000u) >> 24) | (((__bsx) & 0x00ff0000u
) >> 8) | (((__bsx) & 0x0000ff00u) << 8) | ((
(__bsx) & 0x000000ffu) << 24)); }))
80#else
81#define LETOH_16(x)(__extension__ ({ unsigned short int __bsx = (x); ((((__bsx) >>
8) & 0xffu) | (((__bsx) & 0xffu) << 8)); }))
letoh16(x)
82#define LETOH_32(x)(__extension__ ({ register unsigned int __bsx = (x); ((((__bsx
) & 0xff000000u) >> 24) | (((__bsx) & 0x00ff0000u
) >> 8) | (((__bsx) & 0x0000ff00u) << 8) | ((
(__bsx) & 0x000000ffu) << 24)); }))
letoh32(x)
83#endif
84
85#endif /* others */
86
87/**
88 * Read a device's expansion ROM.
89 *
90 * Reads the device's expansion ROM and stores the data in the memory pointed
91 * to by \c buffer. The buffer must be at least \c pci_device::rom_size
92 * bytes.
93 *
94 * \param dev Device whose expansion ROM is to be read.
95 * \param buffer Memory in which to store the ROM.
96 *
97 * \return
98 * Zero on success or an \c errno value on failure.
99 */
100int
101pci_device_read_rom( struct pci_device * dev, void * buffer )
102{
103 if ( (dev == NULL((void*)0)) || (buffer == NULL((void*)0)) ) {
104 return EFAULT14;
105 }
106
107
108 return (pci_sys->methods->read_rom)( dev, buffer );
109}
110
111/**
112 * Probe a PCI (VGA) device to determine if its the boot VGA device
113 *
114 * \param dev Device whose VGA status to query
115 * \return
116 * Zero if not the boot VGA, 1 if the boot VGA.
117 */
118int
119pci_device_is_boot_vga( struct pci_device * dev )
120{
121 if (!pci_sys->methods->boot_vga)
122 return 0;
123 return pci_sys->methods->boot_vga( dev );
124}
125
126/**
127 * Probe a PCI device to determine if a kernel driver is attached.
128 *
129 * \param dev Device to query
130 * \return
131 * Zero if no driver attached, 1 if attached kernel drviver
132 */
133int
134pci_device_has_kernel_driver( struct pci_device * dev )
135{
136 if (!pci_sys->methods->has_kernel_driver)
137 return 0;
138 return pci_sys->methods->has_kernel_driver( dev );
139}
140
141/**
142 * Probe a PCI device to learn information about the device.
143 *
144 * Probes a PCI device to learn various information about the device. Before
145 * calling this function, the only public fields in the \c pci_device
146 * structure that have valid values are \c pci_device::domain,
147 * \c pci_device::bus, \c pci_device::dev, and \c pci_device::func.
148 *
149 * \param dev Device to be probed.
150 *
151 * \return
152 * Zero on success or an \c errno value on failure.
153 */
154int
155pci_device_probe( struct pci_device * dev )
156{
157 if ( dev == NULL((void*)0) ) {
158 return EFAULT14;
159 }
160
161
162 return (pci_sys->methods->probe)( dev );
163}
164
165
166/**
167 * Map the specified BAR so that it can be accessed by the CPU.
168 *
169 * Maps the specified BAR for access by the processor. The pointer to the
170 * mapped region is stored in the \c pci_mem_region::memory pointer for the
171 * BAR.
172 *
173 * \param dev Device whose memory region is to be mapped.
174 * \param region Region, on the range [0, 5], that is to be mapped.
175 * \param write_enable Map for writing (non-zero).
176 *
177 * \return
178 * Zero on success or an \c errno value on failure.
179 *
180 * \sa pci_device_map_range, pci_device_unmap_range
181 * \deprecated
182 */
183int
184pci_device_map_region(struct pci_device * dev, unsigned region,
185 int write_enable)
186{
187 const unsigned map_flags =
188 (write_enable) ? PCI_DEV_MAP_FLAG_WRITABLE(1U<<0) : 0;
189
190 if ((region > 5) || (dev->regions[region].size == 0)) {
191 return ENOENT2;
192 }
193
194 if (dev->regions[region].memory != NULL((void*)0)) {
195 return 0;
196 }
197
198 return pci_device_map_range(dev, dev->regions[region].base_addr,
199 dev->regions[region].size, map_flags,
200 &dev->regions[region].memory);
201}
202
203
204/**
205 * Map the specified memory range so that it can be accessed by the CPU.
206 *
207 * Maps the specified memory range for access by the processor. The pointer
208 * to the mapped region is stored in \c addr. In addition, the
209 * \c pci_mem_region::memory pointer for the BAR will be updated.
210 *
211 * \param dev Device whose memory region is to be mapped.
212 * \param base Base address of the range to be mapped.
213 * \param size Size of the range to be mapped.
214 * \param write_enable Map for writing (non-zero).
215 * \param addr Location to store the mapped address.
216 *
217 * \return
218 * Zero on success or an \c errno value on failure.
219 *
220 * \sa pci_device_map_range
221 */
222int pci_device_map_memory_range(struct pci_device *dev,
223 pciaddr_t base, pciaddr_t size,
224 int write_enable, void **addr)
225{
226 return pci_device_map_range(dev, base, size,
227 (write_enable) ? PCI_DEV_MAP_FLAG_WRITABLE(1U<<0) : 0,
228 addr);
229}
230
231
232/**
233 * Map the specified memory range so that it can be accessed by the CPU.
234 *
235 * Maps the specified memory range for access by the processor. The pointer
236 * to the mapped region is stored in \c addr. In addition, the
237 * \c pci_mem_region::memory pointer for the BAR will be updated.
238 *
239 * \param dev Device whose memory region is to be mapped.
240 * \param base Base address of the range to be mapped.
241 * \param size Size of the range to be mapped.
242 * \param map_flags Flag bits controlling how the mapping is accessed.
243 * \param addr Location to store the mapped address.
244 *
245 * \return
246 * Zero on success or an \c errno value on failure.
247 *
248 * \sa pci_device_unmap_range
249 */
250int
251pci_device_map_range(struct pci_device *dev, pciaddr_t base,
252 pciaddr_t size, unsigned map_flags,
253 void **addr)
254{
255 struct pci_device_private *const devp =
256 (struct pci_device_private *) dev;
257 struct pci_device_mapping *mappings;
258 unsigned region;
259 unsigned i;
260 int err = 0;
261
262
263 *addr = NULL((void*)0);
264
265 if (dev == NULL((void*)0)) {
266 return EFAULT14;
267 }
268
269
270 for (region = 0; region < 6; region++) {
271 const struct pci_mem_region const* r = &dev->regions[region];
272
273 if (r->size != 0) {
274 if ((r->base_addr <= base) && ((r->base_addr + r->size) > base)) {
275 if ((base + size) > (r->base_addr + r->size)) {
276 return E2BIG7;
277 }
278
279 break;
280 }
281 }
282 }
283
284 if (region > 5) {
285 return ENOENT2;
286 }
287
288 /* Make sure that there isn't already a mapping with the same base and
289 * size.
290 */
291 for (i = 0; i < devp->num_mappings; i++) {
292 if ((devp->mappings[i].base == base)
293 && (devp->mappings[i].size == size)) {
294 return EINVAL22;
295 }
296 }
297
298
299 mappings = realloc(devp->mappings,
300 (sizeof(devp->mappings[0]) * (devp->num_mappings + 1)));
301 if (mappings == NULL((void*)0)) {
302 return ENOMEM12;
303 }
304
305 mappings[devp->num_mappings].base = base;
306 mappings[devp->num_mappings].size = size;
307 mappings[devp->num_mappings].region = region;
308 mappings[devp->num_mappings].flags = map_flags;
309 mappings[devp->num_mappings].memory = NULL((void*)0);
310
311 if (dev->regions[region].memory == NULL((void*)0)) {
312 err = (*pci_sys->methods->map_range)(dev,
313 &mappings[devp->num_mappings]);
314 }
315
316 if (err == 0) {
317 *addr = mappings[devp->num_mappings].memory;
318 devp->num_mappings++;
319 } else {
320 mappings = realloc(mappings,
321 (sizeof(mappings[0]) * devp->num_mappings));
322 }
323
324 devp->mappings = mappings;
325
326 return err;
327}
328
329
330/**
331 * Unmap the specified BAR so that it can no longer be accessed by the CPU.
332 *
333 * Unmaps the specified BAR that was previously mapped via
334 * \c pci_device_map_region.
335 *
336 * \param dev Device whose memory region is to be mapped.
337 * \param region Region, on the range [0, 5], that is to be mapped.
338 *
339 * \return
340 * Zero on success or an \c errno value on failure.
341 *
342 * \sa pci_device_map_range, pci_device_unmap_range
343 * \deprecated
344 */
345int
346pci_device_unmap_region( struct pci_device * dev, unsigned region )
347{
348 int err;
349
350 if (dev == NULL((void*)0)) {
351 return EFAULT14;
352 }
353
354 if ((region > 5) || (dev->regions[region].size == 0)) {
355 return ENOENT2;
356 }
357
358 err = pci_device_unmap_range(dev, dev->regions[region].memory,
359 dev->regions[region].size);
360 if (!err) {
361 dev->regions[region].memory = NULL((void*)0);
362 }
363
364 return err;
365}
366
367
368/**
369 * Unmap the specified memory range so that it can no longer be accessed by the CPU.
370 *
371 * Unmaps the specified memory range that was previously mapped via
372 * \c pci_device_map_memory_range.
373 *
374 * \param dev Device whose memory is to be unmapped.
375 * \param memory Pointer to the base of the mapped range.
376 * \param size Size, in bytes, of the range to be unmapped.
377 *
378 * \return
379 * Zero on success or an \c errno value on failure.
380 *
381 * \sa pci_device_map_range, pci_device_unmap_range
382 * \deprecated
383 */
384int
385pci_device_unmap_memory_range(struct pci_device *dev, void *memory,
386 pciaddr_t size)
387{
388 return pci_device_unmap_range(dev, memory, size);
389}
390
391
392/**
393 * Unmap the specified memory range so that it can no longer be accessed by the CPU.
394 *
395 * Unmaps the specified memory range that was previously mapped via
396 * \c pci_device_map_memory_range.
397 *
398 * \param dev Device whose memory is to be unmapped.
399 * \param memory Pointer to the base of the mapped range.
400 * \param size Size, in bytes, of the range to be unmapped.
401 *
402 * \return
403 * Zero on success or an \c errno value on failure.
404 *
405 * \sa pci_device_map_range
406 */
407int
408pci_device_unmap_range(struct pci_device *dev, void *memory,
409 pciaddr_t size)
410{
411 struct pci_device_private *const devp =
412 (struct pci_device_private *) dev;
413 unsigned i;
414 int err;
415
416
417 if (dev == NULL((void*)0)) {
1
Assuming 'dev' is not equal to null
2
Taking false branch
418 return EFAULT14;
419 }
420
421 for (i = 0; i < devp->num_mappings; i++) {
3
Loop condition is true. Entering loop body
422 if ((devp->mappings[i].memory == memory)
4
Taking true branch
423 && (devp->mappings[i].size == size)) {
424 break;
5
Execution continues on line 428
425 }
426 }
427
428 if (i == devp->num_mappings) {
6
Taking false branch
429 return ENOENT2;
430 }
431
432
433 err = (*pci_sys->methods->unmap_range)(dev, &devp->mappings[i]);
434 if (!err) {
7
Assuming 'err' is 0
8
Taking true branch
435 const unsigned entries_to_move = (devp->num_mappings - i) - 1;
436
437 if (entries_to_move > 0) {
9
Assuming 'entries_to_move' is <= 0
10
Taking false branch
438 (void) memmove(&devp->mappings[i],
439 &devp->mappings[i + 1],
440 entries_to_move * sizeof(devp->mappings[0]));
441 }
442
443 devp->num_mappings--;
444 devp->mappings = realloc(devp->mappings,
11
Call to 'realloc' has an allocation size of 0 bytes
445 (sizeof(devp->mappings[0]) * devp->num_mappings));
446 }
447
448 return err;
449}
450
451
452/**
453 * Read arbitrary bytes from device's PCI config space
454 *
455 * Reads data from the device's PCI configuration space. As with the system
456 * read command, less data may be returned, without an error, than was
457 * requested. This is particularly the case if a non-root user tries to read
458 * beyond the first 64-bytes of configuration space.
459 *
460 * \param dev Device whose PCI configuration data is to be read.
461 * \param data Location to store the data
462 * \param offset Initial byte offset to read
463 * \param size Total number of bytes to read
464 * \param bytes_read Location to store the actual number of bytes read. This
465 * pointer may be \c NULL.
466 *
467 * \returns
468 * Zero on success or an errno value on failure.
469 *
470 * \note
471 * Data read from PCI configuration space using this routine is \b not
472 * byte-swapped to the host's byte order. PCI configuration data is always
473 * stored in little-endian order, and that is what this routine returns.
474 */
475int
476pci_device_cfg_read( struct pci_device * dev, void * data,
477 pciaddr_t offset, pciaddr_t size,
478 pciaddr_t * bytes_read )
479{
480 pciaddr_t scratch;
481
482 if ( (dev == NULL((void*)0)) || (data == NULL((void*)0)) ) {
483 return EFAULT14;
484 }
485
486 return pci_sys->methods->read( dev, data, offset, size,
487 (bytes_read == NULL((void*)0))
488 ? & scratch : bytes_read );
489}
490
491
492int
493pci_device_cfg_read_u8( struct pci_device * dev, uint8_t * data,
494 pciaddr_t offset )
495{
496 pciaddr_t bytes;
497 int err = pci_device_cfg_read( dev, data, offset, 1, & bytes );
498
499 if ( (err == 0) && (bytes != 1) ) {
500 err = ENXIO6;
501 }
502
503 return err;
504}
505
506
507int
508pci_device_cfg_read_u16( struct pci_device * dev, uint16_t * data,
509 pciaddr_t offset )
510{
511 pciaddr_t bytes;
512 int err = pci_device_cfg_read( dev, data, offset, 2, & bytes );
513
514 if ( (err == 0) && (bytes != 2) ) {
515 err = ENXIO6;
516 }
517
518 *data = LETOH_16( *data )(__extension__ ({ unsigned short int __bsx = (*data); ((((__bsx
) >> 8) & 0xffu) | (((__bsx) & 0xffu) << 8
)); }))
;
519 return err;
520}
521
522
523int
524pci_device_cfg_read_u32( struct pci_device * dev, uint32_t * data,
525 pciaddr_t offset )
526{
527 pciaddr_t bytes;
528 int err = pci_device_cfg_read( dev, data, offset, 4, & bytes );
529
530 if ( (err == 0) && (bytes != 4) ) {
531 err = ENXIO6;
532 }
533
534 *data = LETOH_32( *data )(__extension__ ({ register unsigned int __bsx = (*data); ((((
__bsx) & 0xff000000u) >> 24) | (((__bsx) & 0x00ff0000u
) >> 8) | (((__bsx) & 0x0000ff00u) << 8) | ((
(__bsx) & 0x000000ffu) << 24)); }))
;
535 return err;
536}
537
538
539/**
540 * Write arbitrary bytes to device's PCI config space
541 *
542 * Writes data to the device's PCI configuration space. As with the system
543 * write command, less data may be written, without an error, than was
544 * requested.
545 *
546 * \param dev Device whose PCI configuration data is to be written.
547 * \param data Location of the source data
548 * \param offset Initial byte offset to write
549 * \param size Total number of bytes to write
550 * \param bytes_read Location to store the actual number of bytes written.
551 * This pointer may be \c NULL.
552 *
553 * \returns
554 * Zero on success or an errno value on failure.
555 *
556 * \note
557 * Data written to PCI configuration space using this routine is \b not
558 * byte-swapped from the host's byte order. PCI configuration data is always
559 * stored in little-endian order, so data written with this routine should be
560 * put in that order in advance.
561 */
562int
563pci_device_cfg_write( struct pci_device * dev, const void * data,
564 pciaddr_t offset, pciaddr_t size,
565 pciaddr_t * bytes_written )
566{
567 pciaddr_t scratch;
568
569 if ( (dev == NULL((void*)0)) || (data == NULL((void*)0)) ) {
570 return EFAULT14;
571 }
572
573 return pci_sys->methods->write( dev, data, offset, size,
574 (bytes_written == NULL((void*)0))
575 ? & scratch : bytes_written );
576}
577
578
579int
580pci_device_cfg_write_u8(struct pci_device *dev, uint8_t data,
581 pciaddr_t offset)
582{
583 pciaddr_t bytes;
584 int err = pci_device_cfg_write(dev, & data, offset, 1, & bytes);
585
586 if ( (err == 0) && (bytes != 1) ) {
587 err = ENOSPC28;
588 }
589
590
591 return err;
592}
593
594
595int
596pci_device_cfg_write_u16(struct pci_device *dev, uint16_t data,
597 pciaddr_t offset)
598{
599 pciaddr_t bytes;
600 const uint16_t temp = HTOLE_16(data)(__extension__ ({ unsigned short int __bsx = (data); ((((__bsx
) >> 8) & 0xffu) | (((__bsx) & 0xffu) << 8
)); }))
;
601 int err = pci_device_cfg_write( dev, & temp, offset, 2, & bytes );
602
603 if ( (err == 0) && (bytes != 2) ) {
604 err = ENOSPC28;
605 }
606
607
608 return err;
609}
610
611
612int
613pci_device_cfg_write_u32(struct pci_device *dev, uint32_t data,
614 pciaddr_t offset)
615{
616 pciaddr_t bytes;
617 const uint32_t temp = HTOLE_32(data)(__extension__ ({ register unsigned int __bsx = (data); ((((__bsx
) & 0xff000000u) >> 24) | (((__bsx) & 0x00ff0000u
) >> 8) | (((__bsx) & 0x0000ff00u) << 8) | ((
(__bsx) & 0x000000ffu) << 24)); }))
;
618 int err = pci_device_cfg_write( dev, & temp, offset, 4, & bytes );
619
620 if ( (err == 0) && (bytes != 4) ) {
621 err = ENOSPC28;
622 }
623
624
625 return err;
626}
627
628
629int
630pci_device_cfg_write_bits( struct pci_device * dev, uint32_t mask,
631 uint32_t data, pciaddr_t offset )
632{
633 uint32_t temp;
634 int err;
635
636 err = pci_device_cfg_read_u32( dev, & temp, offset );
637 if ( ! err ) {
638 temp &= ~mask;
639 temp |= data;
640
641 err = pci_device_cfg_write_u32(dev, temp, offset);
642 }
643
644 return err;
645}
646
647void
648pci_device_enable(struct pci_device *dev)
649{
650 if (dev == NULL((void*)0)) {
651 return;
652 }
653
654 if (pci_sys->methods->enable)
655 pci_sys->methods->enable(dev);
656}
657
658/**
659 * Map the legacy memory space for the PCI domain containing \c dev.
660 *
661 * \param dev Device whose memory region is to be mapped.
662 * \param base Base address of the range to be mapped.
663 * \param size Size of the range to be mapped.
664 * \param map_flags Flag bits controlling how the mapping is accessed.
665 * \param addr Location to store the mapped address.
666 *
667 * \returns
668 * Zero on success or an \c errno value on failure.
669 */
670int
671pci_device_map_legacy(struct pci_device *dev, pciaddr_t base, pciaddr_t size,
672 unsigned map_flags, void **addr)
673{
674 if (base > 0x100000 || base + size > 0x100000)
675 return EINVAL22;
676
677 if (!pci_sys->methods->map_legacy)
678 return ENOSYS38;
679
680 return pci_sys->methods->map_legacy(dev, base, size, map_flags, addr);
681}
682
683/**
684 * Unmap the legacy memory space for the PCI domain containing \c dev.
685 *
686 * \param dev Device whose memory region is to be unmapped.
687 * \param addr Location of the mapped address.
688 * \param size Size of the range to be unmapped.
689 *
690 * \returns
691 * Zero on success or an \c errno value on failure.
692 */
693int
694pci_device_unmap_legacy(struct pci_device *dev, void *addr, pciaddr_t size)
695{
696 if (!pci_sys->methods->unmap_legacy)
697 return ENOSYS38;
698
699 return pci_sys->methods->unmap_legacy(dev, addr, size);
700}