root/sys/dev/aq/aq_ring.h
/*
 * aQuantia Corporation Network Driver
 * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   (1) Redistributions of source code must retain the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer.
 *
 *   (2) Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 *
 *   (3)The name of the author may not be used to endorse or promote
 *   products derived from this software without specific prior
 *   written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _AQ_RING_H_
#define _AQ_RING_H_

#include "aq_hw.h"

#define REFILL_THRESHOLD 128


typedef volatile struct {
        uint32_t rss_type:4;
        uint32_t pkt_type:8;
        uint32_t rdm_err:1;
        uint32_t rsvd:6;
        uint32_t rx_cntl:2;
        uint32_t sph:1;
        uint32_t hdr_len:10;
        uint32_t rss_hash;
        uint16_t dd:1;
        uint16_t eop:1;
        uint16_t rx_stat:4;
        uint16_t rx_estat:6;
        uint16_t rsc_cnt:4;
        uint16_t pkt_len;
        uint16_t next_desp;
        uint16_t vlan;
} __attribute__((__packed__)) aq_rx_wb_t;

typedef volatile struct {
        union {
                /* HW RX descriptor */
                struct __packed {
                        uint64_t buf_addr;
                        uint64_t hdr_addr;
                } read;

                /* HW RX descriptor writeback */
                aq_rx_wb_t wb;
        };
} __attribute__((__packed__)) aq_rx_desc_t;

/* Hardware tx descriptor */
typedef volatile struct {
        uint64_t buf_addr;

        union {
                struct {
                        uint32_t type:3;
                        uint32_t :1;
                        uint32_t len:16;
                        uint32_t dd:1;
                        uint32_t eop:1;
                        uint32_t cmd:8;
                        uint32_t :14;
                        uint32_t ct_idx:1;
                        uint32_t ct_en:1;
                        uint32_t pay_len:18;
                } __attribute__((__packed__));
                uint64_t flags;
        };
} __attribute__((__packed__)) aq_tx_desc_t;

enum aq_tx_desc_type {
        tx_desc_type_desc = 1,
        tx_desc_type_ctx = 2,
};

enum aq_tx_desc_cmd {
        tx_desc_cmd_vlan = 1,
        tx_desc_cmd_fcs = 2,
        tx_desc_cmd_ipv4 = 4,
        tx_desc_cmd_l4cs = 8,
        tx_desc_cmd_lso = 0x10,
        tx_desc_cmd_wb = 0x20,
};

/* Hardware tx context descriptor */
typedef volatile union {
        struct __packed {
                uint64_t flags1;
                uint64_t flags2;
        };

        struct __packed {
                uint64_t :40;
                uint32_t tun_len:8;
                uint32_t out_len:16;
                uint32_t type:3;
                uint32_t idx:1;
                uint32_t vlan_tag:16;
                uint32_t cmd:4;
                uint32_t l2_len:7;
                uint32_t l3_len:9;
                uint32_t l4_len:8;
                uint32_t mss_len:16;
        };
} __attribute__((__packed__)) aq_txc_desc_t;

struct aq_ring_stats {
        uint64_t rx_pkts;
        uint64_t rx_bytes;
        uint64_t jumbo_pkts;
        uint64_t rx_err;
        uint64_t irq;

        uint64_t tx_pkts;
        uint64_t tx_bytes;
        uint64_t tx_drops;
        uint64_t tx_queue_full;
};

struct aq_dev;

struct aq_ring {
        struct aq_dev *dev;
        int index;

        struct if_irq irq;
        int msix;
/* RX */
        qidx_t rx_size;
        int rx_max_frame_size;
        void *rx_desc_area_ptr;
        aq_rx_desc_t *rx_descs;
        uint64_t rx_descs_phys;

/* TX */
        int tx_head, tx_tail;
        qidx_t tx_size;
        void *tx_desc_area_ptr;
        aq_tx_desc_t *tx_descs;
        uint64_t tx_descs_phys;

        struct aq_ring_stats stats;
};

int aq_ring_rx_init(struct aq_hw *hw, struct aq_ring *ring);
int aq_ring_tx_init(struct aq_hw *hw, struct aq_ring *ring);

int aq_ring_tx_start(struct aq_hw *hw, struct aq_ring *ring);
int aq_ring_tx_stop(struct aq_hw *hw, struct aq_ring *ring);
int aq_ring_rx_start(struct aq_hw *hw, struct aq_ring *ring);
int aq_ring_rx_stop(struct aq_hw *hw, struct aq_ring *ring);

int aq_ring_tx_tail_update(struct aq_hw *hw, struct aq_ring *ring, uint32_t tail);


extern struct if_txrx aq_txrx;
int             aq_intr(void *arg);

#endif /* _AQ_RING_H_ */