blob: 7c5cf2d61515c39c744a390ff50de47e72bc4959 [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include <zircon/types.h>
#include <ddk/device.h>
#include <ddk/driver.h>
#include <ddk/protocol/pci.h>
#include <zx/handle.h>
#include <fbl/mutex.h>
#include <threads.h>
#include <virtio/virtio.h>
namespace virtio {
class Device {
public:
Device(zx_device_t* bus_device);
virtual ~Device();
zx_device_t* bus_device() { return bus_device_; }
zx_device_t* device() { return device_; }
virtual zx_status_t Bind(pci_protocol_t*, zx_handle_t pci_config_handle, const pci_config_t*);
virtual zx_status_t Init() = 0;
virtual void Unbind();
virtual void Release();
void StartIrqThread();
// interrupt cases that devices may override
virtual void IrqRingUpdate() {}
virtual void IrqConfigChange() {}
// used by Ring class to manipulate config registers
void SetRing(uint16_t index, uint16_t count, zx_paddr_t pa_desc, zx_paddr_t pa_avail, zx_paddr_t pa_used);
uint16_t GetRingSize(uint16_t index);
void RingKick(uint16_t ring_index);
protected:
// read bytes out of BAR 0's config space
template <typename T> T ReadConfigBar(uint16_t offset);
template <typename T> void WriteConfigBar(uint16_t offset, T val);
zx_status_t CopyDeviceConfig(void* _buf, size_t len);
void Reset();
void StatusAcknowledgeDriver();
void StatusDriverOK();
static int IrqThreadEntry(void* arg);
void IrqWorker();
zx_status_t MapBar(uint8_t bar);
// members
zx_device_t* bus_device_ = nullptr;
fbl::Mutex lock_;
// handles to pci bits
pci_protocol_t pci_ = { nullptr, nullptr };
zx::handle pci_config_handle_ = {};
const pci_config_t* pci_config_ = nullptr;
zx::handle irq_handle_ = {};
// bar0 memory map or PIO
uint32_t bar0_pio_base_ = 0;
uint32_t bar0_size_ = 0; // for now, must be set in subclass before Bind()
// based on the capability descriptions multiple bars may need to be mapped
struct bar {
volatile void* mmio_base;
zx::handle mmio_handle;
} bar_[6] = {};
struct {
volatile virtio_pci_common_cfg* common_config;
volatile uint32_t* isr_status;
volatile uint16_t* notify_base;
uint32_t notify_mul;
volatile void* device_config;
} mmio_regs_ = {};
// irq thread object
thrd_t irq_thread_ = {};
// DDK device
zx_device_t* device_ = nullptr;
zx_protocol_device_t device_ops_ = {};
};
} // namespace virtio