// 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.

#include <ddk/binding.h>
#include <ddk/debug.h>
#include <ddk/device.h>
#include <ddk/driver.h>
#include <ddk/protocol/ethernet.h>

#include <zircon/device/ethernet.h>
#include <zircon/listnode.h>
#include <zircon/process.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <threads.h>

#define FIFO_DEPTH 256
#define FIFO_ESIZE sizeof(eth_fifo_entry_t)
#define DEVICE_NAME_LEN 16

// This is used for signaling that eth_tx_thread() should exit.
static const zx_signals_t kSignalFifoTerminate = ZX_USER_SIGNAL_0;

// ensure that we will not exceed fifo capacity
static_assert((FIFO_DEPTH * FIFO_ESIZE) <= 4096, "");

// ethernet device
typedef struct ethdev0 {
    // shared state
    zx_device_t* macdev;
    ethmac_protocol_t mac;
    uint32_t state;

    mtx_t lock;

    // active and idle instances (ethdev_t)
    list_node_t list_active;
    list_node_t list_idle;

    ethmac_info_t info;
    uint32_t status;
    zx_device_t* mxdev;
} ethdev0_t;

// transmit thread has been created
#define ETHDEV_TX_THREAD (1u)

// connected to the ethmac and handling traffic
#define ETHDEV_RUNNING (2u)

// being destroyed
#define ETHDEV_DEAD (4u)

// This client should loopback tx packets to rx path
#define ETHDEV_TX_LOOPBACK (8u)

// This client wants to observe loopback tx packets
#define ETHDEV_TX_LISTEN (16u)

// indicates the device is busy although its lock is released
#define ETHDEV0_BUSY (1u)

// ethernet instance device
typedef struct ethdev {
    list_node_t node;

    ethdev0_t* edev0;

    uint32_t state;
    char name[DEVICE_NAME_LEN];

    // fifos are named from the perspective
    // of the packet from from the client
    // to the network interface
    zx_handle_t tx_fifo;
    uint32_t tx_depth;
    zx_handle_t rx_fifo;
    uint32_t rx_depth;

    // io buffer
    zx_handle_t io_vmo;
    void* io_buf;
    size_t io_size;

    // fifo thread
    thrd_t tx_thr;

    zx_device_t* mxdev;

    uint32_t fail_rx_read;
    uint32_t fail_rx_write;
    uint32_t fail_tx_write;
} ethdev_t;

#define FAIL_REPORT_RATE 50

static void eth_handle_rx(ethdev_t* edev, const void* data, size_t len, uint32_t extra) {
    eth_fifo_entry_t e;
    zx_status_t status;
    uint32_t count;

    // TODO: read multiple and cache locally to reduce syscalls
    if ((status = zx_fifo_read(edev->rx_fifo, &e, sizeof(e), &count)) < 0) {
        if (status == ZX_ERR_SHOULD_WAIT) {
            if ((edev->fail_rx_read++ % FAIL_REPORT_RATE) == 0) {
                dprintf(ERROR, "eth [%s]: no rx buffers available (%u times)\n",
                       edev->name, edev->fail_rx_read);
            }
        } else {
            // Fatal, should force teardown
            dprintf(ERROR, "eth [%s]: rx fifo read failed %d\n", edev->name, status);
        }
        return;
    }

    if ((e.offset >= edev->io_size) || ((e.length > (edev->io_size - e.offset)))) {
        // invalid offset/length. report error. drop packet
        e.length = 0;
        e.flags = ETH_FIFO_INVALID;
    } else if (len > e.length) {
        e.length = 0;
        e.flags = ETH_FIFO_INVALID;
    } else {
        // packet fits. deliver it
        memcpy(edev->io_buf + e.offset, data, len);
        e.length = len;
        e.flags = ETH_FIFO_RX_OK | extra;
    }

    if ((status = zx_fifo_write(edev->rx_fifo, &e, sizeof(e), &count)) < 0) {
        if (status == ZX_ERR_SHOULD_WAIT) {
            if ((edev->fail_rx_write++ % FAIL_REPORT_RATE) == 0) {
                dprintf(ERROR, "eth [%s]: no rx_fifo space available (%u times)\n",
                       edev->name, edev->fail_rx_write);
            }
        } else {
            // Fatal, should force teardown
            dprintf(ERROR, "eth [%s]: rx_fifo write failed %d\n", edev->name, status);
        }
        return;
    }
}

static void eth0_status(void* cookie, uint32_t status) {
    dprintf(TRACE, "eth: status() %08x\n", status);

    ethdev0_t* edev0 = cookie;
    mtx_lock(&edev0->lock);
    edev0->status = status;

    ethdev_t* edev;
    list_for_every_entry(&edev0->list_active, edev, ethdev_t, node) {
        zx_object_signal_peer(edev->rx_fifo, 0, ETH_SIGNAL_STATUS);
    }
    mtx_unlock(&edev0->lock);
}

// TODO: I think if this arrives at the wrong time during teardown we
// can deadlock with the ethermac device
static void eth0_recv(void* cookie, void* data, size_t len, uint32_t flags) {
    ethdev0_t* edev0 = cookie;

    ethdev_t* edev;
    mtx_lock(&edev0->lock);
    list_for_every_entry(&edev0->list_active, edev, ethdev_t, node) {
        eth_handle_rx(edev, data, len, 0);
    }
    mtx_unlock(&edev0->lock);
}

static ethmac_ifc_t ethmac_ifc = {
    .status = eth0_status,
    .recv = eth0_recv,
};

static void eth_tx_echo(ethdev0_t* edev0, const void* data, size_t len) {
    ethdev_t* edev;
    mtx_lock(&edev0->lock);
    list_for_every_entry(&edev0->list_active, edev, ethdev_t, node) {
        if (edev->state & ETHDEV_TX_LISTEN) {
            eth_handle_rx(edev, data, len, ETH_FIFO_RX_TX);
        }
    }
    mtx_unlock(&edev0->lock);
}

static zx_status_t eth_tx_listen_locked(ethdev_t* edev, bool yes) {
    ethdev0_t* edev0 = edev->edev0;

    // update our state
    if (yes) {
        edev->state |= ETHDEV_TX_LISTEN;
    } else {
        edev->state &= (~ETHDEV_TX_LISTEN);
    }

    // determine global state
    yes = false;
    list_for_every_entry(&edev0->list_active, edev, ethdev_t, node) {
        if (edev->state & ETHDEV_TX_LISTEN) {
            yes = true;
        }
    }

    // set everyone's echo flag based on global state
    list_for_every_entry(&edev0->list_active, edev, ethdev_t, node) {
        if (yes) {
            edev->state |= ETHDEV_TX_LOOPBACK;
        } else {
            edev->state &= (~ETHDEV_TX_LOOPBACK);
        }
    }

    return ZX_OK;
}

static int eth_tx_thread(void* arg) {
    ethdev_t* edev = (ethdev_t*)arg;
    ethdev0_t* edev0 = edev->edev0;
    eth_fifo_entry_t entries[FIFO_DEPTH / 2];
    zx_status_t status;
    uint32_t count;

    for (;;) {
        if ((status = zx_fifo_read(edev->tx_fifo, entries, sizeof(entries), &count)) < 0) {
            if (status == ZX_ERR_SHOULD_WAIT) {
                zx_signals_t observed;
                if ((status = zx_object_wait_one(edev->tx_fifo,
                                                 ZX_FIFO_READABLE |
                                                 ZX_FIFO_PEER_CLOSED |
                                                 kSignalFifoTerminate,
                                                 ZX_TIME_INFINITE,
                                                 &observed)) < 0) {
                    dprintf(ERROR, "eth [%s]: tx_fifo: error waiting: %d\n", edev->name, status);
                    break;
                }
                if (observed & kSignalFifoTerminate)
                    break;
                continue;
            } else {
                dprintf(ERROR, "eth [%s]: tx_fifo: cannot read: %d\n", edev->name, status);
                break;
            }
        }

        uint32_t n = count;
        for (eth_fifo_entry_t* e = entries; count > 0; e++) {
            if ((e->offset > edev->io_size) || ((e->length > (edev->io_size - e->offset)))) {
                e->flags = ETH_FIFO_INVALID;
            } else {
                uint32_t opt = count > 1 ? ETHMAC_TX_OPT_MORE : 0u;
                if (opt) {
                    dprintf(SPEW, "setting OPT_MORE (%u packets to go)\n", count);
                }
                edev0->mac.ops->send(edev0->mac.ctx, opt, edev->io_buf + e->offset, e->length);
                e->flags = ETH_FIFO_TX_OK;
                if (edev->state & ETHDEV_TX_LOOPBACK) {
                    eth_tx_echo(edev0, edev->io_buf + e->offset, e->length);
                }
            }
            count--;
        }

        if ((status = zx_fifo_write(edev->tx_fifo, entries, sizeof(eth_fifo_entry_t) * n, &count)) < 0) {
            if (status == ZX_ERR_SHOULD_WAIT) {
                if ((edev->fail_tx_write++ % FAIL_REPORT_RATE) == 0) {
                    dprintf(ERROR, "eth [%s]: no tx_fifo space available (%u times)\n",
                           edev->name, edev->fail_tx_write);
                }
            } else {
                dprintf(ERROR, "eth [%s]: tx_fifo write failed %d\n", edev->name, status);
                break;
            }
        }
        if (count != n) {
            dprintf(ERROR, "eth [%s]: tx_fifo: only wrote %u of %u!\n", edev->name, count, n);
        }
    }

    dprintf(INFO, "eth [%s]: tx_thread: exit: %d\n", edev->name, status);
    return 0;
}

static zx_status_t eth_get_fifos_locked(ethdev_t* edev, void* out_buf, size_t out_len,
                                        size_t* out_actual) {
    if (out_len < sizeof(eth_fifos_t)) {
        return ZX_ERR_INVALID_ARGS;
    }
    if (edev->tx_fifo != ZX_HANDLE_INVALID) {
        return ZX_ERR_ALREADY_BOUND;
    }

    eth_fifos_t* fifos = out_buf;

    zx_status_t status;
    if ((status = zx_fifo_create(FIFO_DEPTH, FIFO_ESIZE, 0, &fifos->tx_fifo, &edev->tx_fifo)) < 0) {
        dprintf(ERROR, "eth_create  [%s]: failed to create tx fifo: %d\n", edev->name, status);
        return status;
    }
    if ((status = zx_fifo_create(FIFO_DEPTH, FIFO_ESIZE, 0, &fifos->rx_fifo, &edev->rx_fifo)) < 0) {
        dprintf(ERROR, "eth_create  [%s]: failed to create rx fifo: %d\n", edev->name, status);
        zx_handle_close(fifos->rx_fifo);
        zx_handle_close(edev->tx_fifo);
        edev->tx_fifo = ZX_HANDLE_INVALID;
        return status;
    }

    edev->tx_depth = FIFO_DEPTH;
    edev->rx_depth = FIFO_DEPTH;
    fifos->tx_depth = FIFO_DEPTH;
    fifos->rx_depth = FIFO_DEPTH;

    *out_actual = sizeof(*fifos);
    return ZX_OK;
}

static ssize_t eth_set_iobuf_locked(ethdev_t* edev, const void* in_buf, size_t in_len) {
    if (in_len < sizeof(zx_handle_t)) {
        return ZX_ERR_INVALID_ARGS;
    }
    if (edev->io_vmo != ZX_HANDLE_INVALID) {
        return ZX_ERR_ALREADY_BOUND;
    }

    zx_handle_t vmo = *((zx_handle_t*)in_buf);

    size_t size;
    zx_status_t status;

    if ((status = zx_vmo_get_size(vmo, &size)) < 0) {
        dprintf(ERROR, "eth [%s]: could not get io_buf size: %d\n", edev->name, status);
        goto fail;
    }

    if ((status = zx_vmar_map(zx_vmar_root_self(), 0, vmo, 0, size,
                              ZX_VM_FLAG_PERM_READ | ZX_VM_FLAG_PERM_WRITE,
                              (uintptr_t*)&edev->io_buf)) < 0) {
        dprintf(ERROR, "eth [%s]: could not map io_buf: %d\n", edev->name, status);
        goto fail;
    }

    edev->io_vmo = vmo;
    edev->io_size = size;

    return ZX_OK;

fail:
    zx_handle_close(vmo);
    return status;
}

static zx_status_t eth_start_locked(ethdev_t* edev) {
    ethdev0_t* edev0 = edev->edev0;

    // Cannot start unless tx/rx rings are configured
    if ((edev->io_vmo == ZX_HANDLE_INVALID) ||
        (edev->tx_fifo == ZX_HANDLE_INVALID) ||
        (edev->rx_fifo == ZX_HANDLE_INVALID)) {
        return ZX_ERR_BAD_STATE;
    }

    if (edev->state & ETHDEV_RUNNING) {
        return ZX_OK;
    }

    if (!(edev->state & ETHDEV_TX_THREAD)) {
        int r = thrd_create_with_name(&edev->tx_thr, eth_tx_thread,
                                      edev, "eth-tx-thread");
        if (r != thrd_success) {
            dprintf(ERROR, "eth [%s]: failed to start tx thread: %d\n", edev->name, r);
            return ZX_ERR_INTERNAL;
        }
        edev->state |= ETHDEV_TX_THREAD;
    }

    zx_status_t status;
    if (list_is_empty(&edev0->list_active)) {
        // Release the lock to allow other device operations in callback routine.
        // Re-acquire lock afterwards. Set busy to prevent problems with other ioctls.
        edev0->state |= ETHDEV0_BUSY;
        mtx_unlock(&edev0->lock);
        status = edev0->mac.ops->start(edev0->mac.ctx, &ethmac_ifc, edev0);
        mtx_lock(&edev0->lock);
        edev0->state &= ~ETHDEV0_BUSY;
    } else {
        status = ZX_OK;
    }

    if (status == ZX_OK) {
        edev->state |= ETHDEV_RUNNING;
        list_delete(&edev->node);
        list_add_tail(&edev0->list_active, &edev->node);
    } else {
        dprintf(ERROR, "eth [%s]: failed to start mac: %d\n", edev->name, status);
    }

    return status;
}

static zx_status_t eth_stop_locked(ethdev_t* edev) {
    ethdev0_t* edev0 = edev->edev0;

    if (edev->state & ETHDEV_RUNNING) {
        edev->state &= (~ETHDEV_RUNNING);
        list_delete(&edev->node);
        list_add_tail(&edev0->list_idle, &edev->node);
        if (list_is_empty(&edev0->list_active)) {
            if (!(edev->state & ETHDEV_DEAD)) {
                // Release the lock to allow other device operations in callback routine.
                // Re-acquire lock afterwards. Set busy to prevent problems with other ioctls.
                edev0->state |= ETHDEV0_BUSY;
                mtx_unlock(&edev0->lock);
                edev0->mac.ops->stop(edev0->mac.ctx);
                mtx_lock(&edev0->lock);
                edev0->state &= ~ETHDEV0_BUSY;
            }
        }
    }

    return ZX_OK;
}

static ssize_t eth_set_client_name_locked(ethdev_t* edev, const void* in_buf, size_t in_len) {
    if (in_len >= DEVICE_NAME_LEN) {
        in_len = DEVICE_NAME_LEN - 1;
    }
    memcpy(edev->name, in_buf, in_len);
    edev->name[in_len] = '\0';
    return ZX_OK;
}

static zx_status_t eth_get_status_locked(ethdev_t* edev, void* out_buf, size_t out_len,
                                  size_t* out_actual) {
    if (out_len < sizeof(uint32_t)) {
        return ZX_ERR_INVALID_ARGS;
    }
    if (edev->rx_fifo == ZX_HANDLE_INVALID) {
        return ZX_ERR_BAD_STATE;
    }
    if (zx_object_signal_peer(edev->rx_fifo, ETH_SIGNAL_STATUS, 0) != ZX_OK) {
        return ZX_ERR_INTERNAL;
    }

    uint32_t* status = out_buf;
    *status = edev->edev0->status;
    *out_actual = sizeof(status);
    return ZX_OK;
}

static zx_status_t eth_ioctl(void* ctx, uint32_t op,
                             const void* in_buf, size_t in_len,
                             void* out_buf, size_t out_len, size_t* out_actual) {

    ethdev_t* edev = ctx;
    mtx_lock(&edev->edev0->lock);
    zx_status_t status;
    if (edev->edev0->state & ETHDEV0_BUSY) {
        dprintf(ERROR, "eth [%s]: cannot perform ioctl while device is busy. ioctl: %u\n",
               edev->name, IOCTL_NUMBER(op));
        status = ZX_ERR_SHOULD_WAIT;
        goto done;
    }

    if (edev->state & ETHDEV_DEAD) {
        status = ZX_ERR_BAD_STATE;
        goto done;
    }

    switch (op) {
    case IOCTL_ETHERNET_GET_INFO: {
        if (out_len < sizeof(eth_info_t)) {
            status = ZX_ERR_BUFFER_TOO_SMALL;
        } else {
            eth_info_t* info = out_buf;
            memset(info, 0, sizeof(*info));
            memcpy(info->mac, edev->edev0->info.mac, ETH_MAC_SIZE);
            if (edev->edev0->info.features & ETHMAC_FEATURE_WLAN) {
                info->features |= ETH_FEATURE_WLAN;
            }
            if (edev->edev0->info.features & ETHMAC_FEATURE_SYNTH) {
                info->features |= ETH_FEATURE_SYNTH;
            }
            info->mtu = edev->edev0->info.mtu;
            *out_actual = sizeof(*info);
            status = ZX_OK;
        }
        break;
    }
    case IOCTL_ETHERNET_GET_FIFOS:
        status = eth_get_fifos_locked(edev, out_buf, out_len, out_actual);
        break;
    case IOCTL_ETHERNET_SET_IOBUF:
        status = eth_set_iobuf_locked(edev, in_buf, in_len);
        break;
    case IOCTL_ETHERNET_START:
        status = eth_start_locked(edev);
        break;
    case IOCTL_ETHERNET_STOP:
        status = eth_stop_locked(edev);
        break;
    case IOCTL_ETHERNET_TX_LISTEN_START:
        status = eth_tx_listen_locked(edev, true);
        break;
    case IOCTL_ETHERNET_TX_LISTEN_STOP:
        status = eth_tx_listen_locked(edev, false);
        break;
    case IOCTL_ETHERNET_SET_CLIENT_NAME:
        status = eth_set_client_name_locked(edev, in_buf, in_len);
        break;
    case IOCTL_ETHERNET_GET_STATUS:
        status = eth_get_status_locked(edev, out_buf, out_len, out_actual);
        break;
    default:
        // TODO: consider if we want this under the edev0->lock or not
        status = device_ioctl(edev->edev0->macdev, op, in_buf, in_len, out_buf, out_len, out_actual);
        break;
    }

done:
    mtx_unlock(&edev->edev0->lock);

    return status;
}

// kill tx thread, release buffers, etc
// called from unbind and close
static void eth_kill_locked(ethdev_t* edev) {
    if (edev->state & ETHDEV_DEAD) {
        return;
    }

    dprintf(TRACE, "eth [%s]: kill: tearing down%s\n",
            edev->name, (edev->state & ETHDEV_TX_THREAD) ? " tx thread" : "");

    // make sure any future ioctls or other ops will fail
    edev->state |= ETHDEV_DEAD;

    // try to convince clients to close us
    if (edev->rx_fifo) {
        zx_handle_close(edev->rx_fifo);
        edev->rx_fifo = ZX_HANDLE_INVALID;
    }
    if (edev->tx_fifo) {
        // Ask the TX thread to exit.
        zx_object_signal(edev->tx_fifo, 0, kSignalFifoTerminate);
    }
    if (edev->io_vmo) {
        zx_handle_close(edev->io_vmo);
        edev->io_vmo = ZX_HANDLE_INVALID;
    }

    if (edev->state & ETHDEV_TX_THREAD) {
        edev->state &= (~ETHDEV_TX_THREAD);
        int ret;
        thrd_join(edev->tx_thr, &ret);
        dprintf(TRACE, "eth [%s]: kill: tx thread exited\n", edev->name);
    }

    if (edev->tx_fifo) {
        zx_handle_close(edev->tx_fifo);
        edev->tx_fifo = ZX_HANDLE_INVALID;
    }

    if (edev->io_buf) {
        zx_vmar_unmap(zx_vmar_root_self(), (uintptr_t)edev->io_buf, 0);
        edev->io_buf = NULL;
    }
    dprintf(TRACE, "eth [%s]: all resources released\n", edev->name);
}

static void eth_release(void* ctx) {
    ethdev_t* edev = ctx;
    free(edev);
}

static zx_status_t eth_close(void* ctx, uint32_t flags) {
    ethdev_t* edev = ctx;

    mtx_lock(&edev->edev0->lock);
    eth_stop_locked(edev);
    eth_kill_locked(edev);
    list_delete(&edev->node);
    mtx_unlock(&edev->edev0->lock);

    return ZX_OK;
}

static zx_protocol_device_t ethdev_ops = {
    .version = DEVICE_OPS_VERSION,
    .close = eth_close,
    .ioctl = eth_ioctl,
    .release = eth_release,
};

static zx_status_t eth0_open(void* ctx, zx_device_t** out, uint32_t flags) {
    ethdev0_t* edev0 = ctx;

    ethdev_t* edev;
    if ((edev = calloc(1, sizeof(ethdev_t))) == NULL) {
        return ZX_ERR_NO_MEMORY;
    }
    edev->edev0 = edev0;

    device_add_args_t args = {
        .version = DEVICE_ADD_ARGS_VERSION,
        .name = "ethernet",
        .ctx = edev,
        .ops = &ethdev_ops,
        .proto_id = ZX_PROTOCOL_ETHERNET,
        .flags = DEVICE_ADD_INSTANCE,
    };

    zx_status_t status;
    if ((status = device_add(edev0->mxdev, &args, &edev->mxdev)) < 0) {
        free(edev);
        return status;
    }

    mtx_lock(&edev0->lock);
    list_add_tail(&edev0->list_idle, &edev->node);
    mtx_unlock(&edev0->lock);

    *out = edev->mxdev;
    return ZX_OK;
}

static void eth0_unbind(void* ctx) {
    ethdev0_t* edev0 = ctx;

    mtx_lock(&edev0->lock);

    // tear down shared memory, fifos, and threads
    // to encourage any open instances to close
    ethdev_t* edev;
    list_for_every_entry(&edev0->list_active, edev, ethdev_t, node) {
        eth_kill_locked(edev);
    }
    list_for_every_entry(&edev0->list_idle, edev, ethdev_t, node) {
        eth_kill_locked(edev);
    }

    mtx_unlock(&edev0->lock);

    device_remove(edev0->mxdev);
}

static void eth0_release(void* ctx) {
    ethdev0_t* edev0 = ctx;
    free(edev0);
}

static zx_protocol_device_t ethdev0_ops = {
    .version = DEVICE_OPS_VERSION,
    .open = eth0_open,
    .unbind = eth0_unbind,
    .release = eth0_release,
};

#define BAD_FEATURES (ETHMAC_FEATURE_RX_QUEUE | ETHMAC_FEATURE_TX_QUEUE)

static zx_status_t eth_bind(void* ctx, zx_device_t* dev, void** cookie) {
    ethdev0_t* edev0;
    if ((edev0 = calloc(1, sizeof(ethdev0_t))) == NULL) {
        return ZX_ERR_NO_MEMORY;
    }

    zx_status_t status;
    if (device_get_protocol(dev, ZX_PROTOCOL_ETHERMAC, &edev0->mac)) {
        dprintf(ERROR, "eth: bind: no ethermac protocol\n");
        status = ZX_ERR_INTERNAL;
        goto fail;
    }

    if ((status = edev0->mac.ops->query(edev0->mac.ctx, 0, &edev0->info)) < 0) {
        dprintf(ERROR, "eth: bind: ethermac query failed: %d\n", status);
        goto fail;
    }

    if (edev0->info.features & BAD_FEATURES) {
        dprintf(ERROR, "eth: bind: ethermac requires unsupported features: %08x\n",
               edev0->info.features & BAD_FEATURES);
        status = ZX_ERR_NOT_SUPPORTED;
        goto fail;
    }

    mtx_init(&edev0->lock, mtx_plain);
    list_initialize(&edev0->list_active);
    list_initialize(&edev0->list_idle);

    edev0->macdev = dev;

    device_add_args_t args = {
        .version = DEVICE_ADD_ARGS_VERSION,
        .name = "ethernet",
        .ctx = edev0,
        .ops = &ethdev0_ops,
        .proto_id = ZX_PROTOCOL_ETHERNET,
    };

    if ((status = device_add(dev, &args, &edev0->mxdev)) < 0) {
        goto fail;
    }

    return ZX_OK;

fail:
    free(edev0);
    return status;
}

static zx_driver_ops_t eth_driver_ops = {
    .version = DRIVER_OPS_VERSION,
    .bind = eth_bind,
};

ZIRCON_DRIVER_BEGIN(ethernet, eth_driver_ops, "zircon", "0.1", 1)
    BI_MATCH_IF(EQ, BIND_PROTOCOL, ZX_PROTOCOL_ETHERMAC),
ZIRCON_DRIVER_END(ethernet)
