1*4882a593Smuzhiyun /* SPDX-License-Identifier: BSD-3-Clause-Clear */ 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. 4*4882a593Smuzhiyun */ 5*4882a593Smuzhiyun 6*4882a593Smuzhiyun #ifndef ATH11K_HTC_H 7*4882a593Smuzhiyun #define ATH11K_HTC_H 8*4882a593Smuzhiyun 9*4882a593Smuzhiyun #include <linux/kernel.h> 10*4882a593Smuzhiyun #include <linux/list.h> 11*4882a593Smuzhiyun #include <linux/bug.h> 12*4882a593Smuzhiyun #include <linux/skbuff.h> 13*4882a593Smuzhiyun #include <linux/timer.h> 14*4882a593Smuzhiyun 15*4882a593Smuzhiyun struct ath11k_base; 16*4882a593Smuzhiyun 17*4882a593Smuzhiyun #define HTC_HDR_ENDPOINTID GENMASK(7, 0) 18*4882a593Smuzhiyun #define HTC_HDR_FLAGS GENMASK(15, 8) 19*4882a593Smuzhiyun #define HTC_HDR_PAYLOADLEN GENMASK(31, 16) 20*4882a593Smuzhiyun #define HTC_HDR_CONTROLBYTES0 GENMASK(7, 0) 21*4882a593Smuzhiyun #define HTC_HDR_CONTROLBYTES1 GENMASK(15, 8) 22*4882a593Smuzhiyun #define HTC_HDR_RESERVED GENMASK(31, 16) 23*4882a593Smuzhiyun 24*4882a593Smuzhiyun #define HTC_SVC_MSG_SERVICE_ID GENMASK(31, 16) 25*4882a593Smuzhiyun #define HTC_SVC_MSG_CONNECTIONFLAGS GENMASK(15, 0) 26*4882a593Smuzhiyun #define HTC_SVC_MSG_SERVICEMETALENGTH GENMASK(23, 16) 27*4882a593Smuzhiyun #define HTC_READY_MSG_CREDITCOUNT GENMASK(31, 16) 28*4882a593Smuzhiyun #define HTC_READY_MSG_CREDITSIZE GENMASK(15, 0) 29*4882a593Smuzhiyun #define HTC_READY_MSG_MAXENDPOINTS GENMASK(23, 16) 30*4882a593Smuzhiyun 31*4882a593Smuzhiyun #define HTC_READY_EX_MSG_HTCVERSION GENMASK(7, 0) 32*4882a593Smuzhiyun #define HTC_READY_EX_MSG_MAXMSGSPERHTCBUNDLE GENMASK(15, 8) 33*4882a593Smuzhiyun 34*4882a593Smuzhiyun #define HTC_SVC_RESP_MSG_SERVICEID GENMASK(31, 16) 35*4882a593Smuzhiyun #define HTC_SVC_RESP_MSG_STATUS GENMASK(7, 0) 36*4882a593Smuzhiyun #define HTC_SVC_RESP_MSG_ENDPOINTID GENMASK(15, 8) 37*4882a593Smuzhiyun #define HTC_SVC_RESP_MSG_MAXMSGSIZE GENMASK(31, 16) 38*4882a593Smuzhiyun #define HTC_SVC_RESP_MSG_SERVICEMETALENGTH GENMASK(7, 0) 39*4882a593Smuzhiyun 40*4882a593Smuzhiyun #define HTC_MSG_MESSAGEID GENMASK(15, 0) 41*4882a593Smuzhiyun #define HTC_SETUP_COMPLETE_EX_MSG_SETUPFLAGS GENMASK(31, 0) 42*4882a593Smuzhiyun #define HTC_SETUP_COMPLETE_EX_MSG_MAXMSGSPERBUNDLEDRECV GENMASK(7, 0) 43*4882a593Smuzhiyun #define HTC_SETUP_COMPLETE_EX_MSG_RSVD0 GENMASK(15, 8) 44*4882a593Smuzhiyun #define HTC_SETUP_COMPLETE_EX_MSG_RSVD1 GENMASK(23, 16) 45*4882a593Smuzhiyun #define HTC_SETUP_COMPLETE_EX_MSG_RSVD2 GENMASK(31, 24) 46*4882a593Smuzhiyun 47*4882a593Smuzhiyun enum ath11k_htc_tx_flags { 48*4882a593Smuzhiyun ATH11K_HTC_FLAG_NEED_CREDIT_UPDATE = 0x01, 49*4882a593Smuzhiyun ATH11K_HTC_FLAG_SEND_BUNDLE = 0x02 50*4882a593Smuzhiyun }; 51*4882a593Smuzhiyun 52*4882a593Smuzhiyun enum ath11k_htc_rx_flags { 53*4882a593Smuzhiyun ATH11K_HTC_FLAG_TRAILER_PRESENT = 0x02, 54*4882a593Smuzhiyun ATH11K_HTC_FLAG_BUNDLE_MASK = 0xF0 55*4882a593Smuzhiyun }; 56*4882a593Smuzhiyun 57*4882a593Smuzhiyun struct ath11k_htc_hdr { 58*4882a593Smuzhiyun u32 htc_info; 59*4882a593Smuzhiyun u32 ctrl_info; 60*4882a593Smuzhiyun } __packed __aligned(4); 61*4882a593Smuzhiyun 62*4882a593Smuzhiyun enum ath11k_htc_msg_id { 63*4882a593Smuzhiyun ATH11K_HTC_MSG_READY_ID = 1, 64*4882a593Smuzhiyun ATH11K_HTC_MSG_CONNECT_SERVICE_ID = 2, 65*4882a593Smuzhiyun ATH11K_HTC_MSG_CONNECT_SERVICE_RESP_ID = 3, 66*4882a593Smuzhiyun ATH11K_HTC_MSG_SETUP_COMPLETE_ID = 4, 67*4882a593Smuzhiyun ATH11K_HTC_MSG_SETUP_COMPLETE_EX_ID = 5, 68*4882a593Smuzhiyun ATH11K_HTC_MSG_SEND_SUSPEND_COMPLETE = 6 69*4882a593Smuzhiyun }; 70*4882a593Smuzhiyun 71*4882a593Smuzhiyun enum ath11k_htc_version { 72*4882a593Smuzhiyun ATH11K_HTC_VERSION_2P0 = 0x00, /* 2.0 */ 73*4882a593Smuzhiyun ATH11K_HTC_VERSION_2P1 = 0x01, /* 2.1 */ 74*4882a593Smuzhiyun }; 75*4882a593Smuzhiyun 76*4882a593Smuzhiyun #define ATH11K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_MASK GENMASK(1, 0) 77*4882a593Smuzhiyun #define ATH11K_HTC_CONN_FLAGS_RECV_ALLOC GENMASK(15, 8) 78*4882a593Smuzhiyun 79*4882a593Smuzhiyun enum ath11k_htc_conn_flags { 80*4882a593Smuzhiyun ATH11K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_ONE_FOURTH = 0x0, 81*4882a593Smuzhiyun ATH11K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_ONE_HALF = 0x1, 82*4882a593Smuzhiyun ATH11K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_THREE_FOURTHS = 0x2, 83*4882a593Smuzhiyun ATH11K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_UNITY = 0x3, 84*4882a593Smuzhiyun ATH11K_HTC_CONN_FLAGS_REDUCE_CREDIT_DRIBBLE = 1 << 2, 85*4882a593Smuzhiyun ATH11K_HTC_CONN_FLAGS_DISABLE_CREDIT_FLOW_CTRL = 1 << 3 86*4882a593Smuzhiyun }; 87*4882a593Smuzhiyun 88*4882a593Smuzhiyun enum ath11k_htc_conn_svc_status { 89*4882a593Smuzhiyun ATH11K_HTC_CONN_SVC_STATUS_SUCCESS = 0, 90*4882a593Smuzhiyun ATH11K_HTC_CONN_SVC_STATUS_NOT_FOUND = 1, 91*4882a593Smuzhiyun ATH11K_HTC_CONN_SVC_STATUS_FAILED = 2, 92*4882a593Smuzhiyun ATH11K_HTC_CONN_SVC_STATUS_NO_RESOURCES = 3, 93*4882a593Smuzhiyun ATH11K_HTC_CONN_SVC_STATUS_NO_MORE_EP = 4 94*4882a593Smuzhiyun }; 95*4882a593Smuzhiyun 96*4882a593Smuzhiyun struct ath11k_htc_ready { 97*4882a593Smuzhiyun u32 id_credit_count; 98*4882a593Smuzhiyun u32 size_ep; 99*4882a593Smuzhiyun } __packed; 100*4882a593Smuzhiyun 101*4882a593Smuzhiyun struct ath11k_htc_ready_extended { 102*4882a593Smuzhiyun struct ath11k_htc_ready base; 103*4882a593Smuzhiyun u32 ver_bundle; 104*4882a593Smuzhiyun } __packed; 105*4882a593Smuzhiyun 106*4882a593Smuzhiyun struct ath11k_htc_conn_svc { 107*4882a593Smuzhiyun u32 msg_svc_id; 108*4882a593Smuzhiyun u32 flags_len; 109*4882a593Smuzhiyun } __packed; 110*4882a593Smuzhiyun 111*4882a593Smuzhiyun struct ath11k_htc_conn_svc_resp { 112*4882a593Smuzhiyun u32 msg_svc_id; 113*4882a593Smuzhiyun u32 flags_len; 114*4882a593Smuzhiyun u32 svc_meta_pad; 115*4882a593Smuzhiyun } __packed; 116*4882a593Smuzhiyun 117*4882a593Smuzhiyun struct ath11k_htc_setup_complete_extended { 118*4882a593Smuzhiyun u32 msg_id; 119*4882a593Smuzhiyun u32 flags; 120*4882a593Smuzhiyun u32 max_msgs_per_bundled_recv; 121*4882a593Smuzhiyun } __packed; 122*4882a593Smuzhiyun 123*4882a593Smuzhiyun struct ath11k_htc_msg { 124*4882a593Smuzhiyun u32 msg_svc_id; 125*4882a593Smuzhiyun u32 flags_len; 126*4882a593Smuzhiyun } __packed __aligned(4); 127*4882a593Smuzhiyun 128*4882a593Smuzhiyun enum ath11k_htc_record_id { 129*4882a593Smuzhiyun ATH11K_HTC_RECORD_NULL = 0, 130*4882a593Smuzhiyun ATH11K_HTC_RECORD_CREDITS = 1 131*4882a593Smuzhiyun }; 132*4882a593Smuzhiyun 133*4882a593Smuzhiyun struct ath11k_htc_record_hdr { 134*4882a593Smuzhiyun u8 id; /* @enum ath11k_htc_record_id */ 135*4882a593Smuzhiyun u8 len; 136*4882a593Smuzhiyun u8 pad0; 137*4882a593Smuzhiyun u8 pad1; 138*4882a593Smuzhiyun } __packed; 139*4882a593Smuzhiyun 140*4882a593Smuzhiyun struct ath11k_htc_credit_report { 141*4882a593Smuzhiyun u8 eid; /* @enum ath11k_htc_ep_id */ 142*4882a593Smuzhiyun u8 credits; 143*4882a593Smuzhiyun u8 pad0; 144*4882a593Smuzhiyun u8 pad1; 145*4882a593Smuzhiyun } __packed; 146*4882a593Smuzhiyun 147*4882a593Smuzhiyun struct ath11k_htc_record { 148*4882a593Smuzhiyun struct ath11k_htc_record_hdr hdr; 149*4882a593Smuzhiyun union { 150*4882a593Smuzhiyun struct ath11k_htc_credit_report credit_report[0]; 151*4882a593Smuzhiyun u8 pauload[0]; 152*4882a593Smuzhiyun }; 153*4882a593Smuzhiyun } __packed __aligned(4); 154*4882a593Smuzhiyun 155*4882a593Smuzhiyun /* note: the trailer offset is dynamic depending 156*4882a593Smuzhiyun * on payload length. this is only a struct layout draft 157*4882a593Smuzhiyun */ 158*4882a593Smuzhiyun struct ath11k_htc_frame { 159*4882a593Smuzhiyun struct ath11k_htc_hdr hdr; 160*4882a593Smuzhiyun union { 161*4882a593Smuzhiyun struct ath11k_htc_msg msg; 162*4882a593Smuzhiyun u8 payload[0]; 163*4882a593Smuzhiyun }; 164*4882a593Smuzhiyun struct ath11k_htc_record trailer[0]; 165*4882a593Smuzhiyun } __packed __aligned(4); 166*4882a593Smuzhiyun 167*4882a593Smuzhiyun enum ath11k_htc_svc_gid { 168*4882a593Smuzhiyun ATH11K_HTC_SVC_GRP_RSVD = 0, 169*4882a593Smuzhiyun ATH11K_HTC_SVC_GRP_WMI = 1, 170*4882a593Smuzhiyun ATH11K_HTC_SVC_GRP_NMI = 2, 171*4882a593Smuzhiyun ATH11K_HTC_SVC_GRP_HTT = 3, 172*4882a593Smuzhiyun ATH11K_HTC_SVC_GRP_CFG = 4, 173*4882a593Smuzhiyun ATH11K_HTC_SVC_GRP_IPA = 5, 174*4882a593Smuzhiyun ATH11K_HTC_SVC_GRP_PKTLOG = 6, 175*4882a593Smuzhiyun 176*4882a593Smuzhiyun ATH11K_HTC_SVC_GRP_TEST = 254, 177*4882a593Smuzhiyun ATH11K_HTC_SVC_GRP_LAST = 255, 178*4882a593Smuzhiyun }; 179*4882a593Smuzhiyun 180*4882a593Smuzhiyun #define SVC(group, idx) \ 181*4882a593Smuzhiyun (int)(((int)(group) << 8) | (int)(idx)) 182*4882a593Smuzhiyun 183*4882a593Smuzhiyun enum ath11k_htc_svc_id { 184*4882a593Smuzhiyun /* NOTE: service ID of 0x0000 is reserved and should never be used */ 185*4882a593Smuzhiyun ATH11K_HTC_SVC_ID_RESERVED = 0x0000, 186*4882a593Smuzhiyun ATH11K_HTC_SVC_ID_UNUSED = ATH11K_HTC_SVC_ID_RESERVED, 187*4882a593Smuzhiyun 188*4882a593Smuzhiyun ATH11K_HTC_SVC_ID_RSVD_CTRL = SVC(ATH11K_HTC_SVC_GRP_RSVD, 1), 189*4882a593Smuzhiyun ATH11K_HTC_SVC_ID_WMI_CONTROL = SVC(ATH11K_HTC_SVC_GRP_WMI, 0), 190*4882a593Smuzhiyun ATH11K_HTC_SVC_ID_WMI_DATA_BE = SVC(ATH11K_HTC_SVC_GRP_WMI, 1), 191*4882a593Smuzhiyun ATH11K_HTC_SVC_ID_WMI_DATA_BK = SVC(ATH11K_HTC_SVC_GRP_WMI, 2), 192*4882a593Smuzhiyun ATH11K_HTC_SVC_ID_WMI_DATA_VI = SVC(ATH11K_HTC_SVC_GRP_WMI, 3), 193*4882a593Smuzhiyun ATH11K_HTC_SVC_ID_WMI_DATA_VO = SVC(ATH11K_HTC_SVC_GRP_WMI, 4), 194*4882a593Smuzhiyun ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC1 = SVC(ATH11K_HTC_SVC_GRP_WMI, 5), 195*4882a593Smuzhiyun ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC2 = SVC(ATH11K_HTC_SVC_GRP_WMI, 6), 196*4882a593Smuzhiyun 197*4882a593Smuzhiyun ATH11K_HTC_SVC_ID_NMI_CONTROL = SVC(ATH11K_HTC_SVC_GRP_NMI, 0), 198*4882a593Smuzhiyun ATH11K_HTC_SVC_ID_NMI_DATA = SVC(ATH11K_HTC_SVC_GRP_NMI, 1), 199*4882a593Smuzhiyun 200*4882a593Smuzhiyun ATH11K_HTC_SVC_ID_HTT_DATA_MSG = SVC(ATH11K_HTC_SVC_GRP_HTT, 0), 201*4882a593Smuzhiyun 202*4882a593Smuzhiyun /* raw stream service (i.e. flash, tcmd, calibration apps) */ 203*4882a593Smuzhiyun ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS = SVC(ATH11K_HTC_SVC_GRP_TEST, 0), 204*4882a593Smuzhiyun ATH11K_HTC_SVC_ID_IPA_TX = SVC(ATH11K_HTC_SVC_GRP_IPA, 0), 205*4882a593Smuzhiyun ATH11K_HTC_SVC_ID_PKT_LOG = SVC(ATH11K_HTC_SVC_GRP_PKTLOG, 0), 206*4882a593Smuzhiyun }; 207*4882a593Smuzhiyun 208*4882a593Smuzhiyun #undef SVC 209*4882a593Smuzhiyun 210*4882a593Smuzhiyun enum ath11k_htc_ep_id { 211*4882a593Smuzhiyun ATH11K_HTC_EP_UNUSED = -1, 212*4882a593Smuzhiyun ATH11K_HTC_EP_0 = 0, 213*4882a593Smuzhiyun ATH11K_HTC_EP_1 = 1, 214*4882a593Smuzhiyun ATH11K_HTC_EP_2, 215*4882a593Smuzhiyun ATH11K_HTC_EP_3, 216*4882a593Smuzhiyun ATH11K_HTC_EP_4, 217*4882a593Smuzhiyun ATH11K_HTC_EP_5, 218*4882a593Smuzhiyun ATH11K_HTC_EP_6, 219*4882a593Smuzhiyun ATH11K_HTC_EP_7, 220*4882a593Smuzhiyun ATH11K_HTC_EP_8, 221*4882a593Smuzhiyun ATH11K_HTC_EP_COUNT, 222*4882a593Smuzhiyun }; 223*4882a593Smuzhiyun 224*4882a593Smuzhiyun struct ath11k_htc_ops { 225*4882a593Smuzhiyun void (*target_send_suspend_complete)(struct ath11k_base *ar); 226*4882a593Smuzhiyun }; 227*4882a593Smuzhiyun 228*4882a593Smuzhiyun struct ath11k_htc_ep_ops { 229*4882a593Smuzhiyun void (*ep_tx_complete)(struct ath11k_base *, struct sk_buff *); 230*4882a593Smuzhiyun void (*ep_rx_complete)(struct ath11k_base *, struct sk_buff *); 231*4882a593Smuzhiyun void (*ep_tx_credits)(struct ath11k_base *); 232*4882a593Smuzhiyun }; 233*4882a593Smuzhiyun 234*4882a593Smuzhiyun /* service connection information */ 235*4882a593Smuzhiyun struct ath11k_htc_svc_conn_req { 236*4882a593Smuzhiyun u16 service_id; 237*4882a593Smuzhiyun struct ath11k_htc_ep_ops ep_ops; 238*4882a593Smuzhiyun int max_send_queue_depth; 239*4882a593Smuzhiyun }; 240*4882a593Smuzhiyun 241*4882a593Smuzhiyun /* service connection response information */ 242*4882a593Smuzhiyun struct ath11k_htc_svc_conn_resp { 243*4882a593Smuzhiyun u8 buffer_len; 244*4882a593Smuzhiyun u8 actual_len; 245*4882a593Smuzhiyun enum ath11k_htc_ep_id eid; 246*4882a593Smuzhiyun unsigned int max_msg_len; 247*4882a593Smuzhiyun u8 connect_resp_code; 248*4882a593Smuzhiyun }; 249*4882a593Smuzhiyun 250*4882a593Smuzhiyun #define ATH11K_NUM_CONTROL_TX_BUFFERS 2 251*4882a593Smuzhiyun #define ATH11K_HTC_MAX_LEN 4096 252*4882a593Smuzhiyun #define ATH11K_HTC_MAX_CTRL_MSG_LEN 256 253*4882a593Smuzhiyun #define ATH11K_HTC_WAIT_TIMEOUT_HZ (1 * HZ) 254*4882a593Smuzhiyun #define ATH11K_HTC_CONTROL_BUFFER_SIZE (ATH11K_HTC_MAX_CTRL_MSG_LEN + \ 255*4882a593Smuzhiyun sizeof(struct ath11k_htc_hdr)) 256*4882a593Smuzhiyun #define ATH11K_HTC_CONN_SVC_TIMEOUT_HZ (1 * HZ) 257*4882a593Smuzhiyun #define ATH11K_HTC_MAX_SERVICE_ALLOC_ENTRIES 8 258*4882a593Smuzhiyun 259*4882a593Smuzhiyun struct ath11k_htc_ep { 260*4882a593Smuzhiyun struct ath11k_htc *htc; 261*4882a593Smuzhiyun enum ath11k_htc_ep_id eid; 262*4882a593Smuzhiyun enum ath11k_htc_svc_id service_id; 263*4882a593Smuzhiyun struct ath11k_htc_ep_ops ep_ops; 264*4882a593Smuzhiyun 265*4882a593Smuzhiyun int max_tx_queue_depth; 266*4882a593Smuzhiyun int max_ep_message_len; 267*4882a593Smuzhiyun u8 ul_pipe_id; 268*4882a593Smuzhiyun u8 dl_pipe_id; 269*4882a593Smuzhiyun 270*4882a593Smuzhiyun u8 seq_no; /* for debugging */ 271*4882a593Smuzhiyun int tx_credits; 272*4882a593Smuzhiyun bool tx_credit_flow_enabled; 273*4882a593Smuzhiyun }; 274*4882a593Smuzhiyun 275*4882a593Smuzhiyun struct ath11k_htc_svc_tx_credits { 276*4882a593Smuzhiyun u16 service_id; 277*4882a593Smuzhiyun u8 credit_allocation; 278*4882a593Smuzhiyun }; 279*4882a593Smuzhiyun 280*4882a593Smuzhiyun struct ath11k_htc { 281*4882a593Smuzhiyun struct ath11k_base *ab; 282*4882a593Smuzhiyun struct ath11k_htc_ep endpoint[ATH11K_HTC_EP_COUNT]; 283*4882a593Smuzhiyun 284*4882a593Smuzhiyun /* protects endpoints */ 285*4882a593Smuzhiyun spinlock_t tx_lock; 286*4882a593Smuzhiyun 287*4882a593Smuzhiyun struct ath11k_htc_ops htc_ops; 288*4882a593Smuzhiyun 289*4882a593Smuzhiyun u8 control_resp_buffer[ATH11K_HTC_MAX_CTRL_MSG_LEN]; 290*4882a593Smuzhiyun int control_resp_len; 291*4882a593Smuzhiyun 292*4882a593Smuzhiyun struct completion ctl_resp; 293*4882a593Smuzhiyun 294*4882a593Smuzhiyun int total_transmit_credits; 295*4882a593Smuzhiyun struct ath11k_htc_svc_tx_credits 296*4882a593Smuzhiyun service_alloc_table[ATH11K_HTC_MAX_SERVICE_ALLOC_ENTRIES]; 297*4882a593Smuzhiyun int target_credit_size; 298*4882a593Smuzhiyun u8 wmi_ep_count; 299*4882a593Smuzhiyun }; 300*4882a593Smuzhiyun 301*4882a593Smuzhiyun int ath11k_htc_init(struct ath11k_base *ar); 302*4882a593Smuzhiyun int ath11k_htc_wait_target(struct ath11k_htc *htc); 303*4882a593Smuzhiyun int ath11k_htc_start(struct ath11k_htc *htc); 304*4882a593Smuzhiyun int ath11k_htc_connect_service(struct ath11k_htc *htc, 305*4882a593Smuzhiyun struct ath11k_htc_svc_conn_req *conn_req, 306*4882a593Smuzhiyun struct ath11k_htc_svc_conn_resp *conn_resp); 307*4882a593Smuzhiyun int ath11k_htc_send(struct ath11k_htc *htc, enum ath11k_htc_ep_id eid, 308*4882a593Smuzhiyun struct sk_buff *packet); 309*4882a593Smuzhiyun struct sk_buff *ath11k_htc_alloc_skb(struct ath11k_base *ar, int size); 310*4882a593Smuzhiyun void ath11k_htc_rx_completion_handler(struct ath11k_base *ar, 311*4882a593Smuzhiyun struct sk_buff *skb); 312*4882a593Smuzhiyun 313*4882a593Smuzhiyun #endif 314