common_iterator.c revision 4f5e7dd7
14f5e7dd7Smrg/* 24f5e7dd7Smrg * (C) Copyright IBM Corporation 2006 34f5e7dd7Smrg * All Rights Reserved. 44f5e7dd7Smrg * 54f5e7dd7Smrg * Permission is hereby granted, free of charge, to any person obtaining a 64f5e7dd7Smrg * copy of this software and associated documentation files (the "Software"), 74f5e7dd7Smrg * to deal in the Software without restriction, including without limitation 84f5e7dd7Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub 94f5e7dd7Smrg * license, and/or sell copies of the Software, and to permit persons to whom 104f5e7dd7Smrg * the Software is furnished to do so, subject to the following conditions: 114f5e7dd7Smrg * 124f5e7dd7Smrg * The above copyright notice and this permission notice (including the next 134f5e7dd7Smrg * paragraph) shall be included in all copies or substantial portions of the 144f5e7dd7Smrg * Software. 154f5e7dd7Smrg * 164f5e7dd7Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 174f5e7dd7Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 184f5e7dd7Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 194f5e7dd7Smrg * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 204f5e7dd7Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 214f5e7dd7Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 224f5e7dd7Smrg * DEALINGS IN THE SOFTWARE. 234f5e7dd7Smrg */ 244f5e7dd7Smrg 254f5e7dd7Smrg/** 264f5e7dd7Smrg * \file common_iterator.c 274f5e7dd7Smrg * Platform independent iterator support routines. 284f5e7dd7Smrg * 294f5e7dd7Smrg * \author Ian Romanick <idr@us.ibm.com> 304f5e7dd7Smrg */ 314f5e7dd7Smrg 324f5e7dd7Smrg#include <stdlib.h> 334f5e7dd7Smrg#include <string.h> 344f5e7dd7Smrg 354f5e7dd7Smrg#include "pciaccess.h" 364f5e7dd7Smrg#include "pciaccess_private.h" 374f5e7dd7Smrg 384f5e7dd7Smrg/** 394f5e7dd7Smrg * Track device iteration state 404f5e7dd7Smrg * 414f5e7dd7Smrg * \private 424f5e7dd7Smrg */ 434f5e7dd7Smrgstruct pci_device_iterator { 444f5e7dd7Smrg unsigned next_index; 454f5e7dd7Smrg 464f5e7dd7Smrg enum { 474f5e7dd7Smrg match_any, 484f5e7dd7Smrg match_slot, 494f5e7dd7Smrg match_id 504f5e7dd7Smrg } mode; 514f5e7dd7Smrg 524f5e7dd7Smrg union { 534f5e7dd7Smrg struct pci_slot_match slot; 544f5e7dd7Smrg struct pci_id_match id; 554f5e7dd7Smrg } match; 564f5e7dd7Smrg}; 574f5e7dd7Smrg 584f5e7dd7Smrg 594f5e7dd7Smrg/** 604f5e7dd7Smrg * Create an iterator based on a regular expression. 614f5e7dd7Smrg * 624f5e7dd7Smrg * \return 634f5e7dd7Smrg * A pointer to a fully initialized \c pci_device_iterator structure on 644f5e7dd7Smrg * success, or \c NULL on failure. 654f5e7dd7Smrg * 664f5e7dd7Smrg * \sa pci_id_match_iterator_create, pci_device_next, pci_iterator_destroy 674f5e7dd7Smrg */ 684f5e7dd7Smrgstruct pci_device_iterator * 694f5e7dd7Smrgpci_slot_match_iterator_create( const struct pci_slot_match * match ) 704f5e7dd7Smrg{ 714f5e7dd7Smrg struct pci_device_iterator * iter; 724f5e7dd7Smrg 734f5e7dd7Smrg if ( pci_sys == NULL ) { 744f5e7dd7Smrg return NULL; 754f5e7dd7Smrg } 764f5e7dd7Smrg 774f5e7dd7Smrg iter = malloc( sizeof( *iter ) ); 784f5e7dd7Smrg if ( iter != NULL ) { 794f5e7dd7Smrg iter->next_index = 0; 804f5e7dd7Smrg 814f5e7dd7Smrg if ( match != NULL ) { 824f5e7dd7Smrg iter->mode = match_slot; 834f5e7dd7Smrg 844f5e7dd7Smrg (void) memcpy( & iter->match.slot, match, sizeof( *match ) ); 854f5e7dd7Smrg } 864f5e7dd7Smrg else { 874f5e7dd7Smrg iter->mode = match_any; 884f5e7dd7Smrg } 894f5e7dd7Smrg } 904f5e7dd7Smrg 914f5e7dd7Smrg return iter; 924f5e7dd7Smrg} 934f5e7dd7Smrg 944f5e7dd7Smrg 954f5e7dd7Smrg/** 964f5e7dd7Smrg * Create an iterator based on a regular expression. 974f5e7dd7Smrg * 984f5e7dd7Smrg * \return 994f5e7dd7Smrg * A pointer to a fully initialized \c pci_device_iterator structure on 1004f5e7dd7Smrg * success, or \c NULL on failure. 1014f5e7dd7Smrg * 1024f5e7dd7Smrg * \sa pci_slot_match_iterator_create, pci_device_next, pci_iterator_destroy 1034f5e7dd7Smrg */ 1044f5e7dd7Smrgstruct pci_device_iterator * 1054f5e7dd7Smrgpci_id_match_iterator_create( const struct pci_id_match * match ) 1064f5e7dd7Smrg{ 1074f5e7dd7Smrg struct pci_device_iterator * iter; 1084f5e7dd7Smrg 1094f5e7dd7Smrg if ( pci_sys == NULL ) { 1104f5e7dd7Smrg return NULL; 1114f5e7dd7Smrg } 1124f5e7dd7Smrg 1134f5e7dd7Smrg iter = malloc( sizeof( *iter ) ); 1144f5e7dd7Smrg if ( iter != NULL ) { 1154f5e7dd7Smrg iter->next_index = 0; 1164f5e7dd7Smrg 1174f5e7dd7Smrg if ( match != NULL ) { 1184f5e7dd7Smrg iter->mode = match_id; 1194f5e7dd7Smrg 1204f5e7dd7Smrg (void) memcpy( & iter->match.id, match, sizeof( *match ) ); 1214f5e7dd7Smrg } 1224f5e7dd7Smrg else { 1234f5e7dd7Smrg iter->mode = match_any; 1244f5e7dd7Smrg } 1254f5e7dd7Smrg } 1264f5e7dd7Smrg 1274f5e7dd7Smrg return iter; 1284f5e7dd7Smrg} 1294f5e7dd7Smrg 1304f5e7dd7Smrg 1314f5e7dd7Smrg/** 1324f5e7dd7Smrg * Destroy an iterator previously created with \c pci_iterator_create. 1334f5e7dd7Smrg * 1344f5e7dd7Smrg * \param iter Iterator to be destroyed. 1354f5e7dd7Smrg * 1364f5e7dd7Smrg * \sa pci_device_next, pci_iterator_create 1374f5e7dd7Smrg */ 1384f5e7dd7Smrgvoid 1394f5e7dd7Smrgpci_iterator_destroy( struct pci_device_iterator * iter ) 1404f5e7dd7Smrg{ 1414f5e7dd7Smrg if ( iter != NULL ) { 1424f5e7dd7Smrg free( iter ); 1434f5e7dd7Smrg } 1444f5e7dd7Smrg} 1454f5e7dd7Smrg 1464f5e7dd7Smrg 1474f5e7dd7Smrg/** 1484f5e7dd7Smrg * Iterate to the next PCI device. 1494f5e7dd7Smrg * 1504f5e7dd7Smrg * \param iter Device iterator returned by \c pci_device_iterate. 1514f5e7dd7Smrg * 1524f5e7dd7Smrg * \return 1534f5e7dd7Smrg * A pointer to a \c pci_device, or \c NULL when all devices have been 1544f5e7dd7Smrg * iterated. 1554f5e7dd7Smrg */ 1564f5e7dd7Smrgstruct pci_device * 1574f5e7dd7Smrgpci_device_next( struct pci_device_iterator * iter ) 1584f5e7dd7Smrg{ 1594f5e7dd7Smrg struct pci_device_private * d = NULL; 1604f5e7dd7Smrg 1614f5e7dd7Smrg if (!iter) 1624f5e7dd7Smrg return NULL; 1634f5e7dd7Smrg 1644f5e7dd7Smrg switch( iter->mode ) { 1654f5e7dd7Smrg case match_any: 1664f5e7dd7Smrg if ( iter->next_index < pci_sys->num_devices ) { 1674f5e7dd7Smrg d = & pci_sys->devices[ iter->next_index ]; 1684f5e7dd7Smrg iter->next_index++; 1694f5e7dd7Smrg } 1704f5e7dd7Smrg 1714f5e7dd7Smrg break; 1724f5e7dd7Smrg 1734f5e7dd7Smrg case match_slot: { 1744f5e7dd7Smrg while ( iter->next_index < pci_sys->num_devices ) { 1754f5e7dd7Smrg struct pci_device_private * const temp = 1764f5e7dd7Smrg & pci_sys->devices[ iter->next_index ]; 1774f5e7dd7Smrg 1784f5e7dd7Smrg iter->next_index++; 1794f5e7dd7Smrg if ( PCI_ID_COMPARE( iter->match.slot.domain, temp->base.domain ) 1804f5e7dd7Smrg && PCI_ID_COMPARE( iter->match.slot.bus, temp->base.bus ) 1814f5e7dd7Smrg && PCI_ID_COMPARE( iter->match.slot.dev, temp->base.dev ) 1824f5e7dd7Smrg && PCI_ID_COMPARE( iter->match.slot.func, temp->base.func ) ) { 1834f5e7dd7Smrg d = temp; 1844f5e7dd7Smrg break; 1854f5e7dd7Smrg } 1864f5e7dd7Smrg } 1874f5e7dd7Smrg 1884f5e7dd7Smrg break; 1894f5e7dd7Smrg } 1904f5e7dd7Smrg 1914f5e7dd7Smrg case match_id: { 1924f5e7dd7Smrg while ( iter->next_index < pci_sys->num_devices ) { 1934f5e7dd7Smrg struct pci_device_private * const temp = 1944f5e7dd7Smrg & pci_sys->devices[ iter->next_index ]; 1954f5e7dd7Smrg 1964f5e7dd7Smrg iter->next_index++; 1974f5e7dd7Smrg if ( PCI_ID_COMPARE( iter->match.id.vendor_id, temp->base.vendor_id ) 1984f5e7dd7Smrg && PCI_ID_COMPARE( iter->match.id.device_id, temp->base.device_id ) 1994f5e7dd7Smrg && PCI_ID_COMPARE( iter->match.id.subvendor_id, temp->base.subvendor_id ) 2004f5e7dd7Smrg && PCI_ID_COMPARE( iter->match.id.subdevice_id, temp->base.subdevice_id ) 2014f5e7dd7Smrg && ((temp->base.device_class & iter->match.id.device_class_mask) 2024f5e7dd7Smrg == iter->match.id.device_class) ) { 2034f5e7dd7Smrg d = temp; 2044f5e7dd7Smrg break; 2054f5e7dd7Smrg } 2064f5e7dd7Smrg } 2074f5e7dd7Smrg 2084f5e7dd7Smrg break; 2094f5e7dd7Smrg } 2104f5e7dd7Smrg } 2114f5e7dd7Smrg 2124f5e7dd7Smrg return (struct pci_device *) d; 2134f5e7dd7Smrg} 2144f5e7dd7Smrg 2154f5e7dd7Smrg 2164f5e7dd7Smrgstruct pci_device * 2174f5e7dd7Smrgpci_device_find_by_slot( uint32_t domain, uint32_t bus, uint32_t dev, 2184f5e7dd7Smrg uint32_t func ) 2194f5e7dd7Smrg{ 2204f5e7dd7Smrg struct pci_device_iterator iter; 2214f5e7dd7Smrg 2224f5e7dd7Smrg 2234f5e7dd7Smrg iter.next_index = 0; 2244f5e7dd7Smrg iter.mode = match_slot; 2254f5e7dd7Smrg iter.match.slot.domain = domain; 2264f5e7dd7Smrg iter.match.slot.bus = bus; 2274f5e7dd7Smrg iter.match.slot.dev = dev; 2284f5e7dd7Smrg iter.match.slot.func = func; 2294f5e7dd7Smrg 2304f5e7dd7Smrg return pci_device_next( & iter ); 2314f5e7dd7Smrg} 232