OSDN Git Service

Fix build on NetBSD-4.
[android-x86/external-libpciaccess.git] / src / common_iterator.c
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  */
43 struct 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  */
68 struct pci_device_iterator *
69 pci_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  */
104 struct pci_device_iterator *
105 pci_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  */
138 void
139 pci_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  */
156 struct pci_device *
157 pci_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
216 struct pci_device *
217 pci_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 }