#ifndef _HPTIOP_H
#define _HPTIOP_H
#include <sys/cdefs.h>
#define DBG 0
#ifdef DBG
int hpt_iop_dbg_level = 0;
#define KdPrint(x) do { if (hpt_iop_dbg_level) printf x; } while (0)
#define HPT_ASSERT(x) assert(x)
#else
#define KdPrint(x)
#define HPT_ASSERT(x)
#endif
#define HPT_SRB_MAX_REQ_SIZE 600
#define HPT_SRB_MAX_QUEUE_SIZE 0x100
#define HPT_SRB_FLAG_HIGH_MEM_ACESS 0x1
#define HPT_SRB_MAX_SIZE ((sizeof(struct hpt_iop_srb) + 0x1f) & ~0x1f)
#ifndef offsetof
#define offsetof(TYPE, MEM) ((size_t)&((TYPE*)0)->MEM)
#endif
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
#define HPT_IOCTL_MAGIC 0xA1B2C3D4
#define HPT_IOCTL_MAGIC32 0x1A2B3C4D
struct hpt_iopmu_itl {
u_int32_t resrved0[4];
u_int32_t inbound_msgaddr0;
u_int32_t inbound_msgaddr1;
u_int32_t outbound_msgaddr0;
u_int32_t outbound_msgaddr1;
u_int32_t inbound_doorbell;
u_int32_t inbound_intstatus;
u_int32_t inbound_intmask;
u_int32_t outbound_doorbell;
u_int32_t outbound_intstatus;
u_int32_t outbound_intmask;
u_int32_t reserved1[2];
u_int32_t inbound_queue;
u_int32_t outbound_queue;
};
#define IOPMU_QUEUE_EMPTY 0xffffffff
#define IOPMU_QUEUE_MASK_HOST_BITS 0xf0000000
#define IOPMU_QUEUE_ADDR_HOST_BIT 0x80000000
#define IOPMU_QUEUE_REQUEST_SIZE_BIT 0x40000000
#define IOPMU_QUEUE_REQUEST_RESULT_BIT 0x40000000
#define IOPMU_MAX_MEM_SUPPORT_MASK_64G 0xfffffff000000000ull
#define IOPMU_MAX_MEM_SUPPORT_MASK_32G 0xfffffff800000000ull
#define IOPMU_OUTBOUND_INT_MSG0 1
#define IOPMU_OUTBOUND_INT_MSG1 2
#define IOPMU_OUTBOUND_INT_DOORBELL 4
#define IOPMU_OUTBOUND_INT_POSTQUEUE 8
#define IOPMU_OUTBOUND_INT_PCI 0x10
#define IOPMU_INBOUND_INT_MSG0 1
#define IOPMU_INBOUND_INT_MSG1 2
#define IOPMU_INBOUND_INT_DOORBELL 4
#define IOPMU_INBOUND_INT_ERROR 8
#define IOPMU_INBOUND_INT_POSTQUEUE 0x10
#define MVIOP_QUEUE_LEN 512
struct hpt_iopmu_mv {
u_int32_t inbound_head;
u_int32_t inbound_tail;
u_int32_t outbound_head;
u_int32_t outbound_tail;
u_int32_t inbound_msg;
u_int32_t outbound_msg;
u_int32_t reserve[10];
u_int64_t inbound_q[MVIOP_QUEUE_LEN];
u_int64_t outbound_q[MVIOP_QUEUE_LEN];
};
struct hpt_iopmv_regs {
u_int32_t reserved[0x20400 / 4];
u_int32_t inbound_doorbell;
u_int32_t inbound_intmask;
u_int32_t outbound_doorbell;
u_int32_t outbound_intmask;
};
#define CL_POINTER_TOGGLE 0x00004000
#define CPU_TO_F0_DRBL_MSG_A_BIT 0x02000000
#pragma pack(1)
struct hpt_iopmu_mvfrey {
u_int32_t reserved[0x4000 / 4];
u_int32_t inbound_base;
u_int32_t inbound_base_high;
u_int32_t reserved2[(0x18 - 8)/ 4];
u_int32_t inbound_write_ptr;
u_int32_t inbound_read_ptr;
u_int32_t reserved3[(0x2c - 0x20) / 4];
u_int32_t inbound_conf_ctl;
u_int32_t reserved4[(0x50 - 0x30) / 4];
u_int32_t outbound_base;
u_int32_t outbound_base_high;
u_int32_t outbound_shadow_base;
u_int32_t outbound_shadow_base_high;
u_int32_t reserved5[(0x68 - 0x60) / 4];
u_int32_t outbound_write;
u_int32_t reserved6[(0x70 - 0x6c) / 4];
u_int32_t outbound_read;
u_int32_t reserved7[(0x88 - 0x74) / 4];
u_int32_t isr_cause;
u_int32_t isr_enable;
u_int32_t reserved8[(0x10200 - 0x4090) / 4];
u_int32_t main_int_cuase;
u_int32_t main_irq_enable;
u_int32_t main_fiq_enable;
u_int32_t pcie_f0_int_enable;
u_int32_t pcie_f1_int_enable;
u_int32_t pcie_f2_int_enable;
u_int32_t pcie_f3_int_enable;
u_int32_t reserved9[(0x10400 - 0x1021c) / 4];
u_int32_t f0_to_cpu_msg_a;
u_int32_t reserved10[(0x20 - 4) / 4];
u_int32_t cpu_to_f0_msg_a;
u_int32_t reserved11[(0x80 - 0x24) / 4];
u_int32_t f0_doorbell;
u_int32_t f0_doorbell_enable;
};
struct mvfrey_inlist_entry {
u_int64_t addr;
u_int32_t intrfc_len;
u_int32_t reserved;
};
struct mvfrey_outlist_entry {
u_int32_t val;
};
#pragma pack()
#define MVIOP_IOCTLCFG_SIZE 0x800
#define MVIOP_MU_QUEUE_ADDR_HOST_MASK (~(0x1full))
#define MVIOP_MU_QUEUE_ADDR_HOST_BIT 4
#define MVIOP_MU_QUEUE_ADDR_IOP_HIGH32 0xffffffff
#define MVIOP_MU_QUEUE_REQUEST_RESULT_BIT 1
#define MVIOP_MU_QUEUE_REQUEST_RETURN_CONTEXT 2
#define MVIOP_MU_INBOUND_INT_MSG 1
#define MVIOP_MU_INBOUND_INT_POSTQUEUE 2
#define MVIOP_MU_OUTBOUND_INT_MSG 1
#define MVIOP_MU_OUTBOUND_INT_POSTQUEUE 2
#define MVIOP_CMD_TYPE_GET_CONFIG (1 << 5)
#define MVIOP_CMD_TYPE_SET_CONFIG (1 << 6)
#define MVIOP_CMD_TYPE_SCSI (1 << 7)
#define MVIOP_CMD_TYPE_IOCTL (1 << 8)
#define MVIOP_CMD_TYPE_BLOCK (1 << 9)
#define MVIOP_REQUEST_NUMBER_START_BIT 16
#define MVFREYIOPMU_QUEUE_REQUEST_RESULT_BIT 0x40000000
enum hpt_iopmu_message {
IOPMU_INBOUND_MSG0_NOP = 0,
IOPMU_INBOUND_MSG0_RESET,
IOPMU_INBOUND_MSG0_FLUSH,
IOPMU_INBOUND_MSG0_SHUTDOWN,
IOPMU_INBOUND_MSG0_STOP_BACKGROUND_TASK,
IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK,
IOPMU_INBOUND_MSG0_RESET_COMM,
IOPMU_INBOUND_MSG0_MAX = 0xff,
IOPMU_OUTBOUND_MSG0_REGISTER_DEVICE_0 = 0x100,
IOPMU_OUTBOUND_MSG0_REGISTER_DEVICE_MAX = 0x1ff,
IOPMU_OUTBOUND_MSG0_UNREGISTER_DEVICE_0 = 0x200,
IOPMU_OUTBOUND_MSG0_UNREGISTER_DEVICE_MAX = 0x2ff,
IOPMU_OUTBOUND_MSG0_REVALIDATE_DEVICE_0 = 0x300,
IOPMU_OUTBOUND_MSG0_REVALIDATE_DEVICE_MAX = 0x3ff,
};
#define IOP_REQUEST_FLAG_SYNC_REQUEST 1
#define IOP_REQUEST_FLAG_BIST_REQUEST 2
#define IOP_REQUEST_FLAG_REMAPPED 4
#define IOP_REQUEST_FLAG_OUTPUT_CONTEXT 8
#define IOP_REQUEST_FLAG_ADDR_BITS 0x40
enum hpt_iop_request_type {
IOP_REQUEST_TYPE_GET_CONFIG = 0,
IOP_REQUEST_TYPE_SET_CONFIG,
IOP_REQUEST_TYPE_BLOCK_COMMAND,
IOP_REQUEST_TYPE_SCSI_COMMAND,
IOP_REQUEST_TYPE_IOCTL_COMMAND,
IOP_REQUEST_TYPE_MAX
};
enum hpt_iop_result_type {
IOP_RESULT_PENDING = 0,
IOP_RESULT_SUCCESS,
IOP_RESULT_FAIL,
IOP_RESULT_BUSY,
IOP_RESULT_RESET,
IOP_RESULT_INVALID_REQUEST,
IOP_RESULT_BAD_TARGET,
IOP_RESULT_CHECK_CONDITION,
};
#pragma pack(1)
struct hpt_iop_request_header {
u_int32_t size;
u_int32_t type;
u_int32_t flags;
u_int32_t result;
u_int64_t context;
};
struct hpt_iop_request_get_config {
struct hpt_iop_request_header header;
u_int32_t interface_version;
u_int32_t firmware_version;
u_int32_t max_requests;
u_int32_t request_size;
u_int32_t max_sg_count;
u_int32_t data_transfer_length;
u_int32_t alignment_mask;
u_int32_t max_devices;
u_int32_t sdram_size;
};
struct hpt_iop_request_set_config {
struct hpt_iop_request_header header;
u_int32_t iop_id;
u_int16_t vbus_id;
u_int16_t max_host_request_size;
u_int32_t reserve[6];
};
struct hpt_iopsg {
u_int32_t size;
u_int32_t eot;
u_int64_t pci_address;
};
#define IOP_BLOCK_COMMAND_READ 1
#define IOP_BLOCK_COMMAND_WRITE 2
#define IOP_BLOCK_COMMAND_VERIFY 3
#define IOP_BLOCK_COMMAND_FLUSH 4
#define IOP_BLOCK_COMMAND_SHUTDOWN 5
struct hpt_iop_request_block_command {
struct hpt_iop_request_header header;
u_int8_t channel;
u_int8_t target;
u_int8_t lun;
u_int8_t pad1;
u_int16_t command;
u_int16_t sectors;
u_int64_t lba;
struct hpt_iopsg sg_list[1];
};
struct hpt_iop_request_scsi_command {
struct hpt_iop_request_header header;
u_int8_t channel;
u_int8_t target;
u_int8_t lun;
u_int8_t pad1;
u_int8_t cdb[16];
u_int32_t dataxfer_length;
struct hpt_iopsg sg_list[1];
};
struct hpt_iop_request_ioctl_command {
struct hpt_iop_request_header header;
u_int32_t ioctl_code;
u_int32_t inbuf_size;
u_int32_t outbuf_size;
u_int32_t bytes_returned;
u_int8_t buf[1];
};
struct hpt_iop_ioctl_param {
u_int32_t Magic;
u_int32_t dwIoControlCode;
unsigned long lpInBuffer;
u_int32_t nInBufferSize;
unsigned long lpOutBuffer;
u_int32_t nOutBufferSize;
unsigned long lpBytesReturned;
} __packed;
#define HPT_IOCTL_FLAG_OPEN 1
#define HPT_CTL_CODE_BSD_TO_IOP(x) ((x)-0xff00)
typedef struct cdev * ioctl_dev_t;
typedef struct thread * ioctl_thread_t;
struct hpt_iop_hba {
struct hptiop_adapter_ops *ops;
union {
struct {
struct hpt_iopmu_itl *mu;
} itl;
struct {
struct hpt_iopmv_regs *regs;
struct hpt_iopmu_mv *mu;
} mv;
struct {
struct hpt_iop_request_get_config *config;
struct hpt_iopmu_mvfrey *mu;
int internal_mem_size;
int list_count;
struct mvfrey_inlist_entry *inlist;
u_int64_t inlist_phy;
u_int32_t inlist_wptr;
struct mvfrey_outlist_entry *outlist;
u_int64_t outlist_phy;
u_int32_t *outlist_cptr;
u_int64_t outlist_cptr_phy;
u_int32_t outlist_rptr;
} mvfrey;
} u;
struct hpt_iop_hba *next;
u_int32_t firmware_version;
u_int32_t interface_version;
u_int32_t max_devices;
u_int32_t max_requests;
u_int32_t max_request_size;
u_int32_t max_sg_count;
u_int32_t msg_done;
device_t pcidev;
u_int32_t pciunit;
ioctl_dev_t ioctl_dev;
bus_dma_tag_t parent_dmat;
bus_dma_tag_t io_dmat;
bus_dma_tag_t srb_dmat;
bus_dma_tag_t ctlcfg_dmat;
bus_dmamap_t srb_dmamap;
bus_dmamap_t ctlcfg_dmamap;
struct resource *bar0_res;
bus_space_tag_t bar0t;
bus_space_handle_t bar0h;
int bar0_rid;
struct resource *bar2_res;
bus_space_tag_t bar2t;
bus_space_handle_t bar2h;
int bar2_rid;
u_int8_t *uncached_ptr;
void *ctlcfg_ptr;
struct hpt_iop_srb *srb_list;
struct resource *irq_res;
void *irq_handle;
struct resource *ctlcfg_res;
void *ctlcfg_handle;
u_int64_t ctlcfgcmd_phy;
u_int32_t config_done;
u_int32_t initialized:1;
struct cam_sim *sim;
struct cam_path *path;
void *req;
struct mtx lock;
#define HPT_IOCTL_FLAG_OPEN 1
u_int32_t flag;
struct hpt_iop_srb* srb[HPT_SRB_MAX_QUEUE_SIZE];
};
#pragma pack()
enum hptiop_family {
INTEL_BASED_IOP = 0,
MV_BASED_IOP,
MVFREY_BASED_IOP,
UNKNOWN_BASED_IOP = 0xf
};
struct hptiop_adapter_ops {
enum hptiop_family family;
int (*iop_wait_ready)(struct hpt_iop_hba *hba, u_int32_t millisec);
int (*internal_memalloc)(struct hpt_iop_hba *hba);
int (*internal_memfree)(struct hpt_iop_hba *hba);
int (*alloc_pci_res)(struct hpt_iop_hba *hba);
void (*release_pci_res)(struct hpt_iop_hba *hba);
void (*enable_intr)(struct hpt_iop_hba *hba);
void (*disable_intr)(struct hpt_iop_hba *hba);
int (*get_config)(struct hpt_iop_hba *hba,
struct hpt_iop_request_get_config *config);
int (*set_config)(struct hpt_iop_hba *hba,
struct hpt_iop_request_set_config *config);
int (*iop_intr)(struct hpt_iop_hba *hba);
void (*post_msg)(struct hpt_iop_hba *hba, u_int32_t msg);
void (*post_req)(struct hpt_iop_hba *hba, struct hpt_iop_srb *srb, bus_dma_segment_t *segs, int nsegs);
int (*do_ioctl)(struct hpt_iop_hba *hba, struct hpt_iop_ioctl_param * pParams);
int (*reset_comm)(struct hpt_iop_hba *hba);
};
struct hpt_iop_srb {
u_int8_t req[HPT_SRB_MAX_REQ_SIZE];
struct hpt_iop_hba *hba;
union ccb *ccb;
struct hpt_iop_srb *next;
bus_dmamap_t dma_map;
u_int64_t phy_addr;
u_int32_t srb_flag;
int index;
struct callout timeout;
};
#define hptiop_lock_adapter(hba) mtx_lock(&(hba)->lock)
#define hptiop_unlock_adapter(hba) mtx_unlock(&(hba)->lock)
#define HPT_OSM_TIMEOUT (20*hz)
#define HPT_DO_IOCONTROL _IOW('H', 0, struct hpt_iop_ioctl_param)
#define HPT_SCAN_BUS _IO('H', 1)
static __inline int hptiop_sleep(struct hpt_iop_hba *hba, void *ident,
int priority, const char *wmesg, int timo)
{
int retval;
retval = msleep(ident, &hba->lock, priority, wmesg, timo);
return retval;
}
#define HPT_DEV_MAJOR 200
#endif