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

mem.c (117159B)


      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 memory commands
      8  */
      9 
     10 #include <shared/bsl.h>
     11 
     12 #include <sal/core/libc.h>
     13 #include <soc/mem.h>
     14 #include <soc/debug.h>
     15 #include <shared/bsl.h>
     16 #include <soc/error.h>
     17 #include <soc/l2x.h>
     18 #include <soc/l3x.h>
     19 #include <soc/soc_ser_log.h>
     20 #ifdef BCM_ISM_SUPPORT
     21 #include <soc/ism.h>
     22 #endif
     23 #include <appl/diag/system.h>
     24 #ifdef BCM_TRIDENT2_SUPPORT
     25 #include <soc/trident2.h>
     26 #endif
     27 #ifdef BCM_TOMAHAWK_SUPPORT
     28 #include <soc/tomahawk.h>
     29 #endif
     30 #ifdef BCM_TOMAHAWK3_SUPPORT
     31 #include <soc/tomahawk3.h>
     32 #endif
     33 
     34 #ifdef BCM_TRIDENT3_SUPPORT
     35 #include <soc/esw/flow_db.h>
     36 #include <soc/esw/flow_db_core.h>
     37 #endif
     38 #ifdef ALPM_ENABLE
     39 #include <soc/alpm.h>
     40 #endif
     41 #ifdef __KERNEL__
     42 #define atoi _shr_ctoi
     43 #endif
     44 
     45 #ifdef INCLUDE_MEM_SCAN
     46 static sal_usecs_t prev_memscan_interval[SOC_MAX_NUM_DEVICES];
     47 static int prev_memscan_rate[SOC_MAX_NUM_DEVICES];
     48 #endif
     49 #ifdef BCM_SRAM_SCAN_SUPPORT
     50 static sal_usecs_t prev_sramscan_interval[SOC_MAX_NUM_DEVICES];
     51 static int prev_sramscan_rate[SOC_MAX_NUM_DEVICES];
     52 #endif
     53 
     54 /* Memory counter array */
     55 static mem_count_t *mem_count[SOC_MAX_NUM_DEVICES];
     56 
     57 /* local defines */
     58 #define FIELD_ID_ARRAY_SIZE  40
     59 
     60 /*
     61  * Utility routine to concatenate the first argument ("first"), with
     62  * the remaining arguments, with commas separating them.
     63  */
     64 
     65 static void
     66 collect_comma_args(args_t *a, char *valstr, char *first)
     67 {
     68     char *s;
     69 
     70     sal_strcpy(valstr, first);
     71 
     72     while ((s = ARG_GET(a)) != 0) {
     73 	sal_strcat(valstr, ",");
     74 	sal_strcat(valstr, s);
     75     }
     76 }
     77 
     78 static void
     79 check_global(int unit, soc_mem_t mem, char *s, int *is_global)
     80 {
     81     soc_field_info_t	*fld;
     82     soc_mem_info_t	*m = &SOC_MEM_INFO(unit, mem);
     83     char                *eqpos;
     84     
     85     eqpos = strchr(s, '=');
     86     if (eqpos != NULL) {
     87         *eqpos++ = 0;
     88     }
     89     for (fld = &m->fields[0]; fld < &m->fields[m->nFields]; fld++) {
     90         if (!sal_strcasecmp(s, SOC_FIELD_NAME(unit, fld->field)) &&
     91             (fld->flags & SOCF_GLOBAL)) {
     92     	    break;
     93         }
     94     }
     95     if (fld == &m->fields[m->nFields]) {
     96         *is_global = 0;
     97     } else {
     98         *is_global = 1;
     99     }
    100 }
    101 
    102 static int
    103 collect_comma_args_with_view(args_t *a, char *valstr, char *first, 
    104                              char *view, int unit, soc_mem_t mem)
    105 {
    106     char *s, *s_copy = NULL, *f_copy = NULL;
    107     int is_global, rv = 0;
    108 
    109     if ((f_copy = sal_alloc(sal_strlen(first) + 1, "first")) == NULL) {
    110         cli_out("cmd_esw_mem_write : Out of memory\n");
    111         rv = -1;
    112         goto done;
    113     }
    114     sal_memset(f_copy, 0, sal_strlen(first) + 1);
    115     sal_strcpy(f_copy, first);
    116 
    117     /* Check if field is global before applying view prefix */
    118     check_global(unit, mem, f_copy, &is_global);
    119     if (!is_global) {
    120         sal_strcpy(valstr, view);
    121         sal_strcat(valstr, first);
    122     } else {
    123         sal_strcpy(valstr, first);
    124     }
    125 
    126     while ((s = ARG_GET(a)) != 0) {
    127         if ((s_copy = sal_alloc(sal_strlen(s) + 1, "s_copy")) == NULL) {
    128             cli_out("cmd_esw_mem_write : Out of memory\n");
    129             rv = -1;
    130             goto done;
    131         }
    132         sal_memset(s_copy, 0, sal_strlen(s) + 1);
    133         sal_strcpy(s_copy, s);
    134         check_global(unit, mem, s_copy, &is_global);
    135         sal_free(s_copy);
    136         sal_strcat(valstr, ",");
    137         if (!is_global) {
    138             sal_strcat(valstr, view);
    139             sal_strcat(valstr, s);
    140         } else {
    141             sal_strcat(valstr, s);
    142         }
    143     }
    144 done:
    145     if (f_copy != NULL) {
    146         sal_free(f_copy);
    147     }
    148     return rv;
    149 }
    150 
    151 static int
    152 _modify_flex_mem_fields(int unit, soc_mem_t mem, uint32 *entry,
    153 		  uint32 *mask, char *mod, int incr)
    154 {
    155 #ifdef BCM_TRIDENT3_SUPPORT
    156     int rv = CMD_NFND;
    157     soc_field_info_t	*fld;
    158     char		*fmod, *fval, *s;
    159     char		*modstr = NULL;
    160     char		*tokstr = NULL;
    161     uint32		fvalue[SOC_MAX_MEM_FIELD_WORDS];
    162     uint32		fincr[SOC_MAX_MEM_FIELD_WORDS];
    163     int			i, entry_dw;
    164     soc_mem_info_t	*m = &SOC_MEM_INFO(unit, mem);
    165     char *mod_ptr = NULL;
    166     soc_field_t key_type_fid = 0;
    167     soc_field_t data_type_fid = 0;
    168     int key_type = 0;
    169     int data_type = 0; 
    170     int flex_view = FALSE;
    171     soc_mem_t mem_view_id;
    172     soc_flow_db_mem_view_field_info_t view_field;
    173     int field_type;
    174     uint32 cnt;
    175     int ix = 0;
    176     uint32 field_id[FIELD_ID_ARRAY_SIZE];
    177     int field_found;
    178     soc_field_info_t soc_field;
    179     char *field_name;
    180 
    181     if (!soc_feature(unit, soc_feature_flex_flow)) {
    182         return CMD_NFND;
    183     }
    184     /* check if flow_db is initialized */
    185     rv = soc_flow_db_status_get(unit);
    186 
    187     if (SOC_FAILURE(rv)) {
    188         return CMD_NFND;
    189     }
    190 
    191     entry_dw = BYTES2WORDS(m->bytes);
    192 
    193     if ((modstr = sal_alloc(ARGS_BUFFER, "modify_mem")) == NULL) {
    194         cli_out("modify_mem_fields: Out of memory\n");
    195         return CMD_FAIL;
    196     }
    197 
    198     sal_strncpy(modstr, mod, ARGS_BUFFER);/* Don't destroy input string */
    199     modstr[ARGS_BUFFER - 1] = 0;
    200 
    201     /* For flex view entry modification, user should always specify the 
    202      * key_type if applicable and data_type.
    203      */
    204     mod_ptr = modstr;
    205     while ((fmod = sal_strtok_r(mod_ptr, ",", &tokstr)) != 0) {
    206         mod_ptr = NULL;                 /* Pass strtok NULL next time */
    207         fval = strchr(fmod, '=');
    208         if (fval != NULL) {       /* Point fval to arg, NULL if none */
    209             *fval++ = 0;          /* Now fmod holds only field name. */
    210 
    211             if (!sal_strcasecmp(fmod, "KEY_TYPE0")) {
    212                 key_type_fid = KEY_TYPE0f;
    213                 parse_long_integer(fvalue, SOC_MAX_MEM_FIELD_WORDS, fval);
    214                 key_type = fvalue[0];
    215             } else if (!sal_strcasecmp(fmod, "KEY_TYPE")) {
    216                 key_type_fid = KEY_TYPEf;
    217                 parse_long_integer(fvalue, SOC_MAX_MEM_FIELD_WORDS, fval);
    218                 key_type = fvalue[0];
    219             } else if (!sal_strcasecmp(fmod, "DATA_TYPE0")) {
    220                 data_type_fid = DATA_TYPE0f;
    221                 parse_long_integer(fvalue, SOC_MAX_MEM_FIELD_WORDS, fval);
    222                 data_type = fvalue[0];
    223             } else if (!sal_strcasecmp(fmod, "DATA_TYPE")) {
    224                 data_type_fid = DATA_TYPEf;
    225                 parse_long_integer(fvalue, SOC_MAX_MEM_FIELD_WORDS, fval);
    226                 data_type = fvalue[0];
    227             }
    228         }  
    229     }
    230     if (key_type_fid || data_type_fid) {
    231         if (!key_type) {
    232             rv = soc_flow_db_mem_to_view_id_get (unit, mem,
    233                        SOC_FLOW_DB_KEY_TYPE_INVALID, data_type,
    234                        0, NULL, (uint32 *)&mem_view_id);
    235         } else {
    236             rv = soc_flow_db_mem_to_view_id_get (unit, mem, 
    237                     key_type, data_type, 0, NULL, (uint32 *)&mem_view_id);
    238         }
    239         /* if error, fall thru to try non-flex action */
    240         if (rv == SOC_E_NONE) {
    241             flex_view = TRUE;
    242         }
    243     }
    244 
    245     if (flex_view == FALSE) {
    246         sal_free(modstr);
    247         return CMD_NFND;
    248     }
    249 
    250     /* restore back modstr */
    251     sal_strncpy(modstr, mod, ARGS_BUFFER);/* Don't destroy input string */
    252     modstr[ARGS_BUFFER - 1] = 0;
    253     mod = modstr;
    254 
    255     if (mask) {
    256 	memset(mask, 0, entry_dw * 4);
    257     }
    258 
    259     while ((fmod = sal_strtok_r(mod, ",", &tokstr)) != 0) {
    260 	mod = NULL;			/* Pass strtok NULL next time */
    261 	fval = strchr(fmod, '=');
    262 	if (fval != NULL) {		/* Point fval to arg, NULL if none */
    263 	    *fval++ = 0;		/* Now fmod holds only field name. */
    264 	}
    265 	if (fmod[0] == 0) {
    266 	    cli_out("Null field name\n");
    267             sal_free(modstr);
    268 	    return CMD_FAIL;
    269 	}
    270 	if (!sal_strcasecmp(fmod, "clear")) {
    271 	    sal_memset(entry, 0, entry_dw * sizeof (*entry));
    272 	    if (mask) {
    273 		memset(mask, 0xff, entry_dw * sizeof (*entry));
    274 	    }
    275 	    continue;
    276 	}
    277         field_found= FALSE;
    278         for (field_type = SOC_FLOW_DB_FIELD_TYPE_CONTROL;
    279                 field_type < SOC_FLOW_DB_FIELD_TYPE_MAX; field_type++) {
    280             rv = soc_flow_db_mem_view_field_list_get(unit, mem_view_id,
    281                              field_type, FIELD_ID_ARRAY_SIZE, field_id, &cnt);
    282             if (SOC_SUCCESS(rv)) {
    283                 for (ix = 0; ix < cnt; ix++) {
    284                     if (field_type == SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY ||
    285                         field_type == 
    286                            SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA) {
    287                         (void) soc_flow_db_mem_view_field_name_get(unit, 
    288                                    mem_view_id, field_id[ix], &field_name);
    289                     }
    290                     else {
    291                         field_name = SOC_FIELD_NAME(unit,field_id[ix]);
    292                     }
    293 
    294                     if (!sal_strcasecmp(fmod, field_name)) {
    295                         field_found=TRUE;
    296                         break;
    297                     }
    298                 }
    299             }
    300 
    301             if (field_found == TRUE) {
    302                 break;
    303             }
    304         }
    305         if (field_found == TRUE) {
    306             rv = soc_flow_db_mem_view_field_info_get(unit,mem_view_id,
    307                        field_id[ix], &view_field);
    308         }
    309         if ((field_found == FALSE) || SOC_FAILURE(rv)) {
    310             sal_free(modstr);
    311             return CMD_NFND;
    312         }
    313         soc_field.field = field_id[ix];
    314         soc_field.len = view_field.width;
    315         soc_field.bp = view_field.offset;
    316         soc_field.flags = view_field.flags;
    317         fld = &soc_field;
    318         mem = mem_view_id;
    319 
    320 	if (!fval) {
    321 	    cli_out("Missing %d-bit value to assign to \"%s\" field \"%s\".\n",
    322                     fld->len,
    323                     SOC_MEM_UFNAME(unit, mem), field_name);
    324             sal_free(modstr);
    325 	    return -1;
    326 	}
    327 	s = strchr(fval, '+');
    328 	if (s == NULL) {
    329 	    s = strchr(fval, '-');
    330 	}
    331 	if (s == fval) {
    332 	    s = NULL;
    333 	}
    334 	if (incr) {
    335 	    if (s != NULL) {
    336 		parse_long_integer(fincr, SOC_MAX_MEM_FIELD_WORDS,
    337 				   s[1] ? &s[1] : "1");
    338 		if (*s == '-') {
    339 		    neg_long_integer(fincr, SOC_MAX_MEM_FIELD_WORDS);
    340 		}
    341 		if (fld->len & 31) {
    342 		    /* Proper treatment of sign extension */
    343 		    fincr[fld->len / 32] &= ~(0xffffffff << (fld->len & 31));
    344 		}
    345 		soc_mem_field_get(unit, mem, entry, fld->field, fvalue);
    346 		add_long_integer(fvalue, fincr, SOC_MAX_MEM_FIELD_WORDS);
    347 		if (fld->len & 31) {
    348 		    /* Proper treatment of sign extension */
    349 		    fvalue[fld->len / 32] &= ~(0xffffffff << (fld->len & 31));
    350 		}
    351 		soc_mem_field_set(unit, mem, entry, fld->field, fvalue);
    352 	    }
    353 	} else {
    354 	    if (s != NULL) {
    355 		*s = 0;
    356 	    }
    357 	    parse_long_integer(fvalue, SOC_MAX_MEM_FIELD_WORDS, fval);
    358 	    for (i = fld->len; i < SOC_MAX_MEM_FIELD_BITS; i++) {
    359 		if (fvalue[i / 32] & 1 << (i & 31)) {
    360 		    cli_out("Value \"%s\" too large for "
    361                             "%d-bit field \"%s\".\n",
    362                             fval, fld->len, field_name);
    363                     sal_free(modstr);
    364 		    return CMD_FAIL;
    365 		}
    366 	    }
    367 	    soc_mem_field_set(unit, mem, entry, fld->field, fvalue);
    368 	}
    369 	if (mask) {
    370 	    sal_memset(fvalue, 0, sizeof (fvalue));
    371 	    for (i = 0; i < fld->len; i++) {
    372 		fvalue[i / 32] |= 1 << (i & 31);
    373 	    }
    374 	    soc_mem_field_set(unit, mem, mask, fld->field, fvalue);
    375 	}
    376     }
    377 
    378     sal_free(modstr);
    379     return CMD_OK;
    380 #else
    381     return CMD_NFND;
    382 #endif
    383 }
    384 /*
    385  * modify_mem_fields
    386  *
    387  *   Verify similar to modify_reg_fields (see reg.c) but works on
    388  *   memory table entries instead of register values.  Handles fields
    389  *   of any length.
    390  *
    391  *   If mask is non-NULL, it receives an entry which is a mask of all
    392  *   fields modified.
    393  *
    394  *   Values may be specified with optional increment or decrement
    395  *   amounts; for example, a MAC address could be 0x1234+2 or 0x1234-1
    396  *   to specify an increment of +2 or -1, respectively.
    397  *
    398  *   If incr is FALSE, the increment is ignored and the plain value is
    399  *   stored in the field (e.g. 0x1234).
    400  *
    401  *   If incr is TRUE, the value portion is ignored.  Instead, the
    402  *   increment value is added to the existing value of the field.  The
    403  *   field value wraps around on overflow.
    404  *
    405  *   Returns -1 on failure, 0 on success.
    406  */
    407 
    408 static int
    409 _modify_mem_fields(int unit, soc_mem_t mem, uint32 *entry,
    410 		  uint32 *mask, char *mod, int incr)
    411 {
    412     soc_field_info_t	*fld;
    413     char		*fmod, *fval, *s;
    414     char		*modstr = NULL;
    415     char		*tokstr = NULL;
    416     uint32		fvalue[SOC_MAX_MEM_FIELD_WORDS];
    417     uint32		fincr[SOC_MAX_MEM_FIELD_WORDS];
    418     int			i, entry_dw;
    419     soc_mem_info_t	*m = &SOC_MEM_INFO(unit, mem);
    420 
    421     entry_dw = BYTES2WORDS(m->bytes);
    422 
    423     if ((modstr = sal_alloc(ARGS_BUFFER, "modify_mem")) == NULL) {
    424         cli_out("modify_mem_fields: Out of memory\n");
    425         return CMD_FAIL;
    426     }
    427 
    428     sal_strncpy(modstr, mod, ARGS_BUFFER);/* Don't destroy input string */
    429     modstr[ARGS_BUFFER - 1] = 0;
    430     mod = modstr;
    431 
    432     if (mask) {
    433 	memset(mask, 0, entry_dw * 4);
    434     }
    435 
    436     while ((fmod = sal_strtok_r(mod, ",", &tokstr)) != 0) {
    437 	mod = NULL;			/* Pass strtok NULL next time */
    438 	fval = strchr(fmod, '=');
    439 	if (fval != NULL) {		/* Point fval to arg, NULL if none */
    440 	    *fval++ = 0;		/* Now fmod holds only field name. */
    441 	}
    442 	if (fmod[0] == 0) {
    443 	    cli_out("Null field name\n");
    444             sal_free(modstr);
    445 	    return -1;
    446 	}
    447 	if (!sal_strcasecmp(fmod, "clear")) {
    448 	    sal_memset(entry, 0, entry_dw * sizeof (*entry));
    449 	    if (mask) {
    450 		memset(mask, 0xff, entry_dw * sizeof (*entry));
    451 	    }
    452 	    continue;
    453 	}
    454 	for (fld = &m->fields[0]; fld < &m->fields[m->nFields]; fld++) {
    455 	    if (!sal_strcasecmp(fmod, SOC_FIELD_NAME(unit, fld->field))) {
    456 		break;
    457 	    }
    458 	}
    459 	if (fld == &m->fields[m->nFields]) {
    460 	    cli_out("No such field \"%s\" in memory \"%s\".\n",
    461                     fmod, SOC_MEM_UFNAME(unit, mem));
    462             sal_free(modstr);
    463 	    return -1;
    464 	}
    465 	if (!fval) {
    466 	    cli_out("Missing %d-bit value to assign to \"%s\" field \"%s\".\n",
    467                     fld->len,
    468                     SOC_MEM_UFNAME(unit, mem), SOC_FIELD_NAME(unit, fld->field));
    469             sal_free(modstr);
    470 	    return -1;
    471 	}
    472 	s = strchr(fval, '+');
    473 	if (s == NULL) {
    474 	    s = strchr(fval, '-');
    475 	}
    476 	if (s == fval) {
    477 	    s = NULL;
    478 	}
    479 	if (incr) {
    480 	    if (s != NULL) {
    481 		parse_long_integer(fincr, SOC_MAX_MEM_FIELD_WORDS,
    482 				   s[1] ? &s[1] : "1");
    483 		if (*s == '-') {
    484 		    neg_long_integer(fincr, SOC_MAX_MEM_FIELD_WORDS);
    485 		}
    486 		if (fld->len & 31) {
    487 		    /* Proper treatment of sign extension */
    488 		    fincr[fld->len / 32] &= ~(0xffffffff << (fld->len & 31));
    489 		}
    490 		soc_mem_field_get(unit, mem, entry, fld->field, fvalue);
    491 		add_long_integer(fvalue, fincr, SOC_MAX_MEM_FIELD_WORDS);
    492 		if (fld->len & 31) {
    493 		    /* Proper treatment of sign extension */
    494 		    fvalue[fld->len / 32] &= ~(0xffffffff << (fld->len & 31));
    495 		}
    496 		soc_mem_field_set(unit, mem, entry, fld->field, fvalue);
    497 	    }
    498 	} else {
    499 	    if (s != NULL) {
    500 		*s = 0;
    501 	    }
    502 	    parse_long_integer(fvalue, SOC_MAX_MEM_FIELD_WORDS, fval);
    503 	    for (i = fld->len; i < SOC_MAX_MEM_FIELD_BITS; i++) {
    504 		if (fvalue[i / 32] & 1 << (i & 31)) {
    505 		    cli_out("Value \"%s\" too large for "
    506                             "%d-bit field \"%s\".\n",
    507                             fval, fld->len, SOC_FIELD_NAME(unit, fld->field));
    508                     sal_free(modstr);
    509 		    return -1;
    510 		}
    511 	    }
    512 	    soc_mem_field_set(unit, mem, entry, fld->field, fvalue);
    513 	}
    514 	if (mask) {
    515 	    sal_memset(fvalue, 0, sizeof (fvalue));
    516 	    for (i = 0; i < fld->len; i++) {
    517 		fvalue[i / 32] |= 1 << (i & 31);
    518 	    }
    519 	    soc_mem_field_set(unit, mem, mask, fld->field, fvalue);
    520 	}
    521     }
    522 
    523     sal_free(modstr);
    524     return 0;
    525 }
    526 
    527 static int
    528 modify_mem_fields(int unit, soc_mem_t mem, uint32 *entry,
    529 		  uint32 *mask, char *mod, int incr)
    530 {
    531     int rv;
    532 
    533     rv = _modify_flex_mem_fields(unit,mem,entry,mask,mod,incr);
    534     if (rv == CMD_NFND) {
    535         return _modify_mem_fields(unit,mem,entry,mask,mod,incr);
    536     } else {
    537         return rv;
    538     }
    539 }
    540 
    541 /*
    542  * mmudebug command
    543  *    No argument: print current state
    544  *    Argument is 1: enable
    545  *    Argument is 0: disable
    546  */
    547 
    548 char mmudebug_usage[] =
    549     "Parameters: [on | off]\n\t"
    550     "Puts the MMU in debug mode (on) or normal mode (off).\n\t"
    551     "With no parameter, displays the current mode.\n\t"
    552     "MMU must be in debug mode to access CBP memories.\n";
    553 
    554 cmd_result_t
    555 mem_mmudebug(int unit, args_t *a)
    556 {
    557     char *s = ARG_GET(a);
    558 
    559     if (!sh_check_attached(ARG_CMD(a), unit)) {
    560 	return CMD_FAIL;
    561     }
    562 
    563     if (s) {
    564 	if (!sal_strcasecmp(s, "on")) {
    565 	    cli_out("Entering debug mode ...\n");
    566 	    if (soc_mem_debug_set(unit, 1) < 0) {
    567                 return CMD_FAIL;
    568             }
    569 	} else if (!sal_strcasecmp(s, "off")) {
    570 	    cli_out("Leaving debug mode ...\n");
    571 	    if (soc_mem_debug_set(unit, 0) < 0) {
    572                 return CMD_FAIL;
    573             }
    574 	} else
    575 	    return CMD_USAGE;
    576     } else {
    577 	int enable = 0;
    578 	soc_mem_debug_get(unit, &enable);
    579 	cli_out("MMU debug mode is %s\n", enable ? "on" : "off");
    580     }
    581 
    582     return CMD_OK;
    583 }
    584 
    585 /*
    586  * Initialize Cell Free Address pool.
    587  */
    588 
    589 char cfapinit_usage[] =
    590     "Parameters: none\n\t"
    591     "Run diags on CFAP pool and initialize CFAP with good entries only\n";
    592 
    593 cmd_result_t
    594 mem_cfapinit(int unit, args_t *a)
    595 {
    596     int r;
    597 
    598     if (!sh_check_attached(ARG_CMD(a), unit)) {
    599 	return CMD_FAIL;
    600     }
    601 
    602     if ((r = soc_mem_cfap_init(unit)) < 0) {
    603 	cli_out("NOTICE: error initializing CFAP: %s\n", soc_errmsg(r));
    604 	return CMD_FAIL;
    605     }
    606 
    607     return CMD_OK;
    608 }
    609 
    610 #ifdef BCM_HERCULES_SUPPORT
    611 /*
    612  * Initialize Cell Free Address pool.
    613  */
    614 
    615 char llainit_usage[] =
    616     "Parameters: [force]\n\t"
    617     "Run diags on LLA and PP and initialize LLA with good entries only\n";
    618 
    619 cmd_result_t
    620 mem_llainit(int unit, args_t *a)
    621 {
    622     char *argforce;
    623     int force = FALSE;
    624 
    625     if (!sh_check_attached(ARG_CMD(a), unit)) {
    626 	return CMD_FAIL;
    627     }
    628 
    629     if ((argforce = ARG_GET(a)) != NULL) {
    630         if (!sal_strcasecmp(argforce, "force")) {
    631             force = TRUE;
    632         } else {
    633             return CMD_USAGE;
    634         }
    635     }
    636 
    637     if (force) {
    638         if (SOC_CONTROL(unit)->lla_map != NULL) {
    639             int i;
    640 	    PBMP_PORT_ITER(unit, i) {
    641                 if (SOC_CONTROL(unit)->lla_map[i] != NULL) {
    642                     sal_free(SOC_CONTROL(unit)->lla_map[i]);
    643                     SOC_CONTROL(unit)->lla_map[i] = NULL;
    644                 }
    645             }
    646         }
    647     }
    648 
    649     return CMD_OK;
    650 }
    651 #endif
    652 
    653 static int
    654 parse_dwords(int count, uint32 *dw, args_t *a)
    655 {
    656     char	*s;
    657     int		i;
    658 
    659     for (i = 0; i < count; i++) {
    660 	if ((s = ARG_GET(a)) == NULL) {
    661 	    cli_out("Not enough data values (have %d, need %d)\n",
    662                     i, count);
    663 	    return -1;
    664 	}
    665 
    666 	dw[i] = parse_integer(s);
    667     }
    668 
    669     if (ARG_CNT(a) > 0) {
    670 	cli_out("Ignoring extra data on command line "
    671                 "(only %d words needed)\n",
    672                 count);
    673     }
    674 
    675     return 0;
    676 }
    677 
    678 cmd_result_t
    679 cmd_esw_mem_write(int unit, args_t *a)
    680 {
    681     int			i, index, start, count, copyno;
    682     char		*tab, *idx, *cnt, *s, *memname, *slam_buf = NULL;
    683     soc_mem_t		mem;
    684     uint32		entry[SOC_MAX_MEM_WORDS];
    685     int			entry_dw, view_len, entry_bytes;
    686     char		copyno_str[8];
    687     int			r, update;
    688     int			rv = CMD_FAIL;
    689     char		*valstr = NULL, *view = NULL;
    690     int			no_cache = 0;
    691     int                 use_slam = 0;
    692     int			acc_type = 0;
    693     int			specific_pipe = 0;
    694 #ifdef BCM_KATANA2_SUPPORT
    695     int port_index[15]=
    696     {1,5,9,13,17,21,25,26,27,28,30,33,37,39,41};
    697     int matched = 0;
    698 #endif /*BCM_KATANA2_SUPPORT */
    699 #if defined(BCM_TOMAHAWK_SUPPORT)
    700     int         enable_mem_mode_check = 1;
    701 #endif /* BCM_TOMAHAWK_SUPPORT */
    702     int         idx_phy = 0;
    703     uint32      flags = SOC_MEM_NO_FLAGS;
    704 
    705     if (!sh_check_attached(ARG_CMD(a), unit)) {
    706 	goto done;
    707     }
    708 
    709     tab = ARG_GET(a);
    710     if (tab != NULL && sal_strcasecmp(tab, "idx_phy") == 0) {
    711         idx_phy = 1;
    712         tab = ARG_GET(a);
    713     }
    714     if (tab != NULL && sal_strcasecmp(tab, "nocache") == 0) {
    715 	no_cache = 1;
    716 	tab = ARG_GET(a);
    717     }
    718     if (tab != NULL && sal_strcasecmp(tab, "pipe_x") == 0) {
    719 	acc_type = _SOC_MEM_ADDR_ACC_TYPE_PIPE_X;
    720         specific_pipe = 1;
    721 	tab = ARG_GET(a);
    722     }
    723     if (tab != NULL && sal_strcasecmp(tab, "pipe_y") == 0) {
    724 	acc_type = _SOC_MEM_ADDR_ACC_TYPE_PIPE_Y;
    725         specific_pipe = 1;
    726 	tab = ARG_GET(a);
    727     }
    728     if (tab != NULL && sal_strcasecmp(tab, "pipe0") == 0) {
    729 	acc_type = _SOC_MEM_ADDR_ACC_TYPE_PIPE_0;
    730         specific_pipe = 1;
    731 	tab = ARG_GET(a);
    732     }
    733     if (tab != NULL && sal_strcasecmp(tab, "pipe1") == 0) {
    734 	acc_type = _SOC_MEM_ADDR_ACC_TYPE_PIPE_1;
    735         specific_pipe = 1;
    736 	tab = ARG_GET(a);
    737     }
    738     if (tab != NULL && sal_strcasecmp(tab, "pipe2") == 0) {
    739 	acc_type = _SOC_MEM_ADDR_ACC_TYPE_PIPE_2;
    740         specific_pipe = 1;
    741 	tab = ARG_GET(a);
    742     }
    743     if (tab != NULL && sal_strcasecmp(tab, "pipe3") == 0) {
    744 	acc_type = _SOC_MEM_ADDR_ACC_TYPE_PIPE_3;
    745         specific_pipe = 1;
    746 	tab = ARG_GET(a);
    747     }
    748     if (tab != NULL && sal_strcasecmp(tab, "pipe4") == 0) {
    749     acc_type = _SOC_MEM_ADDR_ACC_TYPE_PIPE_4;
    750         specific_pipe = 1;
    751     tab = ARG_GET(a);
    752     }
    753     if (tab != NULL && sal_strcasecmp(tab, "pipe5") == 0) {
    754     acc_type = _SOC_MEM_ADDR_ACC_TYPE_PIPE_5;
    755         specific_pipe = 1;
    756     tab = ARG_GET(a);
    757     }
    758     if (tab != NULL && sal_strcasecmp(tab, "pipe6") == 0) {
    759     acc_type = _SOC_MEM_ADDR_ACC_TYPE_PIPE_6;
    760         specific_pipe = 1;
    761     tab = ARG_GET(a);
    762     }
    763     if (tab != NULL && sal_strcasecmp(tab, "pipe7") == 0) {
    764     acc_type = _SOC_MEM_ADDR_ACC_TYPE_PIPE_7;
    765         specific_pipe = 1;
    766     tab = ARG_GET(a);
    767     }
    768 #if defined(BCM_TOMAHAWK_SUPPORT)
    769     if (tab != NULL && sal_strcasecmp(tab, "nocheck_mem_mode") == 0) {
    770         enable_mem_mode_check = 0;
    771 	tab = ARG_GET(a);
    772     }
    773 #endif /* BCM_TOMAHAWK_SUPPORT */
    774     idx = ARG_GET(a);
    775     cnt = ARG_GET(a);
    776     s = ARG_GET(a);
    777 
    778     /* you will need at least one value and all the args .. */
    779     if (!tab || !idx || !cnt || !s || !isint(cnt)) {
    780 	return CMD_USAGE;
    781     }
    782 
    783     /* Deal with VIEW:MEMORY if applicable */
    784     memname = sal_strstr(tab, ":");
    785     view_len = 0;
    786     if (memname != NULL) {
    787         memname++;
    788         view_len = memname - tab;
    789     } else {
    790         memname = tab;
    791     }
    792 
    793     if (parse_memory_name(unit, &mem, memname, &copyno, 0) < 0) {
    794 	cli_out("ERROR: unknown table \"%s\"\n",tab);
    795 	goto done;
    796     }
    797 
    798     if (!SOC_MEM_IS_VALID(unit, mem)) {
    799         cli_out("Error: Memory %s not valid for chip %s.\n",
    800                 SOC_MEM_UFNAME(unit, mem), SOC_UNIT_NAME(unit));
    801         goto done;
    802     }
    803 
    804 #if defined(BCM_HAWKEYE_SUPPORT)
    805     if (SOC_IS_HAWKEYE(unit) && (soc_mem_index_max(unit, mem) <= 0)) {
    806         cli_out("Error: Memory %s not valid for chip %s.\n",
    807                 SOC_MEM_UFNAME(unit, mem), SOC_UNIT_NAME(unit));
    808         goto done;
    809     }
    810 #endif /* BCM_HAWKEYE_SUPPORT */
    811 
    812     if (soc_mem_is_readonly(unit, mem)) {
    813         cli_out("Error: Table %s is read-only\n",
    814                 SOC_MEM_UFNAME(unit, mem));
    815         goto done;
    816     }
    817 
    818     start = parse_memory_index(unit, mem, idx);
    819     count = parse_integer(cnt);
    820 
    821     if (copyno == COPYNO_ALL) {
    822 	copyno_str[0] = 0;
    823     } else {
    824 	sal_sprintf(copyno_str, ".%d", copyno);
    825     }
    826 
    827     entry_dw = soc_mem_entry_words(unit, mem);
    828 
    829     if ((valstr = sal_alloc(ARGS_BUFFER, "reg_set")) == NULL) {
    830         cli_out("cmd_esw_mem_write : Out of memory\n");
    831         goto done;
    832     }
    833 
    834     /*
    835      * If a list of fields were specified, generate the entry from them.
    836      * Otherwise, generate it by reading raw dwords from command line.
    837      */
    838 
    839     if (!isint(s)) {
    840 	/* List of fields */
    841 
    842 	if (view_len == 0) {
    843             collect_comma_args(a, valstr, s);
    844         } else {
    845             if ((view = sal_alloc(view_len + 1, "view_name")) == NULL) {
    846                 cli_out("cmd_esw_mem_write : Out of memory\n");
    847                 goto done;
    848             }
    849             sal_memset(view, 0, view_len + 1);
    850             sal_memcpy(view, tab, view_len);
    851             if (collect_comma_args_with_view(a, valstr, s, view, unit, mem) < 0) {
    852                 cli_out("Out of memory: aborted\n");
    853                 goto done;
    854             }
    855         }
    856 
    857 	memset(entry, 0, sizeof (entry));
    858 
    859 	if (modify_mem_fields(unit, mem, entry, NULL, valstr, FALSE) < 0) {
    860 	    cli_out("Syntax error: aborted\n");
    861 	    goto done;
    862 	}
    863 
    864 	update = TRUE;
    865     } else {
    866 	/* List of numeric values */
    867 
    868 	ARG_PREV(a);
    869 
    870 	if (parse_dwords(entry_dw, entry, a) < 0) {
    871 	    goto done;
    872 	}
    873 
    874 	update = FALSE;
    875     }
    876 
    877     if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) {
    878 	cli_out("WRITE[%s%s], DATA:", SOC_MEM_UFNAME(unit, mem), copyno_str);
    879 	for (i = 0; i < entry_dw; i++) {
    880 	    cli_out(" 0x%x", entry[i]);
    881 	}
    882 	cli_out("\n");
    883     }
    884 
    885     /*
    886      * Created entry, now write it
    887      */
    888 
    889     use_slam = soc_property_get(unit, spn_DIAG_SHELL_USE_SLAM, 0);
    890 #if defined(BCM_TOMAHAWK_SUPPORT)
    891     if (SOC_IS_TOMAHAWKX(unit)) {
    892         if (enable_mem_mode_check &&
    893             soc_th_mem_is_dual_mode(unit, mem, NULL, NULL)) {
    894             use_slam = 0; /* simplify */
    895             LOG_VERBOSE(BSL_LS_SOC_SER, (BSL_META_U(unit,
    896                 "Write slam DISABLED for mem %s\n"),
    897                 SOC_MEM_NAME(unit, mem)));
    898         }
    899     }
    900 #endif /* BCM_TOMAHAWK_SUPPORT */
    901     if (use_slam && count > 1) {
    902         entry_bytes = WORDS2BYTES(soc_mem_entry_words(unit, mem));
    903         slam_buf = soc_cm_salloc(unit, count * entry_bytes, "slam_entry");
    904         if (slam_buf == NULL) {
    905             cli_out("cmd_esw_mem_write : Out of memory\n");
    906             goto done;
    907         }
    908         for (i = 0; i < count; i++) {
    909             sal_memcpy(slam_buf + i * entry_bytes, entry, entry_bytes);
    910         }
    911         r = soc_mem_write_range(unit, mem, copyno, start, start + count - 1, slam_buf);
    912         soc_cm_sfree(unit, slam_buf);
    913         if (r < 0) {
    914             cli_out("Slam ERROR: table %s.%s: %s\n",
    915                     SOC_MEM_UFNAME(unit, mem), copyno_str, soc_errmsg(r));
    916             goto done;
    917         }
    918         for (index = start; index < start + count; index++) {
    919 	    if (update) {
    920 	        modify_mem_fields(unit, mem, entry, NULL, valstr, TRUE);
    921 	    }
    922         }
    923     } else {
    924         for (index = start; index < start + count; index++) {
    925 #ifdef BCM_KATANA2_SUPPORT
    926             if (SOC_IS_KATANA2(unit)) {
    927                 /* In case of SP memories, out of SP0, SP1, SP2 & SP3                 
    928                    only SP0 is valid. i.e only inidices 0,4,8. This check 
    929                    is to avoid processing invalid indices. Issue is handled
    930                    for THDI memories alone. Has to be handled
    931                    for other SP memories in future */
    932 
    933                 if ((mem == THDIEMA_THDI_PORT_SP_CONFIGm ||
    934                             mem == THDIEXT_THDI_PORT_SP_CONFIGm ||
    935                             mem == THDIQEN_THDI_PORT_SP_CONFIGm ||
    936                             mem == THDIRQE_THDI_PORT_SP_CONFIGm ||
    937                             mem == THDI_PORT_SP_CONFIGm) && (index % 4)) {
    938 
    939                     continue;
    940                 }
    941                 if(!SOC_IS_SABER2(unit)) {   
    942                     matched = 0;
    943                     if ((mem == THDIEMA_THDI_PORT_PG_CONFIGm ||
    944                          mem == THDIEXT_THDI_PORT_PG_CONFIGm ||
    945                          mem == THDIQEN_THDI_PORT_PG_CONFIGm ||
    946                          mem == THDIRQE_THDI_PORT_PG_CONFIGm ||
    947                          mem == THDI_PORT_PG_CONFIGm )) {
    948                          for (i = 0; i < 15 ; i ++) {
    949                              if (port_index[i] == (index/8)) { 
    950                                 matched = 1; 
    951                                 break; 
    952                              }
    953                          }
    954 
    955                          if (!matched && (index % 8)) {
    956                              continue;
    957                          }
    958                     }
    959 
    960                 }
    961             }
    962 
    963 #endif /*BCM_KATANA2_SUPPORT */
    964 
    965 #if defined(BCM_TOMAHAWK_SUPPORT)
    966             if (SOC_IS_TOMAHAWKX(unit) && !SOC_IS_TOMAHAWK3(unit)) {
    967                 if (enable_mem_mode_check) {
    968                     if (!soc_th_dual_tcam_index_valid(unit, mem, index)) {
    969                         LOG_VERBOSE(BSL_LS_SOC_SER, (BSL_META_U(unit,
    970                             "Write IGNORED for mem %s, index %d\n"),
    971                             SOC_MEM_NAME(unit, mem), index));
    972                         continue;
    973                     }
    974                 }
    975             }
    976 #endif /* BCM_TOMAHAWK_SUPPORT */
    977 
    978             if (idx_phy) {
    979                 flags |= SOC_MEM_DONT_MAP_INDEX;
    980             }
    981             if (no_cache) {
    982                 flags |= SOC_MEM_DONT_USE_CACHE;
    983             }
    984             if (specific_pipe) {
    985                 if ((r = soc_mem_pipe_select_write(unit,
    986                                                    flags,
    987                                                    mem, copyno, acc_type, index,
    988                                                    entry)) < 0) {
    989                     cli_out("Write ERROR: table %s(Y).%s[%d]: %s\n",
    990                             SOC_MEM_UFNAME(unit, mem), copyno_str,
    991                             index, soc_errmsg(r));
    992                     goto done;
    993                 }
    994             } else if ((r = soc_mem_write_extended(unit,
    995                                                    flags,
    996                                                    mem,
    997                                                    copyno, index, entry)) < 0) {
    998 	        cli_out("Write ERROR: table %s.%s[%d]: %s\n",
    999                         SOC_MEM_UFNAME(unit, mem), copyno_str,
   1000                         index, soc_errmsg(r));
   1001 	        goto done;
   1002 	    }
   1003 
   1004 	    if (update) {
   1005 	        modify_mem_fields(unit, mem, entry, NULL, valstr, TRUE);
   1006 	    }
   1007         }
   1008     }
   1009     rv = CMD_OK;
   1010 
   1011  done:
   1012     if (valstr != NULL) {
   1013        sal_free(valstr);
   1014     }
   1015     if (view != NULL) {
   1016        sal_free(view);
   1017     }
   1018     return rv;
   1019 }
   1020 
   1021 
   1022 /*
   1023  * Modify the fields of a table entry
   1024  */
   1025 cmd_result_t
   1026 cmd_esw_mem_modify(int unit, args_t *a)
   1027 {
   1028     int			index, start, count, copyno, i, view_len;
   1029     char		*tab, *idx, *cnt, *s, *memname;
   1030     soc_mem_t		mem;
   1031     uint32		entry[SOC_MAX_MEM_WORDS], mask[SOC_MAX_MEM_WORDS];
   1032     uint32		changed[SOC_MAX_MEM_WORDS];
   1033     char		*valstr = NULL, *view = NULL;
   1034     int			r, rv = CMD_FAIL;
   1035     int			blk;
   1036 #ifdef BCM_TRIDENT2_SUPPORT
   1037     int                 check_view = FALSE;
   1038     soc_mem_t           mview = INVALIDm;
   1039 #endif /* BCM_TRIDENT2_SUPPORT */
   1040 #ifdef BCM_KATANA2_SUPPORT
   1041     int port_index[15]=
   1042     {1,5,9,13,17,21,25,26,27,28,30,33,37,39,41};
   1043     int matched = 0;
   1044 #endif /*BCM_KATANA2_SUPPORT */
   1045 #if defined(BCM_TOMAHAWK_SUPPORT)
   1046     int         enable_mem_mode_check = 1;
   1047     int       check_lpm_view = FALSE;
   1048     soc_mem_t lpm_view = INVALIDm;
   1049     int       pair_lpm = 0;
   1050 #endif /* BCM_TOMAHAWK_SUPPORT */
   1051     uint32      flags = SOC_MEM_NO_FLAGS;
   1052 
   1053     if (!sh_check_attached(ARG_CMD(a), unit)) {
   1054 	return CMD_FAIL;
   1055     }
   1056 
   1057     tab = ARG_GET(a);
   1058 #if defined(BCM_TOMAHAWK_SUPPORT)
   1059     if (tab != NULL && sal_strcasecmp(tab, "nocheck_mem_mode") == 0) {
   1060         enable_mem_mode_check = 0;
   1061         tab = ARG_GET(a);
   1062     }
   1063 #endif /* BCM_TOMAHAWK_SUPPORT */
   1064     if (tab != NULL && sal_strcasecmp(tab, "idx_phy") == 0) {
   1065         flags = SOC_MEM_DONT_MAP_INDEX;
   1066         tab = ARG_GET(a);
   1067     }
   1068     idx = ARG_GET(a);
   1069     cnt = ARG_GET(a);
   1070     s = ARG_GET(a);
   1071 
   1072     /* you will need at least one dword and all the args .. */
   1073     if (!tab || !idx || !cnt || !s || !isint(cnt)) {
   1074 	return CMD_USAGE;
   1075     }
   1076 
   1077     if ((valstr = sal_alloc(ARGS_BUFFER, "mem_modify")) == NULL) {
   1078         cli_out("cmd_esw_mem_modify : Out of memory\n");
   1079         goto done;
   1080     }
   1081 
   1082     memname = sal_strstr(tab, ":"); 
   1083     view_len = 0; 
   1084     if (memname != NULL) { 
   1085         memname++; 
   1086         view_len = memname - tab; 
   1087     } else { 
   1088         memname = tab; 
   1089     } 
   1090 
   1091     if (parse_memory_name(unit, &mem, memname, &copyno, 0) < 0) {
   1092 	cli_out("ERROR: unknown table \"%s\"\n",tab);
   1093     goto done;
   1094     }
   1095 
   1096     if (view_len == 0) {
   1097         collect_comma_args(a, valstr, s);
   1098     } else {
   1099         if ((view = sal_alloc(view_len + 1, "view_name")) == NULL) {
   1100             cli_out("cmd_esw_mem_modify : Out of memory\n");
   1101             goto done;
   1102         }
   1103 
   1104         sal_memcpy(view, tab, view_len);
   1105         view[view_len] = 0;
   1106 
   1107         if (collect_comma_args_with_view(a, valstr, s, view, unit, mem) < 0) {
   1108             cli_out("Out of memory: aborted\n");
   1109             goto done;
   1110         }
   1111     }
   1112 
   1113     if (!SOC_MEM_IS_VALID(unit, mem)) {
   1114         cli_out("Error: Memory %s not valid for chip %s.\n",
   1115                 SOC_MEM_UFNAME(unit, mem), SOC_UNIT_NAME(unit));
   1116         goto done;
   1117     }
   1118 
   1119 #if defined(BCM_HAWKEYE_SUPPORT)
   1120     if (SOC_IS_HAWKEYE(unit) && (soc_mem_index_max(unit, mem) <= 0)) {
   1121         cli_out("Error: Memory %s not valid for chip %s.\n",
   1122                 SOC_MEM_UFNAME(unit, mem), SOC_UNIT_NAME(unit));
   1123         goto done;
   1124     }
   1125 #endif /* BCM_HAWKEYE_SUPPORT */
   1126 
   1127     if (soc_mem_is_readonly(unit, mem)) {
   1128 	cli_out("ERROR: Table %s is read-only\n", SOC_MEM_UFNAME(unit, mem));
   1129         goto done;
   1130     }
   1131 
   1132     sal_memset(changed, 0, sizeof (changed));
   1133 
   1134     if (modify_mem_fields(unit, mem, changed, mask, valstr, FALSE) < 0) {
   1135 	cli_out("Syntax error: aborted\n");
   1136         goto done;
   1137     }
   1138 
   1139     start = parse_memory_index(unit, mem, idx);
   1140     count = parse_integer(cnt);
   1141 
   1142 #ifdef BCM_TRIDENT2_SUPPORT
   1143     if (SOC_IS_TD2_TT2(unit) &&
   1144         (mem == L3_DEFIP_ALPM_IPV4m || mem == L3_DEFIP_ALPM_IPV4_1m ||
   1145          mem == L3_DEFIP_ALPM_IPV6_64m || mem == L3_DEFIP_ALPM_IPV6_64_1m ||
   1146          mem == L3_DEFIP_ALPM_IPV6_128m)) {
   1147         check_view = TRUE;
   1148         mview = mem;
   1149     }
   1150 #endif /* BCM_TRIDENT2_SUPPORT */
   1151 #ifdef BCM_TOMAHAWK_SUPPORT
   1152     if (SOC_IS_TOMAHAWKX(unit) && (flags & SOC_MEM_DONT_MAP_INDEX)) {
   1153         if (soc_feature(unit, soc_feature_l3_defip_map) &&
   1154             (mem == L3_DEFIPm ||
   1155 #ifdef BCM_TOMAHAWK3_SUPPORT
   1156              mem == L3_DEFIP_LEVEL1m ||
   1157 #endif
   1158              mem == L3_DEFIP_ONLYm ||
   1159              mem == L3_DEFIP_PAIR_128m ||
   1160 #ifdef BCM_TOMAHAWK3_SUPPORT
   1161              mem == L3_DEFIP_PAIR_LEVEL1m ||
   1162 #endif
   1163              mem == L3_DEFIP_PAIR_128_ONLYm)) {
   1164             check_lpm_view = TRUE;
   1165             lpm_view = mem;
   1166             pair_lpm = (mem == L3_DEFIP_PAIR_128m ||
   1167 #ifdef BCM_TOMAHAWK3_SUPPORT
   1168                         mem == L3_DEFIP_PAIR_LEVEL1m ||
   1169 #endif
   1170                         mem == L3_DEFIP_PAIR_128_ONLYm) ? 1 : 0;
   1171         }
   1172     }
   1173 #endif
   1174     /*
   1175      * Take lock to ensure atomic modification of memory.
   1176      */
   1177 
   1178     soc_mem_lock(unit, mem);
   1179 
   1180     rv = CMD_OK;
   1181 
   1182     for (index = start; index < start + count; index++) {
   1183 
   1184         SOC_MEM_BLOCK_ITER(unit, mem, blk) {
   1185 	    if (copyno != COPYNO_ALL && copyno != blk) {
   1186 		continue;
   1187 	    }
   1188 
   1189 #if defined(BCM_TOMAHAWK_SUPPORT)
   1190         if (SOC_IS_TOMAHAWKX(unit)) {
   1191             if (enable_mem_mode_check) {
   1192                 if (!soc_th_dual_tcam_index_valid(unit, mem, index)) {
   1193                     LOG_VERBOSE(BSL_LS_SOC_SER, (BSL_META_U(unit,
   1194                         "Modify IGNORED for mem %s, index %d\n"),
   1195                         SOC_MEM_NAME(unit, mem), index));
   1196                     continue;
   1197                 }
   1198             }
   1199         }
   1200 #endif /* BCM_TOMAHAWK_SUPPORT */
   1201 
   1202 #ifdef BCM_TRIDENT2_SUPPORT
   1203             if (check_view) {
   1204                 if (SOC_IS_TRIDENT2(unit) || SOC_IS_TRIDENT2PLUS(unit)) {
   1205                     mview = _soc_trident2_alpm_bkt_view_get(unit, index);
   1206                 }
   1207 #if defined(ALPM_ENABLE)
   1208 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT)
   1209                 else {
   1210                     mview = soc_alpm_cmn_bkt_view_get(unit, index);
   1211                 }
   1212 #endif
   1213 #endif
   1214                 if (!(mview == INVALIDm || mem == mview)) {
   1215                     continue;
   1216                 }
   1217             }
   1218 #endif /* BCM_TRIDENT2_SUPPORT */
   1219 #ifdef BCM_TOMAHAWK_SUPPORT
   1220         if (check_lpm_view) {
   1221 #ifdef BCM_TOMAHAWK3_SUPPORT
   1222             if (SOC_IS_TOMAHAWK3(unit)) {
   1223                 lpm_view = _soc_th3_lpm_view_get(unit, index, pair_lpm);
   1224             } else
   1225 #endif
   1226             if (SOC_IS_TOMAHAWKX(unit)) {
   1227                 lpm_view = _soc_th_lpm_view_get(unit, index, pair_lpm);
   1228             }
   1229             if (mem != lpm_view) {
   1230                 continue;
   1231             }
   1232         }
   1233 #endif
   1234 	    /*
   1235 	     * Retrieve the current entry, set masked fields to changed
   1236 	     * values, and write back.
   1237 	     */
   1238 
   1239             r = soc_mem_read_physical_index(unit, flags, mem, blk, index, entry);
   1240 
   1241 	    if (r < 0) {
   1242 		cli_out("ERROR: read from %s table copy %d failed: %s\n",
   1243                         SOC_MEM_UFNAME(unit, mem), blk, soc_errmsg(r));
   1244 		rv = CMD_FAIL;
   1245 		break;
   1246 	    }
   1247 
   1248 	    for (i = 0; i < SOC_MAX_MEM_WORDS; i++) {
   1249 		entry[i] = (entry[i] & ~mask[i]) | changed[i];
   1250 	    }
   1251 
   1252 #ifdef BCM_KATANA2_SUPPORT
   1253 
   1254         if (SOC_IS_KATANA2(unit)) {
   1255            /* In case of SP memories, out of SP0, SP1, SP2 & SP3                 
   1256               only SP0 is valid i.e. only indices 0,4,8.This check
   1257               is avoid processing invalid indices. Issue is handled
   1258               for THDI memories alone. Has to be handled
   1259               for other SP memories in future */
   1260 
   1261               if ((mem == THDIEMA_THDI_PORT_SP_CONFIGm ||
   1262                    mem == THDIEXT_THDI_PORT_SP_CONFIGm ||
   1263                    mem == THDIQEN_THDI_PORT_SP_CONFIGm ||
   1264                    mem == THDIRQE_THDI_PORT_SP_CONFIGm ||
   1265                    mem == THDI_PORT_SP_CONFIGm) && (index % 4)) { 
   1266                    continue;
   1267               }
   1268               if (!SOC_IS_SABER2(unit)) {
   1269                   matched = 0;
   1270                    if ((mem == THDIEMA_THDI_PORT_PG_CONFIGm ||
   1271                          mem == THDIEXT_THDI_PORT_PG_CONFIGm ||
   1272                          mem == THDIQEN_THDI_PORT_PG_CONFIGm ||
   1273                          mem == THDIRQE_THDI_PORT_PG_CONFIGm ||
   1274                          mem == THDI_PORT_PG_CONFIGm )) {
   1275                        for (i = 0; i < 15 ; i ++) {
   1276                             if (port_index[i] == (index/8)) { 
   1277                                 matched = 1; 
   1278                                 break; 
   1279                             }
   1280                        }
   1281 
   1282                        if (!matched && (index % 8)) {
   1283                            continue;
   1284                        }
   1285                    }
   1286               }
   1287         }
   1288 
   1289 #endif /*BCM_KATANA2_SUPPORT */
   1290             
   1291         r = soc_mem_write_extended(unit, flags, mem, blk, index, entry);
   1292 
   1293 	    if (r < 0) {
   1294 		    cli_out("ERROR: write to %s table copy %d failed: %s\n",
   1295                     SOC_MEM_UFNAME(unit, mem), blk, soc_errmsg(r));
   1296 		    rv = CMD_FAIL;
   1297 		    break;
   1298 	    }
   1299 	}
   1300 
   1301 	if (rv != CMD_OK) {
   1302 	    break;
   1303 	}
   1304 	modify_mem_fields(unit, mem, changed, NULL, valstr, TRUE);
   1305     }
   1306 
   1307     soc_mem_unlock(unit, mem);
   1308 
   1309  done:
   1310     if (view != NULL) {
   1311         sal_free(view);
   1312     }
   1313     sal_free(valstr);
   1314     return rv;
   1315 }
   1316 
   1317 /*
   1318  * Auxiliary routine to perform either insert or delete
   1319  */
   1320 
   1321 #define TBL_OP_INSERT		0
   1322 #define TBL_OP_DELETE		1
   1323 #define TBL_OP_LOOKUP		2
   1324 
   1325 static cmd_result_t
   1326 do_ins_del_lkup(int unit, args_t *a, int tbl_op)
   1327 {
   1328     soc_control_t	*soc = SOC_CONTROL(unit);
   1329     uint32		entry[SOC_MAX_MEM_WORDS];
   1330     uint32		result[SOC_MAX_MEM_WORDS];
   1331     int			entry_dw = 0, index;
   1332     char		*ufname, *s;
   1333     int			rv = CMD_FAIL;
   1334     char		valstr[1024];
   1335     soc_mem_t		mem;
   1336     int			copyno, update, view_len = 0;
   1337     int			swarl = 0;	/* Indicates operating on
   1338 					   software ARL/L2 table */
   1339     char		*tab, *memname, *view = NULL;
   1340     int			count = 1;
   1341     soc_mem_t		arl_mem = INVALIDm;
   1342     shr_avl_compare_fn	arl_cmp = NULL;
   1343     int			quiet = 0;
   1344     int32               banks = 0;
   1345     int			i=0;
   1346     int8                banknum = SOC_MEM_HASH_BANK_ALL;
   1347 
   1348     if (!sh_check_attached(ARG_CMD(a), unit)) {
   1349 	return CMD_FAIL;
   1350     }
   1351 
   1352     for (;;) {
   1353 	if ((tab = ARG_GET(a)) == NULL) {
   1354 	    return CMD_USAGE;
   1355 	}
   1356 
   1357 	if (isint(tab)) {
   1358 	    count = parse_integer(tab);
   1359 	    continue;
   1360 	}
   1361 
   1362 	if (sal_strcasecmp(tab, "quiet") == 0) {
   1363 	    quiet = 1;
   1364 	    continue;
   1365 	}
   1366         
   1367         if (soc_feature(unit, soc_feature_ism_memory) ||
   1368             soc_feature(unit, soc_feature_shared_hash_mem)) {
   1369             char *bnum;
   1370             int8 num = -1;
   1371             bnum = sal_strstr(tab, "bank");
   1372             if (bnum != NULL) {
   1373                 num = sal_atoi(bnum+4);
   1374                 if (num >= 0 && num < 20) { 
   1375                     banknum = num;
   1376                 }
   1377 	        continue;
   1378             }
   1379             
   1380         } else {
   1381 	    if (sal_strcasecmp(tab, "bank0") == 0) {
   1382 	        banks = SOC_MEM_HASH_BANK0_ONLY;
   1383 	        continue;
   1384 	    }
   1385 
   1386 	    if (sal_strcasecmp(tab, "bank1") == 0) {
   1387 	        banks = SOC_MEM_HASH_BANK1_ONLY;
   1388 	        continue;
   1389 	    }
   1390         }  
   1391 
   1392 	break;
   1393     }
   1394 
   1395 #ifdef BCM_XGS_SWITCH_SUPPORT
   1396     if (soc_feature(unit, soc_feature_arl_hashed)) {
   1397 	arl_mem = L2Xm;
   1398 	arl_cmp = soc_l2x_entry_compare_key;
   1399     }
   1400 #endif
   1401 
   1402     if (!sal_strcasecmp(tab, "sa") || !sal_strcasecmp(tab, "sarl")) {
   1403 	if (soc->arlShadow == NULL) {
   1404 	    cli_out("ERROR: No software ARL table\n");
   1405 	    goto done;
   1406 	}
   1407 	mem = arl_mem;
   1408         if (mem != INVALIDm) {
   1409             copyno = SOC_MEM_BLOCK_ANY(unit, mem);
   1410         }
   1411 	swarl = 1;
   1412     } else {
   1413         memname = sal_strstr(tab, ":");
   1414   	if (memname != NULL) {
   1415   	    memname++;
   1416   	    view_len = memname - tab;
   1417   	} else {
   1418   	    memname = tab;
   1419   	}
   1420         if (parse_memory_name(unit, &mem, memname, &copyno, 0) < 0) {
   1421 	    cli_out("ERROR: unknown table \"%s\"\n", tab);
   1422 	    goto done;
   1423         }
   1424     }
   1425 
   1426     if (!SOC_MEM_IS_VALID(unit, mem)) {
   1427         cli_out("Error: Memory %s not valid for chip %s.\n",
   1428                 (mem != INVALIDm) ? SOC_MEM_UFNAME(unit, mem) : "INVALID",
   1429                 SOC_UNIT_NAME(unit));
   1430         goto done;
   1431     }
   1432 
   1433     if (!soc_mem_is_sorted(unit, mem) &&
   1434 	!soc_mem_is_hashed(unit, mem) &&
   1435         !soc_mem_is_cam(unit, mem) &&
   1436         !soc_mem_is_cmd(unit, mem)) {
   1437 	cli_out("ERROR: %s table is not sorted, hashed, CAM, or command\n",
   1438                 SOC_MEM_UFNAME(unit, mem));
   1439 	goto done;
   1440     }
   1441 
   1442     if ((soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) ||
   1443         (soc_feature(unit, soc_feature_shared_hash_mem) && ((mem == L2Xm) ||
   1444          (mem == L3_ENTRY_ONLYm) || (mem == L3_ENTRY_IPV4_UNICASTm) || 
   1445          (mem == L3_ENTRY_IPV4_MULTICASTm) || (mem == L3_ENTRY_IPV6_UNICASTm) || 
   1446          (mem == L3_ENTRY_IPV6_MULTICASTm)))) {
   1447         if (banknum != SOC_MEM_HASH_BANK_ALL) {
   1448             banks |= ((int32)1 << banknum);
   1449         } else if (banks == 0) {
   1450             banks = SOC_MEM_HASH_BANK_ALL;
   1451         } 
   1452     }
   1453     /* All hash tables have multiple banks from TRX onwards only */
   1454 #ifndef BCM_TRX_SUPPORT
   1455     if (soc_feature(unit, soc_feature_dual_hash) && !SOC_IS_TRX(unit)) {
   1456         if (banks != 0) {
   1457             switch (mem) {
   1458             case L2Xm:
   1459             case MPLS_ENTRYm:
   1460             case VLAN_XLATEm:
   1461             case EGR_VLAN_XLATEm: 
   1462             case L3_ENTRY_IPV4_UNICASTm:
   1463             case L3_ENTRY_IPV4_MULTICASTm:
   1464             case L3_ENTRY_IPV6_UNICASTm:
   1465             case L3_ENTRY_IPV6_MULTICASTm:
   1466                  break;
   1467             default:
   1468                 cli_out("ERROR: %s table does not have multiple banks\n",
   1469                         SOC_MEM_UFNAME(unit, mem));
   1470                 goto done;
   1471             }
   1472         }
   1473     }
   1474 #endif
   1475 
   1476     entry_dw = soc_mem_entry_words(unit, mem);
   1477     ufname = (swarl ? "SARL" : SOC_MEM_UFNAME(unit, mem));
   1478 
   1479     if (tbl_op == TBL_OP_LOOKUP && copyno == COPYNO_ALL) {
   1480 	copyno = SOC_MEM_BLOCK_ANY(unit, mem);
   1481     }
   1482 
   1483     /*
   1484      * If a list of fields were specified, generate the entry from them.
   1485      * Otherwise, generate it by reading raw dwords from command line.
   1486      */
   1487 
   1488     if ((s = ARG_GET(a)) == 0) {
   1489 	cli_out("ERROR: missing data for entry to %s\n",
   1490                 tbl_op == TBL_OP_INSERT ? "insert" :
   1491                 tbl_op == TBL_OP_DELETE ? "delete" : "lookup");
   1492 	goto done;
   1493     }
   1494 
   1495     if (!isint(s)) {
   1496 	/* List of fields */
   1497         sal_memset(valstr, 0, 1024);
   1498         if (view_len == 0) {
   1499             collect_comma_args(a, valstr, s);
   1500 	} else {
   1501   	    if ((view = sal_alloc(view_len + 1, "view_name")) == NULL) {
   1502   	        cli_out("cmd_esw_mem_modify : Out of memory\n");
   1503   	        goto done;
   1504   	    }
   1505   	    sal_memset(view, 0, view_len + 1);
   1506   	    sal_memcpy(view, tab, view_len);
   1507   	    if (collect_comma_args_with_view(a, valstr, s, view, unit, mem) < 0) {
   1508   	        cli_out("Out of memory: aborted\n");
   1509   	        goto done;
   1510   	    }
   1511   	}
   1512 
   1513 	memset(entry, 0, sizeof (entry));
   1514 
   1515 	if (modify_mem_fields(unit, mem, entry, NULL, valstr, FALSE) < 0) {
   1516 	    cli_out("Syntax error in field specification\n");
   1517 	    goto done;
   1518 	}
   1519 
   1520 	update = TRUE;
   1521     } else {
   1522 	/* List of numeric values */
   1523 
   1524 	ARG_PREV(a);
   1525 
   1526 	if (parse_dwords(entry_dw, entry, a) < 0) {
   1527 	    goto done;
   1528 	}
   1529 
   1530 	update = FALSE;
   1531     }
   1532 
   1533     if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) {
   1534 	cli_out("%s[%s], DATA:",
   1535                 tbl_op == TBL_OP_INSERT ? "INSERT" :
   1536                 tbl_op == TBL_OP_DELETE ? "DELETE" : "LOOKUP", ufname);
   1537 	for (i = 0; i < entry_dw; i++) {
   1538 	    cli_out(" 0x%x", entry[i]);
   1539 	}
   1540 	cli_out("\n");
   1541     }
   1542 
   1543     /*
   1544      * Have entry data, now insert, delete, or lookup.
   1545      * For delete and lookup, all fields except the key are ignored.
   1546      * Software ARL/L2 table requires special processing.
   1547      */
   1548 
   1549     while (count--) {
   1550 	switch (tbl_op) {
   1551 	case TBL_OP_INSERT:
   1552 	    if (swarl) {
   1553 		if (soc->arlShadow != NULL) {
   1554 		    sal_mutex_take(soc->arlShadowMutex, sal_mutex_FOREVER);
   1555 		    i = shr_avl_insert(soc->arlShadow,
   1556 				       arl_cmp,
   1557 				       (shr_avl_datum_t *) entry);
   1558 		    sal_mutex_give(soc->arlShadowMutex);
   1559 		} else {
   1560 		    i = SOC_E_NONE;
   1561 		}
   1562 #ifdef BCM_TRIUMPH_SUPPORT
   1563             } else if (mem == EXT_L2_ENTRYm) {
   1564                 i = soc_mem_generic_insert(unit, mem, MEM_BLOCK_ANY, 0,
   1565                                            entry, NULL, 0);
   1566 #endif /* BCM_TRIUMPH_SUPPORT */
   1567 #ifdef BCM_ISM_SUPPORT
   1568             } else if (soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) {
   1569                 if (banks == SOC_MEM_HASH_BANK_ALL) {
   1570                     /* coverity[stack_use_callee] */
   1571                     /* coverity[stack_use_overflow] */
   1572                     i = soc_mem_insert(unit, mem, copyno, entry);
   1573                 } else {
   1574                     i = soc_mem_bank_insert(unit, mem, banks,
   1575                                             copyno, (void *)entry, NULL);
   1576                 }
   1577 #endif
   1578 #ifdef BCM_FIREBOLT2_SUPPORT
   1579             } else if (banks != 0) {
   1580                 switch (mem) {
   1581                 case L2Xm:
   1582                     if (soc_feature(unit, soc_feature_shared_hash_mem)) {
   1583                         i = soc_mem_bank_insert(unit, mem, banks,
   1584                                                 copyno, (void *)entry, NULL);
   1585                     } else {
   1586                         i = soc_fb_l2x_bank_insert(unit, banks,
   1587                                                    (void *)entry);
   1588                     }
   1589                     break;
   1590 #if defined(INCLUDE_L3)
   1591                 case L3_ENTRY_IPV4_UNICASTm:
   1592                 case L3_ENTRY_IPV4_MULTICASTm:
   1593                 case L3_ENTRY_IPV6_UNICASTm:
   1594                 case L3_ENTRY_IPV6_MULTICASTm:
   1595                     if (soc_feature(unit, soc_feature_shared_hash_mem)) {
   1596                         i = soc_mem_bank_insert(unit, mem, banks,
   1597                                                 copyno, (void *)entry, NULL);
   1598                     } else {
   1599                         i = soc_fb_l3x_bank_insert(unit, banks,
   1600                                    (void *)entry);
   1601                     }
   1602                     break;
   1603 #endif
   1604 #if defined(BCM_TRIUMPH_SUPPORT)
   1605                 case MPLS_ENTRYm:
   1606 #endif
   1607                 case VLAN_XLATEm:
   1608                 case VLAN_MACm:
   1609                 case AXP_WRX_WCDm:
   1610                 case AXP_WRX_SVP_ASSIGNMENTm:
   1611 #if defined(BCM_TRIUMPH3_SUPPORT)
   1612                 case FT_SESSIONm:
   1613                 case FT_SESSION_IPV6m:
   1614 #endif
   1615                     i = soc_mem_bank_insert(unit, mem, banks,
   1616                                             copyno, (void *)entry, NULL);
   1617                     break;
   1618                 default:
   1619                     i = SOC_E_INTERNAL;
   1620                     goto done;
   1621                 }
   1622 #endif /* BCM_FIREBOLT2_SUPPORT */
   1623 	    } else {
   1624 		i = soc_mem_insert(unit, mem, copyno, entry);
   1625 	    }
   1626 
   1627             if (i == SOC_E_EXISTS) {
   1628                 i = SOC_E_NONE;
   1629             }
   1630 
   1631 	    if (quiet && i == SOC_E_FULL) {
   1632 		i = SOC_E_NONE;
   1633 	    }
   1634 
   1635 	    if (i < 0) {
   1636 		cli_out("Insert ERROR: %s table insert failed: %s\n",
   1637                         ufname, soc_errmsg(i));
   1638 		goto done;
   1639 	    }
   1640 
   1641 	    break;
   1642 
   1643 	case TBL_OP_DELETE:
   1644 	    if (swarl) {
   1645 		if (soc->arlShadow != NULL) {
   1646 		    sal_mutex_take(soc->arlShadowMutex, sal_mutex_FOREVER);
   1647 		    i = shr_avl_delete(soc->arlShadow,
   1648 				       arl_cmp,
   1649 				       (shr_avl_datum_t *) entry);
   1650 		    sal_mutex_give(soc->arlShadowMutex);
   1651 		} else {
   1652 		    i = SOC_E_NONE;
   1653 		}
   1654 #ifdef BCM_TRX_SUPPORT
   1655             } else if (soc_feature(unit, soc_feature_generic_table_ops)) {
   1656                 i = soc_mem_generic_delete(unit, mem, MEM_BLOCK_ANY,
   1657                                            banks, entry, NULL, 0);
   1658 #endif /* BCM_TRX_SUPPORT */
   1659 #ifdef BCM_FIREBOLT2_SUPPORT
   1660             } else if (banks != 0) {
   1661                 switch (mem) {
   1662                 case L2Xm:
   1663                     i = soc_fb_l2x_bank_delete(unit, banks,
   1664                                                (void *)entry);
   1665                     break;
   1666 #if defined(INCLUDE_L3)
   1667                 case L3_ENTRY_IPV4_UNICASTm:
   1668                 case L3_ENTRY_IPV4_MULTICASTm:
   1669                 case L3_ENTRY_IPV6_UNICASTm:
   1670                 case L3_ENTRY_IPV6_MULTICASTm:
   1671                     i = soc_fb_l3x_bank_delete(unit, banks,
   1672                                (void *)entry);
   1673                     break;
   1674 #endif
   1675                 default:
   1676                     i = SOC_E_INTERNAL;
   1677                     goto done;
   1678                 }
   1679 #endif
   1680 	    } else {
   1681 		i = soc_mem_delete(unit, mem, copyno, entry);
   1682 	    }
   1683 
   1684 	    if (quiet && i == SOC_E_NOT_FOUND) {
   1685 		i = SOC_E_NONE;
   1686 	    }
   1687 
   1688 	    if (i < 0) {
   1689 		cli_out("Delete ERROR: %s table delete failed: %s\n",
   1690                         ufname, soc_errmsg(i));
   1691 		goto done;
   1692 	    }
   1693 
   1694 	    break;
   1695 
   1696 	case TBL_OP_LOOKUP:
   1697 	    if (swarl) {
   1698 		if (soc->arlShadow != NULL) {
   1699 		    sal_mutex_take(soc->arlShadowMutex, sal_mutex_FOREVER);
   1700 		    i = shr_avl_lookup(soc->arlShadow,
   1701 				       arl_cmp,
   1702 				       (shr_avl_datum_t *) entry);
   1703 		    sal_mutex_give(soc->arlShadowMutex);
   1704                     if (i) {
   1705                         i = SOC_E_NONE;
   1706                         index = -1;
   1707                         sal_memcpy(result, entry,
   1708                                soc_mem_entry_words(unit, mem) * 4);
   1709                     } else {
   1710                         i = SOC_E_NOT_FOUND;
   1711                     }
   1712 		} else {
   1713 		    i = SOC_E_NONE;
   1714                     goto done;
   1715 		}
   1716 #ifdef BCM_TRX_SUPPORT
   1717             } else if (soc_feature(unit, soc_feature_generic_table_ops)) {
   1718                 i = soc_mem_generic_lookup(unit, mem, MEM_BLOCK_ANY,
   1719                                            banks, entry, result, &index);
   1720 #endif /* BCM_TRX_SUPPORT */
   1721 #ifdef BCM_FIREBOLT2_SUPPORT
   1722             } else if (banks != 0) {
   1723                 switch (mem) {
   1724                 case L2Xm:
   1725                     i = soc_fb_l2x_bank_lookup(unit, banks,
   1726                                                (void *)entry,
   1727                                                (void *)result,
   1728                                                &index);
   1729                     break;
   1730 #if defined(INCLUDE_L3)
   1731                 case L3_ENTRY_IPV4_UNICASTm:
   1732                 case L3_ENTRY_IPV4_MULTICASTm:
   1733                 case L3_ENTRY_IPV6_UNICASTm:
   1734                 case L3_ENTRY_IPV6_MULTICASTm:
   1735                     i = soc_fb_l3x_bank_lookup(unit, banks,
   1736                                                (void *)entry,
   1737                                                (void *)result,
   1738                                                &index);
   1739                     break;
   1740 #endif
   1741                 default:
   1742                     i = SOC_E_INTERNAL;
   1743                     goto done;
   1744                 }
   1745 #endif /* BCM_FIREBOLT2_SUPPORT */
   1746 	    } else {
   1747 		i = soc_mem_search(unit, mem, copyno,
   1748                                    &index, entry, result, 0);
   1749 	    }
   1750 
   1751 	    if (i < 0) {		/* Error not fatal for lookup */
   1752                 if (i == SOC_E_NOT_FOUND) {
   1753                     cli_out("Lookup: No matching entry found\n");
   1754                 } else {
   1755                     cli_out("Lookup ERROR: read error during search: %s\n",
   1756                             soc_errmsg(i));
   1757                 }
   1758 	    } else { /* Entry found */
   1759 		if (index < 0) {
   1760 		    cli_out("Found in %s.%s: ",
   1761                             ufname, SOC_BLOCK_NAME(unit, copyno));
   1762 		} else {
   1763 		    cli_out("Found %s.%s[%d]: ",
   1764                             ufname, SOC_BLOCK_NAME(unit, copyno), index);
   1765 		}
   1766 		soc_mem_entry_dump(unit, mem, result, BSL_LSS_CLI);
   1767 		cli_out("\n");
   1768             }
   1769 
   1770 	    break;
   1771 
   1772 	default:
   1773 	    assert(0);
   1774 	    break;
   1775 	}
   1776 
   1777 	if (update) {
   1778 	    modify_mem_fields(unit, mem, entry, NULL, valstr, TRUE);
   1779 	}
   1780     }
   1781 
   1782     rv = CMD_OK;
   1783 
   1784  done:
   1785     if (view != NULL) {
   1786         sal_free(view);
   1787     }
   1788     return rv;
   1789 }
   1790 
   1791 /*
   1792  * Insert an entry by key into a sorted table
   1793  */
   1794 
   1795 char insert_usage[] =
   1796     "\nParameters 1: [quiet] [<COUNT>] [bank#] <TABLE> <DW0> .. <DWN>\n"
   1797     "Parameters 2: [quiet] [<COUNT>] <TABLE> <FIELD>=<VALUE> ...\n\t"
   1798     "Number of <DW> must be appropriate to table entry size.\n\t"
   1799     "Entry is inserted in ascending sorted order by key field.\n\t"
   1800     "The quiet option indicates not to complain on table/bucket full.\n\t"
   1801     "Some tables allow restricting the insert to a single bank.\n";
   1802 
   1803 cmd_result_t
   1804 mem_insert(int unit, args_t *a)
   1805 {
   1806     return do_ins_del_lkup(unit, a, TBL_OP_INSERT);
   1807 }
   1808 
   1809 
   1810 /*
   1811  * Delete entries by key from a sorted table
   1812  */
   1813 
   1814 char delete_usage[] =
   1815     "\nParameters 1: [quiet] [<COUNT>] [bank#] <TABLE> <DW0> .. <DWN>\n"
   1816     "Parameters 2: [quiet] [<COUNT>] <TABLE> <FIELD>=<VALUE> ...\n\t"
   1817     "Number of <DW> must be appropriate to table entry size.\n\t"
   1818     "The entry is deleted by key.\n\t"
   1819     "All fields other than the key field(s) are ignored.\n\t"
   1820     "The quiet option indicates not to complain on entry not found.\n\t"
   1821     "Some tables allow restricting the delete to a single bank.\n";
   1822 
   1823 cmd_result_t
   1824 mem_delete(int unit, args_t *a)
   1825 {
   1826     return do_ins_del_lkup(unit, a, TBL_OP_DELETE);
   1827 }
   1828 
   1829 /*
   1830  * Lookup entry an key in a sorted table
   1831  */
   1832 
   1833 char lookup_usage[] =
   1834     "\nParameters 1: [<COUNT>] [bank#] <TABLE> <DW0> .. <DWN>\n"
   1835     "Parameters 2: [<COUNT>] <TABLE> <FIELD>=<VALUE> ...\n\t"
   1836     "Number of <DW> must be appropriate to table entry size.\n\t"
   1837     "The entry is looked up by key.\n\t"
   1838     "All fields other than the key field(s) are ignored.\n\t"
   1839     "Some tables allow restricting the lookup to a single bank.\n";
   1840 
   1841 cmd_result_t
   1842 mem_lookup(int unit, args_t *a)
   1843 {
   1844     return do_ins_del_lkup(unit, a, TBL_OP_LOOKUP);
   1845 }
   1846 
   1847 /*
   1848  * Remove (delete) entries by index from a sorted table
   1849  */
   1850 
   1851 char remove_usage[] =
   1852     "Parameters: <TABLE> <INDEX> [COUNT]\n\t"
   1853     "Deletes an entry from a table by index.\n\t"
   1854     "(For the ARL, reads the table entry and deletes by key).\n";
   1855 
   1856 cmd_result_t
   1857 mem_remove(int unit, args_t *a)
   1858 {
   1859     char		*tab, *ind, *cnt, *ufname;
   1860     soc_mem_t		mem;
   1861     int			copyno;
   1862     int			r, rv = CMD_FAIL;
   1863     int			index, count;
   1864 
   1865     if (!sh_check_attached(ARG_CMD(a), unit)) {
   1866 	goto done;
   1867     }
   1868 
   1869     tab = ARG_GET(a);
   1870     ind = ARG_GET(a);
   1871     cnt = ARG_GET(a);
   1872 
   1873     if (!tab || !ind) {
   1874 	return CMD_USAGE;
   1875     }
   1876 
   1877     if (parse_memory_name(unit, &mem, tab, &copyno, 0) < 0) {
   1878 	cli_out("ERROR: unknown table \"%s\"\n", tab);
   1879 	goto done;
   1880     }
   1881 
   1882     if (!SOC_MEM_IS_VALID(unit, mem)) {
   1883         cli_out("Error: Memory %s not valid for chip %s.\n",
   1884                 SOC_MEM_UFNAME(unit, mem), SOC_UNIT_NAME(unit));
   1885         goto done;
   1886     }
   1887 
   1888     ufname = SOC_MEM_UFNAME(unit, mem);
   1889 
   1890     if (!soc_mem_is_sorted(unit, mem) &&
   1891 	!soc_mem_is_hashed(unit, mem) &&
   1892 	!soc_mem_is_cam(unit, mem)) {
   1893 	cli_out("ERROR: %s table is not sorted, hashed, or CAM\n",
   1894                 ufname);
   1895 	goto done;
   1896     }
   1897 
   1898     count = cnt ? parse_integer(cnt) : 1;
   1899 
   1900     index = parse_memory_index(unit, mem, ind);
   1901 
   1902     while (count-- > 0)
   1903 	if ((r = soc_mem_delete_index(unit, mem, copyno, index)) < 0) {
   1904 	    cli_out("ERROR: delete %s table index 0x%x failed: %s\n",
   1905                     ufname, index, soc_errmsg(r));
   1906 	    goto done;
   1907 	}
   1908 
   1909     rv = CMD_OK;
   1910 
   1911  done:
   1912     return rv;
   1913 }
   1914 
   1915 /*  
   1916  * Pop an entry from a FIFO
   1917  */
   1918 
   1919 char pop_usage[] =
   1920     "\nParameters: [quiet] [<COUNT>] <TABLE>\n"
   1921     "The quiet option indicates not to complain on FIFO empty.\n";
   1922 
   1923 cmd_result_t
   1924 mem_pop(int unit, args_t *a)
   1925 {   
   1926     uint32              result[SOC_MAX_MEM_WORDS];
   1927     char                *ufname;
   1928     int                 rv = CMD_FAIL;
   1929     soc_mem_t           mem;
   1930     int                 copyno;
   1931     char                *tab; 
   1932     int                 count = 1;
   1933     int                 quiet = 0;
   1934     int                 i;
   1935 
   1936     if (!sh_check_attached(ARG_CMD(a), unit)) {
   1937         return CMD_FAIL;
   1938     }
   1939 
   1940     if (!soc_feature(unit, soc_feature_mem_push_pop)) {
   1941         /* feature not supported */
   1942         return CMD_FAIL;
   1943     }
   1944 
   1945     for (;;) {
   1946         if ((tab = ARG_GET(a)) == NULL) {
   1947             return CMD_USAGE;
   1948         }
   1949 
   1950         if (isint(tab)) {
   1951             count = parse_integer(tab);
   1952             continue;
   1953         }
   1954 
   1955         if (sal_strcasecmp(tab, "quiet") == 0) {
   1956             quiet = 1;
   1957             continue;
   1958         }
   1959         break;
   1960     }
   1961 
   1962     if (parse_memory_name(unit, &mem, tab, &copyno, 0) < 0) {
   1963         cli_out("ERROR: unknown table \"%s\"\n", tab);
   1964         goto done;
   1965     }
   1966 
   1967     if (!SOC_MEM_IS_VALID(unit, mem)) {
   1968         cli_out("Error: Memory %s not valid for chip %s.\n",
   1969                 SOC_MEM_UFNAME(unit, mem), SOC_UNIT_NAME(unit));
   1970         goto done;
   1971     }
   1972 
   1973     switch (mem) {
   1974 #if defined (BCM_TRIUMPH_SUPPORT)
   1975         case ING_IPFIX_EXPORT_FIFOm:
   1976         case EGR_IPFIX_EXPORT_FIFOm:
   1977         case EXT_L2_MOD_FIFOm:
   1978 #endif /* BCM_TRIUMPH_SUPPORT */
   1979         case L2_MOD_FIFOm:
   1980 #ifdef BCM_TRIUMPH3_SUPPORT
   1981         case ING_SER_FIFOm:
   1982         case ING_SER_FIFO_Xm:
   1983         case ING_SER_FIFO_Ym:
   1984         case EGR_SER_FIFOm:
   1985         case EGR_SER_FIFO_Xm:
   1986         case EGR_SER_FIFO_Ym:
   1987         case ISM_SER_FIFOm:
   1988 #endif /* BCM_TRIUMPH3_SUPPORT */
   1989 #ifdef BCM_TOMAHAWK_SUPPORT
   1990         case ING_SER_FIFO_PIPE0m:
   1991         case ING_SER_FIFO_PIPE1m:
   1992         case ING_SER_FIFO_PIPE2m:
   1993         case ING_SER_FIFO_PIPE3m:
   1994         case EGR_SER_FIFO_PIPE0m:
   1995         case EGR_SER_FIFO_PIPE1m:
   1996         case EGR_SER_FIFO_PIPE2m:
   1997         case EGR_SER_FIFO_PIPE3m:
   1998         case L2_MGMT_SER_FIFOm:
   1999         case MMU_GCFG_MEM_FAIL_ADDR_64m:
   2000         case MMU_XCFG_MEM_FAIL_ADDR_64m:
   2001         case MMU_XCFG_MEM_FAIL_ADDR_64_XPE0m:
   2002         case MMU_XCFG_MEM_FAIL_ADDR_64_XPE1m:
   2003         case MMU_XCFG_MEM_FAIL_ADDR_64_XPE2m:
   2004         case MMU_XCFG_MEM_FAIL_ADDR_64_XPE3m:
   2005         case MMU_SCFG_MEM_FAIL_ADDR_64m:
   2006         case MMU_SCFG_MEM_FAIL_ADDR_64_SC0m:
   2007         case MMU_SCFG_MEM_FAIL_ADDR_64_SC1m:
   2008         case CENTRAL_CTR_EVICTION_FIFOm:
   2009 #endif /* BCM_TOMAHAWK_SUPPORT */
   2010 #ifdef BCM_TOMAHAWK2_SUPPORT
   2011         case MMU_SEDCFG_MEM_FAIL_ADDR_64m:
   2012         case MMU_SEDCFG_MEM_FAIL_ADDR_64_SC0m:
   2013         case MMU_SEDCFG_MEM_FAIL_ADDR_64_SC1m:
   2014 #endif /* BCM_TOMAHAWK2_SUPPORT */
   2015 #ifdef BCM_56980_A0
   2016         case ING_SER_FIFO_PIPE4m:
   2017         case ING_SER_FIFO_PIPE5m:
   2018         case ING_SER_FIFO_PIPE6m:
   2019         case ING_SER_FIFO_PIPE7m:
   2020         case EGR_SER_FIFO_PIPE4m:
   2021         case EGR_SER_FIFO_PIPE5m:
   2022         case EGR_SER_FIFO_PIPE6m:
   2023         case EGR_SER_FIFO_PIPE7m:
   2024         case EDB_SER_FIFOm:
   2025         case EDB_SER_FIFO_PIPE0m:
   2026         case EDB_SER_FIFO_PIPE1m:
   2027         case EDB_SER_FIFO_PIPE2m:
   2028         case EDB_SER_FIFO_PIPE3m:
   2029         case EDB_SER_FIFO_PIPE4m:
   2030         case EDB_SER_FIFO_PIPE5m:
   2031         case EDB_SER_FIFO_PIPE6m:
   2032         case EDB_SER_FIFO_PIPE7m:
   2033         case EGR_SER_FIFO_2m:
   2034         case EGR_SER_FIFO_2_PIPE0m:
   2035         case EGR_SER_FIFO_2_PIPE1m:
   2036         case EGR_SER_FIFO_2_PIPE2m:
   2037         case EGR_SER_FIFO_2_PIPE3m:
   2038         case EGR_SER_FIFO_2_PIPE4m:
   2039         case EGR_SER_FIFO_2_PIPE5m:
   2040         case EGR_SER_FIFO_2_PIPE6m:
   2041         case EGR_SER_FIFO_2_PIPE7m:
   2042         case MMU_GLBCFG_MEM_FAIL_ADDR_64m:
   2043         case MMU_ITMCFG_MEM_FAIL_ADDR_64_ITM0m:
   2044         case MMU_ITMCFG_MEM_FAIL_ADDR_64_ITM1m:
   2045         case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE0m:
   2046         case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE1m:
   2047         case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE2m:
   2048         case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE3m:
   2049         case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE4m:
   2050         case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE5m:
   2051         case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE6m:
   2052         case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE7m:
   2053         case DLB_ECMP_SER_FIFOm:
   2054 #endif
   2055             break;
   2056         default:
   2057             cli_out("ERROR: %s table does not support FIFO push/pop\n",
   2058                     SOC_MEM_UFNAME(unit, mem));
   2059             goto done;
   2060     }
   2061 
   2062     ufname = SOC_MEM_UFNAME(unit, mem);
   2063 
   2064     if (copyno == COPYNO_ALL) {
   2065         copyno = SOC_MEM_BLOCK_ANY(unit, mem);
   2066     }
   2067 
   2068     if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) {
   2069         cli_out("POP[%s]", ufname);
   2070         cli_out("\n");
   2071     }
   2072 
   2073     while (count--) {
   2074         i = soc_mem_pop(unit, mem, copyno, result);
   2075 
   2076         if (i < 0) {            /* Error not fatal for lookup */
   2077             if (i != SOC_E_NOT_FOUND) {
   2078                 cli_out("Pop ERROR: read error during pop: %s\n",
   2079                         soc_errmsg(i));
   2080             } else if (!quiet) {
   2081                 cli_out("Pop: Fifo empty\n");
   2082             }
   2083         } else { /* Entry popped */
   2084             cli_out("Popped in %s.%s: ",
   2085                     ufname, SOC_BLOCK_NAME(unit, copyno));
   2086             soc_mem_entry_dump(unit, mem, result, BSL_LSS_CLI);
   2087             cli_out("\n");
   2088         }
   2089     }
   2090 
   2091     rv = CMD_OK;
   2092 
   2093  done:
   2094     return rv;
   2095 }
   2096 
   2097 /*
   2098  * Push an entry onto a FIFO
   2099  */
   2100 
   2101 char push_usage[] =
   2102     "\nParameters: [quiet] [<COUNT>] <TABLE>\n"
   2103     "The quiet option indicates not to complain on FIFO full.\n";
   2104 
   2105 cmd_result_t
   2106 mem_push(int unit, args_t *a)
   2107 {
   2108     uint32              entry[SOC_MAX_MEM_WORDS];
   2109     int                 entry_dw;
   2110     char                *ufname, *s;
   2111     int                 rv = CMD_FAIL;
   2112     char                valstr[1024];
   2113     soc_mem_t           mem;
   2114     int                 copyno;
   2115     char                *tab;
   2116     int                 count = 1;
   2117     int                 quiet = 0;
   2118     int                 i;
   2119 
   2120     if (!sh_check_attached(ARG_CMD(a), unit)) {
   2121         return CMD_FAIL;
   2122     }
   2123 
   2124     if (!soc_feature(unit, soc_feature_mem_push_pop)) {
   2125         /* feature not supported */
   2126         return CMD_FAIL;
   2127     }
   2128 
   2129     for (;;) {
   2130         if ((tab = ARG_GET(a)) == NULL) {
   2131             return CMD_USAGE;
   2132         }
   2133 
   2134         if (isint(tab)) {
   2135             count = parse_integer(tab);
   2136             continue;
   2137         }
   2138 
   2139         if (sal_strcasecmp(tab, "quiet") == 0) {
   2140             quiet = 1;
   2141             continue;
   2142         }
   2143         break;
   2144     }
   2145 
   2146     if (parse_memory_name(unit, &mem, tab, &copyno, 0) < 0) {
   2147         cli_out("ERROR: unknown table \"%s\"\n", tab);
   2148         goto done;
   2149     }
   2150 
   2151     if (!SOC_MEM_IS_VALID(unit, mem)) {
   2152         cli_out("Error: Memory %s not valid for chip %s.\n",
   2153                 SOC_MEM_UFNAME(unit, mem), SOC_UNIT_NAME(unit));
   2154         goto done;
   2155     }
   2156 
   2157     switch (mem) { 
   2158 #if defined (BCM_TRIUMPH_SUPPORT)
   2159         case ING_IPFIX_EXPORT_FIFOm:
   2160         case EGR_IPFIX_EXPORT_FIFOm:
   2161         case EXT_L2_MOD_FIFOm:
   2162 #endif /* BCM_TRIUMPH_SUPPORT */
   2163         case L2_MOD_FIFOm:
   2164             break;
   2165         default:
   2166             cli_out("ERROR: %s table does not support FIFO push/pop\n",
   2167                     SOC_MEM_UFNAME(unit, mem));
   2168             goto done;
   2169     }
   2170     
   2171     entry_dw = soc_mem_entry_words(unit, mem);
   2172     ufname = SOC_MEM_UFNAME(unit, mem);
   2173     
   2174     if (copyno == COPYNO_ALL) { 
   2175         copyno = SOC_MEM_BLOCK_ANY(unit, mem);
   2176     }
   2177 
   2178     /* 
   2179      * If a list of fields were specified, generate the entry from them.
   2180      * Otherwise, generate it by reading raw dwords from command line.
   2181      */
   2182 
   2183     if ((s = ARG_GET(a)) == 0) { 
   2184         cli_out("ERROR: missing data for entry to push\n");
   2185         goto done;
   2186     }
   2187 
   2188     if (!isint(s)) {
   2189         /* List of fields */
   2190 
   2191         collect_comma_args(a, valstr, s);
   2192 
   2193         sal_memset(entry, 0, sizeof (entry));
   2194 
   2195         if (modify_mem_fields(unit, mem, entry, NULL, valstr, FALSE) < 0) {
   2196             cli_out("Syntax error in field specification\n");
   2197             goto done;
   2198         }
   2199     } else {
   2200         /* List of numeric values */
   2201 
   2202         ARG_PREV(a);
   2203 
   2204         if (parse_dwords(entry_dw, entry, a) < 0) {
   2205             goto done;
   2206         }
   2207     }
   2208 
   2209     if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) {
   2210         cli_out("PUSH[%s], DATA:", ufname);
   2211         for (i = 0; i < entry_dw; i++) {
   2212             cli_out(" 0x%x", entry[i]);
   2213         }
   2214         cli_out("\n");
   2215     }
   2216 
   2217     /*
   2218      * Have entry data, push entry.
   2219      */
   2220 
   2221     while (count--) {
   2222         i = soc_mem_push(unit, mem, copyno, entry);
   2223         if (quiet && i == SOC_E_FULL) {
   2224             i = SOC_E_NONE;
   2225         }
   2226 
   2227         if (i < 0) {
   2228             cli_out("Push ERROR: %s table push failed: %s\n",
   2229                     ufname, soc_errmsg(i));
   2230             goto done;
   2231         }
   2232     }
   2233 
   2234     rv = CMD_OK;
   2235 
   2236  done:
   2237     return rv;
   2238 }
   2239 
   2240 /*
   2241  * do_search_entry
   2242  *
   2243  *  Auxiliary routine for command_search()
   2244  *  Returns byte position within entry where pattern is found.
   2245  *  Returns -1 if not found.
   2246  *  Finds pattern in either big- or little-endian order.
   2247  */
   2248 
   2249 static int
   2250 do_search_entry(uint8 *entry, int entry_len,
   2251 		uint8 *pat, int pat_len)
   2252 {
   2253     int start, i;
   2254 
   2255     for (start = 0; start <= entry_len - pat_len; start++) {
   2256 	for (i = 0; i < pat_len; i++) {
   2257 	    if (entry[start + i] != pat[i]) {
   2258 		break;
   2259 	    }
   2260 	}
   2261 
   2262 	if (i == pat_len) {
   2263 	    return start;
   2264 	}
   2265 
   2266 	for (i = 0; i < pat_len; i++) {
   2267 	    if (entry[start + i] != pat[pat_len - 1 - i]) {
   2268 		break;
   2269 	    }
   2270 	}
   2271 
   2272 	if (i == pat_len) {
   2273 	    return start;
   2274 	}
   2275     }
   2276 
   2277     return -1;
   2278 }
   2279 
   2280 /*
   2281  * Search a table for a byte pattern
   2282  */
   2283 
   2284 #define SRCH_MAX_PAT		16
   2285 
   2286 char search_usage[] =
   2287     "1. Parameters: [ALL | BIN | FBIN] <TABLE>[.<COPY>] 0x<PATTERN>\n"
   2288 #ifndef COMPILER_STRING_CONST_LIMIT
   2289     "\tDumps table entries containing the specified byte pattern\n\t"
   2290     "anywhere in the entry in big- or little-endian order.\n\t"
   2291     "Example: search arl 0x112233445566\n"
   2292 #endif
   2293     "2. Parameters: [ALL | BIN | FBIN] <TABLE>[.<COPY>]"
   2294          "<FIELD>=<VALUE>[,...]\n"
   2295 #ifndef COMPILER_STRING_CONST_LIMIT
   2296     "\tDumps table entries where the specified fields are equal\n\t"
   2297     "to the specified values.\n\t"
   2298     "Example: search l3 ip_addr=0xf4000001,pnum=10\n\t"
   2299     "The ALL flag indicates to search sorted tables in their\n\t"
   2300     "entirety instead of only entries known to contain data.\n\t"
   2301     "The BIN flag does a binary search of sorted tables in\n\t"
   2302     "the portion known to contain data.\n\t"
   2303     "The FBIN flag does a binary search, and guarantees if there\n\t"
   2304     "are duplicates the lowest matching index will be returned.\n"
   2305 #endif
   2306     ;
   2307 
   2308 cmd_result_t
   2309 mem_search(int unit, args_t *a)
   2310 {
   2311     int			t, rv = CMD_FAIL;
   2312     char		*tab, *patstr;
   2313     soc_mem_t		mem;
   2314     uint32		pat_entry[SOC_MAX_MEM_WORDS];
   2315     uint32		pat_mask[SOC_MAX_MEM_WORDS];
   2316     uint32		entry[SOC_MAX_MEM_WORDS];
   2317     char		valstr[1024];
   2318     uint8		pat[SRCH_MAX_PAT];
   2319     char		*ufname;
   2320     int			patsize = 0, found_count = 0, entry_bytes, entry_dw;
   2321     int			copyno, index, min, max;
   2322     int			byte_search;
   2323     int			all_flag = 0, bin_flag = 0, lowest_match = 0;
   2324 #ifdef BCM_TRIDENT2_SUPPORT
   2325     int       check_view = FALSE;
   2326     soc_mem_t view = INVALIDm;
   2327 #endif /* BCM_TRIDENT2_SUPPORT */
   2328 
   2329     if (!sh_check_attached(ARG_CMD(a), unit)) {
   2330 	goto done;
   2331     }
   2332 
   2333     tab = ARG_GET(a);
   2334 
   2335     while (tab) {
   2336 	if (!sal_strcasecmp(tab, "all")) {
   2337 	    all_flag = 1;
   2338 	} else if (!sal_strcasecmp(tab, "bin")) {
   2339 	    bin_flag = 1;
   2340 	} else if (!sal_strcasecmp(tab, "fbin")) {
   2341 	    bin_flag = 1;
   2342 	    lowest_match = 1;
   2343 	} else {
   2344 	    break;
   2345 	}
   2346 	tab = ARG_GET(a);
   2347     }
   2348 
   2349     patstr = ARG_GET(a);
   2350 
   2351     if (!tab || !patstr) {
   2352 	return CMD_USAGE;
   2353     }
   2354 
   2355     if (parse_memory_name(unit, &mem, tab, &copyno, 0) < 0) {
   2356 	cli_out("ERROR: unknown table \"%s\"\n", tab);
   2357 	goto done;
   2358     }
   2359 
   2360     if (!SOC_MEM_IS_VALID(unit, mem)) {
   2361         cli_out("Error: Memory %s not valid for chip %s.\n",
   2362                 SOC_MEM_UFNAME(unit, mem), SOC_UNIT_NAME(unit));
   2363         goto done;
   2364     }
   2365 
   2366     if (copyno == COPYNO_ALL) {
   2367 	copyno = SOC_MEM_BLOCK_ANY(unit, mem);
   2368     }
   2369 
   2370     entry_bytes = soc_mem_entry_bytes(unit, mem);
   2371     entry_dw = BYTES2WORDS(entry_bytes);
   2372     min = soc_mem_index_min(unit, mem);
   2373     max = soc_mem_index_max(unit, mem);
   2374     ufname = SOC_MEM_UFNAME(unit, mem);
   2375 
   2376     byte_search = isint(patstr);
   2377 
   2378     if (byte_search) {
   2379 	char *s;
   2380 
   2381 	/*
   2382 	 * Search by pattern string.
   2383 	 * Parse pattern string (long hex number) into array of bytes.
   2384 	 */
   2385 
   2386 	if (patstr[0] != '0' ||
   2387 	    (patstr[1] != 'x' && patstr[1] != 'X') || patstr[2] == 0) {
   2388 	    cli_out("ERROR: illegal search pattern, need hex constant\n");
   2389 	    goto done;
   2390 	}
   2391 
   2392 	patstr += 2;
   2393 
   2394 	for (s = patstr; *s; s++) {
   2395 	    if (!isxdigit((unsigned) *s)) {
   2396 		cli_out("ERROR: invalid hex digit in search pattern\n");
   2397 		goto done;
   2398 	    }
   2399 	}
   2400 
   2401 	while (s > patstr + 1) {
   2402 	    s -= 2;
   2403 	    pat[patsize++] = xdigit2i(s[0]) << 4 | xdigit2i(s[1]);
   2404 	}
   2405 
   2406 	if (s > patstr) {
   2407 	    s--;
   2408 	    pat[patsize++] = xdigit2i(s[0]);
   2409 	}
   2410 
   2411 #if 0
   2412 	cli_out("PATTERN: ");
   2413 	for (index = 0; index < patsize; index++) {
   2414 	    cli_out("%02x ", pat[index]);
   2415 	}
   2416 	cli_out("\n");
   2417 #endif
   2418     } else {
   2419 	/*
   2420 	 * Search by pat_entry and pat_mask.
   2421 	 * Collect list of fields
   2422 	 */
   2423 
   2424 	collect_comma_args(a, valstr, patstr);
   2425 
   2426 	memset(pat_entry, 0, sizeof (pat_entry));
   2427 
   2428 	if (modify_mem_fields(unit, mem,
   2429 			      pat_entry, pat_mask,
   2430 			      valstr, FALSE) < 0) {
   2431 	    cli_out("Syntax error: aborted\n");
   2432 	    goto done;
   2433 	}
   2434     }
   2435 
   2436     if (bin_flag) {
   2437 	if (!soc_mem_is_sorted(unit, mem)) {
   2438 	    cli_out("ERROR: can only binary search sorted tables\n");
   2439 	    goto done;
   2440 	}
   2441 
   2442 	if (byte_search) {
   2443 	    cli_out("ERROR: can only binary search for "
   2444                     "<FIELD>=<VALUE>[,...]\n");
   2445 	    goto done;
   2446 	}
   2447 
   2448 	cli_out("Searching %s...\n", ufname);
   2449 
   2450 	t = soc_mem_search(unit, mem, copyno, &index,
   2451 				pat_entry, entry, lowest_match);
   2452         if ((t < 0) && (t != SOC_E_NOT_FOUND)) {
   2453 	    cli_out("Read ERROR: table[%s]: %s\n", ufname, soc_errmsg(t));
   2454 	    goto done;
   2455 	}
   2456 
   2457 	if (t == SOC_E_NONE) {
   2458 	    cli_out("%s[%d]: ", ufname, index);
   2459 	    soc_mem_entry_dump(unit, mem, entry, BSL_LSS_CLI);
   2460 	    cli_out("\n");
   2461 	} else {
   2462 	    cli_out("Nothing found\n");
   2463         }
   2464 
   2465 	rv = CMD_OK;
   2466 	goto done;
   2467     }
   2468 
   2469     if (!all_flag && soc_mem_is_sorted(unit, mem)) {
   2470 	max = soc_mem_index_last(unit, mem, copyno);
   2471     }
   2472 
   2473 #ifdef BCM_TRIDENT2_SUPPORT
   2474     if (SOC_IS_TD2_TT2(unit) &&
   2475         (mem == L3_DEFIP_ALPM_IPV4m || mem == L3_DEFIP_ALPM_IPV4_1m ||
   2476          mem == L3_DEFIP_ALPM_IPV6_64m || mem == L3_DEFIP_ALPM_IPV6_64_1m ||
   2477          mem == L3_DEFIP_ALPM_IPV6_128m)) {
   2478         check_view = TRUE;
   2479         view = mem;
   2480     }
   2481 #endif /* BCM_TRIDENT2_SUPPORT */
   2482 
   2483     cli_out("Searching %s table indexes 0x%x through 0x%x...\n",
   2484             ufname, min, max);
   2485 
   2486     for (index = min; index <= max; index++) {
   2487 	int match;
   2488 
   2489 #ifdef BCM_TRIDENT2_SUPPORT
   2490         if (check_view) {
   2491             if (SOC_IS_TRIDENT2(unit) || SOC_IS_TRIDENT2PLUS(unit)) {
   2492                 view = _soc_trident2_alpm_bkt_view_get(unit, index);
   2493             }
   2494 #if defined(ALPM_ENABLE)
   2495 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT)
   2496             else {
   2497                 view = soc_alpm_cmn_bkt_view_get(unit, index);
   2498             }
   2499 #endif
   2500 #endif
   2501             if (!(view == INVALIDm || mem == view)) {
   2502                 continue;
   2503             }
   2504         }
   2505 #endif /* BCM_TRIDENT2_SUPPORT */
   2506 
   2507 	if ((t = soc_mem_read(unit, mem, copyno, index, entry)) < 0) {
   2508 	    cli_out("Read ERROR: table %s.%s[%d]: %s\n",
   2509                     ufname, SOC_BLOCK_NAME(unit, copyno), index, soc_errmsg(t));
   2510 	    goto done;
   2511 	}
   2512 
   2513 #ifdef BCM_XGS_SWITCH_SUPPORT
   2514 	if (!all_flag) {
   2515 #ifdef BCM_XGS12_SWITCH_SUPPORT
   2516             if SOC_IS_XGS12_SWITCH(unit) {
   2517 	        if (mem == L2Xm &&
   2518 		    !soc_L2Xm_field32_get(unit, entry, VALID_BITf)) {
   2519 		    continue;
   2520 	        }
   2521 
   2522 	        if (mem == L3Xm &&
   2523 		    !soc_L3Xm_field32_get(unit, entry, L3_VALIDf)) {
   2524 		    continue;
   2525 	        }
   2526             }
   2527 #endif /* BCM_XGS12_SWITCH_SUPPORT */
   2528 
   2529 #ifdef BCM_XGS3_SWITCH_SUPPORT
   2530 #ifdef BCM_FIREBOLT_SUPPORT
   2531             if (SOC_IS_FBX(unit) || SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit)) { 
   2532                 switch (mem) {
   2533                     case L2Xm:
   2534                         {
   2535                             soc_field_t vld_fld;
   2536                             vld_fld =
   2537                                 (SOC_IS_TOMAHAWK3(unit) || SOC_IS_TRIDENT3X(unit)) ? BASE_VALIDf : VALIDf;
   2538                             if (!soc_L2Xm_field32_get(unit, entry, vld_fld)) {
   2539                                 continue;
   2540                             }
   2541                         }
   2542                         break; 
   2543                     case L2_USER_ENTRYm:
   2544                         if (!soc_L2_USER_ENTRYm_field32_get(unit, 
   2545                                entry, VALIDf)) {
   2546                             continue;
   2547                         }
   2548                         break;
   2549                     case L3_ENTRY_IPV4_UNICASTm:
   2550                         if (!soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, 
   2551                                entry, VALIDf)) {
   2552                             continue;
   2553                         }
   2554                         break;
   2555                     case L3_ENTRY_IPV4_MULTICASTm:
   2556                         if (soc_mem_field_valid(unit, mem, VALIDf)) {
   2557                             if (!soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit,
   2558                                    entry, VALIDf)) {
   2559                                 continue;
   2560                             }
   2561                         }
   2562 
   2563                         if (soc_mem_field_valid(unit, mem, VALID_0f) &&
   2564                             soc_mem_field_valid(unit, mem, VALID_1f)) {
   2565                             if (!(soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit,
   2566                                    entry, VALID_0f) &&
   2567                                   soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit,
   2568                                    entry, VALID_1f))) {
   2569                                 continue;
   2570                             }
   2571                         }
   2572                         break;
   2573                     case L3_ENTRY_IPV6_UNICASTm:
   2574                         if (!(soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit,
   2575                                 entry, VALID_0f) && 
   2576                               soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit,
   2577                                 entry, VALID_1f))) {
   2578                             continue;
   2579                         }
   2580                         break;
   2581                     case L3_ENTRY_IPV6_MULTICASTm:
   2582                         if (!(soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit,
   2583                                 entry, VALID_0f) &&
   2584                               soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit,
   2585                                 entry, VALID_1f) &&
   2586                               soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit,
   2587                                 entry, VALID_2f) &&
   2588                               soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, 
   2589                                 entry, VALID_3f))) {
   2590                             continue;
   2591                         }
   2592                         break;
   2593                     default:
   2594                         break;
   2595                 }
   2596             }
   2597 #endif /* BCM_FIREBOLT_SUPPORT */
   2598 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   2599 	}
   2600 #endif /* BCM_XGS_SWITCH_SUPPORT */
   2601 
   2602 	if (byte_search) {
   2603 	    match = (do_search_entry((uint8 *) entry, entry_bytes,
   2604 				     pat, patsize) >= 0);
   2605 	} else {
   2606 	    int i;
   2607 
   2608 	    for (i = 0; i < entry_dw; i++)
   2609 		if ((entry[i] & pat_mask[i]) != pat_entry[i])
   2610 		    break;
   2611 
   2612 	    match = (i == entry_dw);
   2613 	}
   2614 
   2615 	if (match) {
   2616 	    cli_out("%s.%s[%d]: ",
   2617                     ufname, SOC_BLOCK_NAME(unit, copyno), index);
   2618 	    soc_mem_entry_dump(unit, mem, entry, BSL_LSS_CLI);
   2619 	    cli_out("\n");
   2620 	    found_count++;
   2621 	}
   2622     }
   2623 
   2624     if (found_count == 0) {
   2625 	cli_out("Nothing found\n");
   2626     }
   2627 
   2628     rv = CMD_OK;
   2629 
   2630  done:
   2631     return rv;
   2632 }
   2633 
   2634 /*
   2635  * Print a one line summary for matching memories
   2636  * If substr_match is NULL, match all memories.
   2637  * If substr_match is non-NULL, match any memories whose name
   2638  * or user-friendly name contains that substring.
   2639  */
   2640 
   2641 static void
   2642 mem_list_summary(int unit, char *substr_match)
   2643 {
   2644     soc_mem_t		mem;
   2645     int			i, copies, dlen;
   2646     int			found = 0;
   2647     char		*dstr;
   2648     int         print_tr = 0;
   2649     const char  *soctr = "soc_tr";
   2650 
   2651     if(substr_match) {
   2652         if(sal_strcmp(substr_match,soctr) == 0){
   2653             print_tr = 1;
   2654             substr_match = NULL;
   2655         }
   2656     }
   2657 
   2658     for (mem = 0; mem < NUM_SOC_MEM; mem++) {
   2659         if (!soc_mem_is_valid(unit, mem)) {
   2660             continue;
   2661         }
   2662 
   2663 #if defined(BCM_HAWKEYE_SUPPORT)
   2664         if (SOC_IS_HAWKEYE(unit) && (soc_mem_index_max(unit, mem) <= 0)) {
   2665             continue;
   2666         }
   2667 #endif /* BCM_HAWKEYE_SUPPORT */
   2668 
   2669         if (substr_match != NULL &&
   2670             strcaseindex(SOC_MEM_NAME(unit, mem), substr_match) == NULL &&
   2671             strcaseindex(SOC_MEM_UFNAME(unit, mem), substr_match) == NULL) {
   2672             continue;
   2673         }
   2674 
   2675         copies = 0;
   2676         SOC_MEM_BLOCK_ITER(unit, mem, i) {
   2677             copies += 1;
   2678         }
   2679 
   2680         dlen = sal_strlen(SOC_MEM_DESC(unit, mem));
   2681         if (dlen > 30) {
   2682             dlen = 26;
   2683             dstr = "...";
   2684         } else {
   2685             dstr = "";
   2686         }
   2687 
   2688         if(print_tr) {
   2689             if(!soc_mem_is_readonly(unit, mem)) {
   2690                 if(soc_mem_index_count(unit,mem) > 3) {
   2691                     cli_out("local mem '%s';\n", SOC_MEM_UFNAME(unit,mem));
   2692                     cli_out("$name; $tr50; $tr51; $tr52;\n");
   2693                 } else if(soc_mem_index_count(unit,mem) > 0) {
   2694                     cli_out("local mem '%s';\n", SOC_MEM_UFNAME(unit,mem));
   2695                     cli_out("$name; $tr50;\n");
   2696                 }
   2697             } else {
   2698                 cli_out("#local mem '%s' Read Only Memory - Not tested\n",
   2699                          SOC_MEM_UFNAME(unit,mem));
   2700             }
   2701         } else {
   2702             if (!found) {
   2703                 cli_out(" %-6s %1s %-28s%6s/%-4s %s\n",
   2704                         "Flags", "C", "Name", "Entry",
   2705                         "Copy", "Description");
   2706                 found = 1;
   2707             }
   2708 
   2709             cli_out(" %c%c%c%c%c%c %1s %-28s%6d",
   2710                     soc_mem_is_readonly(unit, mem) ? 'r' : '-',
   2711                     soc_mem_is_debug(unit, mem) ? 'd' : '-',
   2712                     soc_mem_is_sorted(unit, mem) ? 's' :
   2713                     soc_mem_is_hashed(unit, mem) ? 'h' :
   2714                     soc_mem_is_cam(unit, mem) ? 'A' : '-',
   2715                     soc_mem_is_cbp(unit, mem) ? 'c' : '-',
   2716                     (soc_mem_is_bistepic(unit, mem) ||
   2717                     soc_mem_is_bistffp(unit, mem) ||
   2718                     soc_mem_is_bistcbp(unit, mem)) ? 'b' : '-',
   2719                     soc_mem_is_cachable(unit, mem) ? 'C' : '-',
   2720                     soc_mem_cache_get(unit, mem, SOC_BLOCK_ANY) ? "*" : "",
   2721                     SOC_MEM_UFNAME(unit, mem),
   2722                     soc_mem_index_count(unit, mem));
   2723             if (copies == 1) {
   2724                 cli_out("%5s %*.*s%s\n",
   2725                         "",
   2726                         dlen, dlen, SOC_MEM_DESC(unit, mem), dstr);
   2727             } else {
   2728                 cli_out("/%-4d %*.*s%s\n",
   2729                         copies,
   2730                         dlen, dlen, SOC_MEM_DESC(unit, mem), dstr);
   2731             }
   2732         }
   2733     }
   2734 
   2735     if (found) {
   2736 	cli_out("Flags: (r)eadonly, (d)ebug, (s)orted, (h)ashed\n"
   2737                 "       C(A)M, (c)bp, (b)ist-able, (C)achable\n");
   2738     cli_out("    C: Cache state, * means cache is on\n");
   2739     } else if (substr_match != NULL) {
   2740 	cli_out("No memory found with the substring '%s' in its name.\n",
   2741                 substr_match);
   2742     }
   2743 }
   2744 
   2745 /*
   2746  * List the tables, or fields of a table entry
   2747  */
   2748 
   2749 cmd_result_t
   2750 cmd_esw_mem_list(int unit, args_t *a)
   2751 {
   2752     soc_mem_info_t	*m;
   2753     soc_field_info_t	*fld;
   2754     char		*tab, *s;
   2755     soc_mem_t		mem;
   2756     uint32		entry[SOC_MAX_MEM_WORDS];
   2757     uint32		mask[SOC_MAX_MEM_WORDS];
   2758     int			have_entry, i, dw, copyno;
   2759     int			copies, disabled, dmaable, slamable;
   2760     char		*dmastr, *slamstr;
   2761     uint32		flags;
   2762     int			minidx, maxidx;
   2763     uint8               at;
   2764 
   2765     if (!sh_check_attached(ARG_CMD(a), unit)) {
   2766 	return CMD_FAIL;
   2767     }
   2768 
   2769     if (!soc_property_get(unit, spn_MEMLIST_ENABLE, 1)) {
   2770         return CMD_OK;
   2771     }
   2772     tab = ARG_GET(a);
   2773 
   2774     if (!tab) {
   2775 	mem_list_summary(unit, NULL);
   2776 	return CMD_OK;
   2777     }
   2778 
   2779     if (parse_memory_name(unit, &mem, tab, &copyno, 0) < 0) {
   2780 	if ((s = strchr(tab, '.')) != NULL) {
   2781 	    *s = 0;
   2782 	}
   2783 	mem_list_summary(unit, tab);
   2784 	return CMD_OK;
   2785     }
   2786 
   2787     if (!SOC_MEM_IS_VALID(unit, mem)) {
   2788 	cli_out("ERROR: Memory \"%s\" not valid for this unit\n", tab);
   2789 	return CMD_FAIL;
   2790     }
   2791 
   2792 #if defined(BCM_HAWKEYE_SUPPORT)
   2793     if (SOC_IS_HAWKEYE(unit) && (soc_mem_index_max(unit, mem) <= 0)) {
   2794         cli_out("ERROR: Memory \"%s\" not valid for this unit\n", tab);
   2795         return CMD_FAIL;
   2796     }
   2797 #endif /* BCM_HAWKEYE_SUPPORT */
   2798 
   2799     if (copyno < 0) {
   2800 	copyno = SOC_MEM_BLOCK_ANY(unit, mem);
   2801         if (copyno < 0) {
   2802             cli_out("ERROR: Memory \"%s\" has no instance on this unit\n", tab);
   2803             return CMD_FAIL;
   2804         }
   2805     } else if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) {
   2806 	cli_out("ERROR: Invalid copy number %d for memory %s\n", copyno, tab);
   2807 	return CMD_FAIL;
   2808     }
   2809 
   2810     m = &SOC_MEM_INFO(unit, mem);
   2811     flags = m->flags;
   2812 
   2813     dw = BYTES2WORDS(m->bytes);
   2814 
   2815     if ((s = ARG_GET(a)) == 0) {
   2816 	have_entry = 0;
   2817     } else {
   2818 	for (i = 0; i < dw; i++) {
   2819 	    if (s == 0) {
   2820 		cli_out("Not enough data specified (%d words needed)\n", dw);
   2821 		return CMD_FAIL;
   2822 	    }
   2823 	    entry[i] = parse_integer(s);
   2824 	    s = ARG_GET(a);
   2825 	}
   2826 	if (s) {
   2827 	    cli_out("Extra data specified (ignored)\n");
   2828 	}
   2829 	have_entry = 1;
   2830     }
   2831 
   2832     cli_out("Memory: %s.%s",
   2833             SOC_MEM_NAME(unit, mem),
   2834             SOC_BLOCK_NAME(unit, copyno));
   2835     s = SOC_MEM_UFNAME(unit, mem);
   2836     if (s && *s && sal_strcmp(SOC_MEM_NAME(unit, mem), s) != 0) {
   2837 	    cli_out(" aka %s", s);
   2838     }
   2839     s = SOC_MEM_UFALIAS(unit, mem);
   2840     if (s && *s && sal_strcmp(SOC_MEM_UFNAME(unit, mem), s) != 0) {
   2841 	    cli_out(" alias %s", s);
   2842     }
   2843     cli_out(" address 0x%08x\n", soc_mem_addr_get(unit, mem, 0, copyno, 0, &at));
   2844 
   2845     cli_out("Flags:");
   2846     if (flags & SOC_MEM_FLAG_READONLY) {
   2847 	cli_out(" read-only");
   2848     }
   2849     if (flags & SOC_MEM_FLAG_VALID) {
   2850 	cli_out(" valid");
   2851     }
   2852     if (flags & SOC_MEM_FLAG_DEBUG) {
   2853 	cli_out(" debug");
   2854     }
   2855     if (flags & SOC_MEM_FLAG_SORTED) {
   2856 	cli_out(" sorted");
   2857     }
   2858     if (flags & SOC_MEM_FLAG_CBP) {
   2859 	cli_out(" cbp");
   2860     }
   2861     if (flags & SOC_MEM_FLAG_CACHABLE) {
   2862     	cli_out(" cachable");
   2863         if (soc_mem_cache_get(unit, mem, SOC_BLOCK_ANY)) {
   2864             cli_out("(on)");
   2865         } else {
   2866             cli_out("(off)");
   2867         }
   2868     }
   2869     if (flags & SOC_MEM_FLAG_BISTCBP) {
   2870 	cli_out(" bist-cbp");
   2871     }
   2872     if (flags & SOC_MEM_FLAG_BISTEPIC) {
   2873 	cli_out(" bist-epic");
   2874     }
   2875     if (flags & SOC_MEM_FLAG_BISTFFP) {
   2876 	cli_out(" bist-ffp");
   2877     }
   2878     if (flags & SOC_MEM_FLAG_UNIFIED) {
   2879 	cli_out(" unified");
   2880     }
   2881     if (flags & SOC_MEM_FLAG_HASHED) {
   2882 	cli_out(" hashed");
   2883     }
   2884     if (flags & SOC_MEM_FLAG_WORDADR) {
   2885 	cli_out(" word-addressed");
   2886     }
   2887     if (flags & SOC_MEM_FLAG_BE) {
   2888 	cli_out(" big-endian");
   2889     }
   2890     if (flags & SOC_MEM_FLAG_MULTIVIEW) {
   2891         cli_out(" multiview");
   2892     }
   2893     cli_out("\n");
   2894 
   2895     cli_out("Blocks: ");
   2896     copies = disabled = dmaable = slamable = 0;
   2897     SOC_MEM_BLOCK_ITER(unit, mem, i) {
   2898 	if (SOC_INFO(unit).block_valid[i]) {
   2899 	    dmastr = "";
   2900 	    slamstr = "";
   2901 #ifdef BCM_XGS_SWITCH_SUPPORT
   2902 	    if (soc_mem_dmaable(unit, mem, i)) {
   2903 		dmastr = "/dma";
   2904 		dmaable += 1;
   2905 	    }
   2906 	    if (soc_mem_slamable(unit, mem, i)) {
   2907 		slamstr = "/slam";
   2908 		slamable += 1;
   2909 	    }
   2910 #endif
   2911 	    cli_out(" %s%s%s", SOC_BLOCK_NAME(unit, i), dmastr, slamstr);
   2912 	} else {
   2913 	    cli_out(" [%s]", SOC_BLOCK_NAME(unit, i));
   2914 	    disabled += 1;
   2915 	}
   2916 	copies += 1;
   2917     }
   2918     cli_out(" (%d cop%s", copies, copies == 1 ? "y" : "ies");
   2919     if (disabled) {
   2920 	cli_out(", %d disabled", disabled);
   2921     }
   2922 #ifdef BCM_XGS_SWITCH_SUPPORT
   2923     if (dmaable) {
   2924 	cli_out(", %d dmaable", dmaable);
   2925     }
   2926     if (slamable) {
   2927 	cli_out(", %d slamable", slamable);
   2928     }
   2929 #endif
   2930     cli_out(")\n");
   2931 
   2932     minidx = soc_mem_index_min(unit, mem);
   2933     maxidx = soc_mem_index_max(unit, mem);
   2934     cli_out("Entries: %d with indices %d-%d (0x%x-0x%x)",
   2935             maxidx - minidx + 1,
   2936             minidx,
   2937             maxidx,
   2938             minidx,
   2939             maxidx);
   2940     cli_out(", each %d bytes %d words\n", m->bytes, dw);
   2941 
   2942     cli_out("Entry mask:");
   2943     soc_mem_datamask_get(unit, mem, mask);
   2944     for (i = 0; i < dw; i++) {
   2945 	if (mask[i] == 0xffffffff) {
   2946 	    cli_out(" -1");
   2947 	} else if (mask[i] == 0) {
   2948 	    cli_out(" 0");
   2949 	} else {
   2950 	    cli_out(" 0x%08x", mask[i]);
   2951 	}
   2952     }
   2953     cli_out("\n");
   2954 
   2955 #ifdef BCM_ISM_SUPPORT
   2956     if (soc_feature(unit, soc_feature_ism_memory)) {
   2957         uint8 banks[_SOC_ISM_MAX_BANKS] = {0};
   2958         uint32 bank_size[_SOC_ISM_MAX_BANKS];
   2959         uint8 count;
   2960         if (soc_ism_get_banks_for_mem(unit, mem, banks, bank_size, &count) 
   2961             == SOC_E_NONE) {
   2962             if (count) {
   2963                 uint8 bc;
   2964                 uint32 bmask = 0;
   2965                 for (bc = 0; bc < count; bc++) {
   2966                     bmask |= 1 << banks[bc];
   2967                 }
   2968                 cli_out("ISM bank mask: 0x%x\n", bmask);
   2969             }
   2970         }
   2971     }
   2972 #endif
   2973 
   2974     s = SOC_MEM_DESC(unit, mem);
   2975     if (s && *s) {
   2976 	cli_out("Description: %s\n", s);
   2977     }
   2978 
   2979     for (fld = &m->fields[m->nFields - 1]; fld >= &m->fields[0]; fld--) {
   2980 	cli_out("  %s<%d", SOC_FIELD_NAME(unit, fld->field), fld->bp + fld->len - 1);
   2981 	if (fld->len > 1) {
   2982 	    cli_out(":%d", fld->bp);
   2983 	}
   2984 	if (have_entry) {
   2985 	    uint32 fval[SOC_MAX_MEM_FIELD_WORDS];
   2986 	    char tmp[132];
   2987 
   2988 	    sal_memset(fval, 0, sizeof (fval));
   2989 	    soc_mem_field_get(unit, mem, entry, fld->field, fval);
   2990 	    format_long_integer(tmp, fval, SOC_MAX_MEM_FIELD_WORDS);
   2991 	    cli_out("> = %s\n", tmp);
   2992 	} else {
   2993 	    cli_out(">\n");
   2994 	}
   2995     }
   2996 
   2997     return CMD_OK;
   2998 }
   2999 
   3000 /*
   3001  * Turn on/off software caching of hardware tables
   3002  */
   3003 
   3004 cmd_result_t
   3005 mem_esw_cache(int unit, args_t *a)
   3006 {
   3007     soc_mem_t		mem;
   3008     int			copyno;
   3009     char		*c;
   3010     int			enable, r;
   3011 
   3012     if (!sh_check_attached(ARG_CMD(a), unit)) {
   3013 	return CMD_FAIL;
   3014     }
   3015 
   3016     if (ARG_CNT(a) == 0) {
   3017 	for (enable = 0; enable < 2; enable++) {
   3018 	    cli_out("Caching is %s for:\n", enable ? "on" : "off");
   3019 
   3020 	    for (mem = 0; mem < NUM_SOC_MEM; mem++) {
   3021 		int any_printed;
   3022 
   3023 		if ((!SOC_MEM_IS_VALID(unit, mem)) ||
   3024                     (!soc_mem_is_cachable(unit, mem))) {
   3025 		    continue;
   3026                 }
   3027 
   3028 		any_printed = 0;
   3029 
   3030 		SOC_MEM_BLOCK_ITER(unit, mem, copyno) {
   3031 		    if ((!enable) ==
   3032 			(!soc_mem_cache_get(unit, mem, copyno))) {
   3033 			if (!any_printed) {
   3034 			    cli_out("    ");
   3035 			}
   3036 			cli_out(" %s.%s",
   3037                                 SOC_MEM_UFNAME(unit, mem),
   3038                                 SOC_BLOCK_NAME(unit, copyno));
   3039 			any_printed = 1;
   3040 		    }
   3041 		}
   3042 
   3043 		if (any_printed) {
   3044 		    cli_out("\n");
   3045 		}
   3046 	    }
   3047 	}
   3048 
   3049 	return CMD_OK;
   3050     }
   3051 
   3052     while ((c = ARG_GET(a)) != 0) {
   3053 	switch (*c) {
   3054 	case '+':
   3055 	    enable = 1;
   3056 	    c++;
   3057 	    break;
   3058 	case '-':
   3059 	    enable = 0;
   3060 	    c++;
   3061 	    break;
   3062 	default:
   3063 	    enable = 1;
   3064 	    break;
   3065 	}
   3066 
   3067 	if (parse_memory_name(unit, &mem, c, &copyno, 0) < 0) {
   3068 	    cli_out("%s: Unknown table \"%s\"\n", ARG_CMD(a), c);
   3069 	    return CMD_FAIL;
   3070 	}
   3071 
   3072         if (!SOC_MEM_IS_VALID(unit, mem)) {
   3073             cli_out("Error: Memory %s not valid for chip %s.\n",
   3074                     SOC_MEM_UFNAME(unit, mem), SOC_UNIT_NAME(unit));
   3075             continue;
   3076         }
   3077 
   3078 	if (!soc_mem_is_cachable(unit, mem)) {
   3079 	    cli_out("%s: Memory %s is not cachable\n",
   3080                     ARG_CMD(a), SOC_MEM_UFNAME(unit, mem));
   3081 	    return CMD_FAIL;
   3082 	}
   3083 
   3084 	if ((r = soc_mem_cache_set(unit, mem, copyno, enable)) < 0) {
   3085 	    cli_out("%s: Error setting cachability for %s: %s\n",
   3086                     ARG_CMD(a), SOC_MEM_UFNAME(unit, mem), soc_errmsg(r));
   3087 	    return CMD_FAIL;
   3088 	}
   3089     }
   3090 
   3091     return CMD_OK;
   3092 }
   3093 
   3094 #ifdef INCLUDE_MEM_SCAN
   3095 
   3096 /*
   3097  * Turn on/off memory scan thread
   3098  */
   3099 
   3100 char memscan_usage[] =
   3101     "Parameters: [Interval=<USEC>] [Rate=<ENTRIES>] [on] [off]\n\t"
   3102     "Interval specifies how often to run (0 to stop)\n\t"
   3103     "Rate specifies the number of entries to process per interval\n\t"
   3104     "Any memories that are cached will be scanned (see 'cache' command)\n";
   3105 
   3106 cmd_result_t
   3107 mem_scan(int unit, args_t *a)
   3108 {
   3109     parse_table_t pt;
   3110     int running, rv;
   3111     sal_usecs_t interval = 0;
   3112     int rate = SOC_MEMSCAN_RATE_DEFAULT;
   3113     char *c;
   3114 
   3115     if (!sh_check_attached(ARG_CMD(a), unit)) {
   3116         return CMD_FAIL;
   3117     }
   3118 
   3119     if ((running = soc_mem_scan_running(unit, &rate, &interval)) < 0) {
   3120         cli_out("soc_mem_scan_running %d: ERROR: %s\n",
   3121                 unit, soc_errmsg(running));
   3122         return CMD_FAIL;
   3123     }
   3124 
   3125     if (ARG_CNT(a) == 0) {
   3126         cli_out("%s: %s on unit %d\n",
   3127                 ARG_CMD(a), running ? "Running" : "Not running", unit);
   3128         cli_out("%s:   Interval: %d usec\n",
   3129                 ARG_CMD(a), interval);
   3130         cli_out("%s:   Rate: %d\n",
   3131                 ARG_CMD(a), rate);
   3132 
   3133         return CMD_OK;
   3134     }
   3135 
   3136     parse_table_init(unit, &pt);
   3137     parse_table_add(&pt, "Interval", PQ_INT | PQ_DFL, 0, &interval, 0);
   3138     parse_table_add(&pt, "Rate", PQ_INT | PQ_DFL, 0, &rate, 0);
   3139 
   3140     if (parse_arg_eq(a, &pt) < 0) {
   3141         cli_out("%s: Invalid argument: %s\n", ARG_CMD(a), ARG_CUR(a));
   3142         parse_arg_eq_done(&pt);
   3143         return CMD_FAIL;
   3144     }
   3145 
   3146     parse_arg_eq_done(&pt);
   3147 
   3148     if ((c = ARG_GET(a)) != NULL) {
   3149         if (sal_strcasecmp(c, "off") == 0) {
   3150             interval = 0;
   3151             rate = 0;
   3152         } else if (sal_strcasecmp(c, "on") == 0) {
   3153             interval = prev_memscan_interval[unit];
   3154             rate = prev_memscan_rate[unit];
   3155         } else {
   3156             return CMD_USAGE;
   3157         }
   3158     }
   3159 
   3160     if (interval == 0) {
   3161         sal_usecs_t prev_interval;
   3162         int prev_rate;
   3163 
   3164         rv = soc_mem_scan_running(unit, &prev_rate, &prev_interval);
   3165         if (rv < 0 || prev_rate <= 0) {
   3166             prev_rate = SOC_MEMSCAN_RATE_DEFAULT;
   3167         }
   3168         if (rv < 0 || prev_interval <= 0) {
   3169             prev_interval = SOC_MEMSCAN_INTERVAL_DEFAULT;
   3170         }
   3171         prev_memscan_rate[unit] = prev_rate;
   3172         prev_memscan_interval[unit] = prev_interval;
   3173 
   3174         if ((rv = soc_mem_scan_stop(unit)) < 0) {
   3175             cli_out("soc_mem_scan_stop %d: ERROR: %s\n",
   3176                     unit, soc_errmsg(rv));
   3177             return CMD_FAIL;
   3178         }
   3179 
   3180         cli_out("%s: Stopped on unit %d\n", ARG_CMD(a), unit);
   3181     } else {
   3182         if (0 == rate) {
   3183             cli_out("%s: Start fails since rate 0 is not supported!\n", ARG_CMD(a));
   3184             return CMD_FAIL;
   3185         }
   3186         if ((rv = soc_mem_scan_start(unit, rate, interval)) < 0) {
   3187             cli_out("soc_mem_scan_start %d: ERROR: %s\n",
   3188                     unit, soc_errmsg(rv));
   3189             return CMD_FAIL;
   3190         }
   3191         cli_out("%s: Started on unit %d\n", ARG_CMD(a), unit);
   3192     }
   3193 
   3194     return CMD_OK;
   3195 }
   3196 
   3197 #endif /* INCLUDE_MEM_SCAN */
   3198 
   3199 #ifdef BCM_SRAM_SCAN_SUPPORT
   3200 
   3201 /*
   3202  * Turn on/off sram scan thread
   3203  */
   3204 
   3205 char sramscan_usage[] =
   3206     "Parameters: [Interval=<USEC>] [Rate=<ENTRIES>] [on] [off]\n\t"
   3207     "Interval specifies how often to run (0 to stop)\n\t"
   3208     "Rate specifies the number of entries to process per interval\n\t"
   3209     "Any srams that are cached will be scanned (see 'cache' command)\n";
   3210 
   3211 cmd_result_t
   3212 sram_scan(int unit, args_t *a)
   3213 {
   3214     parse_table_t pt;
   3215     int    running, rv;
   3216     sal_usecs_t interval = 0;
   3217     int    rate = SOC_SRAMSCAN_RATE_DEFAULT;
   3218     char   *c;
   3219 
   3220     if (!sh_check_attached(ARG_CMD(a), unit)) {
   3221         return CMD_FAIL;
   3222     }
   3223 
   3224     if ((running = soc_sram_scan_running(unit, &rate, &interval)) < 0) {
   3225         cli_out("soc_sram_scan_running %d: ERROR: %s\n",
   3226                 unit, soc_errmsg(running));
   3227         return CMD_FAIL;
   3228     }
   3229 
   3230     if (ARG_CNT(a) == 0) {
   3231         cli_out("%s: %s on unit %d\n",
   3232                 ARG_CMD(a), running ? "Running" : "Not running", unit);
   3233         cli_out("%s:   Interval: %d usec\n",
   3234                 ARG_CMD(a), interval);
   3235         cli_out("%s:   Rate: %d\n",
   3236                 ARG_CMD(a), rate);
   3237 
   3238         return CMD_OK;
   3239     }
   3240 
   3241     parse_table_init(unit, &pt);
   3242     parse_table_add(&pt, "Interval", PQ_INT | PQ_DFL, 0, &interval, 0);
   3243     parse_table_add(&pt, "Rate", PQ_INT | PQ_DFL, 0, &rate, 0);
   3244 
   3245     if (parse_arg_eq(a, &pt) < 0) {
   3246         cli_out("%s: Invalid argument: %s\n", ARG_CMD(a), ARG_CUR(a));
   3247         parse_arg_eq_done(&pt);
   3248         return CMD_FAIL;
   3249     }
   3250 
   3251     parse_arg_eq_done(&pt);
   3252 
   3253     if ((c = ARG_GET(a)) != NULL) {
   3254         if (sal_strcasecmp(c, "off") == 0) {
   3255             interval = 0;
   3256             rate = 0;
   3257         } else if (sal_strcasecmp(c, "on") == 0) {
   3258             interval = prev_sramscan_interval[unit];
   3259             rate = prev_sramscan_rate[unit];
   3260         } else {
   3261             return CMD_USAGE;
   3262         }
   3263     }
   3264 
   3265     if (interval == 0) {
   3266         sal_usecs_t prev_interval;
   3267         int prev_rate;
   3268 
   3269         rv = soc_sram_scan_running(unit, &prev_rate, &prev_interval);
   3270         if (rv < 0 || prev_rate <= 0) {
   3271             prev_rate = SOC_SRAMSCAN_RATE_DEFAULT;
   3272         }
   3273         if (rv < 0 || prev_interval <= 0) {
   3274             prev_interval = SOC_SRAMSCAN_INTERVAL_DEFAULT;
   3275         }
   3276         prev_sramscan_rate[unit] = prev_rate;
   3277         prev_sramscan_interval[unit] = prev_interval;
   3278 
   3279         if ((rv = soc_sram_scan_stop(unit)) < 0) {
   3280             cli_out("soc_sram_scan_stop %d: ERROR: %s\n",
   3281                     unit, soc_errmsg(rv));
   3282             return CMD_FAIL;
   3283         }
   3284 
   3285         cli_out("%s: Stopped on unit %d\n", ARG_CMD(a), unit);
   3286     } else {
   3287         if (0 == rate) {
   3288             cli_out("%s: Start fails since rate 0 is not supported!\n", ARG_CMD(a));
   3289             return CMD_FAIL;
   3290         }
   3291         if ((rv = soc_sram_scan_start(unit, rate, interval)) < 0) {
   3292             cli_out("soc_sram_scan_start %d: ERROR: %s\n",
   3293                     unit, soc_errmsg(rv));
   3294             return CMD_FAIL;
   3295         }
   3296         cli_out("%s: Started on unit %d\n", ARG_CMD(a), unit);
   3297     }
   3298     return CMD_OK;
   3299 }
   3300 
   3301 #endif /* BCM_SRAM_SCAN_SUPPORT */
   3302 
   3303 
   3304 #if defined(SER_TR_TEST_SUPPORT)
   3305 char cmd_esw_ser_usage[] =
   3306     "Usages:\n"
   3307 #ifdef COMPILER_STRING_CONST_LIMIT
   3308     "SER [options]\t"
   3309 #else
   3310     " SER INFO   (NOT YET IMPLEMENTED)\n"
   3311     " SER SHOW   (NOT YET IMPLEMENTED)\n"
   3312     " SER LOG [ID=<id>]\n"
   3313     "\tid argument is used to show specified SER log\n"
   3314     " SER INJECT memory=<memID> [Index=<Index>] [Pipe=pipe_x|pipe_y|"
   3315     "pipe0|pipe1|pipe2|pipe3|pipe4|pipe5|pipe6|pipe7] [Xor_bank=0|1]\n"
   3316     "\tpipe argument is allowed only in multi-pipe devices\n"
   3317     "\tXor_bank argument is used to insert error into XOR ram of XOR hash tables.\n"
   3318     " SER INJECT register=<regID> port=<portNum> [Index=<Index>]"
   3319     " [Pipe=pipe_x|pipe_y|pipe0|pipe1|pipe2|pipe3](NOT YET IMPLEMENTED\n"
   3320     "\tWith no optional parameters, Index will default to 0, and Pipe to"
   3321     " pipe_x(pipe0)\n"
   3322 #endif
   3323     ;
   3324 
   3325 /*
   3326  * Function:
   3327  *      cmd_esw_ser
   3328  * Purpose:
   3329  *      Entry point and argument parser for SER diag shell utilities
   3330  * Parameters:
   3331  *      unit    - (IN) Device Number
   3332  *      a       - (IN) A string of user input.  Only the first parameter will
   3333  *                     be used by this function.
   3334  * Returns:
   3335  *      CMD_OK if injection succeeds, CMD_USAGE if there is a problem with user
   3336  *      input, and CMD_FAIL if preconditions are not met or injection fails for
   3337  *      a reason not related to incorrect input.
   3338  */
   3339 cmd_result_t
   3340 esw_ser_inject(int unit, args_t *a) {
   3341     cmd_result_t rv = CMD_USAGE;
   3342     char *mem_name = "", *pipe_name = "";
   3343     int index, tcam_mask, i, idx_phy, xor_bank = 0;
   3344     uint32  flags = 0;
   3345     soc_block_t block = MEM_BLOCK_ANY;
   3346     soc_mem_t mem;
   3347     soc_pipe_select_t pipe = 0;
   3348     parse_table_t pt;
   3349     const char *allowed_pipe_name[] = {
   3350         "pipe_x",
   3351         "pipe_y",
   3352         "pipe0",
   3353         "pipe1",
   3354         "pipe2",
   3355         "pipe3",
   3356         "pipe4",
   3357         "pipe5",
   3358         "pipe6",
   3359         "pipe7",
   3360     };
   3361     const int pipe_num[] = {
   3362         SOC_PIPE_SELECT_X_COMMON,
   3363         SOC_PIPE_SELECT_Y_COMMON,
   3364         SOC_PIPE_SELECT_0,
   3365         SOC_PIPE_SELECT_1,
   3366         SOC_PIPE_SELECT_2,
   3367         SOC_PIPE_SELECT_3,
   3368         SOC_PIPE_SELECT_4,
   3369         SOC_PIPE_SELECT_5,
   3370         SOC_PIPE_SELECT_6,
   3371         SOC_PIPE_SELECT_7,
   3372     };
   3373     parse_table_init(unit, &pt);
   3374     parse_table_add(&pt, "Memory", PQ_STRING,
   3375                     SOC_MEM_NAME(unit,INVALIDm), &(mem_name), NULL);
   3376     parse_table_add(&pt, "Index", PQ_INT,
   3377                     (void *)0, &index, NULL);
   3378     parse_table_add(&pt, "Pipe", PQ_STRING,
   3379                     "pipe_x", &(pipe_name), NULL);
   3380     parse_table_add(&pt, "TCAM", PQ_BOOL,
   3381                     FALSE, &(tcam_mask), NULL);
   3382     parse_table_add(&pt, "idx_phy", PQ_BOOL,
   3383                     FALSE, &(idx_phy), NULL);
   3384     parse_table_add(&pt, "Xor_bank", PQ_BOOL,
   3385                     FALSE, &(xor_bank), NULL);
   3386 
   3387     if(parse_arg_eq(a, &pt) < 0) {
   3388         cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a));
   3389         parse_arg_eq_done(&pt);
   3390         return rv;
   3391     }
   3392 
   3393     if (!(parse_memory_name(unit,&(mem),mem_name,&block,0) >=0)) {
   3394         cli_out("Invalid memory selected.\n");
   3395         parse_arg_eq_done(&pt);
   3396         return rv;
   3397     }
   3398 
   3399     for (i = 0; i < COUNTOF(pipe_num); i++) {
   3400         if (!sal_strcasecmp(pipe_name, allowed_pipe_name[i])) {
   3401             pipe = pipe_num[i];
   3402             break;
   3403         }
   3404     }
   3405 
   3406     if (i == COUNTOF(pipe_num)) {
   3407         cli_out("Invalid pipe selected. Valid entries are:"
   3408                 " pipe_x, pipe_y, pipe0, pipe1, pipe2, pipe3"
   3409                 " pipe4, pipe5, pipe6, pipe7\n");
   3410         parse_arg_eq_done(&pt);
   3411         return rv;
   3412     }
   3413     if (!SOC_SUCCESS(soc_ser_inject_support(unit, mem, pipe))){
   3414         if (soc_ser_inject_support(unit,mem,pipe) == SOC_E_FAIL) {
   3415             cli_out("Injection is not supported because miscellaneous"
   3416                     " initializations have not yet been performed.\n"
   3417                     "Type 'init misc' to do so and try again.\n");
   3418         } else {
   3419             cli_out("The selected memory: %s is valid, but SER correction "
   3420                     "for it is not currently supported.\n", mem_name);
   3421         }
   3422         rv = CMD_FAIL;
   3423         parse_arg_eq_done(&pt);
   3424         return rv;
   3425     }
   3426     if (index < 0) {
   3427         cli_out("Invalid index selected");
   3428         parse_arg_eq_done(&pt);
   3429         return rv;
   3430     }
   3431     if(tcam_mask) {
   3432         flags |= SOC_INJECT_ERROR_TCAM_FLAG;
   3433     }
   3434     if (idx_phy) {
   3435         flags |= SOC_INJECT_ERROR_DONT_MAP_INDEX;
   3436     }
   3437     if (xor_bank) {
   3438         flags |= SOC_INJECT_ERROR_XOR_BANK;
   3439     }
   3440     if (SOC_FAILURE(soc_ser_inject_error(unit, flags, mem, pipe, block, index))) {
   3441         cli_out("Injection failed on %s at index %d %s.\n", mem_name, index,
   3442                 pipe_name);
   3443         rv = CMD_FAIL;
   3444     } else {
   3445         cli_out("Error injected on %s at index %d %s\n", mem_name, index,
   3446                 pipe_name);
   3447         rv = CMD_OK;
   3448     }
   3449 
   3450     parse_arg_eq_done(&pt);
   3451     return rv;
   3452 }
   3453 
   3454 /*
   3455  * Function:
   3456  *      cmd_esw_ser
   3457  * Purpose:
   3458  *      Entry point and argument parser for SER diag shell utilities
   3459  * Parameters:
   3460  *      unit    - (IN) Device Number
   3461  *      a       - (IN) A string of user input.  Only the first parameter will
   3462  *                     be used by this function.
   3463  * Returns:
   3464  *      CMD_OK if the command succeeds, CMD_USAGE if there is a problem with the
   3465  *       input from the user.  Other returns  of type cmd_result_t are possible
   3466  *       depending on the implementation of each utility.
   3467  */
   3468 cmd_result_t
   3469 cmd_esw_ser(int unit, args_t *a){
   3470     char* arg1;
   3471     int i, log_id = 1;
   3472     cmd_result_t rv = CMD_USAGE;
   3473     parse_table_t pt;
   3474     /* pipe argument is allowed only in multi-pipe devices */
   3475     for (i = 0; i < a->a_argc; i++) {
   3476          if (NUM_PIPE(unit) == 1) {
   3477              if (sal_strstr(a->a_argv[i], "pipe") != NULL) {
   3478                  return rv;
   3479              }
   3480          }
   3481     }
   3482     arg1 = ARG_GET(a);
   3483     if (arg1 != NULL && !sal_strcasecmp(arg1, "inject")) {
   3484         rv = esw_ser_inject(unit, a);
   3485     } else if (arg1 != NULL && !sal_strcasecmp(arg1, "info")) {
   3486         cli_out("Info option not yet implemented\n");
   3487         rv = CMD_NOTIMPL;
   3488     } else if (arg1 != NULL && !sal_strcasecmp(arg1, "show")) {
   3489         cli_out("Show option not yet implemented\n");
   3490         rv = CMD_NOTIMPL;
   3491     } else if (arg1 != NULL && !sal_strcasecmp(arg1, "log")) {
   3492         if (ARG_CNT(a) == 0) {
   3493             rv = soc_ser_log_print_all(unit);
   3494             if (rv != 0) {
   3495                 cli_out("Error: getting SER log failed %d!\n", rv);
   3496                 return CMD_USAGE;
   3497             }
   3498         } else {
   3499             parse_table_init(unit, &pt);
   3500             parse_table_add(&pt, "ID", PQ_INT, (void *)0, &log_id, NULL);
   3501 
   3502             if (parse_arg_eq(a, &pt) < 0) {
   3503                 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a));
   3504                 parse_arg_eq_done(&pt);
   3505                 return CMD_USAGE;
   3506             }
   3507 
   3508             if (log_id < 0) {
   3509                 cli_out("Invalid id selected!\n");
   3510                 parse_arg_eq_done(&pt);
   3511                 return CMD_USAGE;
   3512             }
   3513 
   3514             parse_arg_eq_done(&pt);
   3515 
   3516             rv = soc_ser_log_print_one(unit, log_id);
   3517             if (rv != 0) {
   3518                 cli_out("Error: getting SER log failed %d!\n", rv);
   3519                 return CMD_USAGE;
   3520             }
   3521         }
   3522     } else {
   3523         cli_out("Invalid mode selected.\n");
   3524     }
   3525     return rv;
   3526 }
   3527 
   3528 #endif /*defined(SER_TR_TEST_SUPPORT)*/
   3529 
   3530 void mem_watch_counter_init(int unit);
   3531 /*
   3532  * Function:
   3533  *     mem_watch_cb
   3534  * Purpose:
   3535  *     Call back function for memory snooping
   3536  * Parameters:
   3537  *     unit         - (IN)  BCM device number
   3538  *     mem          - (IN)  memory for snooping
   3539  *     flags        - (IN)  SOC_MEM_SNOOP_XXX flags
   3540  *     copyno       - (IN)  Memory block to read/write
   3541  *     index_min    - (IN)  First memory index to read/write
   3542  *     index_max    - (IN)  Last memory index to read/write
   3543  *     data_buffer  - (IN)  buffer of the entry to read/write
   3544  *     user_data    - (IN)  registered snooping user data
   3545  * Returns:
   3546  *     No return value
   3547  */
   3548 static void
   3549 mem_watch_cb(int unit, soc_mem_t mem, uint32 flags, int copyno, int index_min,
   3550              int index_max, void *data_buffer, void *user_data)
   3551 {
   3552     int i;
   3553 
   3554     if (INVALIDm == mem) {
   3555         cli_out("Invalid memory....\n");
   3556         return;
   3557     }
   3558 
   3559     if (index_max < index_min) {
   3560         cli_out("Wrong indexes ....\n");
   3561         return;
   3562     }
   3563     if (mem_count[unit] == NULL) {
   3564         mem_watch_counter_init(unit);
   3565     }
   3566 
   3567     if (SOC_MEM_SNOOP_WRITE_COUNT & flags) {
   3568         mem_count[unit][mem].wr_count_cur += (index_max - index_min + 1);
   3569     }
   3570 
   3571     if (SOC_MEM_SNOOP_READ_COUNT & flags) {
   3572         mem_count[unit][mem].rd_count_cur += (index_max - index_min + 1);
   3573     }
   3574 
   3575     if ((SOC_MEM_SNOOP_WRITE & flags)
   3576         || (SOC_MEM_SNOOP_READ & flags)) {
   3577 
   3578         if (NULL == data_buffer) {
   3579             cli_out("Buffer is NULL .... \n");
   3580             return;
   3581         }
   3582 
   3583         for (i = 0; i <= (index_max - index_min); i++) {
   3584             cli_out("Unit = %d, mem = %s (%d), copyno = %d index = %d, Entry - ",
   3585                     unit, SOC_MEM_NAME(unit, mem), mem, copyno, i + index_min);
   3586             soc_mem_entry_dump(unit,mem, (char *)data_buffer + i, BSL_LSS_CLI);
   3587         }
   3588         cli_out("\n");
   3589     }
   3590 
   3591     return;
   3592 }
   3593 
   3594 /*
   3595  * Function:
   3596  *     mem_watch_counter_init
   3597  * Purpose:
   3598  *     Allocates space and initializes memory counters
   3599  * Parameters:
   3600  *     unit - (IN)  BCM device number
   3601  * Returns:
   3602  *     No return value
   3603  */
   3604 void
   3605 mem_watch_counter_init(int unit)
   3606 {
   3607     soc_mem_t mem;
   3608 
   3609     mem_count[unit] = (mem_count_t*) sal_alloc(sizeof(mem_count_t) * NUM_SOC_MEM, "mem_count");
   3610     for (mem = 0; mem < NUM_SOC_MEM; mem++) {
   3611         if (!SOC_MEM_IS_VALID(unit, mem)) {
   3612             continue;
   3613         }
   3614         mem_count[unit][mem].rd_count_old = 0;
   3615         mem_count[unit][mem].rd_count_cur = 0;
   3616         mem_count[unit][mem].wr_count_old = 0;
   3617         mem_count[unit][mem].wr_count_cur = 0;
   3618     }
   3619     return;
   3620 }
   3621 
   3622 /*
   3623  * Function:
   3624  *     mem_watch_snoop_all
   3625  * Purpose:
   3626  *     Registers or unregisters a snooping call back for all memories
   3627  *     with the specific SOC_MEM_SNOOP_* flags
   3628  * Parameters:
   3629  *     unit   - (IN) BCM device number
   3630  *     flags  - (IN) SOC_MEM_SNOOP_* flags
   3631  *     regist - (IN) register or unregister
   3632  * Returns:
   3633  *     No return value
   3634  */
   3635 void
   3636 mem_watch_snoop_all(int unit, uint32 flags, int regist)
   3637 {
   3638     soc_mem_t mem;
   3639 
   3640     for (mem = 0; mem < NUM_SOC_MEM; mem++) {
   3641         if (!SOC_MEM_IS_VALID(unit, mem)) {
   3642             continue;
   3643         }
   3644         if (regist) {
   3645             soc_mem_snoop_register(unit, mem, flags, mem_watch_cb, NULL);
   3646         } else {
   3647             soc_mem_snoop_unregister(unit, mem, flags);
   3648         }
   3649     }
   3650     return;
   3651 }
   3652 
   3653 /*
   3654  * Function:
   3655  *     mem_watch_start
   3656  * Purpose:
   3657  *     Registers a snooping call back for all memories with
   3658  *     SOC_MEM_SNOOP_READ/WRITE_ALL flags
   3659  * Parameters:
   3660  *     unit - (IN)  BCM device number
   3661  * Returns:
   3662  *     No return value
   3663  */
   3664 void
   3665 mem_watch_start(int unit)
   3666 {
   3667     soc_mem_t mem;
   3668 
   3669     for (mem = 0; mem < NUM_SOC_MEM; mem++) {
   3670         if (!SOC_MEM_IS_VALID(unit, mem)) {
   3671             continue;
   3672         }
   3673         soc_mem_snoop_register(unit, mem, SOC_MEM_SNOOP_WRITE_COUNT
   3674                                | SOC_MEM_SNOOP_READ_COUNT,
   3675                                mem_watch_cb, NULL);
   3676     }
   3677     return;
   3678 }
   3679 
   3680 /*
   3681  * Function:
   3682  *    mem_watch_stop
   3683  * Purpose:
   3684  *     Reset snooping flags SOC_MEM_SNOOP_READ/WRITE_ALL for all memories
   3685  *
   3686  * Parameters:
   3687  *     unit  - (IN)  BCM device number
   3688  *     clear - (IN)  if TRUE, clear counters
   3689  * Returns:
   3690  *     No return value
   3691  */
   3692 static void
   3693 mem_watch_stop(int unit, uint8 clear) {
   3694     soc_mem_t mem;
   3695 
   3696     for (mem = 0; mem < NUM_SOC_MEM; mem++) {
   3697         if (!SOC_MEM_IS_VALID(unit, mem)) {
   3698             continue;
   3699         }
   3700         soc_mem_snoop_unregister(unit, mem, SOC_MEM_SNOOP_WRITE_COUNT
   3701                                  | SOC_MEM_SNOOP_READ_COUNT);
   3702         if (clear == TRUE) {
   3703             mem_count[unit][mem].rd_count_old = 0;
   3704             mem_count[unit][mem].rd_count_cur = 0;
   3705             mem_count[unit][mem].wr_count_old = 0;
   3706             mem_count[unit][mem].wr_count_cur = 0;
   3707         }
   3708     }
   3709     return;
   3710 }
   3711 
   3712 /*
   3713  * Function:
   3714  *     mem_watch_show
   3715  * Purpose:
   3716  *     Show memories that have been read/written
   3717  * Parameters:
   3718  *     unit      - (IN)  BCM device number
   3719  *     show_type - (IN)  config for which type should be showed:
   3720  *                          SOC_MEM_WATCH_SHOW_READ
   3721  *                          SOC_MEM_WATCH_SHOW_WRITE
   3722  *                          SOC_MEM_WATCH_SHOW_READ_WRITE
   3723  *     show_all  - (IN)  if TRUE: also show the memories where the delta of
   3724  *                       read/writes is 0 between 2 invocations of the
   3725  *                       command
   3726  * Returns:
   3727  *     No return value
   3728  * Notes:
   3729  *     mem_watch_start() should be called before calling this function
   3730  */
   3731 static void
   3732 mem_watch_show(int unit, uint32 show_type, uint8 show_all)
   3733 {
   3734     soc_mem_t mem;
   3735     uint32 rd_delta, wr_delta;
   3736 
   3737     mem = -1;
   3738     for (mem = 0; mem < NUM_SOC_MEM; mem++) {
   3739         if (!SOC_MEM_IS_VALID(unit, mem)) {
   3740             continue;
   3741         }
   3742 
   3743         if (!(SOC_MEM_SNOOP_WRITE_COUNT
   3744               & SOC_MEM_INFO(unit, mem).snoop_flags)
   3745             || !(SOC_MEM_SNOOP_READ_COUNT
   3746                  & SOC_MEM_INFO(unit, mem).snoop_flags)) {
   3747             cli_out("WARNING: Memory watch not started on %s\n",
   3748                     SOC_MEM_NAME(unit, mem));
   3749             continue;
   3750         }
   3751 
   3752         rd_delta = mem_count[unit][mem].rd_count_cur
   3753                    - mem_count[unit][mem].rd_count_old;
   3754 
   3755         wr_delta = mem_count[unit][mem].wr_count_cur
   3756                    - mem_count[unit][mem].wr_count_old;
   3757 
   3758         /* Only show momories that have counter update unless "show all" */
   3759         if (show_all == TRUE
   3760             || ((SOC_MEM_WATCH_SHOW_READ & show_type) && (rd_delta != 0))
   3761             || ((SOC_MEM_WATCH_SHOW_WRITE & show_type) && (wr_delta != 0)))
   3762         {
   3763             cli_out("%s ", SOC_MEM_NAME(unit, mem));
   3764         }
   3765 
   3766         if (SOC_MEM_WATCH_SHOW_READ & show_type) {
   3767             if (rd_delta == 0) {
   3768                 if (show_all == TRUE) {
   3769                     cli_out("Read count: %u 0 ",
   3770                             mem_count[unit][mem].rd_count_cur);
   3771                 }
   3772             } else {
   3773                 cli_out("Read count: %u +%u ",
   3774                         mem_count[unit][mem].rd_count_cur, rd_delta);
   3775                 if (mem_count[unit][mem].rd_count_cur
   3776                     < mem_count[unit][mem].rd_count_old) {
   3777                     cli_out("(wrap) ");
   3778                 }
   3779             }
   3780 
   3781             if (!(rd_delta == 0 && show_all == FALSE)) {
   3782                 mem_count[unit][mem].rd_count_old
   3783                 = mem_count[unit][mem].rd_count_cur;
   3784             }
   3785         }
   3786 
   3787         if (SOC_MEM_WATCH_SHOW_WRITE & show_type) {
   3788             if (wr_delta == 0) {
   3789                 if (show_all == TRUE) {
   3790                     cli_out("Write count: %u 0 ",
   3791                             mem_count[unit][mem].wr_count_cur);
   3792                 }
   3793             } else {
   3794                 cli_out("Write count: %u +%u ",
   3795                         mem_count[unit][mem].wr_count_cur, wr_delta);
   3796                 if (mem_count[unit][mem].wr_count_cur
   3797                     < mem_count[unit][mem].wr_count_old) {
   3798                     cli_out("(wrap) ");
   3799                 }
   3800             }
   3801 
   3802             if (!(wr_delta == 0 && show_all == FALSE)) {
   3803                 mem_count[unit][mem].wr_count_old
   3804                 = mem_count[unit][mem].wr_count_cur;
   3805             }
   3806         }
   3807 
   3808         if (show_all == TRUE
   3809             || ((SOC_MEM_WATCH_SHOW_READ & show_type) && (rd_delta != 0))
   3810             || ((SOC_MEM_WATCH_SHOW_WRITE & show_type) && (wr_delta != 0)))
   3811         {
   3812             cli_out("\n");
   3813         }
   3814     }
   3815     return;
   3816 }
   3817 
   3818 static soc_mem_t mem_last=0;
   3819 static 
   3820 int mem_skip(int unit, soc_mem_t mem)
   3821 {
   3822     if (!soc_mem_is_valid(unit, mem)) {
   3823         return 1;
   3824     }
   3825 #ifdef SABER2_DEBUG
   3826     if ((soc_mem_flags(unit, mem) & SOC_MEM_FLAG_READONLY) != 0) {
   3827         /*cli_out("skipping read only memory %s\n", SOC_MEM_NAME(unit,mem));*/
   3828          return 1; 
   3829     }
   3830     if ((soc_mem_flags(unit, mem) & SOC_MEM_FLAG_WRITEONLY) != 0) {
   3831         /*cli_out("skipping write only memory %s\n", SOC_MEM_NAME(unit,mem));*/
   3832          return 1; 
   3833     }
   3834     if ((soc_mem_flags(unit, mem) & SOC_MEM_FLAG_DEBUG) != 0) {
   3835         /*cli_out("skipping debug only memory %s\n", SOC_MEM_NAME(unit,mem));*/
   3836          return 1; 
   3837     }
   3838     if ((soc_mem_flags(unit, mem) & SOC_MEM_FLAG_SIGNAL) != 0) {
   3839         /*cli_out("skipping signal only memory %s\n", SOC_MEM_NAME(unit,mem));*/
   3840          return 1; 
   3841     }
   3842 #endif
   3843     /* People  can add chip specifi memory here */
   3844     if (SOC_IS_SABER2(unit)) {
   3845 #ifdef SABER2_DEBUG     
   3846         switch(mem) {
   3847         case IARB_ING_PHYSICAL_PORTm:
   3848              return 1;
   3849         default:
   3850              break;
   3851         }
   3852 #endif
   3853     }
   3854     return 0;
   3855 }
   3856 cmd_result_t
   3857 mem_first(int unit, args_t *a)
   3858 {
   3859     int count=0;
   3860     soc_mem_t mem;
   3861     for (mem = 0; mem < NUM_SOC_MEM; mem++) {
   3862         if (mem_skip(unit, mem)) {
   3863             continue;
   3864         }
   3865         /* cli_out("First Memory: %s \n", SOC_MEM_NAME(unit, mem)); */
   3866         var_set("mem_name", SOC_MEM_NAME(unit,mem), FALSE, FALSE);
   3867         var_set(SOC_MEM_NAME(unit,mem),"1", TRUE, FALSE);
   3868         mem_last = mem;
   3869         count++;
   3870         break;
   3871     }
   3872     for (mem = mem + 1 ; mem < NUM_SOC_MEM; mem++) {
   3873         if (mem_skip(unit, mem)) {
   3874             continue;
   3875         }
   3876         /* if Any left !! */
   3877         var_unset(SOC_MEM_NAME(unit,mem),TRUE, FALSE,FALSE);
   3878         count++;
   3879     }
   3880     var_set_integer("mem_count", count, FALSE, FALSE);
   3881     return CMD_OK;
   3882 }
   3883 cmd_result_t
   3884 mem_next(int unit, args_t *a)
   3885 {
   3886     soc_mem_t mem;
   3887 
   3888     var_unset(SOC_MEM_NAME(unit,mem_last),TRUE, FALSE,FALSE);
   3889     for (mem = mem_last + 1; mem < NUM_SOC_MEM; mem++) {
   3890         if (mem_skip(unit, mem)) {
   3891             continue;
   3892         }
   3893         /* cli_out("Next Memory: %s \n", SOC_MEM_NAME(unit, mem)); */
   3894         var_set("mem_name", SOC_MEM_NAME(unit,mem), FALSE, FALSE);
   3895         var_set(SOC_MEM_NAME(unit,mem),"1", TRUE, FALSE);
   3896         mem_last = mem;
   3897         return CMD_OK;
   3898     }
   3899     /* Actuall Not Required but better to have it for boundary check */
   3900     var_set("mem_name", "LAST_INVALID_MEMORY", FALSE, FALSE);
   3901     return CMD_OK;
   3902 }
   3903 
   3904 cmd_result_t
   3905 mem_watch(int unit, args_t *a)
   3906 {
   3907     soc_mem_t       mem;
   3908     char            *c, *memname, *subcmd;
   3909     int             copyno;
   3910     int             allmems = 0;
   3911     uint32          show_type;
   3912     uint8           show_all;
   3913 
   3914     if (!sh_check_attached(ARG_CMD(a), unit)) {
   3915         return CMD_FAIL;
   3916     }
   3917 
   3918     if (ARG_CNT(a) == 0) {
   3919         return CMD_USAGE;
   3920     }
   3921 
   3922     if (NULL == (c = ARG_GET(a))) {
   3923         return CMD_USAGE;
   3924     }
   3925 
   3926     subcmd = c;
   3927 
   3928     if (sal_strcasecmp(subcmd, "start") == 0) {
   3929         mem_watch_start(unit);
   3930         return CMD_OK;
   3931     }
   3932 
   3933     if (sal_strcasecmp(subcmd, "stop") == 0) {
   3934         if (NULL == (subcmd = ARG_GET(a))) {
   3935             mem_watch_stop(unit, FALSE);
   3936         } else if (sal_strcasecmp(subcmd, "clear") == 0) {
   3937             mem_watch_stop(unit, TRUE);
   3938         }
   3939         return CMD_OK;
   3940     }
   3941 
   3942     if (sal_strcasecmp(subcmd, "show") == 0) {
   3943         if (NULL == (subcmd = ARG_GET(a))) {
   3944             /* memwatch show */
   3945             show_type = SOC_MEM_WATCH_SHOW_READ_WRITE;
   3946             show_all = FALSE;
   3947         } else if (sal_strcasecmp(subcmd, "read") == 0) {
   3948             if (NULL == (subcmd = ARG_GET(a))) {
   3949                 /* memwatch show read */
   3950                 show_type = SOC_MEM_WATCH_SHOW_READ;
   3951                 show_all = FALSE;
   3952             } else if (sal_strcasecmp(subcmd, "all") == 0) {
   3953                 /* memwatch show read all */
   3954                 show_type = SOC_MEM_WATCH_SHOW_READ;
   3955                 show_all = TRUE;
   3956             } else {
   3957                 return CMD_FAIL;
   3958             }
   3959         } else if (sal_strcasecmp(subcmd, "write") == 0) {
   3960             if (NULL == (subcmd = ARG_GET(a))) {
   3961                 /* memwatch show write */
   3962                 show_type = SOC_MEM_WATCH_SHOW_WRITE;
   3963                 show_all = FALSE;
   3964             } else if (sal_strcasecmp(subcmd, "all") == 0) {
   3965                 /* memwatch show write all */
   3966                 show_type = SOC_MEM_WATCH_SHOW_WRITE;
   3967                 show_all = TRUE;
   3968             } else {
   3969                 return CMD_FAIL;
   3970             }
   3971         } else if (sal_strcasecmp(subcmd, "all") == 0) {
   3972             /* memwatch show all */
   3973             show_type = SOC_MEM_WATCH_SHOW_READ_WRITE;
   3974             show_all = TRUE;
   3975         } else {
   3976             return CMD_FAIL;
   3977         }
   3978 
   3979         mem_watch_show(unit, show_type, show_all);
   3980         return CMD_OK;
   3981     }
   3982 
   3983     if (sal_strcasecmp(c, "*") == 0) {
   3984         allmems = 1;
   3985     } else {
   3986         /* Deal with VIEW:MEMORY if applicable */
   3987         memname = sal_strstr(c, ":");
   3988         if (memname != NULL) {
   3989             memname++;
   3990         } else {
   3991             memname = c;
   3992         }
   3993 
   3994         if (sal_strcasecmp(memname, "delta") == 0) {
   3995             c = ARG_GET(a);
   3996             soc_mem_watch_set(unit, (c && (sal_strcasecmp(c, "on") == 0)) ? 1 : 0);
   3997             return CMD_OK;
   3998         }
   3999 
   4000         if (parse_memory_name(unit, &mem, memname, &copyno, 0) < 0) {
   4001             cli_out("ERROR: unknown table \"%s\"\n", c);
   4002             return CMD_FAIL;
   4003         }
   4004     }
   4005 
   4006     if (NULL == (c = ARG_GET(a))) {
   4007         return CMD_USAGE;
   4008     }
   4009 
   4010     if (sal_strcasecmp(c, "off") == 0) {
   4011         /* unregister single read/write call back */
   4012         if (allmems) {
   4013             mem_watch_snoop_all(unit, SOC_MEM_SNOOP_READ | SOC_MEM_SNOOP_WRITE,
   4014                                 FALSE);
   4015         } else {
   4016             soc_mem_snoop_unregister(unit, mem, SOC_MEM_SNOOP_READ
   4017                                      | SOC_MEM_SNOOP_WRITE);
   4018         }
   4019     } else if (sal_strcasecmp(c, "read") == 0) {
   4020         /* register callback with read flag */
   4021         if (allmems) {
   4022             mem_watch_snoop_all(unit, SOC_MEM_SNOOP_READ, TRUE);
   4023         } else {
   4024             soc_mem_snoop_register(unit, mem, SOC_MEM_SNOOP_READ,
   4025                                    mem_watch_cb, NULL);
   4026         }
   4027     } else if (sal_strcasecmp(c, "write") == 0) {
   4028         /* register callback with write flag */
   4029         if (allmems) {
   4030             mem_watch_snoop_all(unit, SOC_MEM_SNOOP_WRITE, TRUE);
   4031         } else {
   4032             soc_mem_snoop_register(unit, mem, SOC_MEM_SNOOP_WRITE,
   4033                                    mem_watch_cb, NULL);
   4034         }
   4035     } else {
   4036         return CMD_USAGE;
   4037     }
   4038 
   4039     return CMD_OK;
   4040 }
   4041