#ifndef _APPLE_BCE_H_
#define _APPLE_BCE_H_
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/sema.h>
#include <sys/callout.h>
#include <sys/rman.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#define BCE_PCI_VENDOR_APPLE 0x106b
#define BCE_PCI_DEVICE_T2 0x1801
#define BCE_MAX_QUEUE_COUNT 0x100
#define BCE_MAX_CQ_COUNT 64
#define BCE_QUEUE_USER_MIN 2
#define BCE_QUEUE_USER_MAX (BCE_MAX_QUEUE_COUNT - 1)
#define BCE_CMD_SIZE 0x40
#define BCE_FW_PROTOCOL_VER 0x20001
#define BCE_MBOX_TIMEOUT_MS 1000
#define BCE_TIMESTAMP_MS 150
#define BCE_REG_MBOX_OUT 0x820
#define BCE_REG_MBOX_REPLY 0x810
#define BCE_REG_MBOX_REPLY_CTR 0x108
#define BCE_REG_TIMESTAMP 0xC000
#define BCE_REG_DOORBELL_BASE 0x44000
#define BCE_MB_MSG(type, val) (((uint64_t)(type) << 58) | \
((val) & 0x3FFFFFFFFFFFFFFULL))
#define BCE_MB_TYPE(v) ((uint32_t)((v) >> 58))
#define BCE_MB_VALUE(v) ((v) & 0x3FFFFFFFFFFFFFFULL)
enum bce_mb_type {
BCE_MB_REGISTER_CMD_SQ = 0x07,
BCE_MB_REGISTER_CMD_CQ = 0x08,
BCE_MB_REGISTER_QUEUE_REPLY = 0x0B,
BCE_MB_SET_FW_PROTOCOL_VER = 0x0C,
BCE_MB_SLEEP_NO_STATE = 0x14,
BCE_MB_RESTORE_NO_STATE = 0x15,
BCE_MB_SAVE_AND_SLEEP = 0x17,
BCE_MB_RESTORE_AND_WAKE = 0x18,
BCE_MB_SAVE_FAILURE = 0x19,
BCE_MB_SAVE_RESTORE_COMPLETE = 0x1A,
};
enum bce_queue_type {
BCE_QUEUE_CQ = 0,
BCE_QUEUE_SQ = 1,
};
struct bce_qe_completion {
uint64_t result;
uint64_t data_size;
uint16_t qid;
uint16_t completion_index;
uint16_t status;
uint16_t flags;
#define BCE_CQ_FLAG_PENDING 0x8000
} __packed;
enum bce_completion_status {
BCE_COMP_SUCCESS = 0,
BCE_COMP_ERROR = 1,
BCE_COMP_ABORTED = 2,
BCE_COMP_NO_SPACE = 3,
BCE_COMP_OVERRUN = 4,
};
struct bce_qe_submission {
uint64_t length;
uint64_t addr;
uint64_t segl_addr;
uint64_t segl_length;
} __packed;
struct bce_queue_memcfg {
uint16_t qid;
uint16_t el_count;
uint16_t vector_or_cq;
uint16_t _pad;
uint64_t addr;
uint64_t length;
} __packed;
struct bce_sq_completion_data {
uint32_t status;
uint64_t data_size;
uint64_t result;
};
struct bce_queue_sq;
typedef void (*bce_sq_completion_fn)(struct bce_queue_sq *sq);
struct bce_queue_cq {
int qid;
uint32_t el_count;
bus_dma_tag_t dma_tag;
bus_dmamap_t dma_map;
bus_addr_t dma_addr;
struct bce_qe_completion *data;
uint32_t index;
};
struct bce_queue_sq {
int qid;
uint32_t el_size;
uint32_t el_count;
bus_dma_tag_t dma_tag;
bus_dmamap_t dma_map;
bus_addr_t dma_addr;
void *data;
void *userdata;
volatile int available_commands;
uint32_t head;
uint32_t tail;
uint32_t completion_cidx;
uint32_t completion_tail;
struct bce_sq_completion_data *completion_data;
int has_pending;
bce_sq_completion_fn completion;
};
struct bce_queue_cmdq_result {
struct sema cmpl;
uint32_t status;
uint64_t result;
};
struct bce_queue_cmdq {
struct bce_queue_sq *sq;
struct mtx lck;
struct bce_queue_cmdq_result **tres;
};
enum bce_cmdq_cmd {
BCE_CMD_REGISTER_QUEUE = 0x20,
BCE_CMD_UNREGISTER_QUEUE = 0x30,
BCE_CMD_FLUSH_QUEUE = 0x40,
BCE_CMD_SET_QUEUE_PROPERTY = 0x50,
};
struct bce_cmdq_reg_cmd {
uint16_t cmd;
uint16_t flags;
#define BCE_CMDQ_FLAG_NAMED 0x02
#define BCE_CMDQ_FLAG_OUT 0x01
uint16_t qid;
uint16_t _pad;
uint16_t el_count;
uint16_t vector_or_cq;
uint16_t _pad2;
uint16_t name_len;
char name[0x20];
uint64_t addr;
uint64_t length;
} __packed;
struct bce_cmdq_simple_cmd {
uint16_t cmd;
uint16_t flags;
uint16_t qid;
} __packed;
struct bce_mailbox {
struct resource *reg;
volatile int status;
int initialized;
struct sema mb_cmpl;
uint64_t mb_result;
};
struct apple_bce_softc {
device_t sc_dev;
int sc_bar2_rid;
struct resource *sc_bar2;
int sc_bar4_rid;
struct resource *sc_bar4;
int sc_msi_count;
int sc_irq_rid_mbox;
struct resource *sc_irq_mbox;
void *sc_irq_mbox_cookie;
int sc_irq_rid_dma;
struct resource *sc_irq_dma;
void *sc_irq_dma_cookie;
bus_dma_tag_t sc_dma_tag;
struct bce_mailbox sc_mbox;
struct callout sc_timestamp_co;
struct mtx sc_timestamp_lock;
int sc_timestamp_stopped;
struct bce_queue_cq *sc_cmd_cq;
struct bce_queue_cmdq *sc_cmd_cmdq;
void *sc_queues[BCE_MAX_QUEUE_COUNT];
struct mtx sc_queues_lock;
struct bce_queue_cq *sc_cq_list[BCE_MAX_CQ_COUNT];
struct bce_queue_sq *sc_int_sq_list[BCE_MAX_QUEUE_COUNT];
device_t sc_vhci_dev;
};
static __inline void *
bce_sq_element(struct bce_queue_sq *sq, uint32_t idx)
{
return ((char *)sq->data + (idx * sq->el_size));
}
static __inline struct bce_qe_completion *
bce_cq_element(struct bce_queue_cq *cq, uint32_t idx)
{
return (&cq->data[idx]);
}
#endif