]> git.openfabrics.org - ~adrianc/mstflint.git/commitdiff
- addedd support for next gen devices that support new pci capability (0x9)
authorAdrian Chiris <adrianc@mellanox.com>
Mon, 8 Dec 2014 08:55:24 +0000 (10:55 +0200)
committerAdrian Chiris <adrianc@mellanox.com>
Mon, 8 Dec 2014 08:55:24 +0000 (10:55 +0200)
     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

include/mtcr_ul/mtcr.h
mflash/mflash.c
mtcr_ul/mtcr_int_defs.h
mtcr_ul/mtcr_ul.c
mtcr_ul/mtcr_ul_icmd_cif.c

index 9f56c333605641a662877814211b30438679e470..ca584cff527c17636d6be362c3fb1522135372a2 100644 (file)
@@ -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
 }
index 69d78522656f37a7d88104397ea3f9b87b5984b1..54764986be5451431320521fc22ad160a4a62130 100644 (file)
@@ -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;
index fb2e5054551553d7a3b33d32b05520ad01f1282c..6f598bd3e4a27b40d467cca426081170e3a6da83 100644 (file)
@@ -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;
index a54e70b06e4fd826d6a35396df6b4857f2de9a18..3b36be510c39d0d31a6d01805bf3320e2578ab2a 100644 (file)
@@ -82,6 +82,7 @@
 #include <sys/ioctl.h>
 #endif
 
+#include <bit_slice.h>
 #include <mtcr.h>
 #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 <device>/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:
index 0bfa979685b2483e79f3b4f22d7b6effd0de4c84..61d2d7f19f50a741258d6e005e9fd5f93bbf347f 100644 (file)
  * 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
@@ -127,13 +193,13 @@ static int go(mfile *mf) {
 
     DBG_PRINTF("Go()\n");
 
-    if (MREAD4(mf, mf->icmd.ctrl_addr, &reg)) return ME_ICMD_STATUS_CR_FAIL;
+    MREAD4_ICMD(mf, mf->icmd.ctrl_addr, &reg, 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, &reg)) return ME_ICMD_STATUS_CR_FAIL;
+        MREAD4_ICMD(mf, mf->icmd.ctrl_addr, &reg, 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, &reg)) return ME_ICMD_STATUS_CR_FAIL;
+    MREAD4_ICMD(mf, mf->icmd.ctrl_addr, &reg, 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, &reg)) return ME_ICMD_STATUS_CR_FAIL;
+    MREAD4_ICMD(mf, mf->icmd.ctrl_addr, &reg, 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;
 }