1 /*
   2  * Copyright (c) 2009-2015 Solarflare Communications Inc.
   3  * All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions are met:
   7  *
   8  * 1. Redistributions of source code must retain the above copyright notice,
   9  *    this list of conditions and the following disclaimer.
  10  * 2. Redistributions in binary form must reproduce the above copyright notice,
  11  *    this list of conditions and the following disclaimer in the documentation
  12  *    and/or other materials provided with the distribution.
  13  *
  14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  21  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  22  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  23  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  24  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25  *
  26  * The views and conclusions contained in the software and documentation are
  27  * those of the authors and should not be interpreted as representing official
  28  * policies, either expressed or implied, of the FreeBSD Project.
  29  */
  30 
  31 #ifndef _SYS_EFX_MCDI_H
  32 #define _SYS_EFX_MCDI_H
  33 
  34 #include "efx.h"
  35 #include "efx_regs_mcdi.h"
  36 
  37 #ifdef  __cplusplus
  38 extern "C" {
  39 #endif
  40 
  41 /*
  42  * A reboot/assertion causes the MCDI status word to be set after the
  43  * command word is set or a REBOOT event is sent. If we notice a reboot
  44  * via these mechanisms then wait 10ms for the status word to be set.
  45  */
  46 #define EFX_MCDI_STATUS_SLEEP_US        10000
  47 
  48 struct efx_mcdi_req_s {
  49         boolean_t       emr_quiet;
  50         /* Inputs: Command #, input buffer and length */
  51         unsigned int    emr_cmd;
  52         uint8_t         *emr_in_buf;
  53         size_t          emr_in_length;
  54         /* Outputs: retcode, buffer, length, and length used*/
  55         efx_rc_t        emr_rc;
  56         uint8_t         *emr_out_buf;
  57         size_t          emr_out_length;
  58         size_t          emr_out_length_used;
  59         /* Internals: low level transport details */
  60         unsigned int    emr_err_code;
  61         unsigned int    emr_err_arg;
  62 #if EFSYS_OPT_MCDI_PROXY_AUTH
  63         uint32_t        emr_proxy_handle;
  64 #endif
  65 };
  66 
  67 typedef struct efx_mcdi_iface_s {
  68         unsigned int            emi_port;
  69         unsigned int            emi_max_version;
  70         unsigned int            emi_seq;
  71         efx_mcdi_req_t          *emi_pending_req;
  72         boolean_t               emi_ev_cpl;
  73         boolean_t               emi_new_epoch;
  74         int                     emi_aborted;
  75         uint32_t                emi_poll_cnt;
  76         uint32_t                emi_mc_reboot_status;
  77 } efx_mcdi_iface_t;
  78 
  79 extern                  void
  80 efx_mcdi_execute(
  81         __in            efx_nic_t *enp,
  82         __inout         efx_mcdi_req_t *emrp);
  83 
  84 extern                  void
  85 efx_mcdi_execute_quiet(
  86         __in            efx_nic_t *enp,
  87         __inout         efx_mcdi_req_t *emrp);
  88 
  89 extern                  void
  90 efx_mcdi_ev_cpl(
  91         __in            efx_nic_t *enp,
  92         __in            unsigned int seq,
  93         __in            unsigned int outlen,
  94         __in            int errcode);
  95 
  96 #if EFSYS_OPT_MCDI_PROXY_AUTH
  97 extern  __checkReturn   efx_rc_t
  98 efx_mcdi_get_proxy_handle(
  99         __in            efx_nic_t *enp,
 100         __in            efx_mcdi_req_t *emrp,
 101         __out           uint32_t *handlep);
 102 
 103 extern                  void
 104 efx_mcdi_ev_proxy_response(
 105         __in            efx_nic_t *enp,
 106         __in            unsigned int handle,
 107         __in            unsigned int status);
 108 #endif
 109 
 110 extern                  void
 111 efx_mcdi_ev_death(
 112         __in            efx_nic_t *enp,
 113         __in            int rc);
 114 
 115 extern  __checkReturn   efx_rc_t
 116 efx_mcdi_request_errcode(
 117         __in            unsigned int err);
 118 
 119 extern                  void
 120 efx_mcdi_raise_exception(
 121         __in            efx_nic_t *enp,
 122         __in_opt        efx_mcdi_req_t *emrp,
 123         __in            int rc);
 124 
 125 typedef enum efx_mcdi_boot_e {
 126         EFX_MCDI_BOOT_PRIMARY,
 127         EFX_MCDI_BOOT_SECONDARY,
 128         EFX_MCDI_BOOT_ROM,
 129 } efx_mcdi_boot_t;
 130 
 131 extern  __checkReturn           efx_rc_t
 132 efx_mcdi_version(
 133         __in                    efx_nic_t *enp,
 134         __out_ecount_opt(4)     uint16_t versionp[4],
 135         __out_opt               uint32_t *buildp,
 136         __out_opt               efx_mcdi_boot_t *statusp);
 137 
 138 extern  __checkReturn           efx_rc_t
 139 efx_mcdi_read_assertion(
 140         __in                    efx_nic_t *enp);
 141 
 142 extern  __checkReturn           efx_rc_t
 143 efx_mcdi_exit_assertion_handler(
 144         __in                    efx_nic_t *enp);
 145 
 146 extern  __checkReturn           efx_rc_t
 147 efx_mcdi_drv_attach(
 148         __in                    efx_nic_t *enp,
 149         __in                    boolean_t attach);
 150 
 151 extern  __checkReturn           efx_rc_t
 152 efx_mcdi_get_board_cfg(
 153         __in                    efx_nic_t *enp,
 154         __out_opt               uint32_t *board_typep,
 155         __out_opt               efx_dword_t *capabilitiesp,
 156         __out_ecount_opt(6)     uint8_t mac_addrp[6]);
 157 
 158 extern  __checkReturn           efx_rc_t
 159 efx_mcdi_get_phy_cfg(
 160         __in                    efx_nic_t *enp);
 161 
 162 extern  __checkReturn           efx_rc_t
 163 efx_mcdi_firmware_update_supported(
 164         __in                    efx_nic_t *enp,
 165         __out                   boolean_t *supportedp);
 166 
 167 extern  __checkReturn           efx_rc_t
 168 efx_mcdi_macaddr_change_supported(
 169         __in                    efx_nic_t *enp,
 170         __out                   boolean_t *supportedp);
 171 
 172 extern  __checkReturn           efx_rc_t
 173 efx_mcdi_link_control_supported(
 174         __in                    efx_nic_t *enp,
 175         __out                   boolean_t *supportedp);
 176 
 177 extern  __checkReturn           efx_rc_t
 178 efx_mcdi_mac_spoofing_supported(
 179         __in                    efx_nic_t *enp,
 180         __out                   boolean_t *supportedp);
 181 
 182 
 183 #if EFSYS_OPT_BIST
 184 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
 185 extern  __checkReturn           efx_rc_t
 186 efx_mcdi_bist_enable_offline(
 187         __in                    efx_nic_t *enp);
 188 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
 189 extern  __checkReturn           efx_rc_t
 190 efx_mcdi_bist_start(
 191         __in                    efx_nic_t *enp,
 192         __in                    efx_bist_type_t type);
 193 #endif /* EFSYS_OPT_BIST */
 194 
 195 extern  __checkReturn           efx_rc_t
 196 efx_mcdi_get_resource_limits(
 197         __in                    efx_nic_t *enp,
 198         __out_opt               uint32_t *nevqp,
 199         __out_opt               uint32_t *nrxqp,
 200         __out_opt               uint32_t *ntxqp);
 201 
 202 extern  __checkReturn   efx_rc_t
 203 efx_mcdi_log_ctrl(
 204         __in            efx_nic_t *enp);
 205 
 206 extern  __checkReturn   efx_rc_t
 207 efx_mcdi_mac_stats_clear(
 208         __in            efx_nic_t *enp);
 209 
 210 extern  __checkReturn   efx_rc_t
 211 efx_mcdi_mac_stats_upload(
 212         __in            efx_nic_t *enp,
 213         __in            efsys_mem_t *esmp);
 214 
 215 extern  __checkReturn   efx_rc_t
 216 efx_mcdi_mac_stats_periodic(
 217         __in            efx_nic_t *enp,
 218         __in            efsys_mem_t *esmp,
 219         __in            uint16_t period,
 220         __in            boolean_t events);
 221 
 222 
 223 #if EFSYS_OPT_LOOPBACK
 224 extern  __checkReturn   efx_rc_t
 225 efx_mcdi_get_loopback_modes(
 226         __in            efx_nic_t *enp);
 227 #endif /* EFSYS_OPT_LOOPBACK */
 228 
 229 extern  __checkReturn   efx_rc_t
 230 efx_mcdi_phy_module_get_info(
 231         __in                    efx_nic_t *enp,
 232         __in                    uint8_t dev_addr,
 233         __in                    uint8_t offset,
 234         __in                    uint8_t len,
 235         __out_bcount(len)       uint8_t *data);
 236 
 237 #define MCDI_IN(_emr, _type, _ofst)                                     \
 238         ((_type *)((_emr).emr_in_buf + (_ofst)))
 239 
 240 #define MCDI_IN2(_emr, _type, _ofst)                                    \
 241         MCDI_IN(_emr, _type, MC_CMD_ ## _ofst ## _OFST)
 242 
 243 #define MCDI_IN_SET_BYTE(_emr, _ofst, _value)                           \
 244         EFX_POPULATE_BYTE_1(*MCDI_IN2(_emr, efx_byte_t, _ofst),         \
 245                 EFX_BYTE_0, _value)
 246 
 247 #define MCDI_IN_SET_WORD(_emr, _ofst, _value)                           \
 248         EFX_POPULATE_WORD_1(*MCDI_IN2(_emr, efx_word_t, _ofst),         \
 249                 EFX_WORD_0, _value)
 250 
 251 #define MCDI_IN_SET_DWORD(_emr, _ofst, _value)                          \
 252         EFX_POPULATE_DWORD_1(*MCDI_IN2(_emr, efx_dword_t, _ofst),       \
 253                 EFX_DWORD_0, _value)
 254 
 255 #define MCDI_IN_SET_DWORD_FIELD(_emr, _ofst, _field, _value)            \
 256         EFX_SET_DWORD_FIELD(*MCDI_IN2(_emr, efx_dword_t, _ofst),        \
 257                 MC_CMD_ ## _field, _value)
 258 
 259 #define MCDI_IN_POPULATE_DWORD_1(_emr, _ofst, _field1, _value1)         \
 260         EFX_POPULATE_DWORD_1(*MCDI_IN2(_emr, efx_dword_t, _ofst),       \
 261                 MC_CMD_ ## _field1, _value1)
 262 
 263 #define MCDI_IN_POPULATE_DWORD_2(_emr, _ofst, _field1, _value1,         \
 264                 _field2, _value2)                                       \
 265         EFX_POPULATE_DWORD_2(*MCDI_IN2(_emr, efx_dword_t, _ofst),       \
 266                 MC_CMD_ ## _field1, _value1,                            \
 267                 MC_CMD_ ## _field2, _value2)
 268 
 269 #define MCDI_IN_POPULATE_DWORD_3(_emr, _ofst, _field1, _value1,         \
 270                 _field2, _value2, _field3, _value3)                     \
 271         EFX_POPULATE_DWORD_3(*MCDI_IN2(_emr, efx_dword_t, _ofst),       \
 272                 MC_CMD_ ## _field1, _value1,                            \
 273                 MC_CMD_ ## _field2, _value2,                            \
 274                 MC_CMD_ ## _field3, _value3)
 275 
 276 #define MCDI_IN_POPULATE_DWORD_4(_emr, _ofst, _field1, _value1,         \
 277                 _field2, _value2, _field3, _value3, _field4, _value4)   \
 278         EFX_POPULATE_DWORD_4(*MCDI_IN2(_emr, efx_dword_t, _ofst),       \
 279                 MC_CMD_ ## _field1, _value1,                            \
 280                 MC_CMD_ ## _field2, _value2,                            \
 281                 MC_CMD_ ## _field3, _value3,                            \
 282                 MC_CMD_ ## _field4, _value4)
 283 
 284 #define MCDI_IN_POPULATE_DWORD_5(_emr, _ofst, _field1, _value1,         \
 285                 _field2, _value2, _field3, _value3, _field4, _value4,   \
 286                 _field5, _value5)                                       \
 287         EFX_POPULATE_DWORD_5(*MCDI_IN2(_emr, efx_dword_t, _ofst),       \
 288                 MC_CMD_ ## _field1, _value1,                            \
 289                 MC_CMD_ ## _field2, _value2,                            \
 290                 MC_CMD_ ## _field3, _value3,                            \
 291                 MC_CMD_ ## _field4, _value4,                            \
 292                 MC_CMD_ ## _field5, _value5)
 293 
 294 #define MCDI_IN_POPULATE_DWORD_6(_emr, _ofst, _field1, _value1,         \
 295                 _field2, _value2, _field3, _value3, _field4, _value4,   \
 296                 _field5, _value5, _field6, _value6)                     \
 297         EFX_POPULATE_DWORD_6(*MCDI_IN2(_emr, efx_dword_t, _ofst),       \
 298                 MC_CMD_ ## _field1, _value1,                            \
 299                 MC_CMD_ ## _field2, _value2,                            \
 300                 MC_CMD_ ## _field3, _value3,                            \
 301                 MC_CMD_ ## _field4, _value4,                            \
 302                 MC_CMD_ ## _field5, _value5,                            \
 303                 MC_CMD_ ## _field6, _value6)
 304 
 305 #define MCDI_IN_POPULATE_DWORD_7(_emr, _ofst, _field1, _value1,         \
 306                 _field2, _value2, _field3, _value3, _field4, _value4,   \
 307                 _field5, _value5, _field6, _value6, _field7, _value7)   \
 308         EFX_POPULATE_DWORD_7(*MCDI_IN2(_emr, efx_dword_t, _ofst),       \
 309                 MC_CMD_ ## _field1, _value1,                            \
 310                 MC_CMD_ ## _field2, _value2,                            \
 311                 MC_CMD_ ## _field3, _value3,                            \
 312                 MC_CMD_ ## _field4, _value4,                            \
 313                 MC_CMD_ ## _field5, _value5,                            \
 314                 MC_CMD_ ## _field6, _value6,                            \
 315                 MC_CMD_ ## _field7, _value7)
 316 
 317 #define MCDI_IN_POPULATE_DWORD_8(_emr, _ofst, _field1, _value1,         \
 318                 _field2, _value2, _field3, _value3, _field4, _value4,   \
 319                 _field5, _value5, _field6, _value6, _field7, _value7,   \
 320                 _field8, _value8)                                       \
 321         EFX_POPULATE_DWORD_8(*MCDI_IN2(_emr, efx_dword_t, _ofst),       \
 322                 MC_CMD_ ## _field1, _value1,                            \
 323                 MC_CMD_ ## _field2, _value2,                            \
 324                 MC_CMD_ ## _field3, _value3,                            \
 325                 MC_CMD_ ## _field4, _value4,                            \
 326                 MC_CMD_ ## _field5, _value5,                            \
 327                 MC_CMD_ ## _field6, _value6,                            \
 328                 MC_CMD_ ## _field7, _value7,                            \
 329                 MC_CMD_ ## _field8, _value8)
 330 
 331 #define MCDI_IN_POPULATE_DWORD_9(_emr, _ofst, _field1, _value1,         \
 332                 _field2, _value2, _field3, _value3, _field4, _value4,   \
 333                 _field5, _value5, _field6, _value6, _field7, _value7,   \
 334                 _field8, _value8, _field9, _value9)                     \
 335         EFX_POPULATE_DWORD_9(*MCDI_IN2(_emr, efx_dword_t, _ofst),       \
 336                 MC_CMD_ ## _field1, _value1,                            \
 337                 MC_CMD_ ## _field2, _value2,                            \
 338                 MC_CMD_ ## _field3, _value3,                            \
 339                 MC_CMD_ ## _field4, _value4,                            \
 340                 MC_CMD_ ## _field5, _value5,                            \
 341                 MC_CMD_ ## _field6, _value6,                            \
 342                 MC_CMD_ ## _field7, _value7,                            \
 343                 MC_CMD_ ## _field8, _value8,                            \
 344                 MC_CMD_ ## _field9, _value9)
 345 
 346 #define MCDI_IN_POPULATE_DWORD_10(_emr, _ofst, _field1, _value1,        \
 347                 _field2, _value2, _field3, _value3, _field4, _value4,   \
 348                 _field5, _value5, _field6, _value6, _field7, _value7,   \
 349                 _field8, _value8, _field9, _value9, _field10, _value10) \
 350         EFX_POPULATE_DWORD_10(*MCDI_IN2(_emr, efx_dword_t, _ofst),      \
 351                 MC_CMD_ ## _field1, _value1,                            \
 352                 MC_CMD_ ## _field2, _value2,                            \
 353                 MC_CMD_ ## _field3, _value3,                            \
 354                 MC_CMD_ ## _field4, _value4,                            \
 355                 MC_CMD_ ## _field5, _value5,                            \
 356                 MC_CMD_ ## _field6, _value6,                            \
 357                 MC_CMD_ ## _field7, _value7,                            \
 358                 MC_CMD_ ## _field8, _value8,                            \
 359                 MC_CMD_ ## _field9, _value9,                            \
 360                 MC_CMD_ ## _field10, _value10)
 361 
 362 #define MCDI_OUT(_emr, _type, _ofst)                                    \
 363         ((_type *)((_emr).emr_out_buf + (_ofst)))
 364 
 365 #define MCDI_OUT2(_emr, _type, _ofst)                                   \
 366         MCDI_OUT(_emr, _type, MC_CMD_ ## _ofst ## _OFST)
 367 
 368 #define MCDI_OUT_BYTE(_emr, _ofst)                                      \
 369         EFX_BYTE_FIELD(*MCDI_OUT2(_emr, efx_byte_t, _ofst),             \
 370                     EFX_BYTE_0)
 371 
 372 #define MCDI_OUT_WORD(_emr, _ofst)                                      \
 373         EFX_WORD_FIELD(*MCDI_OUT2(_emr, efx_word_t, _ofst),             \
 374                     EFX_WORD_0)
 375 
 376 #define MCDI_OUT_DWORD(_emr, _ofst)                                     \
 377         EFX_DWORD_FIELD(*MCDI_OUT2(_emr, efx_dword_t, _ofst),           \
 378                         EFX_DWORD_0)
 379 
 380 #define MCDI_OUT_DWORD_FIELD(_emr, _ofst, _field)                       \
 381         EFX_DWORD_FIELD(*MCDI_OUT2(_emr, efx_dword_t, _ofst),           \
 382                         MC_CMD_ ## _field)
 383 
 384 #define MCDI_EV_FIELD(_eqp, _field)                                     \
 385         EFX_QWORD_FIELD(*_eqp, MCDI_EVENT_ ## _field)
 386 
 387 #define MCDI_CMD_DWORD_FIELD(_edp, _field)                              \
 388         EFX_DWORD_FIELD(*_edp, MC_CMD_ ## _field)
 389 
 390 #define EFX_MCDI_HAVE_PRIVILEGE(mask, priv)                             \
 391         (((mask) & (MC_CMD_PRIVILEGE_MASK_IN_GRP_ ## priv)) ==              \
 392         (MC_CMD_PRIVILEGE_MASK_IN_GRP_ ## priv))
 393 
 394 typedef enum efx_mcdi_feature_id_e {
 395         EFX_MCDI_FEATURE_FW_UPDATE = 0,
 396         EFX_MCDI_FEATURE_LINK_CONTROL,
 397         EFX_MCDI_FEATURE_MACADDR_CHANGE,
 398         EFX_MCDI_FEATURE_MAC_SPOOFING,
 399         EFX_MCDI_FEATURE_NIDS
 400 } efx_mcdi_feature_id_t;
 401 
 402 #ifdef  __cplusplus
 403 }
 404 #endif
 405 
 406 #endif  /* _SYS_EFX_MCDI_H */