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