From: Adrian Chiris Date: Mon, 8 Dec 2014 08:55:24 +0000 (+0200) Subject: - addedd support for next gen devices that support new pci capability (0x9) X-Git-Url: https://openfabrics.org/gitweb/?a=commitdiff_plain;h=71e21f2a5997824b3002f7dd5b81ceb2af7dbb9c;p=~adrianc%2Fmstflint.git - addedd support for next gen devices that support new pci capability (0x9) this capability allows access to : CR-Space , iCMD command ifc to be utilized in the near future for 5th generation devices and above. - for compatible device with un-supporting fw current flow is kept --- diff --git a/include/mtcr_ul/mtcr.h b/include/mtcr_ul/mtcr.h index 9f56c33..ca584cf 100644 --- a/include/mtcr_ul/mtcr.h +++ b/include/mtcr_ul/mtcr.h @@ -49,6 +49,10 @@ typedef enum MError { ME_NOT_IMPLEMENTED, ME_SEM_LOCKED, ME_MEM_ERROR, + ME_PCI_READ_ERROR, + ME_PCI_WRITE_ERROR, + ME_PCI_SPACE_NOT_SUPPORTED, + ME_PCI_IFC_TOUT, ME_MAD_SEND_FAILED, ME_UNKOWN_ACCESS_TYPE, @@ -93,7 +97,7 @@ typedef enum MError { ME_ICMD_UNKNOWN_STATUS, ME_ICMD_ICM_NOT_AVAIL, ME_ICMD_WRITE_PROTECT, - ME_ICMD_BAD_SIGNATURE, + ME_ICMD_SIZE_EXCEEDS_LIMIT, //errors regarding Tools CMDIF ME_CMDIF_BUSY = 0x300, @@ -190,7 +194,8 @@ typedef enum mtcr_access_method { MTCR_ACCESS_ERROR = 0x0, MTCR_ACCESS_MEMORY = 0x1, MTCR_ACCESS_CONFIG = 0x2, - MTCR_ACCESS_INBAND = 0x3 + MTCR_ACCESS_INBAND = 0x3, + MTCR_ACCESS_AUTO = 0x4, } mtcr_access_method_t; /* * Read 4 bytes, return number of succ. read bytes or -1 on failure @@ -236,6 +241,8 @@ int mget_mdevs_type(mfile *mf, u_int32_t *mtype); */ mfile *mopen(const char *name); +mfile *mopen_adv(const char *name, mtcr_access_method_t access_method); + mfile *mopend(const char *name, int type); mfile *mopen_fw_ctx(void* fw_cmd_context, void* fw_cmd_func); @@ -287,6 +294,7 @@ const char* m_err2str(MError status); int mread_buffer(mfile *mf, unsigned int offset, u_int8_t* data, int byte_len); int mwrite_buffer(mfile *mf, unsigned int offset, u_int8_t* data, int byte_len); +int msupp_fw_ifc_cap(mfile* mf); #ifdef __cplusplus } diff --git a/mflash/mflash.c b/mflash/mflash.c index 69d7852..5476498 100644 --- a/mflash/mflash.c +++ b/mflash/mflash.c @@ -2294,9 +2294,13 @@ int get_dev_info(mflash* mfl) } else if (dev_flags & MDEVS_IB){ mfl->opts[MFO_FW_ACCESS_TYPE_BY_MFILE] = ATBM_INBAND; } else if (HAS_ICMD_IF(mfl->attr.hw_dev_id)){ - if (mfl->opts[MFO_IGNORE_CASHE_REP_GUARD] == 0) { - mfl->opts[MFO_FW_ACCESS_TYPE_BY_MFILE] = ATBM_ICMD; - } + if (mfl->opts[MFO_IGNORE_CASHE_REP_GUARD] == 0) { + if (msupp_fw_ifc_cap(mfl->mf)) { + mfl->opts[MFO_FW_ACCESS_TYPE_BY_MFILE] = ATBM_ICMD; + } else { + mfl->opts[MFO_FW_ACCESS_TYPE_BY_MFILE] = ATBM_INBAND; + } + } } else if (HAS_TOOLS_CMDIF(mfl->attr.hw_dev_id)) { if (mfl->opts[MFO_IGNORE_CASHE_REP_GUARD] == 0) { mfl->opts[MFO_FW_ACCESS_TYPE_BY_MFILE] = ATBM_TOOLS_CMDIF; diff --git a/mtcr_ul/mtcr_int_defs.h b/mtcr_ul/mtcr_int_defs.h index fb2e505..6f598bd 100644 --- a/mtcr_ul/mtcr_int_defs.h +++ b/mtcr_ul/mtcr_int_defs.h @@ -43,12 +43,19 @@ typedef int (*f_mwrite4_block) (mfile *mf, unsigned int offset, u_int32_t* data, typedef int (*f_maccess_reg) (mfile *mf, u_int8_t *data); typedef int (*f_mclose) (mfile* mf); +typedef enum { + AD_ICMD = 1, + AD_CR_SPACE = 2, + AD_SEMAPHORE = 0xa +} address_domain_t; + typedef struct icmd_params_t { int icmd_opened; int took_semaphore; int ctrl_addr; int cmd_addr; + u_int32_t max_cmd_size; int semaphore_addr; int static_cfg_not_done_addr; int static_cfg_not_done_offs; @@ -60,6 +67,10 @@ struct mfile_t { int access_type; int fdlock; + // relevant for devices with pci capability: 0x9 + int supp_fw_ifc; // pciconf - supports 0x9 capability + address_domain_t address_domain; // determines on which address domain reads/writes will be performed + f_mread4 mread4; f_mwrite4 mwrite4; f_mread4_block mread4_block; diff --git a/mtcr_ul/mtcr_ul.c b/mtcr_ul/mtcr_ul.c index a54e70b..3b36be5 100644 --- a/mtcr_ul/mtcr_ul.c +++ b/mtcr_ul/mtcr_ul.c @@ -82,6 +82,7 @@ #include #endif +#include #include #include "tools_utils.h" #include "mtcr_int_defs.h" @@ -131,6 +132,9 @@ struct pciconf_context { int fd; }; +/* Forward decl*/ +static int get_inband_dev_from_pci(char* inband_dev, char* pci_dev); + /* * Lock file section: * @@ -627,10 +631,240 @@ end: #if CONFIG_ENABLE_PCICONF +/* PCI address space related enum*/ +enum { + CAP9_ADDR = 0xc0, + PCI_CAP_PTR = 0x34, + PCI_HDR_SIZE = 0x40, + PCI_EXT_SPACE_ADDR = 0xff, + + PCI_CTRL_OFFSET = 0x4, // for space / semaphore / auto-increment bit + PCI_COUNTER_OFFSET = 0x8, + PCI_SEMAPHORE_OFFSET = 0xc, + PCI_ADDR_OFFSET = 0x10, + PCI_DATA_OFFSET = 0x14, + + PCI_FLAG_BIT_OFFS = 31, + + PCI_SPACE_BIT_OFFS = 0, + PCI_SPACE_BIT_LEN = 16, + + PCI_STATUS_BIT_OFFS = 29, + PCI_STATUS_BIT_LEN = 3, +}; + +/* Mellanox vendor specific enum */ +enum { + CAP_ID = 0x9, + ICMD_DOMAIN = 0x1, + CR_SPACE_DOMAIN = 0x2, + SEMAPHORE_DOMAIN = 0xa, + IFC_MAX_RETRIES = 2048 +}; + +/* PCI operation enum(read or write)*/ +enum { + READ_OP = 0, + WRITE_OP = 1, +}; + + +#define READ4_PCI(mf, val_ptr, pci_offs, err_prefix, action_on_fail) \ + do { \ + int rc; \ + struct pciconf_context *pci_ctx = mf->ctx; \ + rc = pread(pci_ctx->fd, val_ptr, 4, pci_offs); \ + if (rc != 4 ) { \ + if (rc < 0) \ + perror(err_prefix); \ + action_on_fail; \ + } \ + *val_ptr = __le32_to_cpu(*val_ptr);\ + } while (0) + +#define WRITE4_PCI(mf, val, pci_offs, err_prefix, action_on_fail) \ + do { \ + int rc; \ + u_int32_t val_le; \ + struct pciconf_context *pci_ctx = mf->ctx; \ + val_le = __cpu_to_le32(val); \ + rc = pwrite(pci_ctx->fd, &val_le, 4, pci_offs); \ + if (rc != 4 ) { \ + if (rc < 0) \ + perror(err_prefix); \ + action_on_fail; \ + } \ + } while (0) + + +int pci_find_capability(mfile* mf, int cap_id) +{ + unsigned offset; + unsigned char visited[256] = {}; /* Prevent infinite loops */ + unsigned char data[2]; + int ret; + struct pciconf_context *pci_ctx = mf->ctx; + + ret = pread(pci_ctx->fd, data, 1, PCI_CAP_PTR); + if (ret != 1) { + return 0; + } + offset = data[0]; + + while(1) { + if (offset < PCI_HDR_SIZE || offset > PCI_EXT_SPACE_ADDR) { + return 0; + } + + ret = pread(pci_ctx->fd, data, sizeof data, offset); + if (ret != sizeof data) { + return 0; + } + + visited[offset] = 1; + + if (data[0] == cap_id) { + return offset; + } + + offset = data[1]; + if (visited[offset]) { + return 0; + } + } + return 0; +} + +int mtcr_pciconf_cap9_sem(mfile* mf, int state) +{ + u_int32_t lock_val; + u_int32_t counter = 0; + int retries = 0; + + if (!state) {// unlock + WRITE4_PCI(mf, 0, CAP9_ADDR + PCI_SEMAPHORE_OFFSET, "unlock semaphore", return ME_PCI_WRITE_ERROR); + } else { // lock + do { + if (retries > IFC_MAX_RETRIES) { + return ME_SEM_LOCKED; + } + // read semaphore untill 0x0 + READ4_PCI(mf, &lock_val, CAP9_ADDR + PCI_SEMAPHORE_OFFSET, "read counter", return ME_PCI_READ_ERROR); + if (lock_val) { //semaphore is taken + retries++; + msleep(3); // wait for current op to end + continue; + } + //read ticket + READ4_PCI(mf, &counter, CAP9_ADDR + PCI_COUNTER_OFFSET, "read counter", return ME_PCI_READ_ERROR); + //write ticket to semaphore dword + WRITE4_PCI(mf, counter, CAP9_ADDR + PCI_SEMAPHORE_OFFSET, "write counter to semaphore", return ME_PCI_WRITE_ERROR); + // read back semaphore make sure ticket == semaphore else repeat + READ4_PCI(mf, &lock_val, CAP9_ADDR + PCI_SEMAPHORE_OFFSET, "read counter", return ME_PCI_READ_ERROR); + retries++; + } while (counter != lock_val); + } + return ME_OK; +} + +int mtcr_pciconf_wait_on_flag(mfile* mf, u_int8_t expected_val) +{ + int retries = 0; + u_int32_t flag; + do { + if (retries > IFC_MAX_RETRIES) { + return ME_PCI_IFC_TOUT; + } + READ4_PCI(mf, &flag, CAP9_ADDR + PCI_ADDR_OFFSET, "read flag", return ME_PCI_READ_ERROR); + flag = EXTRACT(flag, PCI_FLAG_BIT_OFFS, 1); + retries++; + } while (flag != expected_val); + return ME_OK; +} + +int mtcr_pciconf_set_addr_space(mfile* mf, u_int16_t space) +{ + // read modify write + u_int32_t val; + READ4_PCI(mf, &val, CAP9_ADDR + PCI_CTRL_OFFSET, "read domain", return ME_PCI_READ_ERROR); + val = MERGE(val, space, PCI_SPACE_BIT_OFFS, PCI_SPACE_BIT_LEN); + WRITE4_PCI(mf, val, CAP9_ADDR + PCI_CTRL_OFFSET, "write domain", return ME_PCI_WRITE_ERROR); + // read status and make sure space is supported + READ4_PCI(mf, &val, CAP9_ADDR + PCI_CTRL_OFFSET, "read status", return ME_PCI_READ_ERROR); + if (EXTRACT(val, PCI_STATUS_BIT_OFFS, PCI_STATUS_BIT_LEN) == 0) { + return ME_PCI_SPACE_NOT_SUPPORTED; + } + return ME_OK; +} + +// adrianc: no support for auto-increment feature atm +int mtcr_pciconf_send_pci_cmd_int(mfile *mf, int space, unsigned int offset, u_int32_t* data, int rw) +{ + int rc = ME_OK; + u_int32_t address = offset; + + if ((offset >> 24) & 0xc) { + return ME_BAD_PARAMS; + } + // take semaphore + rc = mtcr_pciconf_cap9_sem(mf, 1); + if (rc) { + return rc; + } + + // set address space + rc = mtcr_pciconf_set_addr_space(mf, space); + if (rc) { + goto cleanup; + } + address = MERGE(address,(rw ? 1 : 0), PCI_FLAG_BIT_OFFS, 1); + + if (rw) { + // write data + WRITE4_PCI(mf, *data, CAP9_ADDR + PCI_DATA_OFFSET, "write value", rc = ME_PCI_WRITE_ERROR; goto cleanup); + // write address + WRITE4_PCI(mf, address, CAP9_ADDR + PCI_ADDR_OFFSET, "write offset", rc = ME_PCI_WRITE_ERROR; goto cleanup); + // wait on flag + mtcr_pciconf_wait_on_flag(mf, 0); + } else { + // write address + WRITE4_PCI(mf, address, CAP9_ADDR + PCI_ADDR_OFFSET, "write offset", rc = ME_PCI_WRITE_ERROR; goto cleanup); + // wait on flag + mtcr_pciconf_wait_on_flag(mf, 1); + // read data + READ4_PCI(mf, data, CAP9_ADDR + PCI_DATA_OFFSET, "read value", rc = ME_PCI_READ_ERROR; goto cleanup); + } +cleanup: + mtcr_pciconf_cap9_sem(mf, 0); + return rc; +} + +// adrianc: no need to lock the file semaphore if we access cr-space through mellanox vendor specific cap int mtcr_pciconf_mread4(mfile *mf, unsigned int offset, u_int32_t *value) +{ + int rc; + rc = mtcr_pciconf_send_pci_cmd_int(mf, mf->address_domain, offset, value, READ_OP); + if (rc) { + return -1; + } + return 4; +} +int mtcr_pciconf_mwrite4(mfile *mf, unsigned int offset, u_int32_t value) +{ + int rc; + rc = mtcr_pciconf_send_pci_cmd_int(mf, mf->address_domain, offset, &value, WRITE_OP); + if (rc) { + return -1; + } + return 4; +} + + +int mtcr_pciconf_mread4_old(mfile *mf, unsigned int offset, u_int32_t *value) { struct pciconf_context *ctx = mf->ctx; int rc; + // adrianc: PCI registers always in le32 offset = __cpu_to_le32(offset); rc = _flock_int(mf->fdlock, LOCK_EX); if (rc) { @@ -657,7 +891,7 @@ pciconf_read_cleanup: return rc; } -int mtcr_pciconf_mwrite4(mfile *mf, unsigned int offset, u_int32_t value) +int mtcr_pciconf_mwrite4_old(mfile *mf, unsigned int offset, u_int32_t value) { struct pciconf_context *ctx = mf->ctx; int rc; @@ -713,14 +947,6 @@ int mtcr_pciconf_open(mfile *mf, const char *name) int rc; struct pciconf_context *ctx; - mf->access_type = MTCR_ACCESS_CONFIG; - - mf->mread4 = mtcr_pciconf_mread4; - mf->mwrite4 = mtcr_pciconf_mwrite4; - mf->mread4_block = mread_chunk_as_multi_mread4; - mf->mwrite4_block = mwrite_chunk_as_multi_mwrite4; - mf->mclose = mtcr_pciconf_mclose; - ctx = (struct pciconf_context*)malloc(sizeof(struct pciconf_context)); if (!ctx) return 1; @@ -732,6 +958,24 @@ int mtcr_pciconf_open(mfile *mf, const char *name) if (ctx->fd < 0) return -1; + mf->access_type = MTCR_ACCESS_CONFIG; + + if (pci_find_capability(mf, CAP_ID)) { + mf->supp_fw_ifc = 1; + } + + if (mf->supp_fw_ifc) { + mf->address_domain = CR_SPACE_DOMAIN; + mf->mread4 = mtcr_pciconf_mread4; + mf->mwrite4 = mtcr_pciconf_mwrite4; + } else { + mf->mread4 = mtcr_pciconf_mread4_old; + mf->mwrite4 = mtcr_pciconf_mwrite4_old; + } + mf->mread4_block = mread_chunk_as_multi_mread4; + mf->mwrite4_block = mwrite_chunk_as_multi_mwrite4; + mf->mclose = mtcr_pciconf_mclose; + /* Kernels before 2.6.12 carry the high bit in each byte * on /config writes, overriding higher bits. * Make sure the high bit is set in some signature bytes, @@ -1109,6 +1353,11 @@ void mdevices_info_destroy(dev_info* dev_info, int len) } mfile *mopen(const char *name) +{ + return mopen_adv(name, MTCR_ACCESS_AUTO); +} + +mfile *mopen_adv(const char *name, mtcr_access_method_t access_method) { mfile *mf; off_t offset; @@ -1152,6 +1401,26 @@ mfile *mopen(const char *name) goto open_failed; } } + // update access according to access method + // if access_method != MTCR_ACCESS_AUTO then we only allow to open conf as memory and via versa + if (access_method == MTCR_ACCESS_AUTO || access_method == access) { + ; + } else if (access_method == MTCR_ACCESS_INBAND) { + char inband_dev[16] = {0}; + if (get_inband_dev_from_pci(inband_dev, mf->dev_name)) { + goto open_failed; + } + free(mf->dev_name); + mf->dev_name = strdup(name); + if (!mf->dev_name) { + goto open_failed; + } + force = 1; + access = access_method; + } else { + access = access_method; + } + if (force) { switch (access) { case MTCR_ACCESS_CONFIG: @@ -1335,7 +1604,7 @@ int mget_mdevs_type(mfile *mf, u_int32_t *mtype) #define IBDR_MAX_NAME_SIZE 128 #define BDF_NAME_SIZE 12 #define DEV_DIR_MAX_SIZE 128 -static + int get_inband_dev_from_pci(char* inband_dev, char* pci_dev) { unsigned domain = 0, bus = 0, dev = 0, func = 0; @@ -1601,9 +1870,17 @@ static int mreg_send_wrapper(mfile* mf, u_int8_t *data, int r_icmd_size, int w_i return ME_MAD_SEND_FAILED; } } else if (supports_icmd(mf)) { - rc = icmd_send_command_int(mf, FLASH_REG_ACCESS, data, w_icmd_size, r_icmd_size, 0); - if (rc) { - return rc; + if (mf->supp_fw_ifc) { // we support accessing fw via icmd space + rc = icmd_send_command_int(mf, FLASH_REG_ACCESS, data, w_icmd_size, r_icmd_size, 0); + if (rc) { + return rc; + } + } else { // send register via inband (maccess_reg_mad will open the device as inband thus consecutives calls will go to the first if) + rc = maccess_reg_mad(mf, data); + if (rc) { + //printf("-E- 2. Access reg mad failed with rc = %#x\n", rc); + return ME_MAD_SEND_FAILED; + } } } else if (supports_tools_cmdif_reg(mf)) { rc = tools_cmdif_reg_access(mf, data, w_icmd_size, r_icmd_size); @@ -1724,7 +2001,12 @@ int mget_max_reg_size(mfile *mf) { return INBAND_MAX_REG_SIZE; } if (supports_icmd(mf)){ // we support icmd and we dont use IB interface -> we use icmd for reg access - return ICMD_MAX_REG_SIZE; + if (mf->supp_fw_ifc) { + return ICMD_MAX_REG_SIZE; + } else { + // we send via inband + return INBAND_MAX_REG_SIZE; + } } if (supports_tools_cmdif_reg(mf)) { return TOOLS_HCR_MAX_REG_SIZE; @@ -1732,6 +2014,10 @@ int mget_max_reg_size(mfile *mf) { return 0; } +int msupp_fw_ifc_cap(mfile* mf) { + return mf->supp_fw_ifc; +} + /************************************ * Function: m_err2str ************************************/ @@ -1752,6 +2038,14 @@ const char* m_err2str(MError status) return "Semaphore locked"; case ME_MEM_ERROR: return "ME_MEM_ERROR"; + case ME_PCI_READ_ERROR: + return "ME_PCI_READ_ERROR"; + case ME_PCI_WRITE_ERROR: + return "ME_PCI_WRITE_ERROR"; + case ME_PCI_SPACE_NOT_SUPPORTED: + return "ME_PCI_SPACE_NOT_SUPPORTED"; + case ME_PCI_IFC_TOUT: + return "ME_PCI_IFC_TOUT"; case ME_MAD_SEND_FAILED: return "ME_MAD_SEND_FAILED"; @@ -1829,8 +2123,8 @@ const char* m_err2str(MError status) return "ME_ICMD_WRITE_PROTECT"; case ME_ICMD_UNKNOWN_STATUS: return "ME_ICMD_UNKNOWN_STATUS"; - case ME_ICMD_BAD_SIGNATURE: - return "ME_ICMD_BAD_SIGNATURE"; + case ME_ICMD_SIZE_EXCEEDS_LIMIT: + return "ME_ICMD_SIZE_EXCEEDS_LIMIT"; // TOOLS HCR access errors case ME_CMDIF_BUSY: diff --git a/mtcr_ul/mtcr_ul_icmd_cif.c b/mtcr_ul/mtcr_ul_icmd_cif.c index 0bfa979..61d2d7f 100644 --- a/mtcr_ul/mtcr_ul_icmd_cif.c +++ b/mtcr_ul/mtcr_ul_icmd_cif.c @@ -43,16 +43,14 @@ * Virtual CR-Space ICMD addresses */ -#define VCR_CTRL_ADDR 0x6404010 -#define VCR_SEMAPHORE62 0x6406000 -#define VCR_CAP_ADDR 0x6405000 -#define VCR_MODE_ADDR 0x6405008 -#define VCR_MAGIC_PAT "virtiCMD" -#define VCR_CMD_ADDR 0x6400000 -#define VCR_CMD_SIZE 0x4000 - - +#define VCR_CTRL_ADDR 0x0 +#define VCR_SEMAPHORE62 0x0 // semaphore Domain +#define VCR_CMD_ADDR 0x1000000 // mailbox addr +#define VCR_CMD_SIZE_ADDR 0x1000 // mailbox size +/* + * Macros for accessing cr-space + */ #define MWRITE_BUF(mf, offset, data, byte_len) \ (((unsigned)(mwrite_buffer((mf), (offset), (data), (byte_len))) != (unsigned)(byte_len)) \ ? ME_ICMD_STATUS_CR_FAIL : ME_OK) @@ -60,13 +58,6 @@ (((unsigned)(mread_buffer((mf), (offset), (data), (byte_len))) != (unsigned)(byte_len)) \ ? ME_ICMD_STATUS_CR_FAIL : ME_OK) -#define MWRITE4_BLOCK(mf, offset, data, byte_len) \ - (((unsigned)(mwrite4_block((mf), (offset), (data), (byte_len))) != (unsigned)(byte_len)) \ - ? ME_ICMD_STATUS_CR_FAIL : ME_OK) -#define MREAD4_BLOCK(mf, offset, data, byte_len) \ - (((unsigned)(mread4_block((mf), (offset), (data), (byte_len))) != (unsigned)(byte_len)) \ - ? ME_ICMD_STATUS_CR_FAIL : ME_OK) - #define MWRITE4(mf, offset, value) \ (((unsigned)(mwrite4((mf), (offset), (value))) != 4U) \ ? ME_ICMD_STATUS_CR_FAIL : ME_OK) @@ -74,6 +65,81 @@ (((unsigned)(mread4((mf), (offset), (ptr))) != 4U) \ ? ME_ICMD_STATUS_CR_FAIL : ME_OK) +//TODO: adrianc: the macros below can be derrived from one common macro SPACE_ACCESS(mf, address_space, access_func, args, exp_rc, action_on_fail) +/* + * Macros for accessing Icmd space + */ +#define SET_SPACE_FOR_ICMD_ACCESS(mf) \ + if (mf->sup_fw_ifc) { \ + mf->address_domain = AD_ICMD; \ + } +#define RESTORE_SPACE(mf) mf->address_domain = AD_CR_SPACE + +#define MWRITE4_ICMD(mf, offset, value, action_on_fail)\ + do {\ + mf->address_domain = AD_ICMD;\ + if (mwrite4(mf, offset, value) != 4) {\ + mf->address_domain = AD_CR_SPACE;\ + action_on_fail;\ + }\ + mf->address_domain = AD_CR_SPACE;\ + }while(0) + +#define MREAD4_ICMD(mf, offset, ptr, action_on_fail)\ + do {\ + mf->address_domain = AD_ICMD;\ + if (mread4(mf, offset, ptr) != 4) {\ + mf->address_domain = AD_CR_SPACE;\ + action_on_fail;\ + }\ + mf->address_domain = AD_CR_SPACE;\ + }while(0) + +#define MWRITE_BUF_ICMD(mf, offset, data, byte_len, action_on_fail)\ + do {\ + mf->address_domain = AD_ICMD;\ + if ((unsigned)mwrite_buffer(mf, offset, data, byte_len) != (unsigned)byte_len) {\ + mf->address_domain = AD_CR_SPACE;\ + action_on_fail;\ + }\ + mf->address_domain = AD_CR_SPACE;\ + }while(0) + +#define MREAD_BUF_ICMD(mf, offset, data, byte_len, action_on_fail)\ + do {\ + mf->address_domain = AD_ICMD;\ + if ((unsigned)mread_buffer(mf, offset, data, byte_len) != (unsigned)byte_len) {\ + mf->address_domain = AD_CR_SPACE;\ + action_on_fail;\ + }\ + mf->address_domain = AD_CR_SPACE;\ + }while(0) + +/* + * Macros for accessing semaphore space + */ +#define MWRITE4_SEMAPHORE(mf, offset, value, action_on_fail)\ + do {\ + mf->address_domain = AD_SEMAPHORE;\ + if (mwrite4(mf, offset, value) != 4) {\ + mf->address_domain = AD_CR_SPACE;\ + action_on_fail;\ + }\ + mf->address_domain = AD_CR_SPACE;\ + }while(0) + + +#define MREAD4_SEMAPHORE(mf, offset, ptr, action_on_fail)\ + do {\ + mf->address_domain = AD_SEMAPHORE;\ + if (mread4(mf, offset, ptr) != 4) {\ + mf->address_domain = AD_CR_SPACE;\ + action_on_fail;\ + }\ + mf->address_domain = AD_CR_SPACE;\ + }while(0) + + #ifdef _DEBUG_MODE #define DBG_PRINTF(...) fprintf(stderr, __VA_ARGS__) #else @@ -127,13 +193,13 @@ static int go(mfile *mf) { DBG_PRINTF("Go()\n"); - if (MREAD4(mf, mf->icmd.ctrl_addr, ®)) return ME_ICMD_STATUS_CR_FAIL; + MREAD4_ICMD(mf, mf->icmd.ctrl_addr, ®, return ME_ICMD_STATUS_CR_FAIL); busy = EXTRACT(reg, BUSY_BITOFF, BUSY_BITLEN); if (busy) return ME_ICMD_STATUS_IFC_BUSY; reg = MERGE(reg, 1, BUSY_BITOFF, BUSY_BITLEN); - if (MWRITE4(mf, mf->icmd.ctrl_addr, reg)) return ME_ICMD_STATUS_CR_FAIL; + MWRITE4_ICMD(mf, mf->icmd.ctrl_addr, reg, return ME_ICMD_STATUS_CR_FAIL); DBG_PRINTF("Busy-bit raised. Waiting for command to exec...\n"); @@ -151,7 +217,7 @@ static int go(mfile *mf) { msleep(wait); // don't hog the cpu with busy-wait if (wait < 8) wait *= 2; // exponential backoff - up-to 8ms between polls } - if (MREAD4(mf, mf->icmd.ctrl_addr, ®)) return ME_ICMD_STATUS_CR_FAIL; + MREAD4_ICMD(mf, mf->icmd.ctrl_addr, ®, return ME_ICMD_STATUS_CR_FAIL); busy = EXTRACT(reg, BUSY_BITOFF, BUSY_BITLEN); } while (busy); @@ -167,9 +233,9 @@ static int go(mfile *mf) { static int set_opcode(mfile *mf, u_int16_t opcode) { u_int32_t reg; - if (MREAD4(mf, mf->icmd.ctrl_addr, ®)) return ME_ICMD_STATUS_CR_FAIL; + MREAD4_ICMD(mf, mf->icmd.ctrl_addr, ®, return ME_ICMD_STATUS_CR_FAIL); reg = MERGE(reg, opcode, OPCODE_BITOFF, OPCODE_BITLEN); - if (MWRITE4(mf, mf->icmd.ctrl_addr, reg)) return ME_ICMD_STATUS_CR_FAIL; + MWRITE4_ICMD(mf, mf->icmd.ctrl_addr, reg, return ME_ICMD_STATUS_CR_FAIL); return ME_OK; } @@ -203,7 +269,7 @@ static int translate_status(int status) { static int get_status(mfile *mf) { u_int32_t reg; - if (MREAD4(mf, mf->icmd.ctrl_addr, ®)) return ME_ICMD_STATUS_CR_FAIL; + MREAD4_ICMD(mf, mf->icmd.ctrl_addr, ®, return ME_ICMD_STATUS_CR_FAIL); return translate_status(EXTRACT(reg, STATUS_BITOFF, STATUS_BITLEN)); } @@ -240,7 +306,7 @@ int icmd_clear_semaphore(mfile *mf) { return ret; } - if (MWRITE4(mf, mf->icmd.semaphore_addr, 0)) return ME_ICMD_STATUS_CR_FAIL; + MWRITE4_SEMAPHORE(mf, mf->icmd.semaphore_addr, 0, return ME_ICMD_STATUS_CR_FAIL); mf->icmd.took_semaphore = 0; return ME_OK; } @@ -263,7 +329,7 @@ int icmd_take_semaphore(mfile *mf) { if (++retries > 256) { return ME_ICMD_STATUS_SEMAPHORE_TO; } - if (MREAD4(mf, mf->icmd.semaphore_addr, &r)) return ME_ICMD_STATUS_CR_FAIL; + MREAD4_SEMAPHORE(mf, mf->icmd.semaphore_addr, &r, return ME_ICMD_STATUS_CR_FAIL); if (! r) break; msleep(rand() % 20); @@ -295,16 +361,21 @@ int icmd_send_command_int(mfile *mf, IN int skip_write) { - int ret; - // open icmd interface by demand - if ((ret = icmd_open(mf))) { - return ret; - } + int ret; + // open icmd interface by demand + if ((ret = icmd_open(mf))) { + return ret; + } + // check data size does not exceed mailbox size + if (write_data_size > (int)mf->icmd.max_cmd_size || \ + read_data_size > (int)mf->icmd.max_cmd_size ) { + return ME_ICMD_SIZE_EXCEEDS_LIMIT; + } - if ((ret = icmd_is_cmd_ifc_ready(mf))) - { - return ret; - } + if ((ret = icmd_is_cmd_ifc_ready(mf))) + { + return ret; + } if ((ret = icmd_take_semaphore(mf))) { return ret; @@ -316,9 +387,7 @@ int icmd_send_command_int(mfile *mf, if (!skip_write) { - if ((ret = MWRITE_BUF(mf, mf->icmd.cmd_addr, data, write_data_size))) { - goto cleanup; - } + MWRITE_BUF_ICMD(mf, mf->icmd.cmd_addr, data, write_data_size, ret=ME_ICMD_STATUS_CR_FAIL; goto cleanup;); } if ((ret = go(mf))) { @@ -329,9 +398,7 @@ int icmd_send_command_int(mfile *mf, goto cleanup; } - if ((ret = MREAD_BUF(mf, mf->icmd.cmd_addr, data, read_data_size))) { - goto cleanup; - } + MREAD_BUF_ICMD(mf, mf->icmd.cmd_addr, data, read_data_size, ret=ME_ICMD_STATUS_CR_FAIL; goto cleanup;); ret = ME_OK; cleanup: @@ -341,19 +408,13 @@ cleanup: static int icmd_init_vcr(mfile* mf) { - // check signature - char sig[sizeof(VCR_MAGIC_PAT) + 1] = {0}; - if (mread_buffer(mf, VCR_CAP_ADDR, (u_int8_t*)sig, 4) != 4) { - return ME_CR_ERROR; - } - - if (strncmp(VCR_MAGIC_PAT, sig, sizeof(VCR_MAGIC_PAT))) { - return ME_ICMD_BAD_SIGNATURE; - } - // we support iCMD via virtual cr-space , update addressess accordingly mf->icmd.cmd_addr = VCR_CMD_ADDR; mf->icmd.ctrl_addr = VCR_CTRL_ADDR; mf->icmd.semaphore_addr = VCR_SEMAPHORE62; + + // get max command size + MREAD4_ICMD(mf,VCR_CMD_SIZE_ADDR, &(mf->icmd.max_cmd_size), return ME_ICMD_STATUS_CR_FAIL;); + // adrianc: they should provide this bit as well in virtual cr-space atm get from cr-space GET_ADDR(mf,STAT_CFG_NOT_DONE_ADDR_CIB, STAT_CFG_NOT_DONE_ADDR_CX4, STAT_CFG_NOT_DONE_ADDR_SW_IB, mf->icmd.static_cfg_not_done_addr); GET_ADDR(mf, STAT_CFG_NOT_DONE_BITOFF_CIB, STAT_CFG_NOT_DONE_BITOFF_CIB, STAT_CFG_NOT_DONE_BITOFF_SW_IB, mf->icmd.static_cfg_not_done_offs); @@ -363,24 +424,14 @@ static int icmd_init_vcr(mfile* mf) int icmd_open(mfile *mf) { - u_int32_t access_type; - int ret; - if (mf->icmd.icmd_opened) { return ME_OK; } + mf->icmd.took_semaphore = 0; // check if we support icmd in virtual CR-Space - if (mget_mdevs_type(mf, &access_type)) { - return ME_ICMD_BAD_PARAM; - } - - if (access_type == MTCR_ACCESS_CONFIG) { - // check signature - ret = icmd_init_vcr(mf); - if (ret != ME_ICMD_BAD_SIGNATURE) { - return ret; - } + if (mf->supp_fw_ifc) { + return icmd_init_vcr(mf); } return ME_ICMD_NOT_SUPPORTED; }