blob: 9550a0d889d008b14ea141abc18c67450c95ab3d [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#ifndef ZIRCON_SYSTEM_DEV_BUS_PCI_DEVICE_PROXY_H_
#define ZIRCON_SYSTEM_DEV_BUS_PCI_DEVICE_PROXY_H_
#include <ddktl/device.h>
#include <ddktl/protocol/pci.h>
#include <lib/zx/channel.h>
#include <stdio.h>
#include <sys/types.h>
namespace pci {
enum PciRpcOp : uint32_t {
PCI_OP_INVALID = 0,
PCI_OP_CONFIG_READ,
PCI_OP_CONFIG_WRITE,
PCI_OP_CONNECT_SYSMEM,
PCI_OP_ENABLE_BUS_MASTER,
PCI_OP_GET_AUXDATA,
PCI_OP_GET_BAR,
PCI_OP_GET_BTI,
PCI_OP_GET_DEVICE_INFO,
PCI_OP_GET_NEXT_CAPABILITY,
PCI_OP_MAP_INTERRUPT,
PCI_OP_QUERY_IRQ_MODE,
PCI_OP_RESET_DEVICE,
PCI_OP_SET_IRQ_MODE,
PCI_OP_MAX,
};
// TODO(ZX-3146): When the kernel driver is removed we should consolidate the pci banjo
// definitions and these rpc messages to avoid duplication.
struct PciMsgCfg {
uint16_t offset;
uint16_t width;
uint32_t value;
};
// In the event of an MMIO bar all the information here will be available
// via VMO operations on the handle passed back.
struct PciMsgBar {
uint32_t id;
bool is_mmio;
uint16_t io_addr;
uint16_t io_size;
};
// For use with QUERY_IRQ_MODE, SET_IRQ_MODE, and MAP_INTERRUPT
struct PciMsgIrq {
zx_pci_irq_mode_t mode;
union {
int32_t which_irq;
uint32_t max_irqs;
uint32_t requested_irqs;
};
};
constexpr uint16_t kPciCapabilityOffsetFirst = 4907u;
struct PciMsgCapaility {
uint16_t id;
uint16_t offset;
bool is_extended;
};
// Outside the range of both standard and extended capailities, this
// exists to give a value to allow GetNextCapaility and GetFirstCapability
// to be served by the same impl on the other end of RPC.
const uint16_t PciCapOffsetFirst = 4097u;
// TODO(ZX-3927): port this to non-zx_pcie structures
using PciMsgDeviceInfo = zx_pcie_device_info_t;
struct PciRpcMsg {
zx_txid_t txid; // handled by zx_channel_call
uint32_t op;
zx_status_t ret;
// Subtract the size of the preceeding 6 uint32_ts to keep
// the structure inside a single page.
union {
bool enable;
PciMsgCfg cfg;
PciMsgIrq irq;
PciMsgBar bar;
PciMsgDeviceInfo info;
PciMsgCapaility cap;
uint8_t data[ZX_PAGE_SIZE - 24u];
uint32_t bti_index;
zx_handle_t handle;
};
};
static_assert(sizeof(PciRpcMsg) <= ZX_PAGE_SIZE);
class DeviceProxy;
using PciDeviceProxyType = ddk::Device<pci::DeviceProxy, ddk::GetProtocolable>;
class DeviceProxy : public PciDeviceProxyType,
public ddk::PciProtocol<pci::DeviceProxy> {
public:
DeviceProxy(zx_device_t* parent, zx_handle_t rpcch)
: PciDeviceProxyType(parent), rpcch_(rpcch) {}
static zx_status_t Create(zx_device_t* parent, zx_handle_t rpcch, const char* name);
// A helper method to reduce the complexity of each individual PciProtocol method.
zx_status_t RpcRequest(PciRpcOp op, zx_handle_t* handle, PciRpcMsg* req, PciRpcMsg* resp);
zx_status_t DdkGetProtocol(uint32_t proto_id, void* out);
void DdkRelease() { delete this; }
// ddk::PciProtocol implementations.
zx_status_t PciGetBar(uint32_t bar_id, zx_pci_bar_t* out_res);
zx_status_t PciEnableBusMaster(bool enable);
zx_status_t PciResetDevice();
zx_status_t PciMapInterrupt(zx_status_t which_irq, zx::interrupt* out_handle);
zx_status_t PciQueryIrqMode(zx_pci_irq_mode_t mode, uint32_t* out_max_irqs);
zx_status_t PciSetIrqMode(zx_pci_irq_mode_t mode, uint32_t requested_irq_count);
zx_status_t PciGetDeviceInfo(zx_pcie_device_info_t* out_into);
zx_status_t PciConfigRead8(uint16_t offset, uint8_t* out_value);
zx_status_t PciConfigRead16(uint16_t offset, uint16_t* out_value);
zx_status_t PciConfigRead32(uint16_t offset, uint32_t* out_value);
zx_status_t PciConfigWrite8(uint16_t offset, uint8_t value);
zx_status_t PciConfigWrite16(uint16_t offset, uint16_t value);
zx_status_t PciConfigWrite32(uint16_t offset, uint32_t value);
zx_status_t PciGetFirstCapability(uint8_t cap_id, uint8_t* out_offset);
zx_status_t PciGetNextCapability(uint8_t cap_id, uint8_t offset, uint8_t* out_offset);
zx_status_t PciGetAuxdata(const char* args,
void* out_data_buffer,
size_t data_size,
size_t* out_data_actual);
zx_status_t PciGetBti(uint32_t index, zx::bti* out_bti);
private:
// Helpers to marshal config-based RPC.
template <typename T>
zx_status_t PciConfigRead(uint16_t offset, T* out_value);
template <typename T>
zx_status_t PciConfigWrite(uint16_t offset, T value);
zx::channel rpcch_;
};
} // namespace pci
#endif // ZIRCON_SYSTEM_DEV_BUS_PCI_DEVICE_PROXY_H_