ledproc.c (49941B)
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 * File: ledproc.c 8 * Purpose: LED Processor Support 9 */ 10 11 #include <assert.h> 12 #include <sal/core/libc.h> 13 #include <shared/bsl.h> 14 #include <bcm/error.h> 15 #include <bcm/link.h> 16 #include <soc/types.h> 17 #include <appl/diag/system.h> 18 19 #ifdef BCM_CMICM_SUPPORT 20 #include <soc/cmicm.h> 21 #endif 22 23 #ifdef BCM_CMICX_SUPPORT 24 #include <shared/cmicfw/cmicx_led.h> 25 #endif /* BCM_CMICX_SUPPORT */ 26 27 #ifdef BCM_PETRA_SUPPORT 28 #include <soc/dpp/mbcm.h> 29 #endif 30 31 #ifdef BCM_TRIDENT_SUPPORT 32 #define TRIDENT_LEDUP_MAX 2 33 #define TRIDENT_LEDUP0_PORT_MAX 36 34 #define TRIUMPH3_LEDUP0_PORT_MAX 52 35 #define HELIX4_LEDUP_PORT_MAX 64 36 #define TRIDENT2_LEDUP0_PORT_MAX 64 37 #define APACHE_LEDUP_PORT_MAX 36 38 #define MONTEREY_LEDUP_PORT_MAX 64 39 #endif /* BCM_TRIDENT_SUPPORT */ 40 41 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_SAND_SUPPORT) 42 #define CMICD_V2_LEDUP_MAX 3 43 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_PETRA_SUPPORT */ 44 45 #ifdef BCM_TOMAHAWK2_SUPPORT 46 #define CMICD_V4_LEDUP_MAX 5 47 #endif /* BCM_TOMAHAWK2_SUPPORT */ 48 49 #ifdef BCM_SABER2_SUPPORT 50 #define SABER2_LEDUP_MAX 2 51 #endif 52 53 #ifdef BCM_GREYHOUND2_SUPPORT 54 #define GREYHOUND2_LEDUP_MAX 2 55 #define GREYHOUND2_LEDUP0_PORT_MAX 57 56 #endif /* BCM_GREYHOUND2_SUPPORT */ 57 58 typedef struct led_info_s { 59 uint32 ctrl; 60 uint32 status; 61 uint32 pram_base; 62 uint32 dram_base; 63 } led_info_t; 64 65 static led_info_t led_info_gen[] = { 66 {CMIC_LED_CTRL,CMIC_LED_STATUS,CMIC_LED_PROGRAM_RAM_BASE, 67 CMIC_LED_DATA_RAM_BASE} 68 }; 69 70 #ifdef BCM_TRIDENT_SUPPORT 71 static led_info_t led_info_tri[] = { 72 {CMICE_LEDUP0_CTRL,CMICE_LEDUP0_STATUS,CMICE_LEDUP0_PROGRAM_RAM_BASE, 73 CMICE_LEDUP0_DATA_RAM_BASE}, 74 {CMICE_LEDUP1_CTRL,CMICE_LEDUP1_STATUS,CMICE_LEDUP1_PROGRAM_RAM_BASE, 75 CMICE_LEDUP1_DATA_RAM_BASE} 76 }; 77 #endif /* BCM_TRIDENT_SUPPORT */ 78 79 #ifdef BCM_CMICM_SUPPORT 80 static led_info_t led_info_cmicm[] = { 81 {CMIC_LEDUP0_CTRL_OFFSET,CMIC_LEDUP0_STATUS_OFFSET,CMIC_LEDUP0_PROGRAM_RAM_OFFSET, 82 CMIC_LEDUP0_DATA_RAM_OFFSET}, 83 {CMIC_LEDUP1_CTRL_OFFSET,CMIC_LEDUP1_STATUS_OFFSET,CMIC_LEDUP1_PROGRAM_RAM_OFFSET, 84 CMIC_LEDUP1_DATA_RAM_OFFSET} 85 }; 86 #endif /* BCM_CMICM_SUPPORT */ 87 88 /* 89 * Change 'led info' clause: This was for BCM_PETRA_SUPPORT (Arad and Jericho 90 * family)and was changed to (BCM_PETRA_SUPPORT || BCM_DNX_SUPPORT) (Jericho-2 family, DNX) to 91 * enable using a similar configuration file (For DNX: dnx.doc) 92 * In the future, this may be changed as per actual DNX board details. 93 */ 94 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT) 95 static led_info_t led_info_cmicd_v2[] = { 96 {CMIC_LEDUP0_CTRL_OFFSET,CMIC_LEDUP0_STATUS_OFFSET,CMIC_LEDUP0_PROGRAM_RAM_OFFSET, 97 CMIC_LEDUP0_DATA_RAM_OFFSET}, 98 {CMIC_LEDUP1_CTRL_OFFSET,CMIC_LEDUP1_STATUS_OFFSET,CMIC_LEDUP1_PROGRAM_RAM_OFFSET, 99 CMIC_LEDUP1_DATA_RAM_OFFSET}, 100 {CMIC_LEDUP2_CTRL_OFFSET,CMIC_LEDUP2_STATUS_OFFSET,CMIC_LEDUP2_PROGRAM_RAM_OFFSET, 101 CMIC_LEDUP2_DATA_RAM_OFFSET} 102 }; 103 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_PETRA_SUPPORT */ 104 105 #ifdef BCM_TOMAHAWK2_SUPPORT 106 static led_info_t led_info_cmicd_v4[] = { 107 {CMIC_LEDUP0_CTRL_OFFSET,CMIC_LEDUP0_STATUS_OFFSET,CMIC_LEDUP0_PROGRAM_RAM_OFFSET, 108 CMIC_LEDUP0_DATA_RAM_OFFSET}, 109 {CMIC_LEDUP1_CTRL_OFFSET,CMIC_LEDUP1_STATUS_OFFSET,CMIC_LEDUP1_PROGRAM_RAM_OFFSET, 110 CMIC_LEDUP1_DATA_RAM_OFFSET}, 111 {CMIC_LEDUP2_CTRL_OFFSET,CMIC_LEDUP2_STATUS_OFFSET,CMIC_LEDUP2_PROGRAM_RAM_OFFSET, 112 CMIC_LEDUP2_DATA_RAM_OFFSET}, 113 {CMIC_LEDUP3_CTRL_OFFSET,CMIC_LEDUP3_STATUS_OFFSET,CMIC_LEDUP3_PROGRAM_RAM_OFFSET, 114 CMIC_LEDUP3_DATA_RAM_OFFSET}, 115 {CMIC_LEDUP4_CTRL_OFFSET,CMIC_LEDUP4_STATUS_OFFSET,CMIC_LEDUP4_PROGRAM_RAM_OFFSET, 116 CMIC_LEDUP4_DATA_RAM_OFFSET} 117 }; 118 #endif /* BCM_TOMAHAWK2_SUPPORT */ 119 120 #ifdef BCM_CMICX_SUPPORT 121 #define CMICX_LED 1 122 #endif /* BCM_CMICX_SUPPORT */ 123 124 /* 125 * Function: ledproc_load 126 * Purpose: Load a program into the LED microprocessor from a buffer 127 * Parameters: unit - StrataSwitch unit # 128 * program - Array of up to 256 program bytes 129 * bytes - Number of bytes in array 130 * Notes: Also clears the LED processor data RAM from 0x80-0xff 131 * so the LED program has a known state at startup. 132 */ 133 134 STATIC void 135 ledproc_load(int unit, uint8 *program, int bytes, led_info_t *led_ptr) 136 { 137 int offset; 138 139 for (offset = 0; offset < CMIC_LED_PROGRAM_RAM_SIZE; offset++) { 140 soc_pci_write(unit, 141 led_ptr->pram_base + CMIC_LED_REG_SIZE * offset, 142 (offset < bytes) ? (uint32) program[offset] : 0); 143 } 144 145 for (offset = 0x80; offset < CMIC_LED_DATA_RAM_SIZE; offset++) { 146 soc_pci_write(unit, 147 led_ptr->dram_base + CMIC_LED_REG_SIZE * offset, 148 0); 149 } 150 } 151 152 #ifndef NO_FILEIO 153 STATIC cmd_result_t 154 ledproc_load_fp(int unit, char *cmd, char *file, FILE *f, 155 led_info_t *led_ptr) 156 /* 157 * Function: ledproc_load_fp 158 * Purpose: Load a program into the LED microprocessor from a file 159 * Parameters: unit - StrataSwitch unit # 160 * cmd - Name of command for error printing 161 * file - Name of file for error printing 162 * f - Open stdio file file pointer containing program 163 * Returns: CMD_XXX 164 * 165 * Notes: File format (ASCII FILE) 166 * 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 167 * 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 168 * ... for a total of 256 bytes, white space ignored. 169 */ 170 { 171 uint8 program[CMIC_LED_PROGRAM_RAM_SIZE]; 172 char input[256], *cp = NULL, *error = NULL; 173 int bytes = 0, line = 0; 174 int offset_size = 0; 175 176 while (!error && (cp = sal_fgets(input, sizeof(input) - 1, f))) { 177 line++; 178 179 while (*cp) { 180 if (isspace((unsigned)(*cp))) { /* Skip whitespace */ 181 cp++; 182 } else { 183 if (!isxdigit((unsigned)*cp) || 184 !isxdigit((unsigned)*(cp+1))) { 185 error = "Invalid hex digit"; 186 break; 187 } 188 offset_size = sizeof(program); 189 if (bytes >= offset_size) { 190 error = "Program memory exceeded"; 191 break; 192 } 193 program[bytes++] = (xdigit2i(*cp) << 4) | xdigit2i(*(cp + 1)); 194 cp += 2; 195 } 196 } 197 } 198 199 if (error) { 200 cli_out("%s: Error loading file %s line %d: %s\n", 201 cmd, file, line, error); 202 return(CMD_FAIL); 203 } 204 205 cli_out("%s: Loading %d bytes into LED program memory\n", 206 cmd, bytes); 207 208 ledproc_load(unit, program, bytes,led_ptr); 209 210 return(CMD_OK); 211 } 212 #endif /* NO_FILEIO */ 213 /* 214 * Function: ledproc_load_args 215 * Purpose: Load a program into the LED microprocessor from an args_t 216 * Parameters: unit - StrataSwitch unit # 217 * a - Remainder of command line containing raw hex data 218 * Returns: CMD_XXX 219 * Notes: Input strings are concatenated and parsed the 220 * same way as ledproc_load_fp. 221 */ 222 STATIC cmd_result_t 223 ledproc_load_args(int unit, args_t *a, led_info_t *led_ptr) 224 /* 225 * Notes: Args format 226 * 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 227 * 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 228 * ... 229 * White space optional. 230 */ 231 { 232 uint8 program[CMIC_LED_PROGRAM_RAM_SIZE]; 233 int bytes = 0; 234 char *cp; 235 int offset_size = 0; 236 237 sal_memset(program, 0, sizeof (program)); 238 239 while ((cp = ARG_GET(a)) != NULL) { 240 while (*cp) { 241 if (isspace((int)(*cp))) { 242 cp++; 243 } else { 244 if (!isxdigit((unsigned)*cp) || 245 !isxdigit((unsigned)*(cp+1))) { 246 cli_out("%s: Invalid character\n", ARG_CMD(a)); 247 return(CMD_FAIL); 248 } 249 250 offset_size = sizeof(program); 251 if (bytes >= offset_size) { 252 cli_out("%s: Program memory exceeded\n", ARG_CMD(a)); 253 return(CMD_FAIL); 254 } 255 program[bytes++] = (xdigit2i(*cp) << 4) | xdigit2i(*(cp + 1)); 256 cp += 2; 257 } 258 } 259 } 260 261 ledproc_load(unit, program, bytes,led_ptr); 262 263 return(CMD_OK); 264 } 265 266 /* 267 * Function: ledproc_linkscan_cb 268 * Purpose: Call back function for LEDs on link change. 269 * Parameters: unit - unit number 270 * port - callback from this port 271 * info - pointer to structure giving status 272 * Returns: nothing 273 * Notes: Each port has one byte of data at address (0x80 + portnum). 274 * For devices which fall under soc_feature_led_data_offset_a0 275 * the offset begins from 0xa0 instead of 0x80 276 * In each byte, bit 0 is used for link status. 277 * In each byte, bit 7 is used for turbo mode indication. 278 */ 279 STATIC void 280 ledproc_linkscan_cb(int unit, soc_port_t port, bcm_port_info_t *info) 281 { 282 uint32 portdata = 0; 283 int byte = LS_LED_DATA_OFFSET + port; 284 led_info_t *led_info; 285 int led_ix; 286 soc_info_t *si; 287 int phy_port = 0; /* physical port number */ 288 289 si = &SOC_INFO(unit); 290 led_info = led_info_gen; 291 led_ix = 0; 292 293 #ifdef BCM_TUCANA_SUPPORT 294 if (SOC_IS_TUCANA(unit)) { 295 byte = LS_TUCANA_LED_DATA_OFFSET + port; 296 } 297 #endif 298 299 #ifdef BCM_RAVEN_SUPPORT 300 if (SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit)) { 301 byte = LS_RAVEN_LED_DATA_OFFSET + port; 302 } 303 #endif 304 305 #ifdef BCM_RAPTOR1_SUPPORT 306 if (SOC_IS_RAPTOR(unit)) { 307 byte = LS_RAPTOR_LED_DATA_OFFSET + port; 308 } 309 #endif 310 311 #ifdef BCM_TRIUMPH_SUPPORT 312 if (SOC_IS_TRIUMPH(unit)) { 313 byte = LS_TR_VL_LED_DATA_OFFSET + port; 314 } 315 #endif 316 317 #ifdef BCM_VALKYRIE_SUPPORT 318 if (SOC_IS_VALKYRIE(unit)) { 319 byte = LS_TR_VL_LED_DATA_OFFSET + port; 320 } 321 #endif 322 323 #ifdef BCM_SCORPION_SUPPORT 324 if (SOC_IS_SC_CQ(unit)) { 325 byte = LS_SC_CQ_LED_DATA_OFFSET + port; 326 } 327 #endif 328 329 if (soc_feature(unit, soc_feature_led_data_offset_a0)) { 330 byte = LS_LED_DATA_OFFSET_A0 + port; 331 } 332 333 if (soc_feature(unit, soc_feature_logical_port_num)) { 334 if (port >= 0 && port < SOC_MAX_NUM_PORTS) { /* safety check */ 335 phy_port = si->port_l2p_mapping[port]; 336 if (soc_feature(unit, soc_feature_led_data_offset_a0)) { 337 byte = LS_LED_DATA_OFFSET_A0 + phy_port; 338 } else { 339 byte = LS_LED_DATA_OFFSET + phy_port; 340 } 341 } 342 } 343 344 #ifdef BCM_CMICX_SUPPORT 345 if (soc_feature(unit, soc_feature_cmicx)) { 346 #if CMICX_LED 347 soc_led_link_status_t led_link_sts; 348 soc_led_port_speed_t led_speed; 349 int speed = 0, rv = BCM_E_NONE; 350 351 led_link_sts.link_sts = (info->linkstatus == BCM_PORT_LINK_STATUS_UP); 352 if (soc_feature(unit, soc_feature_logical_port_num)) { 353 led_link_sts.port = phy_port; 354 } else { 355 led_link_sts.port = port; 356 } 357 #if defined (BCM_ESW_SUPPORT) || defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT) 358 #ifdef BCM_TRIDENT3_SUPPORT 359 /* LED processor captures the state for the two managment ports in 360 * entries 128 and 130 in the accumulation RAM. The first management 361 * port will always have port number [66,129] in the SDK. This is 362 * decremented by one in the LED firmware, so there is no issue. The 363 * second management port reuses port [130,128] in the SDK, which can 364 * also be used for PM31, subport 3. This code differentiates that 365 * special case and provides the needed por number for the second 366 * management port 367 */ 368 369 if (SOC_IS_TRIDENT3X(unit) && port == 130) { 370 if (IS_MANAGEMENT_PORT(unit, port)) { 371 led_link_sts.port = 131; 372 } 373 } 374 #endif /* BCM_TRIDENT3_SUPPORT */ 375 376 #ifdef BCM_TOMAHAWK3_SUPPORT 377 378 /* Mapping xe1 (physical port 258) link status 379 * to accumulation entry of physical port 259. 380 * User should get port status/speed of xe1 (physical port 258) from the 381 * entry of physical port 259 in accumulation RAM and speed array. 382 */ 383 if (SOC_IS_TOMAHAWK3(unit) && phy_port == 258) { 384 led_link_sts.port = 259; 385 } 386 #endif /* BCM_TOMAHAWK3_SUPPORT */ 387 388 soc_cmicx_led_link_status(unit, &led_link_sts); 389 #endif /* BCM_ESW_SUPPORT || BCM_DNXF_SUPPORT */ 390 /* Send port speed info when link goes UP */ 391 if (led_link_sts.link_sts) { 392 /* Use logical port number here */ 393 #if defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT) 394 if (SOC_IS_DNX(unit)) { 395 bcm_port_resource_t resource; 396 rv = bcm_port_resource_get(unit, port, &resource); 397 speed = resource.speed; 398 } else 399 #endif 400 { 401 rv = bcm_port_speed_get(unit, port, &speed); 402 } 403 if (rv != BCM_E_NONE) { 404 cli_out("Error rv %d: Unable to get speed for port %d\n", rv, port); 405 } 406 led_speed.port = led_link_sts.port; 407 led_speed.speed = speed; 408 if (led_speed.speed) { 409 #if defined (BCM_ESW_SUPPORT) || defined(BCM_DNXF_SUPPORT) 410 soc_cmicx_led_speed(unit, &led_speed); 411 #endif /* BCM_ESW_SUPPORT || BCM_DNXF_SUPPORT */ 412 } 413 } 414 415 #endif /* CMICX_LED */ 416 417 /* CMICx-LED port update complete. */ 418 return; 419 } 420 #endif /* BCM_CMICX_SUPPORT */ 421 422 423 #ifdef BCM_PETRA_SUPPORT 424 if (SOC_IS_QAX(unit)) { 425 uint32 physical_phy; 426 bcm_error_t ret; 427 if (port < 0 || port >= SOC_MAX_NUM_PORTS) { /* safety check */ 428 return; 429 } 430 if (soc_feature(unit, soc_feature_logical_port_num)) { 431 ret = MBCM_DPP_DRIVER_CALL(unit, mbcm_dpp_qsgmii_offsets_remove, 432 (unit, phy_port , &physical_phy)); 433 if (ret != BCM_E_NONE) { 434 return; 435 } 436 phy_port = physical_phy; 437 byte = LS_LED_DATA_OFFSET_A0 + phy_port; 438 } 439 } else if (SOC_IS_JERICHO(unit)) { 440 441 if (port < 0 || port >= SOC_MAX_NUM_PORTS) { /* safety check */ 442 return; 443 } 444 445 /* LED processor 0 - handles ports 1-24. port 1 resides in index 1 in data ram */ 446 /* LED processor 1 - handles ports 25-84. port 25 resides in index 1 in data ram */ 447 /* LED processor 2 - handles ports 85-144. port 85 resides in index 1 in data ram */ 448 449 if (soc_feature(unit, soc_feature_logical_port_num)) { 450 if (phy_port <= 24) { 451 led_ix = 0; 452 } else if (phy_port >= 25 && phy_port <= 84) { 453 led_ix = 1; 454 phy_port -= 24; 455 } else if (phy_port > 84) { 456 led_ix = 2; 457 phy_port -= 84; 458 } 459 byte = LS_LED_DATA_OFFSET_A0 + phy_port; 460 } 461 462 } 463 #endif /* BCM_PETRA_SUPPORT */ 464 465 466 #ifdef BCM_TRIDENT_SUPPORT 467 if (SOC_IS_TD_TT(unit) || SOC_IS_TRIUMPH3(unit)) { 468 /* trident first 36 ports in ledproc0, the other 36 ports in ledproc1 */ 469 /* triumph3 first 52 ports are in ledproc0, the other ports are in ledproc1 */ 470 /* Helix4: Port 1-48 and 53-64 are in ledproc0, rest are in ledproc1 - Adjustment made later */ 471 int ledup0_pmax = SOC_IS_TD_TT(unit) ? TRIDENT_LEDUP0_PORT_MAX : 472 (SOC_IS_HELIX4(unit) ? HELIX4_LEDUP_PORT_MAX : TRIUMPH3_LEDUP0_PORT_MAX); 473 474 if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit)) && !SOC_IS_APACHE(unit)) { 475 ledup0_pmax = TRIDENT2_LEDUP0_PORT_MAX; 476 } 477 478 if (SOC_IS_APACHE(unit)) { 479 480 ledup0_pmax = APACHE_LEDUP_PORT_MAX; 481 } 482 483 if (SOC_IS_MONTEREY(unit)) { 484 485 ledup0_pmax = MONTEREY_LEDUP_PORT_MAX; 486 } 487 if (port < 0 || port >= SOC_MAX_NUM_PORTS) { /* safety check */ 488 return; 489 } 490 491 led_info = led_info_tri; 492 phy_port = si->port_l2p_mapping[port]; 493 494 if ((phy_port > ledup0_pmax) && (!SOC_IS_TOMAHAWKX(unit))) { 495 /* For Helix4 this condition should never be true */ 496 phy_port -= ledup0_pmax; 497 led_ix = 1; 498 } 499 500 if (soc_feature(unit, soc_feature_led_data_offset_a0)) { 501 if (SOC_IS_HELIX4(unit)) { 502 if (phy_port > 48 && phy_port < 53) { 503 led_ix = 1; 504 phy_port -= 48; 505 } else if (phy_port > 52) { 506 phy_port -= 4; 507 } 508 byte = LS_LED_DATA_OFFSET_A0 + phy_port; 509 } else if (SOC_IS_TRIUMPH3(unit)) { 510 if (led_ix) { 511 byte = LS_LED_DATA_OFFSET_A0 + phy_port + 4; 512 } else { 513 byte = LS_LED_DATA_OFFSET_A0 + phy_port; 514 if (phy_port == 37) { 515 byte += 12; 516 } else if (phy_port >= 38) { 517 byte -= 4; 518 } 519 } 520 } else if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit)) && !SOC_IS_APACHE(unit) && !SOC_IS_MONTEREY(unit)) { 521 int i, skip_count = 0; 522 for (i=1; i<phy_port; i++) { 523 skip_count += ((si->port_p2l_mapping[i+(led_ix*TRIDENT2_LEDUP0_PORT_MAX)] == -1) ? 1: 0); 524 } 525 byte = LS_LED_DATA_OFFSET_A0 + phy_port - skip_count; 526 if (SOC_IS_TRIDENT2(unit)) { 527 /*offset begin from 0xA0 */ 528 byte -= 1; 529 } 530 } else if (SOC_IS_APACHE(unit)) { 531 byte = LS_LED_DATA_OFFSET_A0 + phy_port - 1; /* Start from the A0 offset */ 532 if (phy_port > 36 && !SOC_IS_MONTEREY(unit)) { /* Ports 37-72 in ledproc1 */ 533 phy_port -= APACHE_LEDUP_PORT_MAX; 534 led_ix = 1; 535 } 536 } else 537 #ifdef BCM_TOMAHAWK_SUPPORT 538 if (SOC_IS_TOMAHAWK(unit)) { 539 /* Tomahawk: Port 1-32 and 97-128 are in ledproc0 540 * Port 33-96 are in ledproc1 541 * Port 129 & 131 are in ledproc2 542 */ 543 if (phy_port > 32 && phy_port < 97) { 544 led_ix = 1; 545 phy_port -= 32; 546 } else if (phy_port == 129 ) { 547 led_ix = 2; 548 phy_port = 1; 549 } else if (phy_port == 131 ) { 550 led_ix = 2; 551 phy_port = 2; 552 } else if (phy_port > 32) { 553 phy_port -= 64; 554 } 555 byte = LS_LED_DATA_OFFSET_A0 + phy_port - 1; 556 } else 557 #ifdef BCM_TOMAHAWK2_SUPPORT 558 if (SOC_IS_TOMAHAWK2(unit)) { 559 if (259 == phy_port) { 560 led_ix = (phy_port - 1) / 64; 561 byte = LS_LED_DATA_OFFSET_A0 + 1; 562 } else { 563 led_ix = (phy_port - 1) / 64; 564 phy_port = (phy_port - 1) % 64 + 1; 565 byte = LS_LED_DATA_OFFSET_A0 + phy_port - 1; 566 } 567 } else 568 #endif /* BCM_TOMAHAWK2_SUPPORT */ 569 #endif /* BCM_TOMAHAWK_SUPPORT */ 570 { 571 byte = LS_LED_DATA_OFFSET_A0 + phy_port; 572 } 573 } else { 574 byte = LS_LED_DATA_OFFSET + phy_port; 575 } 576 } 577 #endif /* BCM_TRIDENT_SUPPORT */ 578 579 #ifdef BCM_GREYHOUND2_SUPPORT 580 if (SOC_IS_GREYHOUND2(unit)) { 581 if (phy_port > GREYHOUND2_LEDUP0_PORT_MAX) { 582 led_ix = 1; 583 /* ledup1 physical port shifted value is GREYHOUND2_LEDUP0_PORT_MAX - 1. */ 584 phy_port -= (GREYHOUND2_LEDUP0_PORT_MAX - 1); 585 } 586 byte = LS_LED_DATA_OFFSET_A0 + phy_port; 587 } 588 #endif /* BCM_GREYHOUND2_SUPPORT */ 589 590 #ifdef BCM_CMICM_SUPPORT 591 if (soc_feature(unit, soc_feature_cmicm)) { 592 led_info = led_info_cmicm; 593 } 594 #endif /* BCM_CMICM_SUPPORT */ 595 596 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_PETRA_SUPPORT) 597 if (soc_feature(unit, soc_feature_led_cmicd_v2)) { 598 led_info = led_info_cmicd_v2; 599 } 600 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_PETRA_SUPPORT */ 601 602 #ifdef BCM_TOMAHAWK2_SUPPORT 603 if (soc_feature(unit, soc_feature_led_cmicd_v4)) { 604 led_info = led_info_cmicd_v4; 605 } 606 #endif /* BCM_TOMAHAWK2_SUPPORT */ 607 608 /* coverity[OVERRUN-LOCAL: FALSE] */ 609 portdata = soc_pci_read(unit, 610 led_info[led_ix].dram_base + CMIC_LED_REG_SIZE * byte); 611 612 if (info->linkstatus == BCM_PORT_LINK_STATUS_UP) { 613 portdata |= 0x01; 614 } else { 615 portdata &= ~0x01; 616 } 617 618 portdata &= ~0x80; 619 620 soc_pci_write(unit, led_info[led_ix].dram_base + CMIC_LED_REG_SIZE * byte, 621 portdata); 622 } 623 624 625 char ledproc_usage[] = 626 "Parameters: [num] [status | start | stop | load <file.hex> |\n\t" 627 " [auto [on | off]] | prog <hexdata> | dump\n\t" 628 "Load the LED Microprocessor with the program specified in <file.hex>.\n\t" 629 "Option 'auto' turns on (by default) or off automatic linkscan\n\t" 630 " updates to the LED processor.\n\t" 631 "Option 'num' selects the specific LED processor. The default is 0\n"; 632 633 cmd_result_t 634 ledproc_cmd(int unit, args_t *a) 635 /* 636 * Function: sh_led 637 * Purpose: Load a led program and start it. 638 * Parameters: unit - unit 639 * a - args, each of the files to be displayed. 640 * Returns: CMD_OK/CMD_FAIL/CMD_USAGE 641 */ 642 { 643 VOL cmd_result_t rv = CMD_OK; 644 #ifndef NO_FILEIO 645 #ifndef NO_CTRL_C 646 jmp_buf ctrl_c; 647 #endif 648 FILE * volatile f = NULL; 649 #endif 650 char *c; 651 volatile uint32 led_ctrl, led_status; 652 volatile int auto_on; 653 int led_max; 654 led_info_t *led_info; 655 led_info_t *led_info_cur; 656 int ix; 657 int phy_port_map = 0, led_up_instance = 0; 658 int skip_force_link_check = FALSE; 659 #if (defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_PETRA_SUPPORT)) && defined(BCM_WARM_BOOT_SUPPORT) 660 uint32 boot_flags; 661 #endif 662 if (!sh_check_attached("ledproc", unit)) { 663 return(CMD_FAIL); 664 } 665 666 if (!soc_feature(unit, soc_feature_led_proc)) { 667 cli_out("%s: LED Micro-controller not available on %s\n", 668 ARG_CMD(a), 669 soc_dev_name(unit)); 670 return(CMD_FAIL); 671 } 672 673 led_info = led_info_gen; 674 led_max = 1; 675 676 #ifdef BCM_TRIDENT_SUPPORT 677 if (SOC_IS_TD_TT(unit) || SOC_IS_TRIUMPH3(unit)) { 678 led_info = led_info_tri; 679 led_max = TRIDENT_LEDUP_MAX; 680 } 681 #endif /* BCM_TRIDENT_SUPPORT */ 682 683 #ifdef BCM_GREYHOUND2_SUPPORT 684 if (SOC_IS_GREYHOUND2(unit)){ 685 led_max = GREYHOUND2_LEDUP_MAX; 686 } 687 #endif /* BCM_GREYHOUND2_SUPPORT */ 688 689 #ifdef BCM_CMICM_SUPPORT 690 if (soc_feature(unit, soc_feature_cmicm)) { 691 led_info = led_info_cmicm; 692 #if defined(BCM_SABER2_SUPPORT) 693 led_max = SABER2_LEDUP_MAX; 694 #endif 695 } 696 #endif /* BCM_CMICM_SUPPORT */ 697 698 /* 699 * Change 'led info' clause: This was for BCM_PETRA_SUPPORT (Arad and Jericho 700 * family)and was changed to (BCM_PETRA_SUPPORT || BCM_DNX_SUPPORT) (Jericho-2 family, DNX) to 701 * enable using a similar configuration file (For DNX: dnx.doc) 702 * In the future, this may be changed as per actual DNX board details. 703 */ 704 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT) 705 if(soc_feature(unit, soc_feature_led_cmicd_v2)) { 706 led_info = led_info_cmicd_v2; 707 led_max = CMICD_V2_LEDUP_MAX; 708 } 709 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_PETRA_SUPPORT */ 710 711 #ifdef BCM_TOMAHAWK2_SUPPORT 712 if(soc_feature(unit, soc_feature_led_cmicd_v4)) { 713 led_info = led_info_cmicd_v4; 714 led_max = CMICD_V4_LEDUP_MAX; 715 } 716 #endif /* BCM_TOMAHAWK2_SUPPORT */ 717 718 #if (defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_PETRA_SUPPORT)) && defined(BCM_WARM_BOOT_SUPPORT) 719 boot_flags = sal_boot_flags_get(); 720 if ((boot_flags & BOOT_F_WARM_BOOT) && 721 (!SOC_IS_ESW(unit) || SOC_IS_TOMAHAWK(unit))) { 722 skip_force_link_check = TRUE; 723 } 724 #endif 725 726 if (bcm_linkscan_unregister(unit, ledproc_linkscan_cb) < 0) { 727 auto_on = FALSE; 728 } else { 729 (void)bcm_linkscan_register(unit, ledproc_linkscan_cb); 730 auto_on = TRUE; 731 } 732 733 if (ARG_CNT(a) == 0) { 734 #ifdef BCM_CMICX_SUPPORT 735 if (soc_feature(unit, soc_feature_cmicx)) { 736 #if CMICX_LED 737 cli_out("LED M0 FW is %s Init DONE; " 738 "auto updating is %s.\n", 739 (SOC_CONTROL(unit)->led_fw_enabled) ? "ON" : "OFF", 740 auto_on ? "ON" : "OFF"); 741 #endif /* CMICX_LED */ 742 return(CMD_OK); 743 } 744 #endif /* BCM_CMICX_SUPPORT */ 745 for (ix = 0; ix < led_max; ix++) { 746 led_ctrl = soc_pci_read(unit, led_info[ix].ctrl); 747 led_status = soc_pci_read(unit, led_info[ix].status); 748 cli_out("%s: LED%d Micro-controller is %s (PC=0x%x State=%s%s); " 749 "auto updating is %s.\n", 750 ARG_CMD(a), 751 ix, 752 (led_ctrl & LC_LED_ENABLE) ? "ON" : "OFF", 753 (led_status & LS_LED_PC), 754 (led_status & LS_LED_INIT) ? "INIT," : "", 755 (led_status & LS_LED_RUN) ? "RUN" : "SLEEP", 756 auto_on ? "ON" : "OFF"); 757 } 758 return(CMD_OK); 759 } 760 761 ix = 0; 762 c = ARG_GET(a); 763 764 /* check if command has processor number specified */ 765 if (isint(c)) { 766 ix = parse_integer(c); 767 if (ix > (led_max - 1)) { 768 cli_out("Invalid uProcessor number: %d, set to 0\n",ix); 769 ix = led_max - 1; 770 } 771 c = ARG_GET(a); 772 } 773 774 led_info_cur = led_info+ix; 775 776 #ifdef BCM_CMICX_SUPPORT 777 if (!soc_feature(unit, soc_feature_cmicx)) 778 #endif /* BCM_CMICX_SUPPORT */ 779 { 780 /* Not for CMICx-LED. */ 781 led_ctrl = soc_pci_read(unit, led_info_cur->ctrl); 782 } 783 784 if (!sal_strcasecmp(c, "status")) { 785 int port; 786 uint32 portdata = 0; 787 int phy_port; 788 #ifdef BCM_TRIDENT_SUPPORT 789 uint32 portdata1 = 0; 790 #endif 791 #ifdef BCM_CMICX_SUPPORT 792 #if CMICX_LED 793 #if defined (BCM_ESW_SUPPORT) || defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT) 794 int rv = SOC_E_NONE; 795 soc_led_port_status_t led_status; 796 #endif /* BCM_ESW_SUPPORT || BCM_DNXF_SUPPORT */ 797 #endif /* CMICX_LED */ 798 #endif /* BCM_CMICX_SUPPORT */ 799 800 /* coverity[overrun-local] */ 801 PBMP_PORT_ITER(unit, port) { 802 803 #ifdef BCM_CMICX_SUPPORT 804 if (soc_feature(unit, soc_feature_cmicx)) { 805 #if CMICX_LED 806 if (!SOC_CONTROL(unit)->led_fw_enabled) { 807 cli_out("LED FW not running\n"); 808 break; 809 } 810 #if defined (BCM_ESW_SUPPORT) || defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT) 811 if (soc_feature(unit, soc_feature_logical_port_num)) { 812 led_status.port = SOC_INFO(unit).port_l2p_mapping[port]; 813 } else { 814 led_status.port = port; 815 } 816 817 /* Display LED output ram status for the port */ 818 led_status.bank = LED_SEND_RAM_BANK; 819 820 rv = soc_cmicx_led_status_get(unit, &led_status); 821 822 if (rv != SOC_E_NONE) { 823 cli_out("Error: Unable to get LED status\n"); 824 return(CMD_FAIL); 825 } else { 826 cli_out("Port %d led status 0x%x\n", port, led_status.status); 827 continue; 828 } 829 #endif /* BCM_ESW_SUPPORT || BCM_DNXF_SUPPORT */ 830 #else 831 continue; 832 #endif /* CMICX_LED */ 833 } 834 #endif /* BCM_CMICX_SUPPORT */ 835 836 #ifdef BCM_PETRA_SUPPORT 837 /* SOC_IS_ARAD includes also later DNX fap devices */ 838 if (SOC_IS_ARAD(unit)) { 839 /* skipping over sfi ports */ 840 if(IS_SFI_PORT(unit,port)) { 841 continue; 842 } 843 } 844 #endif 845 846 if (soc_feature(unit, soc_feature_logical_port_num)) { 847 if (port >= SOC_MAX_NUM_PORTS) { /* safety check */ 848 break; 849 } 850 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 851 } else { 852 phy_port = port; 853 } 854 855 #ifdef BCM_PETRA_SUPPORT 856 if (SOC_IS_QAX(unit)) { 857 uint32 physical_phy; 858 bcm_error_t ret; 859 ret = MBCM_DPP_DRIVER_CALL(unit, mbcm_dpp_qsgmii_offsets_remove, 860 (unit, phy_port , &physical_phy)); 861 if (ret != BCM_E_NONE) { 862 continue; 863 } 864 phy_port = physical_phy; 865 866 } else if (SOC_IS_JERICHO(unit)) { 867 868 /* LED processor 0 - will handle ports 1-24. port 1 resides in index 1 in data ram */ 869 /* LED processor 1 - will handle ports 25-84. port 25 resides in index 1 in data ram */ 870 /* LED processor 2 - will handle ports 85-144. port 85 resides in index 1 in data ram */ 871 872 if (phy_port <= 24) { 873 led_up_instance = 0; 874 } else if (phy_port >= 25 && phy_port <= 84) { 875 led_up_instance = 1; 876 phy_port -= 24; 877 } else if (phy_port > 84) { 878 led_up_instance = 2; 879 phy_port -= 84; 880 } 881 led_info_cur = led_info + led_up_instance; 882 } 883 #endif /* BCM_PETRA_SUPPORT */ 884 885 886 #ifdef BCM_TRIDENT_SUPPORT 887 if (SOC_IS_TD_TT(unit) || SOC_IS_TRIUMPH3(unit)) { 888 /* trident first 36 ports in ledproc0, the other 36 ports in ledproc1*/ 889 /* triumph3 first 52 ports are in ledproc0, the other ports are in ledproc1 */ 890 int ledup0_pmax = SOC_IS_TD_TT(unit) ? TRIDENT_LEDUP0_PORT_MAX : 891 (SOC_IS_HELIX4(unit) ? HELIX4_LEDUP_PORT_MAX : TRIUMPH3_LEDUP0_PORT_MAX); 892 if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit)) && !SOC_IS_APACHE(unit)) { 893 ledup0_pmax = TRIDENT2_LEDUP0_PORT_MAX; 894 } 895 896 if (SOC_IS_APACHE(unit)) { 897 ledup0_pmax = APACHE_LEDUP_PORT_MAX; 898 } 899 if (SOC_IS_MONTEREY(unit)) { 900 ledup0_pmax = MONTEREY_LEDUP_PORT_MAX; 901 } 902 903 #ifdef BCM_TOMAHAWK_SUPPORT 904 if (SOC_IS_TOMAHAWK(unit)) { 905 /* Tomahawk: Port 1-32 and 97-128 are in ledproc0 906 * Port 33-96 are in ledproc1 907 * Port 129 & 131 are in ledproc2 908 */ 909 if (phy_port == 129) { 910 led_info_cur = led_info + 2; 911 phy_port = 1; 912 led_up_instance = 2; 913 } else if (phy_port == 131) { 914 led_info_cur = led_info + 2; 915 phy_port = 2; 916 led_up_instance = 2; 917 } else if (phy_port > 32 && phy_port < 97) { 918 led_info_cur = led_info + 1; 919 phy_port -= 32; 920 led_up_instance = 1; 921 } else if (phy_port > 32) { 922 phy_port -= 64; 923 led_info_cur = led_info; 924 led_up_instance = 0; 925 } 926 } else 927 #ifdef BCM_TOMAHAWK2_SUPPORT 928 if (SOC_IS_TOMAHAWK2(unit)) { 929 led_up_instance = (phy_port - 1) / 64; 930 led_info_cur = led_info + led_up_instance; 931 phy_port = (phy_port - 1) % 64 + 1; 932 } else 933 #endif /* BCM_TOMAHAWK2_SUPPORT */ 934 #endif /* BCM_TOMAHAWK_SUPPORT */ 935 if (phy_port > ledup0_pmax) { 936 phy_port -= ledup0_pmax; 937 led_info_cur = led_info+1; 938 led_up_instance = 1; 939 } else { 940 led_info_cur = led_info; 941 led_up_instance = 0; 942 } 943 if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit)) && !SOC_IS_APACHE(unit) && !SOC_IS_MONTEREY(unit)) { 944 int i, skip_count = 0; 945 for (i=1; i < phy_port; i++) { 946 skip_count += ((SOC_INFO(unit).port_p2l_mapping[i+(led_up_instance*TRIDENT2_LEDUP0_PORT_MAX)] == -1) ? 1: 0); 947 } 948 phy_port -= skip_count; 949 } 950 } 951 #endif /* BCM_TRIDENT_SUPPORT */ 952 953 /* Portmap */ 954 phy_port_map = phy_port; 955 if (SOC_IS_TRIUMPH3(unit)) { 956 if (led_up_instance) { 957 phy_port_map = phy_port + 4; 958 } else { 959 phy_port_map = phy_port; 960 if (phy_port == 37) { 961 phy_port_map += 12; 962 } else if (phy_port >= 38) { 963 phy_port_map -= 4; 964 } 965 } 966 } 967 #ifdef BCM_KATANA2_SUPPORT 968 if (SOC_IS_KATANA2(unit)) { 969 /* For Kt2 we start status from 1, not 0 */ 970 phy_port_map += 1; 971 } 972 973 /* phy_port_map ranges from 1 to 64, while status bits range from 0 to 63 */ 974 #endif /* BCM_CMICM_SUPPORT */ 975 976 977 #ifdef BCM_TRIDENT_SUPPORT 978 if (SOC_IS_TD_TT(unit)) { 979 uint32 byte; 980 #ifdef BCM_TOMAHAWK_SUPPORT 981 if (SOC_IS_TOMAHAWKX(unit)) { 982 /* link status is kept current in bit 0 of 983 data RAM byte (0xA0 + portnum) */ 984 byte = LS_LED_DATA_OFFSET_A0 + phy_port_map - 1; 985 portdata1 = soc_pci_read(unit, 986 led_info_cur->dram_base + CMIC_LED_REG_SIZE * byte); 987 988 /* HW Port status in data RAM (0x00 + portnum) */ 989 portdata = soc_pci_read(unit, led_info_cur->dram_base 990 + CMIC_LED_REG_SIZE * 2 * (phy_port_map - 1)); 991 if (portdata1 & 0x1) { 992 portdata |= 0x80; 993 } else { 994 portdata &= ~0x80; 995 } 996 } else 997 #endif /* BCM_TOMAHAWK_SUPPORT */ 998 { 999 if (soc_feature(unit, soc_feature_led_data_offset_a0)) { 1000 byte = LS_LED_DATA_OFFSET_A0 + phy_port_map; 1001 if (SOC_IS_TRIDENT2(unit) || SOC_IS_APACHE(unit)) { 1002 /*offset begin from 0xA0 */ 1003 byte -= 1; 1004 } 1005 } else { 1006 byte = LS_LED_DATA_OFFSET + phy_port_map; 1007 } 1008 1009 /* read tx/rx activity */ 1010 portdata1 = soc_pci_read(unit, 1011 led_info_cur->dram_base + CMIC_LED_REG_SIZE * byte); 1012 1013 if (portdata1 & 0x1) { 1014 portdata |= 0x80; 1015 } else { 1016 portdata &= ~0x80; 1017 } 1018 if (portdata1 & 0x10) { 1019 portdata |= 0x2; 1020 } else { 1021 portdata &= ~0x2; 1022 } 1023 if (portdata1 & 0x20) { 1024 portdata |= 0x1; 1025 } else { 1026 portdata &= ~0x1; 1027 } 1028 1029 if (SOC_IS_TRIDENT2PLUS(unit)) { 1030 phy_port_map -= 1; 1031 } 1032 1033 portdata1 = soc_pci_read(unit, 1034 led_info_cur->dram_base + CMIC_LED_REG_SIZE * (phy_port_map * 2 + 1)); 1035 portdata1 &= 0xFF; 1036 portdata1 <<= 8; 1037 portdata1 |= 0xFF & soc_pci_read(unit, 1038 led_info_cur->dram_base + CMIC_LED_REG_SIZE * 2 * phy_port_map); 1039 } 1040 } 1041 #endif /* BCM_TRIDENT_SUPPORT */ 1042 1043 #ifdef BCM_PETRA_SUPPORT 1044 if (SOC_IS_ARAD(unit)) { 1045 1046 uint32 byte; 1047 uint32 portdata1; 1048 1049 /* link status is kept current in bit 0 of data RAM byte (0xA0 + portnum) */ 1050 byte = LS_LED_DATA_OFFSET_A0 + phy_port_map; 1051 portdata1 = soc_pci_read(unit, 1052 led_info_cur->dram_base + CMIC_LED_REG_SIZE * byte); 1053 1054 /* HW Port status in data RAM (0x00 + portnum) */ 1055 portdata = soc_pci_read(unit, led_info_cur->dram_base 1056 + CMIC_LED_REG_SIZE * 2 * (phy_port_map)); 1057 if (portdata1 & 0x1) { 1058 portdata |= 0x80; 1059 } else { 1060 portdata &= ~0x80; 1061 } 1062 } 1063 #endif /* BCM_PETRA_SUPPORT */ 1064 1065 1066 /* coverity[overrun-local] */ 1067 if (soc_feature(unit, soc_feature_unimac) && 1068 ((IS_FE_PORT(unit, port)) || (IS_GE_PORT(unit, port)))) { 1069 #ifdef BCM_TRIDENT_SUPPORT 1070 if (SOC_IS_TD_TT(unit)) { 1071 int speed = (portdata1 & 0x18) >> 3; 1072 cli_out("%2d %4s %s %s %s %s %s %s %s %d:%d\n", 1073 port, 1074 SOC_PORT_VALID(unit, port) ? 1075 SOC_PORT_NAME(unit, port) :" ", 1076 (portdata & 0x0001) ? "RX" : " " , 1077 (portdata & 0x0002) ? "TX" : " " , 1078 (portdata & 0x0080) ? "LI" : " " , 1079 (portdata1 & 0x0100)? "LE" : " " , 1080 (portdata1 & 0x0004)? "COL" : " ", 1081 (speed == 0) ? "10M " : 1082 (speed == 1) ? "100M " : 1083 (speed == 2) ? "1G " : 1084 (speed == 3) ? ">=10G" : " ", 1085 (portdata1 & 0x0020) ? "HD" : "FD" , 1086 led_up_instance, phy_port_map 1087 ); 1088 } else 1089 #endif 1090 { 1091 cli_out("%2d %4s %s %s %s %s %s %s %s %s %d:%d\n", 1092 port, 1093 SOC_PORT_VALID(unit, port) ? 1094 SOC_PORT_NAME(unit, port) :" ", 1095 (portdata & 0x0001) ? "RX" : " " , 1096 (portdata & 0x0002) ? "TX" : " " , 1097 (portdata & 0x0080) ? "LI" : " " , 1098 (portdata & 0x0100) ? "LE" : " " , 1099 (portdata & 0x0004) ? "COL" : " ", 1100 (portdata & 0x0008) ? "100" : " ", 1101 (portdata & 0x0010) ? "1G" : " " , 1102 (portdata & 0x0020) ? "HD" : "FD" , 1103 led_up_instance, phy_port_map 1104 ); 1105 } 1106 } else 1107 #ifdef BCM_TOMAHAWK_SUPPORT 1108 if(SOC_IS_TOMAHAWKX(unit)) { 1109 cli_out("%2d %4s %s %s %s %s %s %s %s %d:%d\n", 1110 port, 1111 SOC_PORT_VALID(unit, port) ? 1112 SOC_PORT_NAME(unit, port) :" ", 1113 (portdata & 0x0001) ? "RX" : " " , 1114 (portdata & 0x0002) ? "TX" : " " , 1115 (portdata & 0x0080) ? "LI" : " " , 1116 (portdata & 0x0100) ? "LE" : " " , 1117 (portdata & 0x0004) ? "COL" : " ", 1118 (portdata & 0x0018) ? "10G" : " ", 1119 (portdata & 0x0020) ? "HD" : "FD" , 1120 led_up_instance, phy_port_map 1121 ); 1122 } else 1123 #endif /* BCM_TOMAHAWK_SUPPORT */ 1124 #ifdef BCM_TRIDENT_SUPPORT 1125 if (SOC_IS_TD_TT(unit)) { 1126 int speed = (portdata1 & 0x18) >> 3; 1127 cli_out("%2d %4s %s %s %s %s %s %s %s %d:%d\n", 1128 port, 1129 SOC_PORT_VALID(unit, port) ? 1130 SOC_PORT_NAME(unit, port) :" ", 1131 (portdata & 0x0001) ? "RX" : " " , 1132 (portdata & 0x0002) ? "TX" : " " , 1133 (portdata & 0x0080) ? "LI" : " " , 1134 (portdata1 & 0x0100) ? "LE" : " " , 1135 (portdata1 & 0x0004) ? "COL" : " ", 1136 (speed == 0) ? "10M " : 1137 (speed == 1) ? "100M " : 1138 (speed == 2) ? "1G " : 1139 (speed == 3) ? ">=10G" : " ", 1140 (portdata1 & 0x0020) ? "FD" : "HD" , 1141 led_up_instance, phy_port_map 1142 ); 1143 } else 1144 #endif /* BCM_TRIDENT_SUPPORT */ 1145 { 1146 cli_out("%2d %4s %s %s %s %s %s %s %s %s %d:%d\n", 1147 port, 1148 SOC_PORT_VALID(unit, port) ? 1149 SOC_PORT_NAME(unit, port) :" ", 1150 (portdata & 0x0001) ? "RX" : " " , 1151 (portdata & 0x0002) ? "TX" : " " , 1152 (portdata & 0x0080) ? "LI" : " " , 1153 (portdata & 0x0100) ? "LE" : " " , 1154 (portdata & 0x0004) ? "COL" : " ", 1155 (portdata & 0x0008) ? "100" : " ", 1156 (portdata & 0x0010) ? "1G" : " " , 1157 (portdata & 0x0020) ? "FD" : "HD" , 1158 led_up_instance, phy_port_map 1159 ); 1160 } 1161 } 1162 } else if (!sal_strcasecmp(c, "start")) { 1163 int offset; 1164 1165 #if defined (BCM_CMICX_SUPPORT) 1166 if (soc_feature(unit, soc_feature_cmicx)) { 1167 #if CMICX_LED 1168 int rv = SOC_E_NONE; 1169 #if defined (BCM_ESW_SUPPORT) || defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT) 1170 rv = soc_cmicx_led_enable(unit, LED_START); 1171 #endif /* BCM_ESW_SUPPORT || BCM_DNXF_SUPPORT */ 1172 if (rv != SOC_E_NONE) { 1173 cli_out("Error:Unable to start LED FW\n"); 1174 return(CMD_FAIL); 1175 } else { 1176 return(CMD_OK); 1177 } 1178 #else /* CMICX_LED */ 1179 return(CMD_OK); 1180 #endif /* CMICX_LED */ 1181 } 1182 #endif /* BCM_CMICX_SUPPORT */ 1183 1184 /* The LED data area should be clear whenever program starts */ 1185 1186 soc_pci_write(unit, led_info_cur->ctrl, led_ctrl & ~LC_LED_ENABLE); 1187 1188 for (offset = 0x80; offset < CMIC_LED_DATA_RAM_SIZE; offset++) { 1189 soc_pci_write(unit, 1190 led_info_cur->dram_base + CMIC_LED_REG_SIZE * offset, 1191 0); 1192 } 1193 1194 led_ctrl |= LC_LED_ENABLE; 1195 1196 soc_pci_write(unit, led_info_cur->ctrl, led_ctrl); 1197 1198 if (auto_on && !skip_force_link_check) { 1199 (void)bcm_link_change(unit, PBMP_PORT_ALL(unit)); 1200 } 1201 1202 return(CMD_OK); 1203 } else if (!sal_strcasecmp(c, "stop")) { 1204 1205 #if defined (BCM_CMICX_SUPPORT) 1206 if (soc_feature(unit, soc_feature_cmicx)) { 1207 #if CMICX_LED 1208 int rv = SOC_E_NONE; 1209 #if defined (BCM_ESW_SUPPORT) || defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT) 1210 rv = soc_cmicx_led_enable(unit, LED_STOP); 1211 #endif /* BCM_ESW_SUPPORT || BCM_DNXF_SUPPORT || BCM_DNX_SUPPORT */ 1212 if (rv != SOC_E_NONE) { 1213 cli_out("Error:Unable to stop LED FW\n"); 1214 return(CMD_FAIL); 1215 } else { 1216 return(CMD_OK); 1217 } 1218 #else /* CMICX_LED */ 1219 return(CMD_OK); 1220 #endif /* CMICX_LED */ 1221 } 1222 #endif /* BCM_CMICX_SUPPORT */ 1223 1224 led_ctrl &= ~LC_LED_ENABLE; 1225 soc_pci_write(unit, led_info_cur->ctrl, led_ctrl); 1226 1227 return(CMD_OK); 1228 } else if (!sal_strcasecmp(c, "load")) { 1229 /* 1230 * Try to catch ^C to avoid leaving file open if ^C'd. 1231 * There are still a number of unlikely race conditions here. 1232 * Temporarily stop LED processor if it is currently running. 1233 */ 1234 #ifdef NO_FILEIO 1235 cli_out("no filesystem\n"); 1236 #else 1237 led_info_t *led_info_saved; 1238 led_info_saved = led_info_cur; 1239 soc_pci_write(unit, led_info_saved->ctrl, led_ctrl & ~LC_LED_ENABLE); 1240 if ( 1241 #ifndef NO_CTRL_C 1242 !setjmp(ctrl_c) 1243 #else 1244 TRUE 1245 #endif 1246 ) { 1247 #ifndef NO_CTRL_C 1248 sh_push_ctrl_c(&ctrl_c); 1249 #endif 1250 1251 if ((c = ARG_GET(a)) != NULL) { 1252 f = sal_fopen(c, "r"); 1253 if (!f) { 1254 cli_out("%s: Error: Unable to open file: %s\n", 1255 ARG_CMD(a), c); 1256 rv = CMD_FAIL; 1257 } else { 1258 rv = ledproc_load_fp(unit, ARG_CMD(a), c, 1259 (FILE *)f,led_info_saved); 1260 sal_fclose((FILE *)f); /* Cast for un-volatile */ 1261 f = NULL; 1262 } 1263 } else { 1264 cli_out("%s: Error: No file specified\n", ARG_CMD(a)); 1265 rv = CMD_USAGE; 1266 } 1267 } else if (f) { 1268 sal_fclose((FILE *)f); 1269 f = NULL; 1270 rv = CMD_INTR; 1271 } 1272 /* Restore LED processor if it was running */ 1273 soc_pci_write(unit, led_info_saved->ctrl, led_ctrl); 1274 1275 if (auto_on && !skip_force_link_check) { 1276 (void)bcm_link_change(unit, PBMP_PORT_ALL(unit)); 1277 } 1278 1279 #ifndef NO_CTRL_C 1280 sh_pop_ctrl_c(); 1281 #endif 1282 #endif /* NO_FILEIO */ 1283 } else if (!sal_strcasecmp(c, "prog")) { 1284 if (ARG_CUR(a) == NULL) { 1285 return(CMD_USAGE); 1286 } 1287 1288 led_ctrl &= ~LC_LED_ENABLE; 1289 soc_pci_write(unit, led_info_cur->ctrl, led_ctrl); 1290 1291 return ledproc_load_args(unit, a, led_info_cur); 1292 } else if (!sal_strcasecmp(c, "auto")) { 1293 int new_auto = 1; 1294 1295 if ((c = ARG_GET(a)) != NULL) { 1296 if (!sal_strcasecmp(c, "off")) { 1297 new_auto = 0; 1298 } else if (!sal_strcasecmp(c, "on")) { 1299 new_auto = 1; 1300 } else { 1301 return CMD_USAGE; 1302 } 1303 } 1304 1305 if (new_auto && !auto_on) { 1306 (void)bcm_linkscan_register(unit, ledproc_linkscan_cb); 1307 } 1308 1309 if (!new_auto && auto_on) { 1310 (void)bcm_linkscan_unregister(unit, ledproc_linkscan_cb); 1311 } 1312 1313 if (new_auto && !skip_force_link_check) { 1314 (void)bcm_link_change(unit, PBMP_PORT_ALL(unit)); 1315 } 1316 1317 } else if (!sal_strcasecmp(c, "dump")) { 1318 int offset, max; 1319 1320 for (max = CMIC_LED_PROGRAM_RAM_SIZE - 1; max >= 0; max--) { 1321 if (soc_pci_read(unit, 1322 led_info_cur->pram_base + CMIC_LED_REG_SIZE * max) != 0) { 1323 break; 1324 } 1325 } 1326 1327 for (offset = 0; offset <= max; offset++) { 1328 cli_out(" %02x", soc_pci_read(unit, 1329 led_info_cur->pram_base + CMIC_LED_REG_SIZE * offset)); 1330 if ((offset % 16) == 15) { 1331 cli_out("\n"); 1332 } 1333 } 1334 1335 if (offset % 16 != 0) { 1336 cli_out("\n"); 1337 } 1338 #ifdef BCM_CMICX_SUPPORT 1339 } else if (!sal_strcasecmp(c, "setstatus")) { 1340 if (soc_feature(unit, soc_feature_cmicx)) { 1341 #if CMICX_LED 1342 #if defined (BCM_ESW_SUPPORT) || defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT) 1343 int rv = SOC_E_NONE; 1344 soc_led_port_status_t led_status; 1345 1346 if ((c = ARG_GET(a)) != NULL) { 1347 led_status.port = sal_ctoi(c, 0); 1348 } 1349 1350 if ((c = ARG_GET(a)) != NULL) { 1351 led_status.status = sal_ctoi(c, 0); 1352 } 1353 rv = soc_cmicx_led_status_set(unit, &led_status); 1354 if (rv != SOC_E_NONE) { 1355 cli_out("Error: Unable to set led status\n"); 1356 return(CMD_FAIL); 1357 } 1358 #endif /* BCM_ESW_SUPPORT || BCM_DNXF_SUPPORT */ 1359 #endif /* CMICX_LED */ 1360 } else { 1361 cli_out("Unsupported LED CLI command\n"); 1362 return(CMD_FAIL); 1363 } 1364 } else if (!sal_strcasecmp(c, "accustatus")) { 1365 if (soc_feature(unit, soc_feature_cmicx)) { 1366 #if CMICX_LED 1367 #if defined (BCM_ESW_SUPPORT) || defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT) 1368 int rv = SOC_E_NONE, port; 1369 soc_led_port_status_t led_status; 1370 1371 if (!SOC_CONTROL(unit)->led_fw_enabled) { 1372 cli_out("LED FW not running\n"); 1373 return(CMD_FAIL); 1374 } 1375 1376 /* coverity[overrun-local] */ 1377 PBMP_PORT_ITER(unit, port) { 1378 if (soc_feature(unit, soc_feature_logical_port_num)) { 1379 led_status.port = SOC_INFO(unit).port_l2p_mapping[port]; 1380 } else { 1381 led_status.port = port; 1382 } 1383 1384 /* Display LED accu_ram bank status for the port */ 1385 led_status.bank = LED_ACCU_RAM_BANK; 1386 rv = soc_cmicx_led_status_get(unit, &led_status); 1387 if (rv != SOC_E_NONE) { 1388 cli_out("Error: Unable to get LED status\n"); 1389 return(CMD_FAIL); 1390 } else { 1391 cli_out("Port %d led accu ram status 0x%x\n", port, led_status.status); 1392 continue; 1393 } 1394 } 1395 #endif /* BCM_ESW_SUPPORT || BCM_DNXF_SUPPORT */ 1396 #endif /* CMICX_LED */ 1397 } else { 1398 cli_out("Unsupported LED CLI command\n"); 1399 return(CMD_FAIL); 1400 } 1401 #endif /* BCM_CMICX_SUPPORT */ 1402 } else { 1403 return(CMD_USAGE); 1404 } 1405 1406 return(rv); 1407 }