text: /*
   * Copyright (c) 2019 Intel Corporation
   *
   * SPDX-License-Identifier: Apache-2.0
   */
  
  #include <kernel.h>
  #include <stdbool.h>
  #include <drivers/pcie/pcie.h>
  
  #if CONFIG_PCIE_MSI
  #include <drivers/pcie/msi.h>
  #endif
  
  /* functions documented in drivers/pcie/pcie.h */
  
  bool pcie_probe(pcie_bdf_t bdf, pcie_id_t id)
  {
  	u32_t data;
  
  	data = pcie_conf_read(bdf, PCIE_CONF_ID);
  
  	if (data == PCIE_ID_NONE) {
  		return false;
  	}
  
  	if (id == PCIE_ID_NONE) {
  		return true;
  	}
  
  	return (id == data);
  }
  
  void pcie_set_cmd(pcie_bdf_t bdf, u32_t bits, bool on)
  {
  	u32_t cmdstat;
  
  	cmdstat = pcie_conf_read(bdf, PCIE_CONF_CMDSTAT);
  
  	if (on) {
  		cmdstat |= bits;
  	} else {
  		cmdstat &= ~bits;
  	}
  
  	pcie_conf_write(bdf, PCIE_CONF_CMDSTAT, cmdstat);
  }
  
  static u32_t pcie_get_bar(pcie_bdf_t bdf, unsigned int index, bool io)
  {
  	int bar;
  	u32_t data;
  
  	for (bar = PCIE_CONF_BAR0; bar <= PCIE_CONF_BAR5; ++bar) {
  		data = pcie_conf_read(bdf, bar);
  		if (data == PCIE_CONF_BAR_NONE) {
  			continue;
  		}
  
  		if ((PCIE_CONF_BAR_IO(data) && io) ||
  		    (PCIE_CONF_BAR_MEM(data) && !io)) {
  			if (index == 0) {
  				return PCIE_CONF_BAR_ADDR(data);
  			}
  
  			--index;
  		}
  
  		if (PCIE_CONF_BAR_64(data)) {
  			++bar;
  		}
  	}
  
  	return PCIE_CONF_BAR_NONE;
  }
  
  u32_t pcie_get_mbar(pcie_bdf_t bdf, unsigned int index)
  {
  	return pcie_get_bar(bdf, index, false);
  }
  
  unsigned int pcie_wired_irq(pcie_bdf_t bdf)
  {
  	u32_t data = pcie_conf_read(bdf, PCIE_CONF_INTR);
  
  	return PCIE_CONF_INTR_IRQ(data);
  }
  
  u32_t pcie_get_iobar(pcie_bdf_t bdf, unsigned int index)
  {
  	return pcie_get_bar(bdf, index, true);
  }
  
  bool pcie_irq_enable(pcie_bdf_t bdf, unsigned int irq)
  {
  #if CONFIG_PCIE_MSI
  	if (pcie_set_msi(bdf, irq))
  		return true;
  #endif
  
  	u32_t data;
  
  	data = pcie_conf_read(bdf, PCIE_CONF_INTR);
  	if (PCIE_CONF_INTR_IRQ(data) == irq) {
  		irq_enable(irq);
  		return true;
  	}
  
  	return false;
  }
  