x86: Extend PCI driver module with support for metadata and configuration writes
This patch adds the 'meta' field to the generic driver structure to point to optional driver-defined metadata. It also modifies the associated initialization routine to populate it and updates the 16X50 UART driver to use the new initialization routine signature. This patch also adds a function to perform PCI configuration register writes, definitions for the PCI Command configuration register address and some of the bits in that register, and a function to set additional bits in that register. Finally, it adds macros to help with performing MMIO to and from PCI devices.
This commit is contained in:
parent
c6ef8454a1
commit
6dc27579bc
|
@ -63,6 +63,36 @@ pci_config_read(pci_config_addr_t addr)
|
|||
return inl(PCI_CONFIG_DATA_PORT);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Write to the PCI configuration data port.
|
||||
* \param addr Address of PCI configuration register.
|
||||
* \param data Value to write.
|
||||
*/
|
||||
void
|
||||
pci_config_write(pci_config_addr_t addr, uint32_t data)
|
||||
{
|
||||
set_addr(addr);
|
||||
|
||||
outl(PCI_CONFIG_DATA_PORT, data);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Enable PCI command bits of the specified PCI configuration
|
||||
* register.
|
||||
* \param addr Address of PCI configuration register.
|
||||
* \param flags Flags used to enable PCI command bits.
|
||||
*/
|
||||
void
|
||||
pci_command_enable(pci_config_addr_t addr, uint32_t flags)
|
||||
{
|
||||
uint32_t data;
|
||||
|
||||
addr.reg_off = 0x04; /* PCI COMMAND_REGISTER */
|
||||
|
||||
data = pci_config_read(addr);
|
||||
pci_config_write(addr, data | flags);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Set current PIRQ to interrupt queue agent. PCI based interrupts
|
||||
* PIRQ[A:H] are then available for consumption by either the 8259
|
||||
|
@ -201,12 +231,16 @@ pci_pirq_set_irq(PIRQ pirq, uint8_t irq, uint8_t route_to_legacy)
|
|||
* firmware.
|
||||
* \param c_this Structure that will be initialized to represent the driver.
|
||||
* \param pci_addr PCI base address of device.
|
||||
* \param meta Base address of optional driver-defined metadata.
|
||||
*/
|
||||
void
|
||||
pci_init_bar0(pci_driver_t *c_this, pci_config_addr_t pci_addr)
|
||||
pci_init_bar0(pci_driver_t *c_this,
|
||||
pci_config_addr_t pci_addr,
|
||||
uintptr_t meta)
|
||||
{
|
||||
pci_addr.reg_off = PCI_CONFIG_REG_BAR0;
|
||||
/* The BAR0 value is masked to clear non-address bits. */
|
||||
c_this->mmio = pci_config_read(pci_addr) & ~0xFFF;
|
||||
c_this->meta = meta;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#define CPU_X86_DRIVERS_LEGACY_PC_PCI_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "helpers.h"
|
||||
|
||||
/** PCI configuration register identifier for Base Address Register 0 (BAR0) */
|
||||
#define PCI_CONFIG_REG_BAR0 0x10
|
||||
|
@ -67,6 +68,11 @@ typedef enum {
|
|||
PIRQH,
|
||||
} PIRQ;
|
||||
|
||||
/** PCI command register bit to enable bus mastering */
|
||||
#define PCI_CMD_2_BUS_MST_EN BIT(2)
|
||||
/** PCI command register bit to enable memory space */
|
||||
#define PCI_CMD_1_MEM_SPACE_EN BIT(1)
|
||||
|
||||
/**
|
||||
* PCI configuration address
|
||||
*
|
||||
|
@ -88,16 +94,27 @@ typedef union pci_config_addr {
|
|||
} pci_config_addr_t;
|
||||
|
||||
uint32_t pci_config_read(pci_config_addr_t addr);
|
||||
void pci_config_write(pci_config_addr_t addr, uint32_t data);
|
||||
void pci_command_enable(pci_config_addr_t addr, uint32_t flags);
|
||||
|
||||
/**
|
||||
* PCI device driver instance with a single MMIO range.
|
||||
* PCI device driver instance with an optional single MMIO range and optional
|
||||
* metadata.
|
||||
*/
|
||||
typedef struct pci_driver {
|
||||
uintptr_t mmio; /**< MMIO range base address */
|
||||
uintptr_t meta; /**< Driver-defined metadata base address */
|
||||
} pci_driver_t;
|
||||
|
||||
void pci_init_bar0(pci_driver_t *c_this, pci_config_addr_t pci_addr);
|
||||
void pci_init_bar0(pci_driver_t *c_this,
|
||||
pci_config_addr_t pci_addr,
|
||||
uintptr_t meta);
|
||||
int pci_irq_agent_set_pirq(IRQAGENT agent, INTR_PIN pin, PIRQ pirq);
|
||||
void pci_pirq_set_irq(PIRQ pirq, uint8_t irq, uint8_t route_to_legacy);
|
||||
|
||||
#define PCI_MMIO_READL(c_this, dest, reg_addr) \
|
||||
dest = *((volatile uint32_t *)((c_this).mmio + (reg_addr)))
|
||||
#define PCI_MMIO_WRITEL(c_this, reg_addr, src) \
|
||||
*((volatile uint32_t *)((c_this).mmio + (reg_addr))) = (src)
|
||||
|
||||
#endif /* CPU_X86_DRIVERS_LEGACY_PC_PCI_H_ */
|
||||
|
|
|
@ -79,7 +79,7 @@ uart_16x50_init(uart_16x50_driver_t *c_this,
|
|||
/* This assumes that the UART had an MMIO range assigned to it by the
|
||||
* firmware during boot.
|
||||
*/
|
||||
pci_init_bar0(c_this, pci_addr);
|
||||
pci_init_bar0(c_this, pci_addr, 0);
|
||||
|
||||
uart_16x50_regs_t *regs = (uart_16x50_regs_t *)c_this->mmio;
|
||||
|
||||
|
|
Loading…
Reference in a new issue