root/drivers/pci/pci-bridge-emul.h
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __PCI_BRIDGE_EMUL_H__
#define __PCI_BRIDGE_EMUL_H__

#include <linux/kernel.h>

/* PCI configuration space of a PCI-to-PCI bridge. */
struct pci_bridge_emul_conf {
        __le16 vendor;
        __le16 device;
        __le16 command;
        __le16 status;
        __le32 class_revision;
        u8 cache_line_size;
        u8 latency_timer;
        u8 header_type;
        u8 bist;
        __le32 bar[2];
        u8 primary_bus;
        u8 secondary_bus;
        u8 subordinate_bus;
        u8 secondary_latency_timer;
        u8 iobase;
        u8 iolimit;
        __le16 secondary_status;
        __le16 membase;
        __le16 memlimit;
        __le16 pref_mem_base;
        __le16 pref_mem_limit;
        __le32 prefbaseupper;
        __le32 preflimitupper;
        __le16 iobaseupper;
        __le16 iolimitupper;
        u8 capabilities_pointer;
        u8 reserve[3];
        __le32 romaddr;
        u8 intline;
        u8 intpin;
        __le16 bridgectrl;
};

/* PCI configuration space of the PCIe capabilities */
struct pci_bridge_emul_pcie_conf {
        u8 cap_id;
        u8 next;
        __le16 cap;
        __le32 devcap;
        __le16 devctl;
        __le16 devsta;
        __le32 lnkcap;
        __le16 lnkctl;
        __le16 lnksta;
        __le32 slotcap;
        __le16 slotctl;
        __le16 slotsta;
        __le16 rootctl;
        __le16 rootcap;
        __le32 rootsta;
        __le32 devcap2;
        __le16 devctl2;
        __le16 devsta2;
        __le32 lnkcap2;
        __le16 lnkctl2;
        __le16 lnksta2;
        __le32 slotcap2;
        __le16 slotctl2;
        __le16 slotsta2;
};

struct pci_bridge_emul;

typedef enum { PCI_BRIDGE_EMUL_HANDLED,
               PCI_BRIDGE_EMUL_NOT_HANDLED } pci_bridge_emul_read_status_t;

struct pci_bridge_emul_ops {
        /*
         * Called when reading from the regular PCI bridge
         * configuration space. Return PCI_BRIDGE_EMUL_HANDLED when the
         * operation has handled the read operation and filled in the
         * *value, or PCI_BRIDGE_EMUL_NOT_HANDLED when the read should
         * be emulated by the common code by reading from the
         * in-memory copy of the configuration space.
         */
        pci_bridge_emul_read_status_t (*read_base)(struct pci_bridge_emul *bridge,
                                                   int reg, u32 *value);

        /*
         * Same as ->read_base(), except it is for reading from the
         * PCIe capability configuration space.
         */
        pci_bridge_emul_read_status_t (*read_pcie)(struct pci_bridge_emul *bridge,
                                                   int reg, u32 *value);

        /*
         * Same as ->read_base(), except it is for reading from the
         * PCIe extended capability configuration space.
         */
        pci_bridge_emul_read_status_t (*read_ext)(struct pci_bridge_emul *bridge,
                                                  int reg, u32 *value);

        /*
         * Called when writing to the regular PCI bridge configuration
         * space. old is the current value, new is the new value being
         * written, and mask indicates which parts of the value are
         * being changed.
         */
        void (*write_base)(struct pci_bridge_emul *bridge, int reg,
                           u32 old, u32 new, u32 mask);

        /*
         * Same as ->write_base(), except it is for writing from the
         * PCIe capability configuration space.
         */
        void (*write_pcie)(struct pci_bridge_emul *bridge, int reg,
                           u32 old, u32 new, u32 mask);

        /*
         * Same as ->write_base(), except it is for writing from the
         * PCIe extended capability configuration space.
         */
        void (*write_ext)(struct pci_bridge_emul *bridge, int reg,
                          u32 old, u32 new, u32 mask);
};

struct pci_bridge_reg_behavior;

struct pci_bridge_emul {
        struct pci_bridge_emul_conf conf;
        struct pci_bridge_emul_pcie_conf pcie_conf;
        const struct pci_bridge_emul_ops *ops;
        struct pci_bridge_reg_behavior *pci_regs_behavior;
        struct pci_bridge_reg_behavior *pcie_cap_regs_behavior;
        void *data;
        u8 pcie_start;
        u8 ssid_start;
        bool has_pcie;
        u16 subsystem_vendor_id;
        u16 subsystem_id;
};

enum {
        /*
         * PCI bridge does not support forwarding of prefetchable memory
         * requests between primary and secondary buses.
         */
        PCI_BRIDGE_EMUL_NO_PREFMEM_FORWARD = BIT(0),

        /*
         * PCI bridge does not support forwarding of IO requests between
         * primary and secondary buses.
         */
        PCI_BRIDGE_EMUL_NO_IO_FORWARD = BIT(1),
};

int pci_bridge_emul_init(struct pci_bridge_emul *bridge,
                         unsigned int flags);
void pci_bridge_emul_cleanup(struct pci_bridge_emul *bridge);

int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where,
                              int size, u32 *value);
int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
                               int size, u32 value);

#endif /* __PCI_BRIDGE_EMUL_H__ */