common_iterator.c revision cad31331
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_iterator.c 27 * Platform independent iterator support routines. 28 * 29 * \author Ian Romanick <idr@us.ibm.com> 30 */ 31 32#include <stdlib.h> 33#include <string.h> 34 35#include "pciaccess.h" 36#include "pciaccess_private.h" 37 38/** 39 * Track device iteration state 40 * 41 * \private 42 */ 43struct pci_device_iterator { 44 unsigned next_index; 45 46 enum { 47 match_any, 48 match_slot, 49 match_id 50 } mode; 51 52 union { 53 struct pci_slot_match slot; 54 struct pci_id_match id; 55 } match; 56}; 57 58 59/** 60 * Create an iterator based on a regular expression. 61 * 62 * \return 63 * A pointer to a fully initialized \c pci_device_iterator structure on 64 * success, or \c NULL on failure. 65 * 66 * \sa pci_id_match_iterator_create, pci_device_next, pci_iterator_destroy 67 */ 68struct pci_device_iterator * 69pci_slot_match_iterator_create( const struct pci_slot_match * match ) 70{ 71 struct pci_device_iterator * iter; 72 73 if ( pci_sys == NULL ) { 74 return NULL; 75 } 76 77 iter = malloc( sizeof( *iter ) ); 78 if ( iter != NULL ) { 79 iter->next_index = 0; 80 81 if ( match != NULL ) { 82 iter->mode = match_slot; 83 84 (void) memcpy( & iter->match.slot, match, sizeof( *match ) ); 85 } 86 else { 87 iter->mode = match_any; 88 } 89 } 90 91 return iter; 92} 93 94 95/** 96 * Create an iterator based on a regular expression. 97 * 98 * \return 99 * A pointer to a fully initialized \c pci_device_iterator structure on 100 * success, or \c NULL on failure. 101 * 102 * \sa pci_slot_match_iterator_create, pci_device_next, pci_iterator_destroy 103 */ 104struct pci_device_iterator * 105pci_id_match_iterator_create( const struct pci_id_match * match ) 106{ 107 struct pci_device_iterator * iter; 108 109 if ( pci_sys == NULL ) { 110 return NULL; 111 } 112 113 iter = malloc( sizeof( *iter ) ); 114 if ( iter != NULL ) { 115 iter->next_index = 0; 116 117 if ( match != NULL ) { 118 iter->mode = match_id; 119 120 (void) memcpy( & iter->match.id, match, sizeof( *match ) ); 121 } 122 else { 123 iter->mode = match_any; 124 } 125 } 126 127 return iter; 128} 129 130 131/** 132 * Destroy an iterator previously created with \c pci_iterator_create. 133 * 134 * \param iter Iterator to be destroyed. 135 * 136 * \sa pci_device_next, pci_iterator_create 137 */ 138void 139pci_iterator_destroy( struct pci_device_iterator * iter ) 140{ 141 if ( iter != NULL ) { 142 free( iter ); 143 } 144} 145 146 147/** 148 * Iterate to the next PCI device. 149 * 150 * \param iter Device iterator returned by \c pci_device_iterate. 151 * 152 * \return 153 * A pointer to a \c pci_device, or \c NULL when all devices have been 154 * iterated. 155 */ 156struct pci_device * 157pci_device_next( struct pci_device_iterator * iter ) 158{ 159 struct pci_device_private * d = NULL; 160 161 if (!iter) 162 return NULL; 163 164 switch( iter->mode ) { 165 case match_any: 166 if ( iter->next_index < pci_sys->num_devices ) { 167 d = & pci_sys->devices[ iter->next_index ]; 168 iter->next_index++; 169 } 170 171 break; 172 173 case match_slot: { 174 while ( iter->next_index < pci_sys->num_devices ) { 175 struct pci_device_private * const temp = 176 & pci_sys->devices[ iter->next_index ]; 177 178 iter->next_index++; 179 if ( PCI_ID_COMPARE( iter->match.slot.domain, temp->base.domain ) 180 && PCI_ID_COMPARE( iter->match.slot.bus, temp->base.bus ) 181 && PCI_ID_COMPARE( iter->match.slot.dev, temp->base.dev ) 182 && PCI_ID_COMPARE( iter->match.slot.func, temp->base.func ) ) { 183 d = temp; 184 break; 185 } 186 } 187 188 break; 189 } 190 191 case match_id: { 192 while ( iter->next_index < pci_sys->num_devices ) { 193 struct pci_device_private * const temp = 194 & pci_sys->devices[ iter->next_index ]; 195 196 iter->next_index++; 197 if ( PCI_ID_COMPARE( iter->match.id.vendor_id, temp->base.vendor_id ) 198 && PCI_ID_COMPARE( iter->match.id.device_id, temp->base.device_id ) 199 && PCI_ID_COMPARE( iter->match.id.subvendor_id, temp->base.subvendor_id ) 200 && PCI_ID_COMPARE( iter->match.id.subdevice_id, temp->base.subdevice_id ) 201 && ((temp->base.device_class & iter->match.id.device_class_mask) 202 == iter->match.id.device_class) ) { 203 d = temp; 204 break; 205 } 206 } 207 208 break; 209 } 210 } 211 212 return (struct pci_device *) d; 213} 214 215 216struct pci_device * 217pci_device_find_by_slot( uint32_t domain, uint32_t bus, uint32_t dev, 218 uint32_t func ) 219{ 220 struct pci_device_iterator iter; 221 222 223 iter.next_index = 0; 224 iter.mode = match_slot; 225 iter.match.slot.domain = domain; 226 iter.match.slot.bus = bus; 227 iter.match.slot.dev = dev; 228 iter.match.slot.func = func; 229 230 return pci_device_next( & iter ); 231} 232