1*17169044Sbrutus /* 2*17169044Sbrutus * CDDL HEADER START 3*17169044Sbrutus * 4*17169044Sbrutus * The contents of this file are subject to the terms of the 5*17169044Sbrutus * Common Development and Distribution License (the "License"). 6*17169044Sbrutus * You may not use this file except in compliance with the License. 7*17169044Sbrutus * 8*17169044Sbrutus * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*17169044Sbrutus * or http://www.opensolaris.org/os/licensing. 10*17169044Sbrutus * See the License for the specific language governing permissions 11*17169044Sbrutus * and limitations under the License. 12*17169044Sbrutus * 13*17169044Sbrutus * When distributing Covered Code, include this CDDL HEADER in each 14*17169044Sbrutus * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*17169044Sbrutus * If applicable, add the following below this CDDL HEADER, with the 16*17169044Sbrutus * fields enclosed by brackets "[]" replaced with your own identifying 17*17169044Sbrutus * information: Portions Copyright [yyyy] [name of copyright owner] 18*17169044Sbrutus * 19*17169044Sbrutus * CDDL HEADER END 20*17169044Sbrutus */ 21*17169044Sbrutus 22*17169044Sbrutus /* 23*17169044Sbrutus * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24*17169044Sbrutus * Use is subject to license terms. 25*17169044Sbrutus */ 26*17169044Sbrutus 27*17169044Sbrutus #ifndef _SYS_IOAT_H 28*17169044Sbrutus #define _SYS_IOAT_H 29*17169044Sbrutus 30*17169044Sbrutus #pragma ident "%Z%%M% %I% %E% SMI" 31*17169044Sbrutus 32*17169044Sbrutus #ifdef __cplusplus 33*17169044Sbrutus extern "C" { 34*17169044Sbrutus #endif 35*17169044Sbrutus 36*17169044Sbrutus #include <sys/types.h> 37*17169044Sbrutus #include <sys/dcopy.h> 38*17169044Sbrutus #include <sys/dcopy_device.h> 39*17169044Sbrutus 40*17169044Sbrutus 41*17169044Sbrutus /* ioat ioctls */ 42*17169044Sbrutus #define IOATIOC ('T'<< 8) 43*17169044Sbrutus typedef enum { 44*17169044Sbrutus IOAT_IOCTL_WRITE_REG = (IOATIOC | 0x0), 45*17169044Sbrutus IOAT_IOCTL_READ_REG = (IOATIOC | 0x1), 46*17169044Sbrutus IOAT_IOCTL_TEST = (IOATIOC | 0x2) 47*17169044Sbrutus } ioat_ioctl_enum_t; 48*17169044Sbrutus 49*17169044Sbrutus typedef struct ioat_ioctl_reg_s { 50*17169044Sbrutus uint_t size; 51*17169044Sbrutus uint_t addr; 52*17169044Sbrutus uint64_t data; 53*17169044Sbrutus } ioat_ioctl_reg_t; 54*17169044Sbrutus typedef ioat_ioctl_reg_t ioat_ioctl_wrreg_t; 55*17169044Sbrutus typedef ioat_ioctl_reg_t ioat_ioctl_rdreg_t; 56*17169044Sbrutus 57*17169044Sbrutus #ifdef _KERNEL 58*17169044Sbrutus /* *** Driver Private Below *** */ 59*17169044Sbrutus 60*17169044Sbrutus /* IOAT_DMACAPABILITY flags */ 61*17169044Sbrutus #define IOAT_DMACAP_PAGEBREAK 0x1 62*17169044Sbrutus #define IOAT_DMACAP_CRC 0x2 63*17169044Sbrutus #define IOAT_DMACAP_MARKERSKIP 0x4 64*17169044Sbrutus #define IOAT_DMACAP_XOR 0x8 65*17169044Sbrutus #define IOAT_DMACAP_DCA 0x10 66*17169044Sbrutus 67*17169044Sbrutus /* IOAT_INTRCTL bits */ 68*17169044Sbrutus #define IOAT_INTRCTL_MASTER_EN 0x1 69*17169044Sbrutus #define IOAT_INTRCTL_INTR_STAT 0x2 70*17169044Sbrutus 71*17169044Sbrutus /* MMIO Registers */ 72*17169044Sbrutus #define IOAT_CHANCNT 0x0 /* 8-bit */ 73*17169044Sbrutus #define IOAT_XFERCAP 0x1 /* 8-bit */ 74*17169044Sbrutus #define IOAT_GENCTRL 0x2 /* 8-bit */ 75*17169044Sbrutus #define IOAT_INTRCTL 0x3 /* 8-bit */ 76*17169044Sbrutus #define IOAT_ATTNSTATUS 0x4 /* 32-bit */ 77*17169044Sbrutus #define IOAT_CBVER 0x8 /* 8-bit */ 78*17169044Sbrutus #define IOAT_PERPORT_OFF 0xA /* 16-bit */ 79*17169044Sbrutus #define IOAT_INTRDELAY 0xC /* 16-bit */ 80*17169044Sbrutus #define IOAT_CSSTATUS 0xE /* 16-bit */ 81*17169044Sbrutus #define IOAT_DMACAPABILITY 0x10 /* 32-bit */ 82*17169044Sbrutus 83*17169044Sbrutus #define IOAT_CHANNELREG_OFFSET 0x80 84*17169044Sbrutus 85*17169044Sbrutus /* Channel Registers */ 86*17169044Sbrutus #define IOAT_CHAN_CTL 0x0 /* 16-bit */ 87*17169044Sbrutus #define IOAT_CHAN_COMP 0x2 /* 16-bit */ 88*17169044Sbrutus #define IOAT_CHAN_CMPL_LO 0x18 /* 32-bit */ 89*17169044Sbrutus #define IOAT_CHAN_CMPL_HI 0x1C /* 32-bit */ 90*17169044Sbrutus #define IOAT_CHAN_ERR 0x28 /* 32-bit */ 91*17169044Sbrutus #define IOAT_CHAN_ERRMASK 0x2C /* 32-bit */ 92*17169044Sbrutus #define IOAT_CHAN_DCACTRL 0x30 /* 32-bit */ 93*17169044Sbrutus 94*17169044Sbrutus #define IOAT_V1_CHAN_STS_LO 0x4 /* 32-bit */ 95*17169044Sbrutus #define IOAT_V1_CHAN_STS_HI 0x8 /* 32-bit */ 96*17169044Sbrutus #define IOAT_V1_CHAN_ADDR_LO 0x0C /* 32-bit */ 97*17169044Sbrutus #define IOAT_V1_CHAN_ADDR_HI 0x10 /* 32-bit */ 98*17169044Sbrutus #define IOAT_V1_CHAN_CMD 0x14 /* 8-bit */ 99*17169044Sbrutus 100*17169044Sbrutus #define IOAT_V2_CHAN_CMD 0x4 /* 8-bit */ 101*17169044Sbrutus #define IOAT_V2_CHAN_CNT 0x6 /* 16-bit */ 102*17169044Sbrutus #define IOAT_V2_CHAN_STS_LO 0x8 /* 32-bit */ 103*17169044Sbrutus #define IOAT_V2_CHAN_STS_HI 0xC /* 32-bit */ 104*17169044Sbrutus #define IOAT_V2_CHAN_ADDR_LO 0x10 /* 32-bit */ 105*17169044Sbrutus #define IOAT_V2_CHAN_ADDR_HI 0x14 /* 32-bit */ 106*17169044Sbrutus 107*17169044Sbrutus #define IOAT_CHAN_STS_ADDR_MASK 0xFFFFFFFFFFFFFFC0 108*17169044Sbrutus #define IOAT_CHAN_STS_XFER_MASK 0x3F 109*17169044Sbrutus #define IOAT_CHAN_STS_FAIL_MASK 0x6 110*17169044Sbrutus #define IOAT_CMPL_INDEX(channel) \ 111*17169044Sbrutus (((*channel->ic_cmpl & IOAT_CHAN_STS_ADDR_MASK) - \ 112*17169044Sbrutus ring->cr_phys_desc) >> 6) 113*17169044Sbrutus #define IOAT_CMPL_FAILED(channel) \ 114*17169044Sbrutus (*channel->ic_cmpl & IOAT_CHAN_STS_FAIL_MASK) 115*17169044Sbrutus 116*17169044Sbrutus 117*17169044Sbrutus typedef struct ioat_chan_desc_s { 118*17169044Sbrutus uint32_t dd_res0; 119*17169044Sbrutus uint32_t dd_ctrl; 120*17169044Sbrutus uint64_t dd_res1; 121*17169044Sbrutus uint64_t dd_res2; 122*17169044Sbrutus uint64_t dd_next_desc; 123*17169044Sbrutus uint64_t dd_res4; 124*17169044Sbrutus uint64_t dd_res5; 125*17169044Sbrutus uint64_t dd_res6; 126*17169044Sbrutus uint64_t dd_res7; 127*17169044Sbrutus } ioat_chan_desc_t; 128*17169044Sbrutus 129*17169044Sbrutus /* dca dd_ctrl bits */ 130*17169044Sbrutus #define IOAT_DESC_CTRL_OP_CNTX ((uint32_t)0xFF << 24) 131*17169044Sbrutus #define IOAT_DESC_CTRL_CNTX_CHNG 0x1 132*17169044Sbrutus typedef struct ioat_chan_dca_desc_s { 133*17169044Sbrutus uint32_t dd_cntx; 134*17169044Sbrutus uint32_t dd_ctrl; 135*17169044Sbrutus uint64_t dd_res1; 136*17169044Sbrutus uint64_t dd_res2; 137*17169044Sbrutus uint64_t dd_next_desc; 138*17169044Sbrutus uint64_t dd_res4; 139*17169044Sbrutus uint64_t dd_res5; 140*17169044Sbrutus uint64_t dd_res6; 141*17169044Sbrutus uint64_t dd_res7; 142*17169044Sbrutus } ioat_chan_dca_desc_t; 143*17169044Sbrutus 144*17169044Sbrutus /* dma dd_ctrl bits */ 145*17169044Sbrutus #define IOAT_DESC_CTRL_OP_DMA (0x0 << 24) 146*17169044Sbrutus #define IOAT_DESC_DMACTRL_NULL 0x20 147*17169044Sbrutus #define IOAT_DESC_CTRL_FENCE 0x10 148*17169044Sbrutus #define IOAT_DESC_CTRL_CMPL 0x8 149*17169044Sbrutus #define IOAT_DESC_CTRL_INTR 0x1 150*17169044Sbrutus typedef struct ioat_chan_dma_desc_s { 151*17169044Sbrutus uint32_t dd_size; 152*17169044Sbrutus uint32_t dd_ctrl; 153*17169044Sbrutus uint64_t dd_src_paddr; 154*17169044Sbrutus uint64_t dd_dest_paddr; 155*17169044Sbrutus uint64_t dd_next_desc; 156*17169044Sbrutus uint64_t dd_next_src_paddr; /* v2 only */ 157*17169044Sbrutus uint64_t dd_next_dest_paddr; /* v2 only */ 158*17169044Sbrutus uint64_t dd_res6; 159*17169044Sbrutus uint64_t dd_res7; 160*17169044Sbrutus } ioat_chan_dma_desc_t; 161*17169044Sbrutus 162*17169044Sbrutus 163*17169044Sbrutus typedef enum { 164*17169044Sbrutus IOAT_CBv1, 165*17169044Sbrutus IOAT_CBv2 166*17169044Sbrutus } ioat_version_t; 167*17169044Sbrutus 168*17169044Sbrutus /* ioat private data per command */ 169*17169044Sbrutus typedef struct ioat_cmd_private_s { 170*17169044Sbrutus uint64_t ip_generation; 171*17169044Sbrutus uint64_t ip_index; 172*17169044Sbrutus dcopy_cmd_t ip_next; 173*17169044Sbrutus } ioat_cmd_private_t; 174*17169044Sbrutus 175*17169044Sbrutus /* descriptor ring state */ 176*17169044Sbrutus typedef struct ioat_channel_ring_s { 177*17169044Sbrutus /* protects cr_cmpl_gen & cr_cmpl_last */ 178*17169044Sbrutus kmutex_t cr_cmpl_mutex; 179*17169044Sbrutus 180*17169044Sbrutus /* desc ring generation for the last completion we saw */ 181*17169044Sbrutus uint64_t cr_cmpl_gen; 182*17169044Sbrutus 183*17169044Sbrutus /* last descriptor index we saw complete */ 184*17169044Sbrutus uint64_t cr_cmpl_last; 185*17169044Sbrutus 186*17169044Sbrutus /* protects cr_desc_* */ 187*17169044Sbrutus kmutex_t cr_desc_mutex; 188*17169044Sbrutus 189*17169044Sbrutus /* 190*17169044Sbrutus * last descriptor posted. used to update its next pointer when we 191*17169044Sbrutus * add a new desc. Also used to tack the completion (See comment for 192*17169044Sbrutus * cr_desc_gen_prev). 193*17169044Sbrutus */ 194*17169044Sbrutus uint64_t cr_desc_prev; 195*17169044Sbrutus 196*17169044Sbrutus /* where to put the next descriptor */ 197*17169044Sbrutus uint64_t cr_desc_next; 198*17169044Sbrutus 199*17169044Sbrutus /* what the current desc ring generation is */ 200*17169044Sbrutus uint64_t cr_desc_gen; 201*17169044Sbrutus 202*17169044Sbrutus /* 203*17169044Sbrutus * used during cmd_post to track the last desc posted. cr_desc_next 204*17169044Sbrutus * and cr_desc_gen will be pointing to the next free desc after 205*17169044Sbrutus * writing the descriptor to the ring. But we want to track the 206*17169044Sbrutus * completion for the last descriptor posted. 207*17169044Sbrutus */ 208*17169044Sbrutus uint64_t cr_desc_gen_prev; 209*17169044Sbrutus 210*17169044Sbrutus /* the last desc in the ring (for wrap) */ 211*17169044Sbrutus uint64_t cr_desc_last; 212*17169044Sbrutus 213*17169044Sbrutus /* pointer to the head of the ring */ 214*17169044Sbrutus ioat_chan_desc_t *cr_desc; 215*17169044Sbrutus 216*17169044Sbrutus /* physical address of the head of the ring */ 217*17169044Sbrutus uint64_t cr_phys_desc; 218*17169044Sbrutus 219*17169044Sbrutus /* back pointer to the channel state */ 220*17169044Sbrutus struct ioat_channel_s *cr_chan; 221*17169044Sbrutus 222*17169044Sbrutus /* for CB v2, number of desc posted (written to IOAT_V2_CHAN_CNT) */ 223*17169044Sbrutus uint_t cr_post_cnt; 224*17169044Sbrutus } ioat_channel_ring_t; 225*17169044Sbrutus 226*17169044Sbrutus /* track channel state so we can handle a failure */ 227*17169044Sbrutus typedef enum { 228*17169044Sbrutus IOAT_CHANNEL_OK = 0, 229*17169044Sbrutus IOAT_CHANNEL_IN_FAILURE = 1 230*17169044Sbrutus } ic_channel_state_t; 231*17169044Sbrutus 232*17169044Sbrutus typedef struct ioat_channel_s *ioat_channel_t; 233*17169044Sbrutus struct ioat_channel_s { 234*17169044Sbrutus /* channel's ring state */ 235*17169044Sbrutus ioat_channel_ring_t *ic_ring; 236*17169044Sbrutus 237*17169044Sbrutus /* IOAT_CBv1 || IOAT_CBv2 */ 238*17169044Sbrutus ioat_version_t ic_ver; 239*17169044Sbrutus 240*17169044Sbrutus /* 241*17169044Sbrutus * state to determine if it's OK to post the the channel and if all 242*17169044Sbrutus * future polls should return failure. 243*17169044Sbrutus */ 244*17169044Sbrutus ic_channel_state_t ic_channel_state; 245*17169044Sbrutus 246*17169044Sbrutus /* channel command cache (*_cmd_alloc, *_cmd_free, etc) */ 247*17169044Sbrutus kmem_cache_t *ic_cmd_cache; 248*17169044Sbrutus 249*17169044Sbrutus /* dcopy state for dcopy_device_channel_notify() call */ 250*17169044Sbrutus dcopy_handle_t ic_dcopy_handle; 251*17169044Sbrutus 252*17169044Sbrutus /* location in memory where completions are DMA'ed into */ 253*17169044Sbrutus volatile uint64_t *ic_cmpl; 254*17169044Sbrutus 255*17169044Sbrutus /* channel specific registers */ 256*17169044Sbrutus uint8_t *ic_regs; 257*17169044Sbrutus 258*17169044Sbrutus /* if this channel is using DCA */ 259*17169044Sbrutus boolean_t ic_dca_active; 260*17169044Sbrutus 261*17169044Sbrutus /* DCA ID the channel is currently pointing to */ 262*17169044Sbrutus uint32_t ic_dca_current; 263*17169044Sbrutus 264*17169044Sbrutus /* devices channel number */ 265*17169044Sbrutus uint_t ic_chan_num; 266*17169044Sbrutus 267*17169044Sbrutus /* number of descriptors in ring */ 268*17169044Sbrutus uint_t ic_chan_desc_cnt; 269*17169044Sbrutus 270*17169044Sbrutus /* descriptor ring alloc state */ 271*17169044Sbrutus ddi_dma_handle_t ic_desc_dma_handle; 272*17169044Sbrutus size_t ic_desc_alloc_size; 273*17169044Sbrutus ddi_acc_handle_t ic_desc_handle; 274*17169044Sbrutus ddi_dma_cookie_t ic_desc_cookies; 275*17169044Sbrutus 276*17169044Sbrutus /* completion buffer alloc state */ 277*17169044Sbrutus ddi_dma_handle_t ic_cmpl_dma_handle; 278*17169044Sbrutus size_t ic_cmpl_alloc_size; 279*17169044Sbrutus ddi_acc_handle_t ic_cmpl_handle; 280*17169044Sbrutus ddi_dma_cookie_t ic_cmpl_cookie; 281*17169044Sbrutus uint64_t ic_phys_cmpl; 282*17169044Sbrutus 283*17169044Sbrutus /* if inuse, we need to re-init the channel during resume */ 284*17169044Sbrutus boolean_t ic_inuse; 285*17169044Sbrutus 286*17169044Sbrutus /* backpointer to driver state */ 287*17169044Sbrutus struct ioat_state_s *ic_state; 288*17169044Sbrutus }; 289*17169044Sbrutus 290*17169044Sbrutus typedef struct ioat_rs_s *ioat_rs_hdl_t; 291*17169044Sbrutus 292*17169044Sbrutus /* driver state */ 293*17169044Sbrutus typedef struct ioat_state_s { 294*17169044Sbrutus dev_info_t *is_dip; 295*17169044Sbrutus int is_instance; 296*17169044Sbrutus 297*17169044Sbrutus kmutex_t is_mutex; 298*17169044Sbrutus 299*17169044Sbrutus /* register handle and pointer to registers */ 300*17169044Sbrutus ddi_acc_handle_t is_reg_handle; 301*17169044Sbrutus uint8_t *is_genregs; 302*17169044Sbrutus 303*17169044Sbrutus /* IOAT_CBv1 || IOAT_CBv2 */ 304*17169044Sbrutus ioat_version_t is_ver; 305*17169044Sbrutus 306*17169044Sbrutus /* channel state */ 307*17169044Sbrutus ioat_channel_t is_channel; 308*17169044Sbrutus size_t is_chansize; 309*17169044Sbrutus ioat_rs_hdl_t is_channel_rs; 310*17169044Sbrutus 311*17169044Sbrutus ddi_iblock_cookie_t is_iblock_cookie; 312*17169044Sbrutus 313*17169044Sbrutus /* device info */ 314*17169044Sbrutus uint_t is_chanoff; 315*17169044Sbrutus uint_t is_num_channels; 316*17169044Sbrutus uint_t is_maxxfer; 317*17169044Sbrutus uint_t is_cbver; 318*17169044Sbrutus uint_t is_intrdelay; 319*17169044Sbrutus uint_t is_status; 320*17169044Sbrutus uint_t is_capabilities; 321*17169044Sbrutus 322*17169044Sbrutus /* dcopy_device_register()/dcopy_device_unregister() state */ 323*17169044Sbrutus dcopy_device_handle_t is_device_handle; 324*17169044Sbrutus dcopy_device_info_t is_deviceinfo; 325*17169044Sbrutus } ioat_state_t; 326*17169044Sbrutus 327*17169044Sbrutus 328*17169044Sbrutus int ioat_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred, 329*17169044Sbrutus int *rval); 330*17169044Sbrutus 331*17169044Sbrutus void ioat_rs_init(ioat_state_t *state, uint_t min_val, uint_t max_val, 332*17169044Sbrutus ioat_rs_hdl_t *handle); 333*17169044Sbrutus void ioat_rs_fini(ioat_rs_hdl_t *handle); 334*17169044Sbrutus int ioat_rs_alloc(ioat_rs_hdl_t handle, uint_t *rs); 335*17169044Sbrutus void ioat_rs_free(ioat_rs_hdl_t handle, uint_t rs); 336*17169044Sbrutus 337*17169044Sbrutus int ioat_channel_init(ioat_state_t *state); 338*17169044Sbrutus void ioat_channel_fini(ioat_state_t *state); 339*17169044Sbrutus void ioat_channel_suspend(ioat_state_t *state); 340*17169044Sbrutus int ioat_channel_resume(ioat_state_t *state); 341*17169044Sbrutus 342*17169044Sbrutus int ioat_channel_alloc(void *device_private, dcopy_handle_t handle, int flags, 343*17169044Sbrutus uint_t size, dcopy_query_channel_t *info, void *channel_private); 344*17169044Sbrutus void ioat_channel_free(void *channel_private); 345*17169044Sbrutus void ioat_channel_intr(ioat_channel_t channel); 346*17169044Sbrutus int ioat_cmd_alloc(void *channel, int flags, dcopy_cmd_t *cmd); 347*17169044Sbrutus void ioat_cmd_free(void *channel, dcopy_cmd_t *cmd); 348*17169044Sbrutus int ioat_cmd_post(void *channel, dcopy_cmd_t cmd); 349*17169044Sbrutus int ioat_cmd_poll(void *channel, dcopy_cmd_t cmd); 350*17169044Sbrutus void ioat_unregister_complete(void *device_private, int status); 351*17169044Sbrutus 352*17169044Sbrutus 353*17169044Sbrutus #endif /* _KERNEL */ 354*17169044Sbrutus 355*17169044Sbrutus #ifdef __cplusplus 356*17169044Sbrutus } 357*17169044Sbrutus #endif 358*17169044Sbrutus 359*17169044Sbrutus #endif /* _SYS_IOAT_H */ 360