blob: 079aafb0ec5d84f4dd17b673abc1c74296636470 [file] [log] [blame]
// Copyright 2017 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.
#ifndef SRC_CONNECTIVITY_ETHERNET_DRIVERS_VIRTIO_ETHERNET_H_
#define SRC_CONNECTIVITY_ETHERNET_DRIVERS_VIRTIO_ETHERNET_H_
#include <fuchsia/hardware/ethernet/c/banjo.h>
#include <fuchsia/hardware/ethernet/cpp/banjo.h>
#include <lib/virtio/device.h>
#include <lib/virtio/ring.h>
#include <lib/zircon-internal/thread_annotations.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <zircon/compiler.h>
#include <zircon/types.h>
#include <memory>
#include <ddk/io-buffer.h>
#include <ddktl/device.h>
#include <fbl/macros.h>
#include <virtio/net.h>
namespace virtio {
class EthernetDevice;
using DeviceType = ddk::Device<EthernetDevice, ddk::GetProtocolable, ddk::Unbindable>;
class EthernetDevice : public Device,
// Mixins for protocol device:
public DeviceType,
// Mixin for Ethernet banjo protocol:
public ddk::EthernetImplProtocol<EthernetDevice, ddk::base_protocol> {
public:
explicit EthernetDevice(zx_device_t* device, zx::bti, std::unique_ptr<Backend> backend);
virtual ~EthernetDevice();
zx_status_t Init() override TA_EXCL(state_lock_);
void DdkRelease() TA_EXCL(state_lock_);
void DdkUnbind(ddk::UnbindTxn txn) { virtio::Device::Unbind(std::move(txn)); }
zx_status_t DdkGetProtocol(uint32_t proto_id, void* out);
// VirtIO callbacks
void IrqRingUpdate() override TA_EXCL(state_lock_);
void IrqConfigChange() override TA_EXCL(state_lock_);
// DDK protocol hooks; see fuchsia/hardware/ethernet/c/banjo.h
zx_status_t EthernetImplQuery(uint32_t options, ethernet_info_t* info) TA_EXCL(state_lock_);
void EthernetImplStop() TA_EXCL(state_lock_);
zx_status_t EthernetImplStart(const ethernet_ifc_protocol_t* ifc) TA_EXCL(state_lock_);
void EthernetImplQueueTx(uint32_t options, ethernet_netbuf_t* netbuf,
ethernet_impl_queue_tx_callback completion_cb, void* cookie)
TA_EXCL(state_lock_);
const char* tag() const override { return "virtio-net"; }
zx_status_t EthernetImplSetParam(uint32_t param, int32_t value, const uint8_t* data_buffer,
size_t data_size) {
return ZX_ERR_NOT_SUPPORTED;
}
void EthernetImplGetBti(zx::bti* out_bti) {
// return ZX_ERR_NOT_SUPPORTED;
}
private:
static constexpr size_t kFailureWarnRate = 100;
DISALLOW_COPY_ASSIGN_AND_MOVE(EthernetDevice);
// Implementation of IrqRingUpdate; returns true if it should be called again.
bool IrqRingUpdateInternal() TA_EXCL(state_lock_);
// DDK device hooks; see ddk/device.h
void ReleaseLocked() TA_REQ(state_lock_);
// Mutexes to control concurrent access
mtx_t state_lock_;
mtx_t tx_lock_;
// Virtqueues; see section 5.1.2 of the spec
// This driver doesn't currently support multi-queueing, automatic
// steering, or the control virtqueue, so only a single queue is needed in
// each direction.
Ring rx_;
Ring tx_;
std::unique_ptr<io_buffer_t[]> bufs_;
size_t unkicked_ TA_GUARDED(tx_lock_);
size_t tx_failed_descriptor_alloc_ TA_GUARDED(tx_lock_);
size_t unrecycled_;
// Saved net device configuration out of the pci config BAR
virtio_net_config_t config_ TA_GUARDED(state_lock_);
size_t virtio_hdr_len_;
// Ethernet callback interface; see fuchsia/hardware/ethernet/c/banjo.h
ethernet_ifc_protocol_t ifc_ TA_GUARDED(state_lock_);
};
} // namespace virtio
#endif // SRC_CONNECTIVITY_ETHERNET_DRIVERS_VIRTIO_ETHERNET_H_