162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci#if defined(__i386__) || defined(__x86_64__)
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include <helpers/helpers.h>
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci/*
762306a36Sopenharmony_ci * pci_acc_init
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * PCI access helper function depending on libpci
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * **pacc : if a valid pci_dev is returned
1262306a36Sopenharmony_ci *         *pacc must be passed to pci_acc_cleanup to free it
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci * domain: domain
1562306a36Sopenharmony_ci * bus:    bus
1662306a36Sopenharmony_ci * slot:   slot
1762306a36Sopenharmony_ci * func:   func
1862306a36Sopenharmony_ci * vendor: vendor
1962306a36Sopenharmony_ci * device: device
2062306a36Sopenharmony_ci * Pass -1 for one of the six above to match any
2162306a36Sopenharmony_ci *
2262306a36Sopenharmony_ci * Returns :
2362306a36Sopenharmony_ci * struct pci_dev which can be used with pci_{read,write}_* functions
2462306a36Sopenharmony_ci *                to access the PCI config space of matching pci devices
2562306a36Sopenharmony_ci */
2662306a36Sopenharmony_cistruct pci_dev *pci_acc_init(struct pci_access **pacc, int domain, int bus,
2762306a36Sopenharmony_ci			     int slot, int func, int vendor, int dev)
2862306a36Sopenharmony_ci{
2962306a36Sopenharmony_ci	struct pci_filter filter_nb_link;
3062306a36Sopenharmony_ci	struct pci_dev *device;
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	*pacc = pci_alloc();
3362306a36Sopenharmony_ci	if (*pacc == NULL)
3462306a36Sopenharmony_ci		return NULL;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	pci_filter_init(*pacc, &filter_nb_link);
3762306a36Sopenharmony_ci	filter_nb_link.domain	= domain;
3862306a36Sopenharmony_ci	filter_nb_link.bus	= bus;
3962306a36Sopenharmony_ci	filter_nb_link.slot	= slot;
4062306a36Sopenharmony_ci	filter_nb_link.func	= func;
4162306a36Sopenharmony_ci	filter_nb_link.vendor	= vendor;
4262306a36Sopenharmony_ci	filter_nb_link.device	= dev;
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	pci_init(*pacc);
4562306a36Sopenharmony_ci	pci_scan_bus(*pacc);
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	for (device = (*pacc)->devices; device; device = device->next) {
4862306a36Sopenharmony_ci		if (pci_filter_match(&filter_nb_link, device))
4962306a36Sopenharmony_ci			return device;
5062306a36Sopenharmony_ci	}
5162306a36Sopenharmony_ci	pci_cleanup(*pacc);
5262306a36Sopenharmony_ci	return NULL;
5362306a36Sopenharmony_ci}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci/* Typically one wants to get a specific slot(device)/func of the root domain
5662306a36Sopenharmony_ci   and bus */
5762306a36Sopenharmony_cistruct pci_dev *pci_slot_func_init(struct pci_access **pacc, int slot,
5862306a36Sopenharmony_ci				       int func)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	return pci_acc_init(pacc, 0, 0, slot, func, -1, -1);
6162306a36Sopenharmony_ci}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci#endif /* defined(__i386__) || defined(__x86_64__) */
64