openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

reg.c (63213B)


      1 /* 
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * socdiag register commands
      8  */
      9 
     10 #include <shared/bsl.h>
     11 
     12 #include <sal/core/libc.h>
     13 #include <shared/bsl.h>
     14 #include <soc/counter.h>
     15 #include <sal/appl/pci.h>
     16 #include <soc/debug.h>
     17 #ifdef BCM_IPROC_SUPPORT
     18 #include <soc/iproc.h>
     19 #endif
     20 
     21 #include <appl/diag/system.h>
     22 #include <appl/diag/sysconf.h>
     23 #include <ibde.h>
     24 
     25 /* 
     26  * Utility routine to concatenate the first argument ("first"), with
     27  * the remaining arguments, with commas separating them.
     28  */
     29 
     30 static void
     31 collect_comma_args(args_t *a, char *valstr, char *first)
     32 {
     33     char           *s;
     34 
     35     sal_strcpy(valstr, first);
     36 
     37     while ((s = ARG_GET(a)) != 0) {
     38 	sal_strcat(valstr, ",");
     39 	sal_strcat(valstr, s);
     40     }
     41 }
     42 
     43 /* 
     44  * Utility routine to determine whether register type requires
     45  * block and access type information.
     46  */
     47 
     48 static int 
     49 reg_type_is_schan_reg(int reg_type)
     50 {
     51     switch (reg_type) {
     52     case soc_schan_reg:
     53     case soc_genreg:
     54     case soc_portreg:
     55     case soc_ppportreg:
     56     case soc_cosreg:
     57         return 1;
     58     default:
     59         break;
     60     }
     61     return 0;
     62 }
     63 
     64 /* 
     65  * modify_reg_fields
     66  *
     67  *   Takes a soc_reg_t 'regno', pointer to current value 'val',
     68  *   and a string 'mod' containing a field replacement spec of the form
     69  *   "FIELD=value".   The string may contain more than one spec separated
     70  *   by commas.  Updates the field in the register value accordingly,
     71  *   leaving all other unmodified fields intact.  If the string CLEAR is
     72  *   present in the list, the current register value is zeroed.
     73  *   If mask is non-NULL, it receives a mask of all fields modified.
     74  *
     75  *   Examples with modreg:
     76  *        modreg fe_mac1 lback=1        (modifies only lback field)
     77  *        modreg config ip_cfg=2        (modifies only ip_cfg field)
     78  *        modreg config clear,ip_cfg=2,cpu_pri=4  (zeroes all other fields)
     79  *
     80  *   Note that if "clear" appears in the middle of the list, the
     81  *   values in the list before "clear" are ignored.
     82  *
     83  *   Returns CMD_FAIL on failure, CMD_OK on success.
     84  */
     85 
     86 static int
     87 modify_reg_fields(int unit, soc_reg_t regno,
     88 		  uint64 *val, uint64 *mask /* out param */, char *mod)
     89 {
     90     soc_field_info_t *fld;
     91     char           *fmod, *fval;
     92     char           *modstr;
     93     char           *tokstr;
     94     soc_reg_info_t *reg = &SOC_REG_INFO(unit, regno);
     95     uint64          fvalue;
     96     uint64          fldmask;
     97     uint64          tmask;
     98 
     99     if ((modstr = sal_alloc(ARGS_BUFFER, "modify_reg")) == NULL) {
    100         cli_out("modify_reg_fields: Out of memory\n");
    101         return CMD_FAIL;
    102     }
    103 
    104     sal_strncpy(modstr, mod, ARGS_BUFFER);/* Don't destroy input string */
    105     modstr[ARGS_BUFFER - 1] = 0;
    106     mod = modstr;
    107 
    108     if (mask) {
    109 	COMPILER_64_ZERO(*mask);
    110     }
    111 
    112     while ((fmod = sal_strtok_r(mod, ",", &tokstr)) != 0) {
    113 	mod = NULL;		       /* Pass strtok NULL next time */
    114 	fval = sal_strchr(fmod, '=');
    115 	if (fval) {		       /* Point fval to arg, NULL if none */
    116 	    *fval++ = 0;	       /* Now fmod holds only field name. */
    117 	}
    118 	if (fmod[0] == 0) {
    119 	    cli_out("Null field name\n");
    120             sal_free(modstr);
    121 	    return CMD_FAIL;
    122 	}
    123 	if (!sal_strcasecmp(fmod, "clear")) {
    124 	    COMPILER_64_ZERO(*val);
    125 	    if (mask) {
    126 		COMPILER_64_ALLONES(*mask);
    127 	    }
    128 	    continue;
    129 	}
    130 	for (fld = &reg->fields[0]; fld < &reg->fields[reg->nFields]; fld++) {
    131 	    if (!sal_strcasecmp(fmod, SOC_FIELD_NAME(unit, fld->field))) {
    132 		break;
    133 	    }
    134 	}
    135 	if (fld == &reg->fields[reg->nFields]) {
    136 	    cli_out("No such field \"%s\" in register \"%s\".\n",
    137                     fmod, SOC_REG_NAME(unit, regno));
    138             sal_free(modstr);
    139 	    return CMD_FAIL;
    140 	}
    141 	if (!fval) {
    142 	    cli_out("Missing %d-bit value to assign to \"%s\" "
    143                     "field \"%s\".\n",
    144                     fld->len, SOC_REG_NAME(unit, regno), SOC_FIELD_NAME(unit, fld->field));
    145             sal_free(modstr);
    146 	    return CMD_FAIL;
    147 	}
    148 	fvalue = parse_uint64(fval);
    149 
    150 	/* Check that field value fits in field */
    151 	COMPILER_64_MASK_CREATE(tmask, fld->len, 0);
    152 	COMPILER_64_NOT(tmask);
    153 	COMPILER_64_AND(tmask, fvalue);
    154 
    155 	if (!COMPILER_64_IS_ZERO(tmask)) {
    156 	    cli_out("Value \"%s\" too large for %d-bit field \"%s\".\n",
    157                     fval, fld->len, SOC_FIELD_NAME(unit, fld->field));
    158             sal_free(modstr);
    159 	    return CMD_FAIL;
    160 	}
    161 
    162 	if (reg->flags & SOC_REG_FLAG_64_BITS) {
    163 	    soc_reg64_field_set(unit, regno, val, fld->field, fvalue);
    164 	} else {
    165 	    uint32          tmp;
    166             uint32 ftmp;
    167 	    COMPILER_64_TO_32_LO(tmp, *val);
    168 	    COMPILER_64_TO_32_LO(ftmp, fvalue);
    169 	    soc_reg_field_set(unit, regno, &tmp, fld->field, ftmp);
    170 	    COMPILER_64_SET(*val, 0, tmp);
    171 	    COMPILER_64_SET(fvalue, 0, ftmp);
    172 	}
    173 
    174 	COMPILER_64_MASK_CREATE(fldmask, fld->len, fld->bp);
    175 	if (mask) {
    176 	    COMPILER_64_OR(*mask, fldmask);
    177 	}
    178     }
    179 
    180     sal_free(modstr);
    181     return CMD_OK;
    182 }
    183 
    184 #define PRINT_COUNT(str, len, wrap, prefix) \
    185     if ((wrap > 0) && (len > wrap)) { \
    186         cli_out("\n%s", prefix); \
    187         len = sal_strlen(prefix); \
    188     } \
    189     cli_out("%s", str); \
    190     len += sal_strlen(str)
    191 
    192 
    193 /* 
    194  * Print a SOC internal register with fields broken out.
    195  */
    196 void
    197 reg_print(int unit, soc_regaddrinfo_t *ainfo, uint64 val, uint32 flags,
    198 	  char *fld_sep, int wrap, char *field_names)
    199 {
    200     soc_reg_info_t *reginfo = &SOC_REG_INFO(unit, ainfo->reg);
    201     int             f;
    202     uint64          val64, resval, resfld;
    203     char            buf[80];
    204     char            line_buf[256];
    205     int		    linelen = 0;
    206     int		    nprint;
    207     int32           addr32 = ainfo->addr;
    208     char            temp_field_name[80];
    209 
    210     if (flags & REG_PRINT_HEX) {
    211 	if (SOC_REG_IS_64(unit, ainfo->reg)) {
    212 	    cli_out("%08x%08x\n",
    213                     COMPILER_64_HI(val),
    214                     COMPILER_64_LO(val));
    215 	} else {
    216 	    cli_out("%08x\n",
    217                     COMPILER_64_LO(val));
    218 	}
    219 	return;
    220     }
    221 
    222     if (flags & REG_PRINT_CHG) {
    223 	SOC_REG_RST_VAL_GET(unit, ainfo->reg, resval);
    224 	if (COMPILER_64_EQ(val, resval)) {	/* no changed fields */
    225 	    return;
    226 	}
    227     } else {
    228 	COMPILER_64_ZERO(resval);
    229     }
    230 
    231     soc_reg_sprint_addr(unit, buf, ainfo);
    232 
    233     if (soc_feature(unit, soc_feature_new_sbus_format)) {
    234         sal_sprintf(line_buf, "%s[%d][0x%x]=", buf, 
    235                     SOC_BLOCK_INFO(unit, ainfo->block).cmic,
    236                     addr32);
    237     } else {
    238         sal_sprintf(line_buf, "%s[0x%x]=", buf, addr32);
    239     }
    240     PRINT_COUNT(line_buf, linelen, wrap, "   ");
    241 
    242     format_uint64(line_buf, val);
    243     PRINT_COUNT(line_buf, linelen, -1, "");
    244 
    245     if (flags & REG_PRINT_RAW) {
    246 	cli_out("\n");
    247 	return;
    248     }
    249 
    250     PRINT_COUNT(": <", linelen, wrap, "   ");
    251 
    252     nprint = 0;
    253     for (f = reginfo->nFields - 1; f >= 0; f--) {
    254 	soc_field_info_t *fld = &reginfo->fields[f];
    255 	val64 = soc_reg64_field_get(unit, ainfo->reg, val, fld->field);
    256         if (field_names != NULL) {
    257             sal_strncpy(temp_field_name, ",", 2);
    258             sal_strncat(temp_field_name, SOC_FIELD_NAME(unit, fld->field),
    259                         sizeof(temp_field_name) - 4);
    260             sal_strncat(temp_field_name, ",", 1 );
    261             if (sal_strstr(field_names, temp_field_name) == NULL) {
    262                 continue;
    263             }
    264         }
    265 	if (flags & REG_PRINT_CHG) {
    266 	    resfld = soc_reg64_field_get(unit, ainfo->reg, resval, fld->field);
    267 	    if (COMPILER_64_EQ(val64, resfld)) {
    268 		continue;
    269 	    }
    270 	}
    271 
    272 	if (nprint > 0) {
    273 	    sal_sprintf(line_buf, "%s", fld_sep);
    274             PRINT_COUNT(line_buf, linelen, -1, "");
    275 	}
    276 	sal_sprintf(line_buf, "%s=", SOC_FIELD_NAME(unit, fld->field));
    277 
    278         PRINT_COUNT(line_buf, linelen, wrap, "   ");
    279 	format_uint64(line_buf, val64);
    280 
    281         PRINT_COUNT(line_buf, linelen, -1, "");
    282 	nprint += 1;
    283     }
    284 
    285     cli_out(">\n");
    286 }
    287 
    288  /* 
    289   * modify_reg_above_64_fields
    290   *     
    291   * Exclusive function for modifying register having width >64b  
    292   * 
    293   * Returns -1 on failure, 0 on success
    294  */
    295  static int
    296  modify_reg_above_64_fields(int unit, 
    297                             soc_reg_t regno,
    298                             soc_reg_above_64_val_t val, 
    299                             soc_reg_above_64_val_t *mask,
    300                             char *mod)
    301  {
    302      soc_field_info_t *fld;
    303      char           *fmod, *fval;
    304      char           *modstr;
    305      soc_reg_info_t *reg = &SOC_REG_INFO(unit, regno);
    306      soc_reg_above_64_val_t  fvalue, tmask, fldmask;
    307      char *tokstr;
    308  
    309      if ((modstr = sal_alloc(ARGS_BUFFER, "modify_reg")) == NULL) {
    310          cli_out( "modify_reg_fields: Out of memory\n");
    311          return CMD_FAIL;
    312      }
    313  
    314      strncpy(modstr, mod, ARGS_BUFFER);/* Don't destroy input string */
    315      modstr[ARGS_BUFFER - 1] = 0;
    316      mod = modstr;
    317      if (mask) {
    318          SOC_REG_ABOVE_64_CLEAR(*mask);
    319      }
    320  
    321      while ((fmod = sal_strtok_r(mod, ",", &tokstr)) != 0) {
    322          mod = NULL;            /* Pass strtok NULL next time */
    323          fval = strchr(fmod, '=');
    324          if (fval) {            /* Point fval to arg, NULL if none */
    325              *fval++ = 0;       /* Now fmod holds only field name. */
    326          }
    327          if (fmod[0] == 0) {
    328              cli_out( "Null field name\n");
    329              sal_free(modstr);
    330              return -1;
    331          }
    332          if (!sal_strcasecmp(fmod, "clear")) {
    333              SOC_REG_ABOVE_64_CLEAR(val);
    334              if (mask) {
    335                  SOC_REG_ABOVE_64_ALLONES(*mask);
    336              }
    337              continue;
    338          }
    339          for (fld = &reg->fields[0]; fld < &reg->fields[reg->nFields]; fld++) {
    340              if (!sal_strcasecmp(fmod, SOC_FIELD_NAME(unit, fld->field))) {
    341                  break;
    342              }
    343          }
    344          if (fld == &reg->fields[reg->nFields]) {
    345              cli_out( "No such field \"%s\" in register \"%s\".\n",
    346                     fmod, SOC_REG_NAME(unit, regno));
    347              sal_free(modstr);
    348              return -1;
    349          }
    350          if (!fval) {
    351              cli_out( "Missing %d-bit value to assign to \"%s\" field \"%s\".\n",
    352                     fld->len, SOC_REG_NAME(unit, regno),
    353                     SOC_FIELD_NAME(unit, fld->field));
    354              sal_free(modstr);
    355              return -1;
    356          }
    357          parse_long_integer(fvalue, SOC_REG_ABOVE_64_MAX_SIZE_U32, fval);
    358          /* Check that field value fits in field */
    359          SOC_REG_ABOVE_64_CREATE_MASK(tmask, fld->len, 0)
    360          SOC_REG_ABOVE_64_NOT(tmask)
    361          SOC_REG_ABOVE_64_AND(tmask, fvalue)
    362  
    363          if (!SOC_REG_ABOVE_64_IS_ZERO(tmask)) {
    364              cli_out( "Value \"%s\" too large for %d-bit field \"%s\".\n",
    365                     fval, fld->len, SOC_FIELD_NAME(unit, fld->field));
    366              sal_free(modstr);
    367              return -1;
    368          }
    369  
    370  
    371         soc_reg_above_64_field_set(unit, regno, val, fld->field, fvalue);
    372  
    373  
    374          SOC_REG_ABOVE_64_CREATE_MASK(fldmask, fld->len, fld->bp);
    375          if (mask) {
    376              SOC_REG_ABOVE_64_OR(*mask, fldmask);
    377          }
    378      }
    379      sal_free(modstr);
    380      return 0;
    381  }
    382  
    383  /* 
    384   * reg_above_64_print
    385   *
    386   * Print a SOC internal register with fields broken out.
    387   * This is a exclusive function for printing registers having width >64b  
    388  */
    389  void 
    390  reg_above_64_print(int unit, 
    391                     soc_regaddrinfo_t *ainfo, 
    392                     soc_reg_above_64_val_t val, 
    393                     uint32 flags,
    394                     char *fld_sep, 
    395                     int wrap)
    396  {
    397      soc_reg_info_t *reginfo = &SOC_REG_INFO(unit, ainfo->reg);
    398      int             f;
    399      char            buf[80];
    400      char            line_buf[256];
    401      int             linelen = 0;
    402      int             nprint;
    403      int             rlen;
    404      int             skip;
    405      soc_reg_above_64_val_t          resval, fieldval, resfld;
    406  
    407      if (flags & REG_PRINT_HEX) {
    408          format_long_integer(line_buf, val, SOC_REG_ABOVE_64_MAX_SIZE_U32);
    409          cli_out( "%s\n", line_buf);
    410          return;
    411      }
    412  
    413      if (flags & REG_PRINT_ADDR ) {
    414          if(SOC_REG_IS_ABOVE_64(unit, ainfo->reg)) {
    415              rlen = SOC_REG_ABOVE_64_INFO(unit, ainfo->reg).size;
    416          } else if (SOC_REG_IS_64(unit, ainfo->reg)){
    417              rlen = 2;
    418          } else {
    419              rlen = 1;
    420          }
    421          format_spec_long_integer(line_buf, val, rlen);
    422  
    423          skip = 0;
    424          if(SOC_REG_IS_ARRAY(unit, ainfo->reg)) {
    425              skip = ainfo->idx*SOC_REG_ARRAY_INFO(unit, ainfo->reg).element_skip;
    426          } else if (SOC_REG_ARRAY(unit, ainfo->reg)) {
    427              if (SOC_REG_ARRAY2(unit, ainfo->reg)) {
    428                  skip = ainfo->idx*2;
    429              } else {
    430                  skip = ainfo->idx;
    431              }
    432          }
    433          cli_out( "0x%02X 0x%04X: %s\n",SOC_BLOCK_INFO(unit, ainfo->block).schan,SOC_REG_INFO(unit,ainfo->reg).offset + skip, line_buf);
    434          return;
    435      }
    436  
    437      if (flags & REG_PRINT_CHG) {
    438          SOC_REG_ABOVE_64_RST_VAL_GET(unit, ainfo->reg, resval);
    439          if (SOC_REG_ABOVE_64_IS_EQUAL(val, resval)) {    /* no changed fields */
    440              return;
    441          }
    442      } else {
    443          SOC_REG_ABOVE_64_CLEAR(resval);
    444      }
    445  
    446      soc_reg_sprint_addr(unit, buf, ainfo);
    447  
    448      sal_sprintf(line_buf, "%s[0x%x]=", buf, ainfo->addr);
    449      PRINT_COUNT(line_buf, linelen, wrap, "   ");
    450  
    451      format_long_integer(line_buf, val, SOC_REG_ABOVE_64_MAX_SIZE_U32);
    452      PRINT_COUNT(line_buf, linelen, -1, "");
    453  
    454      if (flags & REG_PRINT_RAW) {
    455          cli_out( "\n");
    456          return;
    457      }
    458  
    459      PRINT_COUNT(": <", linelen, wrap, "   ");
    460  
    461      nprint = 0;
    462      for (f = reginfo->nFields - 1; f >= 0; f--) {
    463          soc_field_info_t *fld = &reginfo->fields[f];
    464          soc_reg_above_64_field_get(unit, ainfo->reg, val, fld->field, fieldval);
    465          if (flags & REG_PRINT_CHG) {
    466              soc_reg_above_64_field_get(unit, ainfo->reg, resval, fld->field, resfld);
    467              if (SOC_REG_ABOVE_64_IS_EQUAL(fieldval, resfld)) {
    468                  continue;
    469              }
    470          }
    471           {
    472              if (nprint > 0)
    473              {
    474                  sal_sprintf(line_buf, "%s", fld_sep);
    475                  PRINT_COUNT(line_buf, linelen, -1, "");
    476              }
    477              sal_sprintf(line_buf, "%s=", SOC_FIELD_NAME(unit, fld->field));
    478  
    479              PRINT_COUNT(line_buf, linelen, wrap, "   ");
    480              format_long_integer(line_buf, fieldval, (fld->len+31)/32);
    481              PRINT_COUNT(line_buf, linelen, -1, "");
    482  
    483          }
    484  
    485          nprint += 1;
    486          /*cli_out( "\n");*/
    487  
    488      }
    489  
    490      cli_out( ">\n");
    491  }
    492  
    493  
    494  
    495 
    496 /* 
    497  * Reads and displays all SOC registers specified by alist structure.
    498  */
    499 int
    500 reg_print_all(int unit, soc_regaddrlist_t *alist, uint32 flags, 
    501               char *field_names)
    502 {
    503     int             j;
    504     uint64          value;
    505     int             r, rv = 0;
    506     soc_regaddrinfo_t *ainfo;
    507     soc_reg_above_64_val_t value_above_64;
    508 
    509     assert(alist);
    510 
    511     for (j = 0; j < alist->count; j++) {
    512 	ainfo = &alist->ainfo[j];
    513         if (SOC_REG_IS_ABOVE_64(unit, ainfo->reg)) {
    514             SOC_IF_ERROR_RETURN(soc_reg_above_64_get(
    515                                 unit, ainfo->reg, ainfo->port, 
    516                                 SOC_REG_IS_ARRAY(unit, ainfo->reg) ? 
    517                                 ainfo->idx : 0, value_above_64));
    518             reg_above_64_print(unit, ainfo, value_above_64, flags, ",", 62 );
    519             continue;
    520         }
    521 	if ((r = soc_anyreg_read(unit, ainfo, &value)) < 0) {
    522 	    char            buf[80];
    523 	    soc_reg_sprint_addr(unit, buf, ainfo);
    524 	    cli_out("ERROR: read from register %s failed: %s\n",
    525                     buf, soc_errmsg(r));
    526 	    rv = -1;
    527 	} else {
    528 	    reg_print(unit, ainfo, value, flags, ",", 62, field_names);
    529 	}
    530     }
    531 
    532     return rv;
    533 }
    534 
    535 /*
    536  * Register Types - for getreg and dump commands
    537  */
    538 
    539 static regtype_entry_t regtypes[] = {
    540  { "PCIC",	soc_pci_cfg_reg,"PCI Configuration space" },
    541  { "PCIM",	soc_cpureg,	"PCI Memory space (CMIC)" },
    542  { "MCS",	soc_mcsreg,	"MicroController Subsystem" },
    543  { "IPROC",     soc_iprocreg,   "iProc Subsystem" },
    544  { "SOC",	soc_schan_reg,	"SOC internal registers" },
    545  { "SCHAN",	soc_schan_reg,	"SOC internal registers" },
    546  { "PHY",	soc_phy_reg,	"PHY registers via MII (phyID<<8|phyADDR)" },
    547  { "MW",	soc_hostmem_w,	"Host Memory 32-bit" },
    548  { "MH",	soc_hostmem_h,	"Host Memory 16-bit" },
    549  { "MB",	soc_hostmem_b,	"Host Memory 8-bit" },
    550  { "MEM",	soc_hostmem_w,	"Host Memory 32-bit" },	/* Backward compat */
    551 };
    552 
    553 #define regtypes_count	COUNTOF(regtypes)
    554 
    555 regtype_entry_t *regtype_lookup_name(char* str)
    556 {
    557     int i;
    558 
    559     for (i = 0; i < regtypes_count; i++) {
    560 	if (!sal_strcasecmp(str,regtypes[i].name)) {
    561 	    return &regtypes[i];
    562         }
    563     }
    564 
    565     return 0;
    566 }
    567 
    568 void regtype_print_all(void)
    569 {
    570     int i;
    571 
    572     cli_out("Register types supported by setreg, getreg, and dump:\n");
    573 
    574     for (i = 0; i < regtypes_count; i++)
    575 	cli_out("\t%-10s -%s\n", regtypes[i].name, regtypes[i].help);
    576 }
    577 
    578 /* 
    579  * Get a register by type.
    580  *
    581  * doprint:  Boolean.  If set, display data.
    582  */
    583 int
    584 _reg_get_by_type(int unit, sal_vaddr_t vaddr, soc_block_t block, int acc_type,
    585          soc_regtype_t regtype, uint64 *outval, uint32 flags)
    586 {
    587     int             rv = CMD_OK;
    588     int             r;
    589     uint16          phy_rd_data;
    590     uint32          regaddr = (uint32)vaddr;
    591     soc_regaddrinfo_t ainfo;
    592     int		    is64 = FALSE;
    593     int               blk, cmic, schan, i;
    594 
    595     switch (regtype) {
    596     case soc_pci_cfg_reg:
    597         if (regaddr & 3) {
    598             cli_out("ERROR: PCI config addr must be multiple of 4\n");
    599             rv = CMD_FAIL;
    600         } else {
    601             COMPILER_64_SET(*outval, 0, bde->pci_conf_read(unit, regaddr));
    602         }
    603         break;
    604     case soc_cpureg:
    605         if (regaddr & 3) {
    606             cli_out("ERROR: PCI memory addr must be multiple of 4\n");
    607             rv = CMD_FAIL;
    608         } else {
    609             COMPILER_64_SET(*outval, 0, soc_pci_read(unit, regaddr));
    610         }
    611         break;
    612 #ifdef BCM_CMICM_SUPPORT
    613     case soc_mcsreg:
    614         if (regaddr & 3) {
    615             cli_out("ERROR: MCS memory addr must be multiple of 4\n");
    616             rv = CMD_FAIL;
    617         } else {
    618             COMPILER_64_SET(*outval, 0, soc_pci_mcs_read(unit, regaddr));
    619         }
    620         break;
    621 #endif
    622 #ifdef BCM_IPROC_SUPPORT
    623     case soc_iprocreg:
    624         if (regaddr & 3) {
    625             cli_out("ERROR: iProc memory addr must be multiple of 4\n");
    626             rv = CMD_FAIL;
    627         } else {
    628             COMPILER_64_SET(*outval, 0, soc_cm_iproc_read(unit, regaddr));
    629         }
    630         break;
    631 #endif
    632     case soc_schan_reg:
    633     case soc_genreg:
    634     case soc_portreg:
    635 	case soc_cosreg:
    636     case soc_pipereg:
    637     case soc_xpereg:
    638     case soc_itmreg:
    639     case soc_ebreg:
    640     case soc_slicereg:
    641     case soc_layerreg:
    642         soc_regaddrinfo_extended_get (unit, &ainfo, block, acc_type, regaddr);
    643             if (ainfo.reg >= 0) {
    644             is64 = SOC_REG_IS_64(unit, ainfo.reg);
    645         }
    646         /* Defensive check to ensure that the supplied 'block' is valid */
    647         blk = -1;
    648         for (i = 0; SOC_BLOCK_INFO(unit, i).type >= 0; i++) {
    649             if (regtype == soc_schan_reg) {
    650                 schan = SOC_BLOCK_INFO(unit, i).schan;
    651                 if(schan == block) {
    652                     blk = i;
    653                 }
    654             } else {
    655                 cmic = SOC_BLOCK_INFO(unit, i).cmic;
    656                 if(cmic == block) {
    657                     blk = i;
    658                 }
    659             }
    660         }
    661 
    662         if(blk == -1) {
    663             cli_out("ERROR: Invalid block specified \n");
    664             rv = CMD_FAIL;
    665         }
    666 
    667         if(rv == CMD_OK) {
    668             soc_regaddrinfo_extended_get (unit, &ainfo, block, acc_type, regaddr);
    669             /* Defensive check to ensure that the register extracted is valid */
    670             if (ainfo.reg == -1) {
    671                 cli_out("ERROR: Unable to resolve register with supplied data \n");
    672                 rv = CMD_FAIL;
    673             } else if (ainfo.reg >= 0) {
    674                 is64 = SOC_REG_IS_64(unit, ainfo.reg);
    675             }
    676 
    677             if(rv == CMD_OK) {
    678                 r = soc_anyreg_read(unit, &ainfo, outval);
    679                 if (r < 0) {
    680                     cli_out("ERROR: soc_reg32_read failed: %s\n", soc_errmsg(r));
    681                     rv = CMD_FAIL;
    682                 }
    683             }
    684         }
    685 
    686         break;
    687 
    688     case soc_hostmem_w:
    689         COMPILER_64_SET(*outval, 0, *((uint32 *)INT_TO_PTR(vaddr)));
    690         break;
    691 
    692     case soc_hostmem_h:
    693         COMPILER_64_SET(*outval, 0, *((uint16 *)INT_TO_PTR(vaddr)));
    694         break;
    695 
    696     case soc_hostmem_b:
    697         COMPILER_64_SET(*outval, 0, *((uint8 *)INT_TO_PTR(vaddr)));
    698         break;
    699 
    700     case soc_phy_reg:
    701 	/* Leave for MII debug reads */
    702 	if ((r = soc_miim_read(unit,
    703 			       (uint8) (regaddr >> 8 & 0xff),	/* Phy ID */
    704 			       (uint8) (regaddr & 0xff),	/* Phy addr */
    705 			       &phy_rd_data)) < 0) {
    706 	    cli_out("ERROR: soc_miim_read failed: %s\n", soc_errmsg(r));
    707 	    rv = CMD_FAIL;
    708 	} else {
    709 	    COMPILER_64_SET(*outval, 0, (uint32) phy_rd_data);
    710 	}
    711 	break;
    712 
    713     default:
    714 	assert(0);
    715 	rv = CMD_FAIL;
    716 	break;
    717     }
    718 
    719     if ((rv == CMD_OK) && (flags & REG_PRINT_DO_PRINT)) {
    720 	if (flags & REG_PRINT_HEX) {
    721 	    if (is64) {
    722 		cli_out("%08x%08x\n",
    723                         COMPILER_64_HI(*outval),
    724                         COMPILER_64_LO(*outval));
    725 	    } else {
    726 		cli_out("%08x\n",
    727                         COMPILER_64_LO(*outval));
    728 	    }
    729 	} else {
    730 	    char buf[80];
    731 
    732 	    format_uint64(buf, *outval);
    733 
    734 	    cli_out("%s[%p] = %s\n",
    735                     soc_regtypenames[regtype], INT_TO_PTR(vaddr), buf);
    736 	}
    737     }
    738 
    739     return rv;
    740 }
    741 
    742 /* 
    743  * Set a register by type.  For SOC registers, is64 is used to
    744  * indicate if this is a 64 bit register.  Otherwise, is64 is
    745  * ignored.
    746  */
    747 int
    748 _reg_set_by_type(int unit, sal_vaddr_t vaddr, soc_block_t block, int acc_type,
    749          soc_regtype_t regtype, uint64 regval)
    750 {
    751     int             rv = CMD_OK, r;
    752     uint32          regaddr = (uint32)vaddr;
    753     uint32          val32;
    754     soc_regaddrinfo_t ainfo;
    755     int               blk, cmic, schan, i;
    756 
    757     COMPILER_64_TO_32_LO(val32, regval);
    758 
    759     switch (regtype) {
    760     case soc_pci_cfg_reg:
    761 	bde->pci_conf_write(unit, regaddr, val32);
    762 	break;
    763 
    764     case soc_cpureg:
    765 	soc_pci_write(unit, regaddr, val32);
    766 	break;
    767 
    768 #ifdef BCM_CMICM_SUPPORT
    769     case soc_mcsreg:
    770         soc_pci_mcs_write(unit, regaddr, val32);
    771         break;
    772 #endif
    773 #ifdef BCM_IPROC_SUPPORT
    774     case soc_iprocreg:
    775         soc_cm_iproc_write(unit, regaddr, val32);
    776         break;
    777 #endif
    778     case soc_schan_reg:
    779     case soc_genreg:
    780     case soc_portreg:
    781     case soc_cosreg:
    782     case soc_pipereg:
    783     case soc_xpereg:
    784     case soc_itmreg:
    785     case soc_ebreg:
    786     case soc_slicereg:
    787     case soc_layerreg:
    788         /* Defensive check to ensure that the supplied 'block' is valid */
    789         blk = -1;
    790         for (i = 0; SOC_BLOCK_INFO(unit, i).type >= 0; i++) {
    791             if (regtype == soc_schan_reg) {
    792                 schan = SOC_BLOCK_INFO(unit, i).schan;
    793                 if(schan == block) {
    794                     blk = i;
    795                 }
    796             } else {
    797                 cmic = SOC_BLOCK_INFO(unit, i).cmic;
    798                 if(cmic == block) {
    799                     blk = i;
    800                 }
    801             }
    802         }
    803 
    804         if(blk == -1) {
    805             cli_out("ERROR: Invalid block specified \n");
    806             rv = CMD_FAIL;
    807         }
    808 
    809         if(rv == CMD_OK) {
    810             soc_regaddrinfo_extended_get(unit, &ainfo, block, acc_type, regaddr);
    811 
    812             /* Defensive check to ensure that the register extracted is valid */
    813             if (ainfo.reg == -1) {
    814                 cli_out("ERROR: Unable to resolve register with supplied data \n");
    815                 rv = CMD_FAIL;
    816             }
    817             else {
    818                 r = soc_anyreg_write(unit, &ainfo, regval);
    819                 if (r < 0) {
    820                     cli_out("ERROR: write reg failed: %s\n", soc_errmsg(r));
    821                     rv = CMD_FAIL;
    822                 }
    823            }
    824        }
    825 
    826         break;
    827 
    828     case soc_hostmem_w:
    829         *((uint32 *)INT_TO_PTR(vaddr)) = val32;
    830         break;
    831 
    832     case soc_hostmem_h:
    833         *((uint16 *)INT_TO_PTR(vaddr)) = val32;
    834         break;
    835 
    836     case soc_hostmem_b:
    837         *((uint8 *)INT_TO_PTR(vaddr)) = val32;
    838         break;
    839 
    840     case soc_phy_reg:
    841 	/* Leave for MII debug writes */
    842 	if ((r = soc_miim_write(unit,
    843 				(uint8) (regaddr >> 8 & 0xff),	/* Phy ID */
    844 				(uint8) (regaddr & 0xff),	/* Phy addr */
    845 				(uint16) val32)) < 0) {
    846 	    cli_out("ERROR: write miim failed: %s\n", soc_errmsg(r));
    847 	    rv = CMD_FAIL;
    848 	}
    849 	break;
    850 
    851     default:
    852 	assert(0);
    853 	rv = CMD_FAIL;
    854 	break;
    855     }
    856 
    857     return rv;
    858 }
    859 
    860 /* 
    861  * Gets a memory value or register from the SOC.
    862  * Syntax: getreg [<regtype>] <offset|symbol>
    863  */
    864 
    865 cmd_result_t
    866 cmd_esw_reg_get(int unit, args_t *a)
    867 {
    868     uint64          regval;
    869     uint32          regaddr = 0;
    870     sal_vaddr_t     vaddr;
    871     int             rv = CMD_OK, acc_type = 0;
    872     regtype_entry_t *rt;
    873     soc_regaddrlist_t alist;
    874     char           *name, *block, *access_type;
    875     uint32          flags = REG_PRINT_DO_PRINT;
    876     soc_block_t blk_num = 0;
    877     char *field_names = NULL, *temp_field_name = NULL;
    878     uint8 offset=0;
    879 
    880     if (0 == sh_check_attached(ARG_CMD(a), unit)) {
    881         return CMD_FAIL;
    882     }
    883 
    884     /* 
    885      * If first arg is a register type, take it and use the next argument
    886      * as the name or address, otherwise default to register type "soc."
    887      */
    888     name = ARG_GET(a);
    889 
    890     for (;;) {
    891         if (name != NULL && !sal_strcasecmp(name, "raw")) {
    892             flags |= REG_PRINT_RAW;
    893             name = ARG_GET(a);
    894         } else if (name != NULL && !sal_strcasecmp(name, "hex")) {
    895             flags |= REG_PRINT_HEX;
    896             name = ARG_GET(a);
    897         } else if (name != NULL && !sal_strcasecmp(name, "chg")) {
    898             flags |= REG_PRINT_CHG;
    899             name = ARG_GET(a);
    900         } else {
    901             break;
    902         }
    903     }
    904 
    905     if (name == NULL) {
    906         return CMD_USAGE;
    907     }
    908 
    909     if ((rt = regtype_lookup_name(name)) != 0) {
    910         if ((name = ARG_GET(a)) == 0) {
    911             return CMD_USAGE;
    912         }
    913     } else {
    914         rt = regtype_lookup_name("schan");
    915     }
    916     if (0 == rt) {
    917         cli_out("Unknown register.\n");
    918         return (CMD_FAIL);
    919     }
    920 
    921     if (soc_regaddrlist_alloc(&alist) < 0) {
    922         cli_out("Could not allocate address list.  Memory error.\n");
    923         return CMD_FAIL;
    924     }
    925 
    926     if (isint(name)) {
    927         /* Numerical address given */
    928         vaddr = parse_address(name);
    929         if (!reg_type_is_schan_reg(rt->type)) {
    930             blk_num = 0;
    931             acc_type = 0;
    932         } else if (soc_feature(unit, soc_feature_new_sbus_format)) {
    933             if ((block = ARG_GET(a)) == 0) {
    934                 cli_out("ERROR: This format of Getreg requires block-id to be specified.\n");
    935                 return CMD_FAIL;
    936             } else {
    937                 if (!isint(block)) {
    938                     cli_out("ERROR: block-id is not integer.\n");
    939                     return CMD_FAIL;
    940                 }
    941                 blk_num = parse_address(block);
    942             }
    943             if (soc_feature(unit, soc_feature_two_ingress_pipes)) {
    944                 if ((access_type = ARG_GET(a)) == 0) {
    945                     cli_out("ERROR: Access-type not specified.\n");
    946                     return CMD_FAIL;
    947                 } else {
    948                     if (!isint(access_type)) {
    949                         cli_out("ERROR: Access-type is not integer.\n");
    950                         return CMD_FAIL;
    951                     }
    952                     acc_type = parse_address(access_type);
    953                 }
    954             }
    955         }
    956         rv = _reg_get_by_type(unit, vaddr, blk_num, acc_type, rt->type, &regval, flags);
    957     } else {
    958         if (*name == '$') {
    959             name++;
    960         }
    961         field_names = NULL;
    962         while ((temp_field_name = ARG_GET(a)) != NULL) {
    963             if (field_names == NULL) {
    964                 if ((field_names = sal_alloc(ARGS_BUFFER, "reg_set")) == NULL) {
    965                      return (CMD_FAIL);
    966                 }
    967                 sal_strncpy(field_names, ",", 2);
    968             }
    969             for (offset=0 ; offset < sal_strlen(temp_field_name);offset++) {
    970                  temp_field_name[offset] = toupper((int)
    971                                                    temp_field_name[offset]);
    972             } 
    973             sal_strncat(field_names, temp_field_name, 
    974                         sal_strlen(temp_field_name));
    975             sal_strncat(field_names, ",", 1);
    976         }
    977 
    978         /* Symbolic name given, print all or some values ... */
    979         if (rt->type == soc_cpureg) {
    980             if (parse_cmic_regname(unit, name, &regaddr) < 0) {
    981                 cli_out("ERROR: bad argument to GETREG PCIM: %s\n", name);
    982                 rv = CMD_FAIL;
    983             } else {
    984                 rv = _reg_get_by_type(unit, regaddr, -1, -1,
    985                                       rt->type, &regval, flags);
    986             }
    987         } else if (parse_symbolic_reference(unit, &alist, name) < 0) {
    988             cli_out("Syntax error parsing \"%s\"\n", name);
    989             rv = CMD_FAIL;
    990         } else if (alist.ainfo->reg >= NUM_SOC_REG) {
    991             cli_out("Invalid register \"%s\"\n", name);
    992             rv = CMD_FAIL;
    993         } else if (reg_print_all(unit, &alist, flags, field_names) < 0) {
    994             rv = CMD_FAIL;
    995         }
    996     }
    997     soc_regaddrlist_free(&alist);
    998     if (field_names  != NULL) {
    999         sal_free(field_names);
   1000     }
   1001     return rv;
   1002 }
   1003 
   1004 /* 
   1005  * Auxilliary routine to handle setreg and modreg.
   1006  *      mod should be 0 for setreg, which takes either a value or a
   1007  *              list of <field>=<value>, and in the latter case, sets all
   1008  *              non-specified fields to zero.
   1009  *      mod should be 1 for modreg, which does a read-modify-write of
   1010  *              the register and permits value to be specified by a list
   1011  *              of <field>=<value>[,...] only.
   1012  */
   1013 
   1014 STATIC cmd_result_t
   1015 do_reg_set(int unit, args_t *a, int mod)
   1016 {
   1017     uint64          regval;
   1018     uint32          regaddr = 0;
   1019     uint32          flags = 0;
   1020     sal_vaddr_t     vaddr;
   1021     int             rv = CMD_OK, i, acc_type = 0;
   1022     regtype_entry_t *rt;
   1023     soc_regaddrlist_t alist = {0, NULL};
   1024     soc_regaddrinfo_t *ainfo;
   1025     char           *name, *block, *access_type, *arg1;
   1026     char           *s, *valstr = NULL;
   1027     soc_block_t blk_num = 0;
   1028     soc_reg_above_64_val_t value_above_64;
   1029 
   1030     COMPILER_64_ALLONES(regval);
   1031 
   1032     if (0 == sh_check_attached(ARG_CMD(a), unit)) {
   1033         return  CMD_FAIL;
   1034     }
   1035 
   1036     arg1 = ARG_GET(a);
   1037     for(;;) {
   1038         if (arg1 != NULL && !sal_strcasecmp(arg1, "nocache")) {
   1039             flags |= SOC_REG_DONT_USE_CACHE;
   1040             arg1 = ARG_GET(a);
   1041         } else {
   1042             break;
   1043         }
   1044     }
   1045 
   1046     name = arg1;
   1047     if (name == 0) {
   1048         return  CMD_USAGE;
   1049     }
   1050 
   1051     /* 
   1052      * If first arg is an access type, take it and use the next argument
   1053      * as the name, otherwise use default access type.
   1054      * modreg command does not allow this and assumes soc.
   1055      */
   1056 
   1057     if ((0 == mod) && (rt = regtype_lookup_name(name)) != 0) {
   1058         if ((name = ARG_GET(a)) == 0) {
   1059             return CMD_USAGE;
   1060         }
   1061     } else {
   1062         rt = regtype_lookup_name("schan");
   1063         if (0 == rt) {
   1064             return CMD_FAIL;
   1065         }
   1066     }
   1067 
   1068     if (isint(name)) {
   1069         if (!reg_type_is_schan_reg(rt->type)) {
   1070             blk_num = 0;
   1071             acc_type = 0;
   1072         } else if (soc_feature(unit, soc_feature_new_sbus_format)) {
   1073             if ((block = ARG_GET(a)) == 0) {
   1074                 cli_out("ERROR: This format of Setreg requires block-id to be specified.\n");
   1075                 return CMD_FAIL;
   1076             } else {
   1077                 if (!isint(block)) {
   1078                     cli_out("ERROR: block-id is not integer.\n");
   1079                     return CMD_FAIL;
   1080                 }
   1081                 blk_num = parse_address(block);
   1082             }
   1083             if (soc_feature(unit, soc_feature_two_ingress_pipes)) {
   1084                 if ((access_type = ARG_GET(a)) == 0) {
   1085                     cli_out("ERROR: Access-type not specified.\n");
   1086                     return CMD_FAIL;
   1087                 } else {
   1088                     if (!isint(access_type)) {
   1089                         cli_out("ERROR: Access-type is not integer.\n");
   1090                         return CMD_FAIL;
   1091                     }
   1092                     acc_type = parse_address(access_type);
   1093                 }
   1094             }
   1095         }
   1096     }
   1097     /* 
   1098      * Parse the value field.  If there are more than one, string them
   1099      * together with commas separating them (to make field-based setreg
   1100      * inputs more convenient).
   1101      */
   1102 
   1103     if ((s = ARG_GET(a)) == 0) {
   1104         cli_out("Syntax error: missing value\n");
   1105         return  CMD_USAGE;
   1106     } 
   1107  
   1108     if ((valstr = sal_alloc(ARGS_BUFFER, "reg_set")) == NULL) {
   1109         cli_out("do_reg_set: Out of memory\n");
   1110         return CMD_FAIL;
   1111     }
   1112 
   1113     collect_comma_args(a, valstr, s);
   1114 
   1115     if (mod && isint(valstr)) {
   1116         sal_free(valstr);
   1117         return CMD_USAGE;
   1118     }
   1119 
   1120 
   1121     if (soc_regaddrlist_alloc(&alist) < 0) {
   1122         cli_out("Could not allocate address list.  Memory error.\n");
   1123         sal_free(valstr);
   1124         return CMD_FAIL;
   1125     }
   1126 
   1127     if (!mod && isint(name)) {
   1128         /* Numerical address given */
   1129         vaddr = parse_address(name);
   1130         regval = parse_uint64(valstr);
   1131         rv = _reg_set_by_type(unit, vaddr, blk_num, acc_type, rt->type, regval);
   1132     } else {
   1133         /* Symbolic name given, set all or some values ... */
   1134         if (*name == '$') {
   1135             name++;
   1136         }
   1137         if (rt->type == soc_cpureg) {
   1138             if (parse_cmic_regname(unit, name, &regaddr) < 0) {
   1139                 cli_out("ERROR: bad argument to SETREG PCIM: %s\n", name);
   1140                 rv = CMD_FAIL;
   1141             } else {
   1142                 regval = parse_uint64(valstr);
   1143                 rv = _reg_set_by_type(unit, regaddr, -1, -1, rt->type, regval);
   1144             }
   1145         } else if (parse_symbolic_reference(unit, &alist, name) < 0) {
   1146             cli_out("Syntax error parsing \"%s\"\n", name);
   1147             rv = CMD_FAIL;
   1148         } else {
   1149             if (isint(valstr)) { /* valstr is numeric */
   1150                 regval = parse_uint64(valstr);
   1151                 parse_long_integer(value_above_64, 
   1152                                    SOC_REG_ABOVE_64_MAX_SIZE_U32, 
   1153                                    valstr);
   1154             }
   1155 
   1156             for (i = 0; i < alist.count; i++) {
   1157                 ainfo = &alist.ainfo[i];
   1158 
   1159                 if (!isint(valstr)) { /* valstr is Field/value pairs */
   1160                     /* 
   1161                      * valstr must be a field replacement spec.
   1162                      * In modreg mode, read the current register value,
   1163                      * and modify it.  In setreg mode,
   1164                      * assume a starting value of zero and modify it.
   1165                      */
   1166                     if (mod) { /* read-modify-write */
   1167                         if (SOC_REG_IS_ABOVE_64(unit, ainfo->reg)) {
   1168                             rv = soc_reg_above_64_get(unit, 
   1169                                  ainfo->reg, ainfo->port,  
   1170                                  SOC_REG_IS_ARRAY(unit, ainfo->reg) ? 
   1171                                  ainfo->idx : 0, value_above_64);
   1172                         } else {
   1173                            rv = soc_anyreg_read(unit, ainfo, &regval);
   1174                         }
   1175                         if (rv < 0) {
   1176                             char buf[80];
   1177                             soc_reg_sprint_addr(unit, buf, ainfo);
   1178                             cli_out("ERROR: read from register %s failed: %s\n",
   1179                                     buf, soc_errmsg(rv));
   1180                         }
   1181                     } else {
   1182                         COMPILER_64_ZERO(regval);
   1183                         SOC_REG_ABOVE_64_CLEAR(value_above_64);
   1184                     }
   1185                     if (rv == CMD_OK) {
   1186                         if (SOC_REG_IS_ABOVE_64(unit, ainfo->reg)) {
   1187                             rv = modify_reg_above_64_fields(unit, 
   1188                                         ainfo->reg, value_above_64, 
   1189                                         (soc_reg_above_64_val_t *) 0,valstr);
   1190                         } else {
   1191                             rv = modify_reg_fields(unit, 
   1192                                         ainfo->reg, &regval, NULL, valstr);
   1193                         }
   1194 
   1195                     }
   1196                 }
   1197                 if (rv == CMD_OK) {
   1198                     if (SOC_REG_IS_ABOVE_64(unit, ainfo->reg)) {
   1199                          rv = soc_reg_above_64_set( unit, 
   1200                                   ainfo->reg, ainfo->port, 
   1201                                   SOC_REG_IS_ARRAY(unit, ainfo->reg) ? 
   1202                                   ainfo->idx : 0, value_above_64);
   1203                          if (rv == 0) {
   1204                              continue;
   1205                          }
   1206                          break;
   1207                     }
   1208                     if (flags & SOC_REG_DONT_USE_CACHE) {
   1209                         SOC_MEM_TEST_SKIP_CACHE_SET(unit, TRUE);
   1210                     }
   1211                     rv = soc_anyreg_write(unit, ainfo, regval);
   1212                     if (flags & SOC_REG_DONT_USE_CACHE) {
   1213                         SOC_MEM_TEST_SKIP_CACHE_SET(unit, FALSE);
   1214                     }
   1215                     if (rv < 0) {
   1216                         char buf[80];
   1217                         soc_reg_sprint_addr(unit, buf, ainfo);
   1218                         cli_out("ERROR: write to register %s failed: %s\n",
   1219                                 buf, soc_errmsg(rv));
   1220                     }
   1221                 }
   1222                 if (rv != CMD_OK) {
   1223                     break;
   1224                 }
   1225             }
   1226         }
   1227     }
   1228     sal_free(valstr);
   1229     soc_regaddrlist_free(&alist);
   1230     return rv;
   1231 }
   1232 
   1233 /* 
   1234  * Sets a memory value or register on the SOC.
   1235  * Syntax 1: setreg [<regtype>] <offset|symbol> <value>
   1236  * Syntax 2: setreg [<regtype>] <offset|symbol> <field>=<value>[,...]
   1237  */
   1238 cmd_result_t
   1239 cmd_esw_reg_set(int unit, args_t *a)
   1240 {
   1241     return do_reg_set(unit, a, 0);
   1242 }
   1243 
   1244 /* 
   1245  * Read/modify/write a memory value or register on the SOC.
   1246  * Syntax: modreg [<regtype>] <offset|symbol> <field>=<value>[,...]
   1247  */
   1248 cmd_result_t
   1249 cmd_esw_reg_mod(int unit, args_t * a)
   1250 {
   1251     return do_reg_set(unit, a, 1);
   1252 }
   1253 
   1254 char regcmp_usage[] =
   1255 #ifdef COMPILER_STRING_CONST_LIMIT
   1256     "Usage: regcmp [args...]\n"
   1257 #else
   1258     "Parameters: [-q] [<LOOPS>] <REG> [<VALUE>] [==|!=] <VALUE>\n\t"
   1259     "If the optional <VALUE> on the left is given, starts by writing\n\t"
   1260     "<VALUE> to <REG>.   Then loops up to <LOOPS> times reading <REG>,\n\t"
   1261     "comparing if it is equal (==) or not equal (!=) to the <VALUE> on\n\t"
   1262     "the right, and stopping if the compare fails.  If -q is specified, no\n\t"
   1263     "output is displayed.  <LOOPS> defaults to 1 and may be * for\n\t"
   1264     "indefinite.  If the compare fails, the command result is 1.  If the\n\t"
   1265     "loops expire (compares succeed), the result is 0.  The result may be\n\t"
   1266     "tested in an IF statement.  Also, each <VALUE> can consist of\n\t"
   1267     "<FIELD>=<VALUE>[,...] to compare individual fields.  Examples:\n\t"
   1268     "    if \"regcmp -q 1 rpkt.fe0 == 0\" \"echo RPKT IS ZERO\"\n\t"
   1269     "    if \"regcmp -q config.e0 == fil_en=1\" \"echo FILTERING ENABLED\"\n"
   1270 #endif
   1271     ;
   1272 
   1273 cmd_result_t
   1274 reg_cmp(int unit, args_t *a)
   1275 {
   1276 #ifndef SOC_NO_NAMES
   1277     soc_reg_t       reg;
   1278 #endif
   1279     soc_regaddrlist_t alist;
   1280     soc_regaddrinfo_t *ainfo;
   1281     char           *name = NULL, *count_str;
   1282     char           *read_str, *write_str, *op_str;
   1283     uint64          read_val, read_mask, write_val, reg_val, tmp_val;
   1284     int             equal, i, quiet, loop;
   1285     int             are_equal;
   1286     int rv = CMD_OK;
   1287 
   1288     if (!(count_str = ARG_GET(a))) {
   1289         return (CMD_USAGE);
   1290     }
   1291 
   1292     if (!sal_strcmp(count_str, "-q")) {
   1293         quiet = TRUE;
   1294         if (!(count_str = ARG_GET(a))) {
   1295             return (CMD_USAGE);
   1296         }
   1297     } else {
   1298         quiet = FALSE;
   1299     }
   1300 
   1301     if (!sal_strcmp(count_str, "*")) {
   1302         loop = -1;
   1303     } else if (isint(count_str)) {
   1304         if ((loop = parse_integer(count_str)) < 0) {
   1305             cli_out("%s: Invalid loop count: %s\n", ARG_CMD(a), count_str);
   1306             return (CMD_FAIL);
   1307         }
   1308     } else {
   1309         name = count_str;
   1310         loop = 1;
   1311     }
   1312 
   1313     if (!name && !(name = ARG_GET(a))) {
   1314         return (CMD_USAGE);
   1315     }
   1316 
   1317     write_str = ARG_GET(a);
   1318     op_str = ARG_GET(a);
   1319     read_str = ARG_GET(a);
   1320 
   1321     /* Must have WRITE ==|!= READ or ==|!= READ */
   1322 
   1323     if (!read_str) {
   1324         read_str = op_str;
   1325         op_str = write_str;
   1326         write_str = NULL;
   1327     } else if (ARG_CNT(a)) {
   1328         return (CMD_USAGE);
   1329     }
   1330 
   1331     if (!read_str || !op_str) {
   1332         return (CMD_USAGE);
   1333     }
   1334 
   1335     if (!sal_strcmp(op_str, "==")) {
   1336         equal = TRUE;
   1337     } else if (!sal_strcmp(op_str, "!=")) {
   1338         equal = FALSE;
   1339     } else {
   1340         return (CMD_USAGE);
   1341     }
   1342 
   1343     if (*name == '$') {
   1344         name++;
   1345     }
   1346 
   1347     /* Symbolic name given, set all or some values ... */
   1348 
   1349     if (soc_regaddrlist_alloc(&alist) < 0) {
   1350         cli_out("Could not allocate address list.  Memory error.\n");
   1351         return CMD_FAIL;
   1352     }
   1353 
   1354     if (parse_symbolic_reference(unit, &alist, name) < 0) {
   1355         cli_out("%s: Syntax error parsing \"%s\"\n", ARG_CMD(a), name);
   1356         soc_regaddrlist_free(&alist);
   1357         return (CMD_FAIL);
   1358     }
   1359 
   1360     ainfo = &alist.ainfo[0];
   1361 #ifndef SOC_NO_NAMES
   1362     reg = ainfo->reg;
   1363 #endif
   1364 
   1365     COMPILER_64_ALLONES(read_mask);
   1366 
   1367     if (isint(read_str)) {
   1368         read_val = parse_uint64(read_str);
   1369     } else {
   1370         COMPILER_64_ZERO(read_val);
   1371         if (modify_reg_fields(unit, ainfo->reg, &read_val,
   1372                               &read_mask, read_str) < 0) {
   1373             cli_out("%s: Syntax error: %s\n", ARG_CMD(a), read_str);
   1374             soc_regaddrlist_free(&alist);
   1375             return (CMD_USAGE);
   1376         }
   1377     }
   1378 
   1379     if (write_str) {
   1380         if (isint(write_str)) {
   1381             write_val = parse_uint64(write_str);
   1382         } else {
   1383             COMPILER_64_ZERO(write_val);
   1384             if (modify_reg_fields(unit, ainfo->reg, &write_val,
   1385                                   (uint64 *) 0, write_str) < 0) {
   1386                 cli_out("%s: Syntax error: %s\n", ARG_CMD(a), write_str);
   1387                 soc_regaddrlist_free(&alist);
   1388                 return (CMD_USAGE);
   1389             }
   1390         }
   1391     }
   1392 
   1393     do {
   1394         for (i = 0; i < alist.count; i++) {
   1395             int             r;
   1396 
   1397             ainfo = &alist.ainfo[i];
   1398             if (write_str) {
   1399                 if ((r = soc_anyreg_write(unit, ainfo, write_val)) < 0) {
   1400                     cli_out("%s: ERROR: Write register %s.%d failed: %s\n",
   1401                             ARG_CMD(a), SOC_REG_NAME(unit, reg), i, soc_errmsg(r));
   1402                     soc_regaddrlist_free(&alist);
   1403                     return (CMD_FAIL);
   1404                 }
   1405             }
   1406 
   1407             if ((r = soc_anyreg_read(unit, ainfo, &reg_val)) < 0) {
   1408                 cli_out("%s: ERROR: Read register %s.%d failed: %s\n",
   1409                         ARG_CMD(a), SOC_REG_NAME(unit, reg), i, soc_errmsg(r));
   1410                 soc_regaddrlist_free(&alist);
   1411                 return (CMD_FAIL);
   1412             }
   1413 
   1414             tmp_val = reg_val;
   1415             COMPILER_64_AND(tmp_val, read_mask);
   1416             COMPILER_64_XOR(tmp_val, read_val);
   1417             are_equal = COMPILER_64_IS_ZERO(tmp_val);
   1418             if ((!are_equal && equal) || (are_equal && !equal)) {
   1419                 if (!quiet) {
   1420                     char buf1[80], buf2[80];
   1421                     cli_out("%s: %s.%d ", ARG_CMD(a), SOC_REG_NAME(unit, reg), i);
   1422                     format_uint64(buf1, read_val);
   1423                     format_uint64(buf2, reg_val);
   1424                     cli_out("%s %s %s\n", buf1, equal ? "!=" : "==", buf2);
   1425                 }
   1426                 soc_regaddrlist_free(&alist);
   1427                 return (1);
   1428             }
   1429         }
   1430 
   1431         if (loop > 0) {
   1432             loop--;
   1433         }
   1434     } while (loop);
   1435 
   1436     soc_regaddrlist_free(&alist);
   1437     return rv;
   1438 }
   1439 
   1440 /* 
   1441  * Lists registers containing a specific pattern
   1442  *
   1443  * If use_reset is true, ignores val and uses reset default value.
   1444  */
   1445 
   1446 static void
   1447 do_reg_list(int unit, soc_regaddrinfo_t *ainfo, int use_reset, uint64 regval)
   1448 {
   1449     soc_reg_t       reg = ainfo->reg;
   1450     soc_reg_info_t *reginfo = &SOC_REG_INFO(unit, reg);
   1451     soc_field_info_t *fld;
   1452     int             f;
   1453     uint32          flags;
   1454     uint64          mask, fldval, rval, rmsk;
   1455     char            buf[80];
   1456     char            rval_str[20], rmsk_str[20], dval_str[20];
   1457     int		    i, copies, disabled;
   1458 
   1459     if (!SOC_REG_IS_VALID(unit, reg)) {
   1460 	cli_out("Register %s is not valid for chip %s\n",
   1461                 SOC_REG_NAME(unit, reg), SOC_UNIT_NAME(unit));
   1462 	return;
   1463     }
   1464 
   1465     flags = reginfo->flags;
   1466 
   1467     COMPILER_64_ALLONES(mask);
   1468 
   1469     SOC_REG_RST_VAL_GET(unit, reg, rval);
   1470     SOC_REG_RST_MSK_GET(unit, reg, rmsk);
   1471     format_uint64(rval_str, rval);
   1472     format_uint64(rmsk_str, rmsk);
   1473     if (use_reset) {
   1474         regval = rval;
   1475         mask = rmsk;
   1476     } else {
   1477 	format_uint64(dval_str, regval);
   1478     }
   1479 
   1480     soc_reg_sprint_addr(unit, buf, ainfo);
   1481 
   1482     cli_out("Register: %s", buf);
   1483 #if !defined(SOC_NO_ALIAS)
   1484     if (soc_reg_alias[reg] && *soc_reg_alias[reg]) {
   1485         cli_out(" alias %s", soc_reg_alias[reg]);
   1486     }
   1487 #endif /* !defined(SOC_NO_ALIAS) */
   1488     cli_out(" %s register", soc_regtypenames[reginfo->regtype]);
   1489     cli_out(" address 0x%08x\n", ainfo->addr);
   1490 
   1491     cli_out("Flags:");
   1492     if (flags & SOC_REG_FLAG_64_BITS) {
   1493         cli_out(" 64-bits");
   1494     }
   1495     if (flags & SOC_REG_FLAG_32_BITS) {
   1496         cli_out(" 32-bits");
   1497     }
   1498     if (flags & SOC_REG_FLAG_ABOVE_64_BITS) {
   1499         cli_out(" Above 64-bits");
   1500     }
   1501 
   1502     if (flags & SOC_REG_FLAG_COUNTER) {
   1503         cli_out(" counter");
   1504     }
   1505     if (flags & SOC_REG_FLAG_ARRAY) {
   1506         cli_out(" array[%d-%d]", 0, reginfo->numels-1);
   1507     }
   1508     if (flags & SOC_REG_FLAG_NO_DGNL) {
   1509         cli_out(" no-diagonals");
   1510     }
   1511     if (flags & SOC_REG_FLAG_RO) {
   1512         cli_out(" read-only");
   1513     }
   1514     if (flags & SOC_REG_FLAG_WO) {
   1515         cli_out(" write-only");
   1516     }
   1517     if (flags & SOC_REG_FLAG_ED_CNTR) {
   1518         cli_out(" error/discard-counter");
   1519     }
   1520     if (flags & SOC_REG_FLAG_SPECIAL) {
   1521         cli_out(" special");
   1522     }
   1523     if (flags & SOC_REG_FLAG_EMULATION) {
   1524         cli_out(" emulation");
   1525     }
   1526     if (flags & SOC_REG_FLAG_VARIANT1) {
   1527         cli_out(" variant1");
   1528     }
   1529     if (flags & SOC_REG_FLAG_VARIANT2) {
   1530         cli_out(" variant2");
   1531     }
   1532     if (flags & SOC_REG_FLAG_VARIANT3) {
   1533         cli_out(" variant3");
   1534     }
   1535     if (flags & SOC_REG_FLAG_VARIANT4) {
   1536         cli_out(" variant4");
   1537     }
   1538     cli_out("\n");
   1539 
   1540     cli_out("Blocks:");
   1541     copies = disabled = 0;
   1542     for (i = 0; SOC_BLOCK_INFO(unit, i).type >= 0; i++) {
   1543 	/* if (SOC_BLOCK_INFO(unit, i).type & reginfo->block) { */
   1544         /* if (SOC_BLOCK_IN_LIST(reginfo->block, SOC_BLOCK_INFO(unit, i).type)) { */
   1545         if (SOC_BLOCK_IS_TYPE(unit, i, reginfo->block)) {
   1546 	    if (SOC_INFO(unit).block_valid[i]) {
   1547 		cli_out(" %s", SOC_BLOCK_NAME(unit, i));
   1548 	    } else {
   1549 		cli_out(" [%s]", SOC_BLOCK_NAME(unit, i));
   1550 		disabled += 1;
   1551 	    }
   1552 	    copies += 1;
   1553 	}
   1554     }
   1555     cli_out(" (%d cop%s", copies, copies == 1 ? "y" : "ies");
   1556     if (disabled) {
   1557 	cli_out(", %d disabled", disabled);
   1558     }
   1559     cli_out(")\n");
   1560 
   1561 #if !defined(SOC_NO_DESC)
   1562     if (soc_reg_desc[reg] && *soc_reg_desc[reg]) {
   1563 	cli_out("Description: %s\n", soc_reg_desc[reg]);
   1564     }
   1565 #endif /* !defined(SOC_NO_ALIAS) */
   1566     cli_out("Displaying:");
   1567     if (use_reset) {
   1568 	cli_out(" reset defaults");
   1569     } else {
   1570 	cli_out(" value %s", dval_str);
   1571     }
   1572     cli_out(", reset value %s mask %s\n", rval_str, rmsk_str);
   1573 
   1574     for (f = reginfo->nFields - 1; f >= 0; f--) {
   1575 	fld = &reginfo->fields[f];
   1576 	cli_out("  %s<%d", SOC_FIELD_NAME(unit, fld->field),
   1577                 fld->bp + fld->len - 1);
   1578 	if (fld->len > 1) {
   1579 	    cli_out(":%d", fld->bp);
   1580 	}
   1581 	fldval = soc_reg64_field_get(unit, reg, mask, fld->field);
   1582 	if (use_reset && COMPILER_64_IS_ZERO(fldval)) {
   1583 	    cli_out("> = x");
   1584 	} else {
   1585 	    fldval = soc_reg64_field_get(unit, reg, regval, fld->field);
   1586 	    format_uint64(buf, fldval);
   1587 	    cli_out("> = %s", buf);
   1588 	}
   1589 	if (fld->flags & (SOCF_RO|SOCF_WO)) {
   1590 	    cli_out(" [");
   1591 	    i = 0;
   1592 	    if (fld->flags & SOCF_RO) {
   1593 		cli_out("%sRO", i++ ? "," : "");
   1594 	    }
   1595 	    if (fld->flags & SOCF_WO) {
   1596 		cli_out("%sWO", i++ ? "," : "");
   1597 	    }
   1598 	    cli_out("]");
   1599 	}
   1600 	cli_out("\n");
   1601     }
   1602 }
   1603 
   1604 #define	PFLAG_ALIAS	0x01
   1605 #define	PFLAG_SUMMARY	0x02
   1606 
   1607 static void
   1608 _print_regname(int unit, soc_reg_t reg, int *col, int pflags)
   1609 {
   1610     int             len;
   1611     soc_reg_info_t *reginfo;
   1612 
   1613     reginfo = &SOC_REG_INFO(unit, reg);
   1614     len = sal_strlen(SOC_REG_NAME(unit, reg)) + 1;
   1615 
   1616     if (pflags & PFLAG_SUMMARY) {
   1617 	char	tname, *dstr1, *dstr2, *bname;
   1618 	int	dlen, copies, i;
   1619 	char	nstr[128], bstr[64];
   1620 
   1621 	switch (reginfo->regtype) {
   1622 	case soc_schan_reg:	tname = 's'; break;
   1623 	case soc_cpureg:	tname = 'c'; break;
   1624 	case soc_genreg:	tname = 'g'; break;
   1625 	case soc_portreg:	tname = 'p'; break;
   1626 	case soc_cosreg:	tname = 'o'; break;
   1627         case soc_pipereg:       tname = 'p'; break;
   1628         case soc_xpereg:        tname = 'x'; break;
   1629         case soc_itmreg:        tname = 'i'; break;
   1630         case soc_ebreg:        tname = 'e'; break;
   1631         case soc_slicereg:      tname = 's'; break;
   1632         case soc_layerreg:      tname = 'l'; break;
   1633 	case soc_hostmem_w:
   1634 	case soc_hostmem_h:
   1635 	case soc_hostmem_b:	tname = 'm'; break;
   1636 	case soc_phy_reg:	tname = 'f'; break;
   1637 	case soc_pci_cfg_reg:	tname = 'P'; break;
   1638 	default:		tname = '?'; break;
   1639 	}
   1640 #if !defined(SOC_NO_DESC)
   1641 	dstr2 = sal_strchr(soc_reg_desc[reg], '\n');
   1642 	if (dstr2 == NULL) {
   1643 	    dlen = sal_strlen(soc_reg_desc[reg]);
   1644 	} else {
   1645 	    dlen = dstr2 - soc_reg_desc[reg];
   1646 	}
   1647 	if (dlen > 30) {
   1648 	    dlen = 30;
   1649 	    dstr2 = "...";
   1650 	} else {
   1651 	    dstr2 = "";
   1652 	}
   1653 	dstr1 = soc_reg_desc[reg];
   1654 #else /* defined(SOC_NO_DESC) */
   1655 	dlen = 1;
   1656 	dstr1 = "";
   1657 	dstr2 = "";
   1658 #endif /* defined(SOC_NO_DESC) */
   1659 	if (reginfo->flags & SOC_REG_FLAG_ARRAY) {
   1660 	    sal_sprintf(nstr, "%s[%d]", SOC_REG_NAME(unit, reg), reginfo->numels);
   1661 	} else {
   1662 	    sal_sprintf(nstr, "%s", SOC_REG_NAME(unit, reg));
   1663 	}
   1664 
   1665 	copies = 0;
   1666 	bname = NULL;
   1667 	for (i = 0; SOC_BLOCK_INFO(unit, i).type >= 0; i++) {
   1668 	    /*if (SOC_BLOCK_INFO(unit, i).type & reginfo->block) {*/
   1669             if (SOC_BLOCK_IS_TYPE(unit, i, reginfo->block)) {
   1670 		if (bname == NULL) {
   1671 		    bname = SOC_BLOCK_NAME(unit, i);
   1672 		}
   1673 		copies += 1;
   1674 	    }
   1675 	}
   1676 	if (copies > 1) {
   1677 	    sal_sprintf(bstr, "%d/%s", copies, bname);
   1678 	} else if (copies == 1) {
   1679 	    sal_sprintf(bstr, "%s", bname);
   1680 	} else {
   1681 	    sal_sprintf(bstr, "none");
   1682 	}
   1683 	cli_out(" %c%c%c%c%c  %-26s %-8.8s  %*.*s%s\n",
   1684                 tname,
   1685                 (reginfo->flags & SOC_REG_FLAG_64_BITS) ? '6' : '3',
   1686                 (reginfo->flags & SOC_REG_FLAG_COUNTER) ? 'c' : '-',
   1687                 (reginfo->flags & SOC_REG_FLAG_ED_CNTR) ? 'e' : '-',
   1688                 (reginfo->flags & SOC_REG_FLAG_RO) ? 'r' :
   1689                 (reginfo->flags & SOC_REG_FLAG_WO) ? 'w' : '-',
   1690                 nstr,
   1691                 bstr,
   1692                 dlen, dlen, dstr1, dstr2);
   1693 	return;
   1694     }
   1695     if (*col < 0) {
   1696 	cli_out("  ");
   1697 	*col = 2;
   1698     }
   1699     if (*col + len > ((pflags & PFLAG_ALIAS) ? 65 : 72)) {
   1700 	cli_out("\n  ");
   1701 	*col = 2;
   1702     }
   1703     cli_out("%s%s ", SOC_REG_NAME(unit, reg), SOC_REG_ARRAY(unit, reg) ? "[]" : "");
   1704 #if !defined(SOC_NO_ALIAS)
   1705     if ((pflags & PFLAG_ALIAS) && soc_reg_alias[reg]) {
   1706         len += sal_strlen(soc_reg_alias[reg]) + 8;
   1707         cli_out("(aka %s) ", soc_reg_alias[reg]);
   1708     }
   1709 #endif /* !defined(SOC_NO_ALIAS) */
   1710     *col += len;
   1711 }
   1712 
   1713 static void
   1714 _list_regs_by_type(int unit, soc_block_t blk, int *col, int pflag)
   1715 {
   1716     soc_reg_t       reg;
   1717 
   1718     *col = -1;
   1719     for (reg = 0; reg < NUM_SOC_REG; reg++) {
   1720         if (!SOC_REG_IS_VALID(unit, reg)) {
   1721             continue;
   1722         }
   1723 	/*if (SOC_REG_INFO(unit, reg).block & blk) {*/
   1724         if (SOC_BLOCK_IN_LIST(SOC_REG_INFO(unit, reg).block, blk)) {
   1725             _print_regname(unit, reg, col, pflag);
   1726         }
   1727     }
   1728     cli_out("\n");
   1729 }
   1730 
   1731 cmd_result_t
   1732 cmd_esw_reg_list(int unit, args_t *a)
   1733 {
   1734     char           *str;
   1735     char           *val;
   1736     uint64          value;
   1737     soc_regaddrinfo_t ainfo;
   1738     int             found;
   1739     int             rv = CMD_OK;
   1740     int             all_regs;
   1741     soc_reg_t       reg;
   1742     int             col;
   1743     int		    pflag;
   1744 
   1745     if (!sh_check_attached(ARG_CMD(a), unit)) {
   1746 	return CMD_FAIL;
   1747     }
   1748 
   1749     if (!soc_property_get(unit, spn_REGLIST_ENABLE, 1)) {
   1750         return CMD_OK;
   1751     }
   1752 
   1753     ainfo.reg = INVALIDr;
   1754     pflag = 0;
   1755     col = -1;
   1756 
   1757     /* Parse options */
   1758     while (((str = ARG_GET(a)) != NULL) && (str[0] == '-')) {
   1759 	while (str[0] && str[0] == '-') {
   1760 	    str += 1;
   1761 	}
   1762         if (sal_strcasecmp(str, "alias") == 0 ||
   1763 	    sal_strcasecmp(str, "a") == 0) {	/* list w/ alias */
   1764             pflag |= PFLAG_ALIAS;
   1765 	    continue;
   1766 	}
   1767         if (sal_strcasecmp(str, "summary") == 0 ||
   1768 	    sal_strcasecmp(str, "s") == 0) {	/* list w/ summary */
   1769             pflag |= PFLAG_SUMMARY;
   1770 	    continue;
   1771         }
   1772 	if (sal_strcasecmp(str, "counters") == 0 ||
   1773 	    sal_strcasecmp(str, "c") == 0) {	/* list counters */
   1774             cli_out("unit %d counters\n", unit);
   1775             for (reg = 0; reg < NUM_SOC_REG; reg++) {
   1776                 if (!SOC_REG_IS_VALID(unit, reg))
   1777                     continue;
   1778                 if (!SOC_REG_IS_COUNTER(unit, reg))
   1779                     continue;
   1780                 _print_regname(unit, reg, &col, pflag);
   1781             }
   1782             cli_out("\n\n");
   1783             return CMD_OK;
   1784         }
   1785 	if (sal_strcasecmp(str, "ed") == 0 ||
   1786 	    sal_strcasecmp(str, "e") == 0) {	/* error/discard */
   1787             cli_out("unit %d error/discard counters\n", unit);
   1788             for (reg = 0; reg < NUM_SOC_REG; reg++) {
   1789                 if (!SOC_REG_IS_VALID(unit, reg)) {
   1790                     continue;
   1791                 }
   1792                 if (!(SOC_REG_INFO(unit, reg).flags & SOC_REG_FLAG_ED_CNTR)) {
   1793                     continue;
   1794                 }
   1795                 _print_regname(unit, reg, &col, pflag);
   1796             }
   1797             cli_out("\n\n");
   1798             return CMD_OK;
   1799         }
   1800 	if (sal_strcasecmp(str, "type") == 0 ||
   1801 	    sal_strcasecmp(str, "t") == 0) {	/* list by type */
   1802             int	       i;
   1803             soc_info_t *si = &SOC_INFO(unit);
   1804 
   1805 	    for (i = 0; i < COUNTOF(si->has_block); i++) {
   1806 		if (!(si->has_block[i])) {
   1807 		    continue;
   1808 		}
   1809 		cli_out("unit %d %s registers\n",
   1810                         unit,
   1811                         soc_block_name_lookup_ext(si->has_block[i], unit));
   1812 		col = -1;
   1813                 _list_regs_by_type(unit, si->has_block[i], &col, pflag);
   1814 	    }
   1815             cli_out("\n");
   1816             return CMD_OK;
   1817         }
   1818 	cli_out("ERROR: unrecognized option: %s\n", str);
   1819 	return CMD_FAIL;
   1820     }
   1821 
   1822     if (!str) {
   1823 	return CMD_USAGE;
   1824     }
   1825 
   1826     if ((val = ARG_GET(a)) != NULL) {
   1827 	value = parse_uint64(val);
   1828     } else {
   1829 	COMPILER_64_ZERO(value);
   1830     }
   1831 
   1832 
   1833     if (isint(str)) {
   1834 	/* 
   1835 	 * Address given, look up SOC register.
   1836 	 */
   1837 	char            buf[80];
   1838 	uint32          addr;
   1839 	addr = parse_integer(str);
   1840 	soc_regaddrinfo_get(unit, &ainfo, addr);
   1841 	if (!ainfo.valid || (int)ainfo.reg < 0) {
   1842 	    cli_out("Unknown register address: 0x%x\n", addr);
   1843 	    rv = CMD_FAIL;
   1844 	} else {
   1845 	    soc_reg_sprint_addr(unit, buf, &ainfo);
   1846 	    cli_out("Address %s\n", buf);
   1847 	}
   1848     } else {
   1849         soc_regaddrlist_t alist;
   1850 
   1851         if (soc_regaddrlist_alloc(&alist) < 0) {
   1852             cli_out("Could not allocate address list.  Memory error.\n");
   1853             return CMD_FAIL;
   1854         }
   1855 
   1856 	/* 
   1857 	 * Symbolic name.
   1858 	 * First check if the register is there as exact match.
   1859 	 * If not, list all substring matches.
   1860 	 */
   1861 
   1862 	all_regs = 0;
   1863 	if (*str == '$') {
   1864 	    str++;
   1865 	} else if (*str == '*') {
   1866 	    str++;
   1867 	    all_regs = 1;
   1868 	}
   1869 
   1870 	if (all_regs || parse_symbolic_reference(unit, &alist, str) < 0) {
   1871 	    found = 0;
   1872 	    for (reg = 0; reg < NUM_SOC_REG; reg++) {
   1873 		if (!SOC_REG_IS_VALID(unit, reg)) {
   1874 		    continue;
   1875 		}
   1876 		if (strcaseindex(SOC_REG_NAME(unit, reg), str) != 0) {
   1877 		    if (!found && !all_regs) {
   1878 			cli_out("Unknown register; possible matches are:\n");
   1879 		    }
   1880                     _print_regname(unit, reg, &col, pflag);
   1881 		    found = 1;
   1882 		}
   1883 	    }
   1884 	    if (!found) {
   1885 		cli_out("No matching register found");
   1886 	    }
   1887 	    cli_out("\n");
   1888 	    rv = CMD_FAIL;
   1889 	} else {
   1890 	    ainfo = alist.ainfo[0];
   1891 	}
   1892 
   1893         soc_regaddrlist_free(&alist);
   1894     }
   1895 
   1896     /* 
   1897      * Now have ainfo -- if reg is no longer INVALIDr
   1898      */
   1899 
   1900     if (ainfo.reg != INVALIDr) {
   1901 	if (val) {
   1902 	    do_reg_list(unit, &ainfo, 0, value);
   1903 	} else {
   1904             COMPILER_64_ZERO(value);
   1905 	    do_reg_list(unit, &ainfo, 1, value);
   1906 	}
   1907     }
   1908 
   1909     return rv;
   1910 }
   1911 
   1912 /* 
   1913  * Editreg allows modifying register fields.
   1914  * Works on fully qualified SOC registers only.
   1915  */
   1916 
   1917 cmd_result_t
   1918 cmd_esw_reg_edit(int unit, args_t *a)
   1919 {
   1920     soc_reg_info_t *reginfo;
   1921     soc_field_info_t *fld;
   1922     soc_regaddrlist_t alist;
   1923     soc_reg_t       reg;
   1924     uint64	    v64;
   1925     uint32          val, dfl, fv;
   1926     char            ans[64], dfl_str[64];
   1927     char           *name = ARG_GET(a);
   1928     int             r, rv = CMD_FAIL;
   1929     int             i, f;
   1930 
   1931     if (!sh_check_attached(ARG_CMD(a), unit)) {
   1932 	return rv;
   1933     }
   1934 
   1935     if (!name) {
   1936 	return CMD_USAGE;
   1937     }
   1938 
   1939     if (*name == '$') {
   1940 	name++;
   1941     }
   1942 
   1943     if (soc_regaddrlist_alloc(&alist) < 0) {
   1944         cli_out("Could not allocate address list.  Memory error.\n");
   1945         return CMD_FAIL;
   1946     }
   1947 
   1948     if (parse_symbolic_reference(unit, &alist, name) < 0) {
   1949         cli_out("Syntax error parsing \"%s\"\n", name);
   1950         soc_regaddrlist_free(&alist);
   1951         return (rv);
   1952     }
   1953 
   1954     reg = alist.ainfo[0].reg;
   1955     reginfo = &SOC_REG_INFO(unit, reg);
   1956 
   1957     /* 
   1958      * If more than one register was specified, read the first one
   1959      * and write the edited value to all of them.
   1960      */
   1961 
   1962     if (soc_anyreg_read(unit, &alist.ainfo[0], &v64) < 0) {
   1963         cli_out("ERROR: read reg failed\n");
   1964         soc_regaddrlist_free(&alist);
   1965         return (rv);
   1966     }
   1967 
   1968     COMPILER_64_TO_32_LO(val, v64);
   1969 
   1970     cli_out("Current value: 0x%x\n", val);
   1971 
   1972     for (f = 0; f < (int)reginfo->nFields; f++) {
   1973 	fld = &reginfo->fields[f];
   1974 	dfl = soc_reg_field_get(unit, reg, val, fld->field);
   1975 	sal_sprintf(dfl_str, "0x%x", dfl);
   1976 	sal_sprintf(ans,		       /* Also use ans[] for prompt */
   1977 		"  %s<%d", SOC_FIELD_NAME(unit, fld->field), fld->bp + fld->len - 1);
   1978 	if (fld->len > 1) {
   1979 	    sal_sprintf(ans + sal_strlen(ans), ":%d", fld->bp);
   1980 	}
   1981     /* coverity[secure_coding] */
   1982 	sal_strcat(ans, ">? ");
   1983 	if (sal_readline(ans, ans, sizeof(ans), dfl_str) == 0 || ans[0] == 0) {
   1984 	    cli_out("Aborted\n");
   1985         soc_regaddrlist_free(&alist);
   1986         return (rv);
   1987 	}
   1988 	fv = parse_integer(ans);
   1989 	if (fv & ~((1 << (fld->len - 1) << 1) - 1)) {
   1990 	    cli_out("Value too big for %d-bit field, try again.\n",
   1991                     fld->len);
   1992 	    f--;
   1993 	} else {
   1994 	    soc_reg_field_set(unit, reg, &val, fld->field, fv);
   1995 	}
   1996     }
   1997 
   1998     cli_out("Writing new value: 0x%x\n", val);
   1999 
   2000     for (i = 0; i < alist.count; i++) {
   2001         COMPILER_64_SET(v64, 0, val);
   2002 
   2003 	if ((r = soc_anyreg_write(unit, &alist.ainfo[i], v64)) < 0) {
   2004 	    cli_out("ERROR: write reg 0x%x failed: %s\n",
   2005                     alist.ainfo[i].addr, soc_errmsg(r));
   2006         soc_regaddrlist_free(&alist);
   2007         return (rv);
   2008 	}
   2009     }
   2010 
   2011     rv = CMD_OK;
   2012 
   2013     soc_regaddrlist_free(&alist);
   2014     return rv;
   2015 }
   2016 void 
   2017 reg_watch_cb(int unit, soc_reg_t reg, soc_regaddrinfo_t *ainfo, uint32 flags, 
   2018              uint32 data_hi, uint32 data_lo, void *user_data)
   2019 {   
   2020     uint64 value;
   2021 
   2022     if (!SOC_REG_IS_VALID(unit, reg)) {
   2023         return;
   2024     }   
   2025     COMPILER_64_SET(value,data_hi,data_lo);
   2026     if (flags & SOC_REG_SNOOP_READ) {
   2027 #if !defined(SOC_NO_NAMES)
   2028         cli_out("Unit=%d REGISTER=%s(Read) \t",unit,soc_reg_name[reg]);
   2029 #endif
   2030         if (data_hi != 0) {
   2031             cli_out("HighData=0x%08x \t",data_hi);
   2032             cli_out("LowData=0x%08x \n",data_lo);
   2033         } else {
   2034             cli_out("Data=0x%08x \n",data_lo);
   2035         }
   2036         reg_print(unit, ainfo, value, REG_PRINT_DO_PRINT, ",", 62, NULL);
   2037     } else {
   2038         if (flags & SOC_REG_SNOOP_WRITE) {
   2039 #if !defined(SOC_NO_NAMES)
   2040             cli_out("Unit=%d REGISTER=%s(WRITE) \t",unit,soc_reg_name[reg]);
   2041 #endif
   2042             if (data_hi != 0) {
   2043                 cli_out("HighData=0x%08x \t",data_hi);
   2044                 cli_out("LowData=0x%08x \n",data_lo);
   2045             } else {
   2046                 cli_out("Data=0x%08x \n",data_lo);
   2047             }
   2048             reg_print(unit, ainfo, value, REG_PRINT_DO_PRINT, ",", 62, NULL);
   2049         }
   2050     }
   2051     return;
   2052 }
   2053 
   2054 void reg_watch_snoop_all(int unit, uint32 flags, int regist)
   2055 {
   2056     soc_reg_t       reg;
   2057 
   2058     for (reg = 0; reg < NUM_SOC_REG; reg++) {
   2059         if (!SOC_REG_IS_VALID(unit, reg)) {
   2060             continue;
   2061         }
   2062         if (regist) {
   2063             soc_reg_snoop_register(unit, reg, flags, reg_watch_cb, NULL);
   2064         } else {
   2065             soc_reg_snoop_unregister(unit, reg);
   2066         }
   2067     }
   2068     return;
   2069 }
   2070 
   2071 cmd_result_t
   2072 reg_watch(int unit, args_t *a)
   2073 {
   2074     soc_regaddrlist_t alist;
   2075     soc_reg_t       reg = INVALIDr;
   2076     /* uint64	    v64; */
   2077     char           *name = ARG_GET(a);
   2078     char           *c;
   2079     int             rv = CMD_FAIL;
   2080     int             allregs = 0;
   2081 
   2082     if (!sh_check_attached(ARG_CMD(a), unit)) {
   2083 	return rv;
   2084     }
   2085 
   2086     if (!name) {
   2087 	return CMD_USAGE;
   2088     }
   2089 
   2090     if (sal_strcasecmp(name, "*") == 0) {
   2091         allregs = 1;
   2092     } else {
   2093         if (sal_strcasecmp(name, "delta") == 0) {
   2094             c = ARG_GET(a);
   2095             soc_reg_watch_set(unit, (c && (sal_strcasecmp(c, "on") == 0)) ? 1 : 0);
   2096             return CMD_OK;
   2097         }
   2098 
   2099         if (soc_regaddrlist_alloc(&alist) < 0) {
   2100             cli_out("Could not allocate address list.  Memory error.\n");
   2101             return CMD_FAIL;
   2102         }
   2103 
   2104         if (parse_symbolic_reference(unit, &alist, name) < 0) {
   2105             cli_out("Syntax error parsing \"%s\"\n", name);
   2106             soc_regaddrlist_free(&alist);
   2107             return (rv);
   2108         }
   2109         reg = alist.ainfo[0].reg;
   2110     }
   2111 
   2112     if (NULL == (c = ARG_GET(a))) {
   2113         return CMD_USAGE;
   2114     }
   2115 
   2116     if (sal_strcasecmp(c, "off") == 0) {
   2117         /* unregister call back */
   2118         if (allregs) {
   2119             reg_watch_snoop_all(unit, 0, FALSE);
   2120         } else {
   2121             soc_reg_snoop_unregister(unit, reg);
   2122         }
   2123     } else if (sal_strcasecmp(c, "read") == 0) {
   2124         /* register callback with read flag */
   2125         if (allregs) {
   2126             reg_watch_snoop_all(unit, SOC_REG_SNOOP_READ, TRUE);
   2127         } else {
   2128             soc_reg_snoop_register(unit, reg, SOC_REG_SNOOP_READ,
   2129                                    reg_watch_cb, NULL);
   2130         }
   2131     } else if (sal_strcasecmp(c, "write") == 0) {
   2132         /* register callback with write flag */
   2133         if (allregs) {
   2134             reg_watch_snoop_all(unit, SOC_REG_SNOOP_READ, TRUE);
   2135         } else {
   2136             soc_reg_snoop_register(unit, reg, SOC_REG_SNOOP_WRITE,
   2137                                    reg_watch_cb, NULL);
   2138         }
   2139     } else {
   2140         return CMD_USAGE;
   2141     }
   2142     if (bsl_check(bslLayerAppl, bslSourceTests, bslSeverityNormal, unit) == 0) {
   2143         cli_out("** Also enable Tests debug by \"debug soc TESTS info\" \n");
   2144     }
   2145     return CMD_OK;
   2146 }