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 = ®->fields[0]; fld < ®->fields[reg->nFields]; fld++) { 131 if (!sal_strcasecmp(fmod, SOC_FIELD_NAME(unit, fld->field))) { 132 break; 133 } 134 } 135 if (fld == ®->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 = ®info->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 = ®->fields[0]; fld < ®->fields[reg->nFields]; fld++) { 340 if (!sal_strcasecmp(fmod, SOC_FIELD_NAME(unit, fld->field))) { 341 break; 342 } 343 } 344 if (fld == ®->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 = ®info->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 ®types[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, ®val, 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, ®addr) < 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, ®val, 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, ®addr) < 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, ®val); 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, ®val, 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, ®_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 = ®info->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 = ®info->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 }