blob: 9c64255b5c7ed079576d9bd71e294f0f42fb830a [file] [log] [blame] [edit]
// Copyright 2016 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_KERNEL_OBJECT_INCLUDE_OBJECT_PCI_DEVICE_DISPATCHER_H_
#define ZIRCON_KERNEL_OBJECT_INCLUDE_OBJECT_PCI_DEVICE_DISPATCHER_H_
#if WITH_KERNEL_PCIE
#include <sys/types.h>
#include <zircon/rights.h>
#include <zircon/syscalls/pci.h>
#include <zircon/types.h>
#include <dev/pci_common.h>
#include <dev/pcie_device.h>
#include <fbl/intrusive_single_list.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>
#include <kernel/lockdep.h>
#include <kernel/mutex.h>
#include <kernel/spinlock.h>
#include <object/dispatcher.h>
#include <object/handle.h>
#include <object/interrupt_dispatcher.h>
#include <vm/vm_aspace.h>
class PciInterruptDispatcher;
class PciDeviceDispatcher final
: public SoloDispatcher<PciDeviceDispatcher, ZX_DEFAULT_PCI_DEVICE_RIGHTS> {
public:
static zx_status_t Create(uint32_t index, zx_pcie_device_info_t* out_info,
KernelHandle<PciDeviceDispatcher>* out_handle, zx_rights_t* out_rights);
~PciDeviceDispatcher() final;
zx_obj_type_t get_type() const final { return ZX_OBJ_TYPE_PCI_DEVICE; }
const fbl::RefPtr<PcieDevice>& device() { return device_; }
void ReleaseDevice();
// TODO(cja): revisit Enable____ methods to be automatic when vmos are handed
// out so there is less of a dispatcher surface to worry about.
zx_status_t EnableBusMaster(bool enable);
zx_status_t EnableMmio(bool enable);
zx_status_t EnablePio(bool enable);
const pcie_bar_info_t* GetBar(uint32_t bar_num);
zx_status_t GetConfig(pci_config_info_t* out);
zx_status_t ResetDevice();
zx_status_t MapInterrupt(int32_t which_irq, KernelHandle<InterruptDispatcher>* interrupt_handle,
zx_rights_t* rights);
zx_status_t QueryIrqModeCaps(zx_pci_irq_mode_t mode, uint32_t* out_max_irqs);
zx_status_t SetIrqMode(zx_pci_irq_mode_t mode, uint32_t requested_irq_count);
bool irqs_maskable() const TA_REQ(lock_) { return irqs_maskable_; }
private:
PciDeviceDispatcher(fbl::RefPtr<PcieDevice> device, zx_pcie_device_info_t* out_info);
PciDeviceDispatcher(const PciDeviceDispatcher&) = delete;
PciDeviceDispatcher& operator=(const PciDeviceDispatcher&) = delete;
// Lock protecting upward facing APIs. Generally speaking, this lock is
// held for the duration of most of our dispatcher API implementations. It
// is unsafe to ever attempt to acquire this lock during a callback from the
// PCI bus driver level.
DECLARE_MUTEX(PciDeviceDispatcher) lock_;
fbl::RefPtr<PcieDevice> device_ TA_GUARDED(lock_);
uint irqs_avail_cnt_ TA_GUARDED(lock_) = 0;
bool irqs_maskable_ TA_GUARDED(lock_) = false;
};
#endif // if WITH_KERNEL_PCIE
#endif // ZIRCON_KERNEL_OBJECT_INCLUDE_OBJECT_PCI_DEVICE_DISPATCHER_H_