117169044Sbrutus /* 217169044Sbrutus * CDDL HEADER START 317169044Sbrutus * 417169044Sbrutus * The contents of this file are subject to the terms of the 517169044Sbrutus * Common Development and Distribution License (the "License"). 617169044Sbrutus * You may not use this file except in compliance with the License. 717169044Sbrutus * 817169044Sbrutus * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 917169044Sbrutus * or http://www.opensolaris.org/os/licensing. 1017169044Sbrutus * See the License for the specific language governing permissions 1117169044Sbrutus * and limitations under the License. 1217169044Sbrutus * 1317169044Sbrutus * When distributing Covered Code, include this CDDL HEADER in each 1417169044Sbrutus * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1517169044Sbrutus * If applicable, add the following below this CDDL HEADER, with the 1617169044Sbrutus * fields enclosed by brackets "[]" replaced with your own identifying 1717169044Sbrutus * information: Portions Copyright [yyyy] [name of copyright owner] 1817169044Sbrutus * 1917169044Sbrutus * CDDL HEADER END 2017169044Sbrutus */ 2117169044Sbrutus 2217169044Sbrutus /* 23*eca2601cSRandy Fishel * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 2417169044Sbrutus * Use is subject to license terms. 2517169044Sbrutus */ 2617169044Sbrutus 2717169044Sbrutus #ifndef _SYS_IOAT_H 2817169044Sbrutus #define _SYS_IOAT_H 2917169044Sbrutus 3017169044Sbrutus #ifdef __cplusplus 3117169044Sbrutus extern "C" { 3217169044Sbrutus #endif 3317169044Sbrutus 3417169044Sbrutus #include <sys/types.h> 3517169044Sbrutus #include <sys/dcopy.h> 3617169044Sbrutus #include <sys/dcopy_device.h> 3717169044Sbrutus 3817169044Sbrutus 3917169044Sbrutus /* ioat ioctls */ 4017169044Sbrutus #define IOATIOC ('T'<< 8) 4117169044Sbrutus typedef enum { 4217169044Sbrutus IOAT_IOCTL_WRITE_REG = (IOATIOC | 0x0), 4317169044Sbrutus IOAT_IOCTL_READ_REG = (IOATIOC | 0x1), 4417169044Sbrutus IOAT_IOCTL_TEST = (IOATIOC | 0x2) 4517169044Sbrutus } ioat_ioctl_enum_t; 4617169044Sbrutus 4717169044Sbrutus typedef struct ioat_ioctl_reg_s { 4817169044Sbrutus uint_t size; 4917169044Sbrutus uint_t addr; 5017169044Sbrutus uint64_t data; 5117169044Sbrutus } ioat_ioctl_reg_t; 5217169044Sbrutus typedef ioat_ioctl_reg_t ioat_ioctl_wrreg_t; 5317169044Sbrutus typedef ioat_ioctl_reg_t ioat_ioctl_rdreg_t; 5417169044Sbrutus 5517169044Sbrutus #ifdef _KERNEL 5617169044Sbrutus /* *** Driver Private Below *** */ 5717169044Sbrutus 5817169044Sbrutus /* IOAT_DMACAPABILITY flags */ 5917169044Sbrutus #define IOAT_DMACAP_PAGEBREAK 0x1 6017169044Sbrutus #define IOAT_DMACAP_CRC 0x2 6117169044Sbrutus #define IOAT_DMACAP_MARKERSKIP 0x4 6217169044Sbrutus #define IOAT_DMACAP_XOR 0x8 6317169044Sbrutus #define IOAT_DMACAP_DCA 0x10 6417169044Sbrutus 6517169044Sbrutus /* IOAT_INTRCTL bits */ 6617169044Sbrutus #define IOAT_INTRCTL_MASTER_EN 0x1 6717169044Sbrutus #define IOAT_INTRCTL_INTR_STAT 0x2 6817169044Sbrutus 6917169044Sbrutus /* MMIO Registers */ 7017169044Sbrutus #define IOAT_CHANCNT 0x0 /* 8-bit */ 7117169044Sbrutus #define IOAT_XFERCAP 0x1 /* 8-bit */ 7217169044Sbrutus #define IOAT_GENCTRL 0x2 /* 8-bit */ 7317169044Sbrutus #define IOAT_INTRCTL 0x3 /* 8-bit */ 7417169044Sbrutus #define IOAT_ATTNSTATUS 0x4 /* 32-bit */ 7517169044Sbrutus #define IOAT_CBVER 0x8 /* 8-bit */ 7617169044Sbrutus #define IOAT_PERPORT_OFF 0xA /* 16-bit */ 7717169044Sbrutus #define IOAT_INTRDELAY 0xC /* 16-bit */ 7817169044Sbrutus #define IOAT_CSSTATUS 0xE /* 16-bit */ 7917169044Sbrutus #define IOAT_DMACAPABILITY 0x10 /* 32-bit */ 8017169044Sbrutus 8117169044Sbrutus #define IOAT_CHANNELREG_OFFSET 0x80 8217169044Sbrutus 8317169044Sbrutus /* Channel Registers */ 8417169044Sbrutus #define IOAT_CHAN_CTL 0x0 /* 16-bit */ 8517169044Sbrutus #define IOAT_CHAN_COMP 0x2 /* 16-bit */ 8617169044Sbrutus #define IOAT_CHAN_CMPL_LO 0x18 /* 32-bit */ 8717169044Sbrutus #define IOAT_CHAN_CMPL_HI 0x1C /* 32-bit */ 8817169044Sbrutus #define IOAT_CHAN_ERR 0x28 /* 32-bit */ 8917169044Sbrutus #define IOAT_CHAN_ERRMASK 0x2C /* 32-bit */ 9017169044Sbrutus #define IOAT_CHAN_DCACTRL 0x30 /* 32-bit */ 9117169044Sbrutus 9217169044Sbrutus #define IOAT_V1_CHAN_STS_LO 0x4 /* 32-bit */ 9317169044Sbrutus #define IOAT_V1_CHAN_STS_HI 0x8 /* 32-bit */ 9417169044Sbrutus #define IOAT_V1_CHAN_ADDR_LO 0x0C /* 32-bit */ 9517169044Sbrutus #define IOAT_V1_CHAN_ADDR_HI 0x10 /* 32-bit */ 9617169044Sbrutus #define IOAT_V1_CHAN_CMD 0x14 /* 8-bit */ 9717169044Sbrutus 9817169044Sbrutus #define IOAT_V2_CHAN_CMD 0x4 /* 8-bit */ 9917169044Sbrutus #define IOAT_V2_CHAN_CNT 0x6 /* 16-bit */ 10017169044Sbrutus #define IOAT_V2_CHAN_STS_LO 0x8 /* 32-bit */ 10117169044Sbrutus #define IOAT_V2_CHAN_STS_HI 0xC /* 32-bit */ 10217169044Sbrutus #define IOAT_V2_CHAN_ADDR_LO 0x10 /* 32-bit */ 10317169044Sbrutus #define IOAT_V2_CHAN_ADDR_HI 0x14 /* 32-bit */ 10417169044Sbrutus 10517169044Sbrutus #define IOAT_CHAN_STS_ADDR_MASK 0xFFFFFFFFFFFFFFC0 10617169044Sbrutus #define IOAT_CHAN_STS_XFER_MASK 0x3F 10717169044Sbrutus #define IOAT_CHAN_STS_FAIL_MASK 0x6 10817169044Sbrutus #define IOAT_CMPL_INDEX(channel) \ 10917169044Sbrutus (((*channel->ic_cmpl & IOAT_CHAN_STS_ADDR_MASK) - \ 11017169044Sbrutus ring->cr_phys_desc) >> 6) 11117169044Sbrutus #define IOAT_CMPL_FAILED(channel) \ 11217169044Sbrutus (*channel->ic_cmpl & IOAT_CHAN_STS_FAIL_MASK) 11317169044Sbrutus 11417169044Sbrutus 11517169044Sbrutus typedef struct ioat_chan_desc_s { 11617169044Sbrutus uint32_t dd_res0; 11717169044Sbrutus uint32_t dd_ctrl; 11817169044Sbrutus uint64_t dd_res1; 11917169044Sbrutus uint64_t dd_res2; 12017169044Sbrutus uint64_t dd_next_desc; 12117169044Sbrutus uint64_t dd_res4; 12217169044Sbrutus uint64_t dd_res5; 12317169044Sbrutus uint64_t dd_res6; 12417169044Sbrutus uint64_t dd_res7; 12517169044Sbrutus } ioat_chan_desc_t; 12617169044Sbrutus 12717169044Sbrutus /* dca dd_ctrl bits */ 12817169044Sbrutus #define IOAT_DESC_CTRL_OP_CNTX ((uint32_t)0xFF << 24) 12917169044Sbrutus #define IOAT_DESC_CTRL_CNTX_CHNG 0x1 13017169044Sbrutus typedef struct ioat_chan_dca_desc_s { 13117169044Sbrutus uint32_t dd_cntx; 13217169044Sbrutus uint32_t dd_ctrl; 13317169044Sbrutus uint64_t dd_res1; 13417169044Sbrutus uint64_t dd_res2; 13517169044Sbrutus uint64_t dd_next_desc; 13617169044Sbrutus uint64_t dd_res4; 13717169044Sbrutus uint64_t dd_res5; 13817169044Sbrutus uint64_t dd_res6; 13917169044Sbrutus uint64_t dd_res7; 14017169044Sbrutus } ioat_chan_dca_desc_t; 14117169044Sbrutus 14217169044Sbrutus /* dma dd_ctrl bits */ 14317169044Sbrutus #define IOAT_DESC_CTRL_OP_DMA (0x0 << 24) 14417169044Sbrutus #define IOAT_DESC_DMACTRL_NULL 0x20 14517169044Sbrutus #define IOAT_DESC_CTRL_FENCE 0x10 14617169044Sbrutus #define IOAT_DESC_CTRL_CMPL 0x8 147*eca2601cSRandy Fishel #define IOAT_DESC_CTRL_NODSTSNP 0x4 148*eca2601cSRandy Fishel #define IOAT_DESC_CTRL_NOSRCSNP 0x2 14917169044Sbrutus #define IOAT_DESC_CTRL_INTR 0x1 15017169044Sbrutus typedef struct ioat_chan_dma_desc_s { 15117169044Sbrutus uint32_t dd_size; 15217169044Sbrutus uint32_t dd_ctrl; 15317169044Sbrutus uint64_t dd_src_paddr; 15417169044Sbrutus uint64_t dd_dest_paddr; 15517169044Sbrutus uint64_t dd_next_desc; 15617169044Sbrutus uint64_t dd_next_src_paddr; /* v2 only */ 15717169044Sbrutus uint64_t dd_next_dest_paddr; /* v2 only */ 15817169044Sbrutus uint64_t dd_res6; 15917169044Sbrutus uint64_t dd_res7; 16017169044Sbrutus } ioat_chan_dma_desc_t; 16117169044Sbrutus 16217169044Sbrutus 16317169044Sbrutus typedef enum { 16417169044Sbrutus IOAT_CBv1, 16517169044Sbrutus IOAT_CBv2 16617169044Sbrutus } ioat_version_t; 16717169044Sbrutus 16817169044Sbrutus /* ioat private data per command */ 16917169044Sbrutus typedef struct ioat_cmd_private_s { 17017169044Sbrutus uint64_t ip_generation; 17117169044Sbrutus uint64_t ip_index; 172*eca2601cSRandy Fishel uint64_t ip_start; 17317169044Sbrutus dcopy_cmd_t ip_next; 17417169044Sbrutus } ioat_cmd_private_t; 17517169044Sbrutus 17617169044Sbrutus /* descriptor ring state */ 17717169044Sbrutus typedef struct ioat_channel_ring_s { 17817169044Sbrutus /* protects cr_cmpl_gen & cr_cmpl_last */ 17917169044Sbrutus kmutex_t cr_cmpl_mutex; 18017169044Sbrutus 18117169044Sbrutus /* desc ring generation for the last completion we saw */ 18217169044Sbrutus uint64_t cr_cmpl_gen; 18317169044Sbrutus 18417169044Sbrutus /* last descriptor index we saw complete */ 18517169044Sbrutus uint64_t cr_cmpl_last; 18617169044Sbrutus 18717169044Sbrutus /* protects cr_desc_* */ 18817169044Sbrutus kmutex_t cr_desc_mutex; 18917169044Sbrutus 19017169044Sbrutus /* 19117169044Sbrutus * last descriptor posted. used to update its next pointer when we 19217169044Sbrutus * add a new desc. Also used to tack the completion (See comment for 19317169044Sbrutus * cr_desc_gen_prev). 19417169044Sbrutus */ 19517169044Sbrutus uint64_t cr_desc_prev; 19617169044Sbrutus 19717169044Sbrutus /* where to put the next descriptor */ 19817169044Sbrutus uint64_t cr_desc_next; 19917169044Sbrutus 20017169044Sbrutus /* what the current desc ring generation is */ 20117169044Sbrutus uint64_t cr_desc_gen; 20217169044Sbrutus 20317169044Sbrutus /* 20417169044Sbrutus * used during cmd_post to track the last desc posted. cr_desc_next 20517169044Sbrutus * and cr_desc_gen will be pointing to the next free desc after 20617169044Sbrutus * writing the descriptor to the ring. But we want to track the 20717169044Sbrutus * completion for the last descriptor posted. 20817169044Sbrutus */ 20917169044Sbrutus uint64_t cr_desc_gen_prev; 21017169044Sbrutus 21117169044Sbrutus /* the last desc in the ring (for wrap) */ 21217169044Sbrutus uint64_t cr_desc_last; 21317169044Sbrutus 21417169044Sbrutus /* pointer to the head of the ring */ 21517169044Sbrutus ioat_chan_desc_t *cr_desc; 21617169044Sbrutus 21717169044Sbrutus /* physical address of the head of the ring */ 21817169044Sbrutus uint64_t cr_phys_desc; 21917169044Sbrutus 22017169044Sbrutus /* back pointer to the channel state */ 22117169044Sbrutus struct ioat_channel_s *cr_chan; 22217169044Sbrutus 22317169044Sbrutus /* for CB v2, number of desc posted (written to IOAT_V2_CHAN_CNT) */ 22417169044Sbrutus uint_t cr_post_cnt; 22517169044Sbrutus } ioat_channel_ring_t; 22617169044Sbrutus 22717169044Sbrutus /* track channel state so we can handle a failure */ 22817169044Sbrutus typedef enum { 22917169044Sbrutus IOAT_CHANNEL_OK = 0, 23017169044Sbrutus IOAT_CHANNEL_IN_FAILURE = 1 23117169044Sbrutus } ic_channel_state_t; 23217169044Sbrutus 23317169044Sbrutus typedef struct ioat_channel_s *ioat_channel_t; 23417169044Sbrutus struct ioat_channel_s { 23517169044Sbrutus /* channel's ring state */ 23617169044Sbrutus ioat_channel_ring_t *ic_ring; 23717169044Sbrutus 23817169044Sbrutus /* IOAT_CBv1 || IOAT_CBv2 */ 23917169044Sbrutus ioat_version_t ic_ver; 24017169044Sbrutus 24117169044Sbrutus /* 24217169044Sbrutus * state to determine if it's OK to post the the channel and if all 24317169044Sbrutus * future polls should return failure. 24417169044Sbrutus */ 24517169044Sbrutus ic_channel_state_t ic_channel_state; 24617169044Sbrutus 24717169044Sbrutus /* channel command cache (*_cmd_alloc, *_cmd_free, etc) */ 24817169044Sbrutus kmem_cache_t *ic_cmd_cache; 24917169044Sbrutus 25017169044Sbrutus /* dcopy state for dcopy_device_channel_notify() call */ 25117169044Sbrutus dcopy_handle_t ic_dcopy_handle; 25217169044Sbrutus 25317169044Sbrutus /* location in memory where completions are DMA'ed into */ 25417169044Sbrutus volatile uint64_t *ic_cmpl; 25517169044Sbrutus 25617169044Sbrutus /* channel specific registers */ 25717169044Sbrutus uint8_t *ic_regs; 25817169044Sbrutus 25917169044Sbrutus /* if this channel is using DCA */ 26017169044Sbrutus boolean_t ic_dca_active; 26117169044Sbrutus 26217169044Sbrutus /* DCA ID the channel is currently pointing to */ 26317169044Sbrutus uint32_t ic_dca_current; 26417169044Sbrutus 26517169044Sbrutus /* devices channel number */ 26617169044Sbrutus uint_t ic_chan_num; 26717169044Sbrutus 26817169044Sbrutus /* number of descriptors in ring */ 26917169044Sbrutus uint_t ic_chan_desc_cnt; 27017169044Sbrutus 27117169044Sbrutus /* descriptor ring alloc state */ 27217169044Sbrutus ddi_dma_handle_t ic_desc_dma_handle; 27317169044Sbrutus size_t ic_desc_alloc_size; 27417169044Sbrutus ddi_acc_handle_t ic_desc_handle; 27517169044Sbrutus ddi_dma_cookie_t ic_desc_cookies; 27617169044Sbrutus 27717169044Sbrutus /* completion buffer alloc state */ 27817169044Sbrutus ddi_dma_handle_t ic_cmpl_dma_handle; 27917169044Sbrutus size_t ic_cmpl_alloc_size; 28017169044Sbrutus ddi_acc_handle_t ic_cmpl_handle; 28117169044Sbrutus ddi_dma_cookie_t ic_cmpl_cookie; 28217169044Sbrutus uint64_t ic_phys_cmpl; 28317169044Sbrutus 28417169044Sbrutus /* if inuse, we need to re-init the channel during resume */ 28517169044Sbrutus boolean_t ic_inuse; 28617169044Sbrutus 28717169044Sbrutus /* backpointer to driver state */ 28817169044Sbrutus struct ioat_state_s *ic_state; 28917169044Sbrutus }; 29017169044Sbrutus 29117169044Sbrutus typedef struct ioat_rs_s *ioat_rs_hdl_t; 29217169044Sbrutus 29317169044Sbrutus /* driver state */ 29417169044Sbrutus typedef struct ioat_state_s { 29517169044Sbrutus dev_info_t *is_dip; 29617169044Sbrutus int is_instance; 29717169044Sbrutus 29817169044Sbrutus kmutex_t is_mutex; 29917169044Sbrutus 30017169044Sbrutus /* register handle and pointer to registers */ 30117169044Sbrutus ddi_acc_handle_t is_reg_handle; 30217169044Sbrutus uint8_t *is_genregs; 30317169044Sbrutus 30417169044Sbrutus /* IOAT_CBv1 || IOAT_CBv2 */ 30517169044Sbrutus ioat_version_t is_ver; 30617169044Sbrutus 30717169044Sbrutus /* channel state */ 30817169044Sbrutus ioat_channel_t is_channel; 30917169044Sbrutus size_t is_chansize; 31017169044Sbrutus ioat_rs_hdl_t is_channel_rs; 31117169044Sbrutus 31217169044Sbrutus ddi_iblock_cookie_t is_iblock_cookie; 31317169044Sbrutus 31417169044Sbrutus /* device info */ 31517169044Sbrutus uint_t is_chanoff; 31617169044Sbrutus uint_t is_num_channels; 31717169044Sbrutus uint_t is_maxxfer; 31817169044Sbrutus uint_t is_cbver; 31917169044Sbrutus uint_t is_intrdelay; 32017169044Sbrutus uint_t is_status; 32117169044Sbrutus uint_t is_capabilities; 32217169044Sbrutus 32317169044Sbrutus /* dcopy_device_register()/dcopy_device_unregister() state */ 32417169044Sbrutus dcopy_device_handle_t is_device_handle; 32517169044Sbrutus dcopy_device_info_t is_deviceinfo; 32617169044Sbrutus } ioat_state_t; 32717169044Sbrutus 32817169044Sbrutus 32917169044Sbrutus int ioat_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred, 33017169044Sbrutus int *rval); 33117169044Sbrutus 33217169044Sbrutus void ioat_rs_init(ioat_state_t *state, uint_t min_val, uint_t max_val, 33317169044Sbrutus ioat_rs_hdl_t *handle); 33417169044Sbrutus void ioat_rs_fini(ioat_rs_hdl_t *handle); 33517169044Sbrutus int ioat_rs_alloc(ioat_rs_hdl_t handle, uint_t *rs); 33617169044Sbrutus void ioat_rs_free(ioat_rs_hdl_t handle, uint_t rs); 33717169044Sbrutus 33817169044Sbrutus int ioat_channel_init(ioat_state_t *state); 33917169044Sbrutus void ioat_channel_fini(ioat_state_t *state); 34017169044Sbrutus void ioat_channel_suspend(ioat_state_t *state); 34117169044Sbrutus int ioat_channel_resume(ioat_state_t *state); 34219397407SSherry Moore void ioat_channel_quiesce(ioat_state_t *); 34317169044Sbrutus 34417169044Sbrutus int ioat_channel_alloc(void *device_private, dcopy_handle_t handle, int flags, 34517169044Sbrutus uint_t size, dcopy_query_channel_t *info, void *channel_private); 34617169044Sbrutus void ioat_channel_free(void *channel_private); 34717169044Sbrutus void ioat_channel_intr(ioat_channel_t channel); 34817169044Sbrutus int ioat_cmd_alloc(void *channel, int flags, dcopy_cmd_t *cmd); 34917169044Sbrutus void ioat_cmd_free(void *channel, dcopy_cmd_t *cmd); 35017169044Sbrutus int ioat_cmd_post(void *channel, dcopy_cmd_t cmd); 35117169044Sbrutus int ioat_cmd_poll(void *channel, dcopy_cmd_t cmd); 35217169044Sbrutus void ioat_unregister_complete(void *device_private, int status); 35317169044Sbrutus 35417169044Sbrutus 35517169044Sbrutus #endif /* _KERNEL */ 35617169044Sbrutus 35717169044Sbrutus #ifdef __cplusplus 35817169044Sbrutus } 35917169044Sbrutus #endif 36017169044Sbrutus 36117169044Sbrutus #endif /* _SYS_IOAT_H */ 362