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
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,
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,
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
*/
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);
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
}
} 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;
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;
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;
#include <sys/ioctl.h>
#endif
+#include <bit_slice.h>
#include <mtcr.h>
#include "tools_utils.h"
#include "mtcr_int_defs.h"
int fd;
};
+/* Forward decl*/
+static int get_inband_dev_from_pci(char* inband_dev, char* pci_dev);
+
/*
* Lock file section:
*
#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) {
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;
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;
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 <device>/config writes, overriding higher bits.
* Make sure the high bit is set in some signature bytes,
}
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;
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:
#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;
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);
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;
return 0;
}
+int msupp_fw_ifc_cap(mfile* mf) {
+ return mf->supp_fw_ifc;
+}
+
/************************************
* Function: m_err2str
************************************/
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";
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:
* 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)
(((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)
(((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
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");
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);
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;
}
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));
}
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;
}
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);
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;
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))) {
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:
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);
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;
}