1// Copyright 2017 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#pragma once 6 7#include "backend.h" 8#include <zircon/thread_annotations.h> 9 10namespace virtio { 11 12class PciBackend : public Backend { 13public: 14 PciBackend(pci_protocol_t pci, zx_pcie_device_info_t info); 15 zx_status_t Bind() override; 16 virtual zx_status_t Init() = 0; 17 const char* tag() { return tag_; } 18 19 zx_status_t InterruptValid() override; 20 zx_status_t WaitForInterrupt() override; 21 22protected: 23 pci_protocol_t pci_ = {nullptr, nullptr}; 24 zx_pcie_device_info_t info_; 25 fbl::Mutex lock_; 26 char tag_[16]; // pci[XX:XX.X] + \0, aligned to 8 27 28 DISALLOW_COPY_ASSIGN_AND_MOVE(PciBackend); 29}; 30 31class PciLegacyBackend : public PciBackend { 32public: 33 PciLegacyBackend(pci_protocol_t pci, zx_pcie_device_info_t info) 34 : PciBackend(pci, info) {} 35 virtual ~PciLegacyBackend(); 36 zx_status_t Init() override; 37 38 void DriverStatusOk() override; 39 void DriverStatusAck() override; 40 void DeviceReset() override; 41 uint32_t IsrStatus() override; 42 bool ReadFeature(uint32_t feature) override; 43 void SetFeature(uint32_t feature) override; 44 zx_status_t ConfirmFeatures() override; 45 46 // These handle reading and writing a device's device config to allow derived 47 // virtio devices to work with fields only they know about. For most virtio 48 // devices they will have their device config copied over via 49 // CopyDeviceConfig when device config interrupts are asserted and will not 50 // need to call these directly. 51 void DeviceConfigRead(uint16_t offset, uint8_t* value) override; 52 void DeviceConfigRead(uint16_t offset, uint16_t* value) override; 53 void DeviceConfigRead(uint16_t offset, uint32_t* value) override; 54 void DeviceConfigRead(uint16_t offset, uint64_t* value) override; 55 void DeviceConfigWrite(uint16_t offset, uint8_t value) override; 56 void DeviceConfigWrite(uint16_t offset, uint16_t value) override; 57 void DeviceConfigWrite(uint16_t offset, uint32_t value) override; 58 void DeviceConfigWrite(uint16_t offset, uint64_t value) override; 59 60 // Handle the virtio queues for the device. Due to configuration layouts changing 61 // depending on backend this has to be handled by the backend itself. 62 uint16_t GetRingSize(uint16_t index) override; 63 void SetRing(uint16_t index, uint16_t count, zx_paddr_t pa_desc, zx_paddr_t pa_avail, 64 zx_paddr_t pa_used) override; 65 void RingKick(uint16_t ring_index) override; 66 67private: 68 void IoReadLocked(uint16_t port, uint8_t* val); 69 void IoReadLocked(uint16_t port, uint16_t* val); 70 void IoReadLocked(uint16_t port, uint32_t* val); 71 void IoWriteLocked(uint16_t port, uint8_t val); 72 void IoWriteLocked(uint16_t port, uint16_t val); 73 void IoWriteLocked(uint16_t port, uint32_t val); 74 void SetStatusBits(uint8_t bits); 75 uint16_t bar0_base_ TA_GUARDED(lock_); 76 uint16_t device_cfg_offset_ TA_GUARDED(lock_); 77 78 DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(PciLegacyBackend); 79}; 80 81class PciModernBackend : public PciBackend { 82public: 83 PciModernBackend(pci_protocol_t pci, zx_pcie_device_info_t info) 84 : PciBackend(pci, info) {} 85 // The dtor handles cleanup of allocated bars because we cannot tear down 86 // the mappings safely while the virtio device is being used by a driver. 87 virtual ~PciModernBackend(){}; 88 zx_status_t Init() override; 89 90 void DriverStatusOk() override; 91 void DriverStatusAck() override; 92 void DeviceReset() override; 93 uint32_t IsrStatus() override; 94 bool ReadFeature(uint32_t feature) override; 95 void SetFeature(uint32_t feature) override; 96 zx_status_t ConfirmFeatures() override; 97 98 // These handle writing to/from a device's device config to allow derived 99 // virtio devices to work with fields only they know about. 100 void DeviceConfigRead(uint16_t offset, uint8_t* value) override; 101 void DeviceConfigRead(uint16_t offset, uint16_t* value) override; 102 void DeviceConfigRead(uint16_t offset, uint32_t* value) override; 103 void DeviceConfigRead(uint16_t offset, uint64_t* value) override; 104 void DeviceConfigWrite(uint16_t offset, uint8_t value) override; 105 void DeviceConfigWrite(uint16_t offset, uint16_t value) override; 106 void DeviceConfigWrite(uint16_t offset, uint32_t value) override; 107 void DeviceConfigWrite(uint16_t offset, uint64_t value) override; 108 109 // Callbacks called during PciBackend's parsing of capabilities in Bind() 110 void CommonCfgCallbackLocked(const virtio_pci_cap_t& cap) TA_REQ(lock_); 111 void NotifyCfgCallbackLocked(const virtio_pci_cap_t& cap) TA_REQ(lock_); 112 void IsrCfgCallbackLocked(const virtio_pci_cap_t& cap) TA_REQ(lock_); 113 void DeviceCfgCallbackLocked(const virtio_pci_cap_t& cap) TA_REQ(lock_); 114 void PciCfgCallbackLocked(const virtio_pci_cap_t& cap) TA_REQ(lock_); 115 116 // Handle the virtio queues for the device. Due to configuration layouts changing 117 // depending on backend this has to be handled by the backend itself. 118 uint16_t GetRingSize(uint16_t index) override; 119 void SetRing(uint16_t index, uint16_t count, zx_paddr_t pa_desc, zx_paddr_t pa_avail, 120 zx_paddr_t pa_used) override; 121 void RingKick(uint16_t ring_index) override; 122 char* tag() { return tag_; } 123 124private: 125 zx_status_t MapBar(uint8_t bar); 126 127 struct bar { 128 uintptr_t mmio_base; 129 zx::handle mmio_handle; 130 } bar_[6] = {{0, {}}}; 131 132 uintptr_t notify_base_ = 0; 133 volatile uint32_t* isr_status_ = nullptr; 134 uintptr_t device_cfg_ TA_GUARDED(lock_) = 0; 135 volatile virtio_pci_common_cfg_t* common_cfg_ TA_GUARDED(lock_) = nullptr; 136 uint32_t notify_off_mul_; 137 138 DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(PciModernBackend); 139}; 140 141} // namespace virtio 142