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. 28cad31331Smrg * 294f5e7dd7Smrg * \author Ian Romanick <idr@us.ibm.com> 304f5e7dd7Smrg */ 3149310723Smrg#ifdef HAVE_CONFIG_H 3249310723Smrg#include "config.h" 3349310723Smrg#endif 344f5e7dd7Smrg 354f5e7dd7Smrg#include <stdlib.h> 364f5e7dd7Smrg#include <string.h> 374f5e7dd7Smrg 384f5e7dd7Smrg#include "pciaccess.h" 394f5e7dd7Smrg#include "pciaccess_private.h" 404f5e7dd7Smrg 414f5e7dd7Smrg/** 424f5e7dd7Smrg * Track device iteration state 43cad31331Smrg * 444f5e7dd7Smrg * \private 454f5e7dd7Smrg */ 464f5e7dd7Smrgstruct pci_device_iterator { 474f5e7dd7Smrg unsigned next_index; 484f5e7dd7Smrg 494f5e7dd7Smrg enum { 504f5e7dd7Smrg match_any, 514f5e7dd7Smrg match_slot, 524f5e7dd7Smrg match_id 534f5e7dd7Smrg } mode; 544f5e7dd7Smrg 554f5e7dd7Smrg union { 564f5e7dd7Smrg struct pci_slot_match slot; 574f5e7dd7Smrg struct pci_id_match id; 584f5e7dd7Smrg } match; 594f5e7dd7Smrg}; 604f5e7dd7Smrg 614f5e7dd7Smrg 624f5e7dd7Smrg/** 634f5e7dd7Smrg * Create an iterator based on a regular expression. 644f5e7dd7Smrg * 654f5e7dd7Smrg * \return 664f5e7dd7Smrg * A pointer to a fully initialized \c pci_device_iterator structure on 674f5e7dd7Smrg * success, or \c NULL on failure. 684f5e7dd7Smrg * 694f5e7dd7Smrg * \sa pci_id_match_iterator_create, pci_device_next, pci_iterator_destroy 704f5e7dd7Smrg */ 714f5e7dd7Smrgstruct pci_device_iterator * 724f5e7dd7Smrgpci_slot_match_iterator_create( const struct pci_slot_match * match ) 734f5e7dd7Smrg{ 744f5e7dd7Smrg struct pci_device_iterator * iter; 75cad31331Smrg 764f5e7dd7Smrg if ( pci_sys == NULL ) { 774f5e7dd7Smrg return NULL; 784f5e7dd7Smrg } 794f5e7dd7Smrg 804f5e7dd7Smrg iter = malloc( sizeof( *iter ) ); 814f5e7dd7Smrg if ( iter != NULL ) { 824f5e7dd7Smrg iter->next_index = 0; 834f5e7dd7Smrg 844f5e7dd7Smrg if ( match != NULL ) { 854f5e7dd7Smrg iter->mode = match_slot; 864f5e7dd7Smrg 874f5e7dd7Smrg (void) memcpy( & iter->match.slot, match, sizeof( *match ) ); 884f5e7dd7Smrg } 894f5e7dd7Smrg else { 904f5e7dd7Smrg iter->mode = match_any; 914f5e7dd7Smrg } 924f5e7dd7Smrg } 934f5e7dd7Smrg 944f5e7dd7Smrg return iter; 954f5e7dd7Smrg} 964f5e7dd7Smrg 974f5e7dd7Smrg 984f5e7dd7Smrg/** 994f5e7dd7Smrg * Create an iterator based on a regular expression. 1004f5e7dd7Smrg * 1014f5e7dd7Smrg * \return 1024f5e7dd7Smrg * A pointer to a fully initialized \c pci_device_iterator structure on 1034f5e7dd7Smrg * success, or \c NULL on failure. 1044f5e7dd7Smrg * 1054f5e7dd7Smrg * \sa pci_slot_match_iterator_create, pci_device_next, pci_iterator_destroy 1064f5e7dd7Smrg */ 1074f5e7dd7Smrgstruct pci_device_iterator * 1084f5e7dd7Smrgpci_id_match_iterator_create( const struct pci_id_match * match ) 1094f5e7dd7Smrg{ 1104f5e7dd7Smrg struct pci_device_iterator * iter; 111cad31331Smrg 1124f5e7dd7Smrg if ( pci_sys == NULL ) { 1134f5e7dd7Smrg return NULL; 1144f5e7dd7Smrg } 1154f5e7dd7Smrg 1164f5e7dd7Smrg iter = malloc( sizeof( *iter ) ); 1174f5e7dd7Smrg if ( iter != NULL ) { 1184f5e7dd7Smrg iter->next_index = 0; 1194f5e7dd7Smrg 1204f5e7dd7Smrg if ( match != NULL ) { 1214f5e7dd7Smrg iter->mode = match_id; 1224f5e7dd7Smrg 1234f5e7dd7Smrg (void) memcpy( & iter->match.id, match, sizeof( *match ) ); 1244f5e7dd7Smrg } 1254f5e7dd7Smrg else { 1264f5e7dd7Smrg iter->mode = match_any; 1274f5e7dd7Smrg } 1284f5e7dd7Smrg } 1294f5e7dd7Smrg 1304f5e7dd7Smrg return iter; 1314f5e7dd7Smrg} 1324f5e7dd7Smrg 1334f5e7dd7Smrg 1344f5e7dd7Smrg/** 1354f5e7dd7Smrg * Destroy an iterator previously created with \c pci_iterator_create. 136cad31331Smrg * 1374f5e7dd7Smrg * \param iter Iterator to be destroyed. 138cad31331Smrg * 1394f5e7dd7Smrg * \sa pci_device_next, pci_iterator_create 1404f5e7dd7Smrg */ 1414f5e7dd7Smrgvoid 1424f5e7dd7Smrgpci_iterator_destroy( struct pci_device_iterator * iter ) 1434f5e7dd7Smrg{ 1444f5e7dd7Smrg if ( iter != NULL ) { 1454f5e7dd7Smrg free( iter ); 1464f5e7dd7Smrg } 1474f5e7dd7Smrg} 1484f5e7dd7Smrg 1494f5e7dd7Smrg 1504f5e7dd7Smrg/** 1514f5e7dd7Smrg * Iterate to the next PCI device. 152cad31331Smrg * 1534f5e7dd7Smrg * \param iter Device iterator returned by \c pci_device_iterate. 154cad31331Smrg * 1554f5e7dd7Smrg * \return 1564f5e7dd7Smrg * A pointer to a \c pci_device, or \c NULL when all devices have been 1574f5e7dd7Smrg * iterated. 1584f5e7dd7Smrg */ 1594f5e7dd7Smrgstruct pci_device * 1604f5e7dd7Smrgpci_device_next( struct pci_device_iterator * iter ) 1614f5e7dd7Smrg{ 1624f5e7dd7Smrg struct pci_device_private * d = NULL; 1634f5e7dd7Smrg 1644f5e7dd7Smrg if (!iter) 1654f5e7dd7Smrg return NULL; 1664f5e7dd7Smrg 1674f5e7dd7Smrg switch( iter->mode ) { 1684f5e7dd7Smrg case match_any: 1694f5e7dd7Smrg if ( iter->next_index < pci_sys->num_devices ) { 1704f5e7dd7Smrg d = & pci_sys->devices[ iter->next_index ]; 1714f5e7dd7Smrg iter->next_index++; 1724f5e7dd7Smrg } 1734f5e7dd7Smrg 1744f5e7dd7Smrg break; 1754f5e7dd7Smrg 1764f5e7dd7Smrg case match_slot: { 1774f5e7dd7Smrg while ( iter->next_index < pci_sys->num_devices ) { 178cad31331Smrg struct pci_device_private * const temp = 1794f5e7dd7Smrg & pci_sys->devices[ iter->next_index ]; 1804f5e7dd7Smrg 1814f5e7dd7Smrg iter->next_index++; 1824f5e7dd7Smrg if ( PCI_ID_COMPARE( iter->match.slot.domain, temp->base.domain ) 1834f5e7dd7Smrg && PCI_ID_COMPARE( iter->match.slot.bus, temp->base.bus ) 1844f5e7dd7Smrg && PCI_ID_COMPARE( iter->match.slot.dev, temp->base.dev ) 1854f5e7dd7Smrg && PCI_ID_COMPARE( iter->match.slot.func, temp->base.func ) ) { 1864f5e7dd7Smrg d = temp; 1874f5e7dd7Smrg break; 1884f5e7dd7Smrg } 1894f5e7dd7Smrg } 190cad31331Smrg 1914f5e7dd7Smrg break; 1924f5e7dd7Smrg } 1934f5e7dd7Smrg 1944f5e7dd7Smrg case match_id: { 1954f5e7dd7Smrg while ( iter->next_index < pci_sys->num_devices ) { 196cad31331Smrg struct pci_device_private * const temp = 1974f5e7dd7Smrg & pci_sys->devices[ iter->next_index ]; 1984f5e7dd7Smrg 1994f5e7dd7Smrg iter->next_index++; 2004f5e7dd7Smrg if ( PCI_ID_COMPARE( iter->match.id.vendor_id, temp->base.vendor_id ) 2014f5e7dd7Smrg && PCI_ID_COMPARE( iter->match.id.device_id, temp->base.device_id ) 2024f5e7dd7Smrg && PCI_ID_COMPARE( iter->match.id.subvendor_id, temp->base.subvendor_id ) 2034f5e7dd7Smrg && PCI_ID_COMPARE( iter->match.id.subdevice_id, temp->base.subdevice_id ) 204cad31331Smrg && ((temp->base.device_class & iter->match.id.device_class_mask) 2054f5e7dd7Smrg == iter->match.id.device_class) ) { 2064f5e7dd7Smrg d = temp; 2074f5e7dd7Smrg break; 2084f5e7dd7Smrg } 2094f5e7dd7Smrg } 210cad31331Smrg 2114f5e7dd7Smrg break; 2124f5e7dd7Smrg } 2134f5e7dd7Smrg } 2144f5e7dd7Smrg 2154f5e7dd7Smrg return (struct pci_device *) d; 2164f5e7dd7Smrg} 2174f5e7dd7Smrg 2184f5e7dd7Smrg 2194f5e7dd7Smrgstruct pci_device * 2204f5e7dd7Smrgpci_device_find_by_slot( uint32_t domain, uint32_t bus, uint32_t dev, 2214f5e7dd7Smrg uint32_t func ) 2224f5e7dd7Smrg{ 2234f5e7dd7Smrg struct pci_device_iterator iter; 224cad31331Smrg 225cad31331Smrg 2264f5e7dd7Smrg iter.next_index = 0; 2274f5e7dd7Smrg iter.mode = match_slot; 2284f5e7dd7Smrg iter.match.slot.domain = domain; 2294f5e7dd7Smrg iter.match.slot.bus = bus; 2304f5e7dd7Smrg iter.match.slot.dev = dev; 2314f5e7dd7Smrg iter.match.slot.func = func; 2324f5e7dd7Smrg 2334f5e7dd7Smrg return pci_device_next( & iter ); 2344f5e7dd7Smrg} 235