| // Copyright 2018 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. |
| |
| // WARNING: This file is machine generated by fidlc. |
| |
| #pragma once |
| |
| #include <ddk/protocol/ethernet.h> |
| #include <ddktl/device-internal.h> |
| #include <zircon/assert.h> |
| #include <zircon/compiler.h> |
| #include <zircon/listnode.h> |
| #include <zircon/types.h> |
| |
| #include "ethernet-internal.h" |
| |
| // DDK ethmac-protocol support |
| // |
| // :: Proxies :: |
| // |
| // ddk::EthmacProtocolProxy is a simple wrapper around |
| // ethmac_protocol_t. It does not own the pointers passed to it |
| // |
| // :: Mixins :: |
| // |
| // ddk::EthmacProtocol is a mixin class that simplifies writing DDK drivers |
| // that implement the ethmac protocol. It doesn't set the base protocol. |
| // |
| // :: Examples :: |
| // |
| // // A driver that implements a ZX_PROTOCOL_ETHMAC device. |
| // class EthmacDevice { |
| // using EthmacDeviceType = ddk::Device<EthmacDevice, /* ddk mixins */>; |
| // |
| // class EthmacDevice : public EthmacDeviceType, |
| // public ddk::EthmacProtocol<EthmacDevice> { |
| // public: |
| // EthmacDevice(zx_device_t* parent) |
| // : EthmacDeviceType("my-ethmac-protocol-device", parent) {} |
| // |
| // zx_status_t EthmacQuery(uint32_t options, ethmac_info_t* out_info); |
| // |
| // void EthmacStop(); |
| // |
| // zx_status_t EthmacStart(const ethmac_ifc_t* ifc); |
| // |
| // zx_status_t EthmacQueueTx(uint32_t options, ethmac_netbuf_t* netbuf); |
| // |
| // zx_status_t EthmacSetParam(uint32_t param, zx_status_t value, const void* data_buffer, size_t |
| // data_size); |
| // |
| // zx_handle_t EthmacGetBti(); |
| // |
| // ... |
| // }; |
| |
| namespace ddk { |
| |
| template <typename D> |
| class EthmacIfc : public internal::base_mixin { |
| public: |
| EthmacIfc() { |
| internal::CheckEthmacIfcSubclass<D>(); |
| ethmac_ifc_ops_.status = EthmacIfcStatus; |
| ethmac_ifc_ops_.recv = EthmacIfcRecv; |
| ethmac_ifc_ops_.complete_tx = EthmacIfcCompleteTx; |
| } |
| |
| protected: |
| ethmac_ifc_ops_t ethmac_ifc_ops_ = {}; |
| |
| private: |
| static void EthmacIfcStatus(void* ctx, uint32_t status) { |
| static_cast<D*>(ctx)->EthmacIfcStatus(status); |
| } |
| static void EthmacIfcRecv(void* ctx, const void* data_buffer, size_t data_size, |
| uint32_t flags) { |
| static_cast<D*>(ctx)->EthmacIfcRecv(data_buffer, data_size, flags); |
| } |
| // complete_tx() is called to return ownership of a netbuf to the generic ethernet driver. |
| // Return status indicates queue state: |
| // ZX_OK: Packet has been enqueued. |
| // Other: Packet could not be enqueued. |
| // Upon a return of ZX_OK, the packet has been enqueued, but no information is returned as to |
| // the completion state of the transmission itself. |
| static void EthmacIfcCompleteTx(void* ctx, ethmac_netbuf_t* netbuf, zx_status_t status) { |
| static_cast<D*>(ctx)->EthmacIfcCompleteTx(netbuf, status); |
| } |
| }; |
| |
| class EthmacIfcProxy { |
| public: |
| EthmacIfcProxy() : ops_(nullptr), ctx_(nullptr) {} |
| EthmacIfcProxy(const ethmac_ifc_t* proto) : ops_(proto->ops), ctx_(proto->ctx) {} |
| |
| void GetProto(ethmac_ifc_t* proto) { |
| proto->ctx = ctx_; |
| proto->ops = ops_; |
| } |
| bool is_valid() { return ops_ != nullptr; } |
| void clear() { |
| ctx_ = nullptr; |
| ops_ = nullptr; |
| } |
| void Status(uint32_t status) { ops_->status(ctx_, status); } |
| void Recv(const void* data_buffer, size_t data_size, uint32_t flags) { |
| ops_->recv(ctx_, data_buffer, data_size, flags); |
| } |
| // complete_tx() is called to return ownership of a netbuf to the generic ethernet driver. |
| // Return status indicates queue state: |
| // ZX_OK: Packet has been enqueued. |
| // Other: Packet could not be enqueued. |
| // Upon a return of ZX_OK, the packet has been enqueued, but no information is returned as to |
| // the completion state of the transmission itself. |
| void CompleteTx(ethmac_netbuf_t* netbuf, zx_status_t status) { |
| ops_->complete_tx(ctx_, netbuf, status); |
| } |
| |
| private: |
| ethmac_ifc_ops_t* ops_; |
| void* ctx_; |
| }; |
| |
| // The ethernet midlayer will never call ethermac_protocol |
| // methods from multiple threads simultaneously, but it |
| // can call send() methods at the same time as non-send |
| // methods. |
| template <typename D> |
| class EthmacProtocol : public internal::base_mixin { |
| public: |
| EthmacProtocol() { |
| internal::CheckEthmacProtocolSubclass<D>(); |
| ethmac_protocol_ops_.query = EthmacQuery; |
| ethmac_protocol_ops_.stop = EthmacStop; |
| ethmac_protocol_ops_.start = EthmacStart; |
| ethmac_protocol_ops_.queue_tx = EthmacQueueTx; |
| ethmac_protocol_ops_.set_param = EthmacSetParam; |
| ethmac_protocol_ops_.get_bti = EthmacGetBti; |
| } |
| |
| protected: |
| ethmac_protocol_ops_t ethmac_protocol_ops_ = {}; |
| |
| private: |
| // Obtain information about the ethermac device and supported features |
| // Safe to call at any time. |
| static zx_status_t EthmacQuery(void* ctx, uint32_t options, ethmac_info_t* out_info) { |
| return static_cast<D*>(ctx)->EthmacQuery(options, out_info); |
| } |
| // Shut down a running ethermac |
| // Safe to call if the ethermac is already stopped. |
| static void EthmacStop(void* ctx) { static_cast<D*>(ctx)->EthmacStop(); } |
| // Start ethermac running with ifc_virt |
| // Callbacks on ifc may be invoked from now until stop() is called |
| static zx_status_t EthmacStart(void* ctx, const ethmac_ifc_t* ifc) { |
| return static_cast<D*>(ctx)->EthmacStart(ifc); |
| } |
| // Request transmission of the packet in netbuf. Return status indicates queue state: |
| // ZX_ERR_SHOULD_WAIT: Packet is being enqueued. |
| // ZX_OK: Packet has been enqueued. |
| // Other: Packet could not be enqueued. |
| // In the SHOULD_WAIT case the driver takes ownership of the netbuf and must call complete_tx() |
| // to return it once the enqueue is complete. complete_tx() may be used to return the packet |
| // before transmission itself completes, but MUST NOT be called from within the queue_tx() |
| // implementation. |
| // queue_tx() may be called at any time after start() is called including from multiple threads |
| // simultaneously. |
| static zx_status_t EthmacQueueTx(void* ctx, uint32_t options, ethmac_netbuf_t* netbuf) { |
| return static_cast<D*>(ctx)->EthmacQueueTx(options, netbuf); |
| } |
| // Request a settings change for the driver. Return status indicates disposition: |
| // ZX_OK: Request has been handled. |
| // ZX_ERR_NOT_SUPPORTED: Driver does not support this setting. |
| // Other: Error trying to support this request. |
| // |value| and |data| usage are defined for each |param|; see comments above. |
| // set_param() may be called at any time after start() is called including from multiple threads |
| // simultaneously. |
| static zx_status_t EthmacSetParam(void* ctx, uint32_t param, zx_status_t value, |
| const void* data_buffer, size_t data_size) { |
| return static_cast<D*>(ctx)->EthmacSetParam(param, value, data_buffer, data_size); |
| } |
| // Get the BTI handle (needed to pin DMA memory) for this device. |
| // This method is only valid on devices that advertise ETHMAC_FEATURE_DMA |
| // The caller does *not* take ownership of the BTI handle and must never close |
| // the handle. |
| static zx_handle_t EthmacGetBti(void* ctx) { return static_cast<D*>(ctx)->EthmacGetBti(); } |
| }; |
| |
| class EthmacProtocolProxy { |
| public: |
| EthmacProtocolProxy() : ops_(nullptr), ctx_(nullptr) {} |
| EthmacProtocolProxy(const ethmac_protocol_t* proto) : ops_(proto->ops), ctx_(proto->ctx) {} |
| |
| void GetProto(ethmac_protocol_t* proto) { |
| proto->ctx = ctx_; |
| proto->ops = ops_; |
| } |
| bool is_valid() { return ops_ != nullptr; } |
| void clear() { |
| ctx_ = nullptr; |
| ops_ = nullptr; |
| } |
| // Obtain information about the ethermac device and supported features |
| // Safe to call at any time. |
| zx_status_t Query(uint32_t options, ethmac_info_t* out_info) { |
| return ops_->query(ctx_, options, out_info); |
| } |
| // Shut down a running ethermac |
| // Safe to call if the ethermac is already stopped. |
| void Stop() { ops_->stop(ctx_); } |
| // Start ethermac running with ifc_virt |
| // Callbacks on ifc may be invoked from now until stop() is called |
| zx_status_t Start(const ethmac_ifc_t* ifc) { return ops_->start(ctx_, ifc); } |
| // Request transmission of the packet in netbuf. Return status indicates queue state: |
| // ZX_ERR_SHOULD_WAIT: Packet is being enqueued. |
| // ZX_OK: Packet has been enqueued. |
| // Other: Packet could not be enqueued. |
| // In the SHOULD_WAIT case the driver takes ownership of the netbuf and must call complete_tx() |
| // to return it once the enqueue is complete. complete_tx() may be used to return the packet |
| // before transmission itself completes, but MUST NOT be called from within the queue_tx() |
| // implementation. |
| // queue_tx() may be called at any time after start() is called including from multiple threads |
| // simultaneously. |
| zx_status_t QueueTx(uint32_t options, ethmac_netbuf_t* netbuf) { |
| return ops_->queue_tx(ctx_, options, netbuf); |
| } |
| // Request a settings change for the driver. Return status indicates disposition: |
| // ZX_OK: Request has been handled. |
| // ZX_ERR_NOT_SUPPORTED: Driver does not support this setting. |
| // Other: Error trying to support this request. |
| // |value| and |data| usage are defined for each |param|; see comments above. |
| // set_param() may be called at any time after start() is called including from multiple threads |
| // simultaneously. |
| zx_status_t SetParam(uint32_t param, zx_status_t value, const void* data_buffer, |
| size_t data_size) { |
| return ops_->set_param(ctx_, param, value, data_buffer, data_size); |
| } |
| // Get the BTI handle (needed to pin DMA memory) for this device. |
| // This method is only valid on devices that advertise ETHMAC_FEATURE_DMA |
| // The caller does *not* take ownership of the BTI handle and must never close |
| // the handle. |
| zx_handle_t GetBti() { return ops_->get_bti(ctx_); } |
| |
| private: |
| ethmac_protocol_ops_t* ops_; |
| void* ctx_; |
| }; |
| |
| } // namespace ddk |