board.c (23149B)
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: board.c 8 * Purpose: Board driver CLI 9 */ 10 11 #include <sal/types.h> 12 #if !defined(NO_SAL_APPL) 13 #include <sal/appl/config.h> 14 #endif 15 #include <appl/diag/shell.h> 16 #include <appl/diag/system.h> 17 #include <appl/diag/parse.h> 18 #include <appl/diag/ctrans.h> 19 #include <board/board.h> 20 21 #include <shared/bsl.h> 22 23 #if defined(INCLUDE_BOARD) 24 25 char board_cmd_usage[] = 26 "board <subcmd> [options]\n" 27 #ifndef COMPILER_STRING_CONST_LIMIT 28 "Subcommands:\n" 29 " select [name=boardname] [flags=startflags]\n" 30 " Attach and start a board.\n" 31 " If no board name is provided, probe all registered board\n" 32 " drivers and select the first board driver that probes\n" 33 " successfully.\n" 34 " Start flags default to 0 (cold boot). Start flags can be\n" 35 " numeric, or one of 'Cold', 'Warm', or 'CLear'\n" 36 " detach\n" 37 " Stop and detach the current board.\n" 38 " list\n" 39 " Display all registered boards and attributes supported by\n" 40 " each board.\n" 41 " show\n" 42 " Display current board state and configuration name,\n" 43 " description, attributes, and connections.\n" 44 " register builtin\n" 45 " Register or re-register all built in drivers.\n" 46 " register Name=boardname\n" 47 " Register or re-register a built in driver with the given name.\n" 48 " unregister Name=boardname\n" 49 " Unregister a driver with the given name.\n" 50 " attribute name=val\n" 51 " Set the board attribute 'name' to 'value'.\n" 52 " attribute name\n" 53 " Display the current value of board attribute 'name'.\n" 54 " attribute\n" 55 " Display all board attributes supported by the current board.\n" 56 " clear\n" 57 " Clear devices on current board and preserve the current board\n" 58 " configuration.\n" 59 #endif 60 ; 61 62 /* Macro to distinguish between NULL and empty strings */ 63 #define S(s) ((s)?(strlen((s))?(s):"<EMPTY>"):"<NULL>") 64 65 /* Macro to convert BCM errors to CMD shell errors */ 66 #define CMD_SUCCESS(x) (BCM_SUCCESS(x) ? CMD_OK : CMD_FAIL) 67 68 /* Position in board_cmd_flag_list where magic numeric flags land up */ 69 #define NUM_FLAG_OFFSET 3 70 71 /* Decimal number string buffer length */ 72 #define STRBUF 16 73 74 /* Board start string parameters */ 75 STATIC char *board_cmd_flag_list[] = { 76 "Cold", 77 "Warm", 78 "CLear", 79 NULL, /* NUM_FLAG string */ 80 NULL 81 }; 82 83 /* Flag values corresponding to the strings above in 84 board_cmd_flag_list. This would normally have been combined with 85 board_cmd_flag_list in a single structure, but such a structure 86 would work with diag parser functions. */ 87 STATIC uint32 board_cmd_flag_value[] = { 88 BOARD_START_F_COLD_BOOT, 89 BOARD_START_F_WARM_BOOT, 90 BOARD_START_F_CLEAR, 91 0 /* NUM_FLAG value */ 92 }; 93 94 /* 95 * Function: 96 * board_cmd_parse_numeric_start_flag 97 * Purpose: 98 * If there's a numeric start flag, add it to the flag list 99 * Parameters: 100 * args - (IN) argument structure to scan 101 * Returns: 102 * void 103 */ 104 STATIC 105 void board_cmd_parse_numeric_start_flag(args_t *args) 106 { 107 char *arg; 108 char *value; 109 int count; 110 111 count=0; 112 board_cmd_flag_list[NUM_FLAG_OFFSET] = NULL; /* remove any previous flag */ 113 while (ARG_CNT(args) > 0) { 114 arg = ARG_CUR(args); 115 116 /* flag format is f...=value */ 117 if (arg != NULL && (arg[0] == 'f' || arg[0] == 'F')) { 118 value = sal_strchr(arg, '='); 119 if (value) { 120 value++; 121 if (isint(value)) { 122 board_cmd_flag_list[NUM_FLAG_OFFSET] = value; 123 board_cmd_flag_value[NUM_FLAG_OFFSET] = 124 parse_integer(value); 125 break; 126 } 127 } 128 } 129 count++; 130 ARG_NEXT(args); 131 } 132 /* put arg count back */ 133 while (count-- > 0) { 134 ARG_PREV(args); 135 } 136 } 137 138 /* Returns a string corresponding to the r/w access of a board attribute */ 139 #define ATTR_ACCESS(a) ((a) ? "rw" : "ro") 140 141 /* 142 * Function: 143 * board_cmd_list 144 * Purpose: 145 * List names and attributes of all installed board drivers. 146 * Parameters: 147 * none 148 * Returns: 149 * CMD_OK - success 150 * CMD_FAIL - failed 151 */ 152 STATIC cmd_result_t 153 board_cmd_list(void) 154 { 155 board_driver_t **driver; 156 int rv, count, i, j; 157 158 rv = board_drivers_get(0, NULL, &count); 159 160 if (BCM_FAILURE(rv)) { 161 cli_out("board_drivers_get: %s (%d)\n", bcm_errmsg(rv), rv); 162 return CMD_FAIL; 163 } 164 165 driver = sal_alloc(count * sizeof(board_driver_t *), "board_cmd"); 166 167 if (!driver) { 168 return CMD_FAIL; 169 } 170 171 rv = board_drivers_get(count, driver, &count); 172 if (BCM_FAILURE(rv)) { 173 cli_out("board_drivers_get: %s (%d)\n", bcm_errmsg(rv), rv); 174 sal_free(driver); 175 return CMD_FAIL; 176 } 177 178 for (i=0; i<count; i++) { 179 180 cli_out("%s\n", driver[i]->name); 181 182 for (j=0; j<driver[i]->num_attribute; j++) { 183 cli_out(" %s [%s]\n", 184 driver[i]->attribute[j].name, 185 ATTR_ACCESS(driver[i]->attribute[j].set)); 186 } 187 } 188 189 sal_free(driver); 190 return CMD_OK; 191 } 192 193 /* 194 * Function: 195 * board_cmd_start 196 * Purpose: 197 * Start a board based on parameters passed or config variables. 198 * If a name is given, use that name, otherwise if there's a 199 * "board_name" config variable, use that. When all else fails, 200 * probe for a board. If the probe fails, then error out, 201 * otherwise attach the board. Once the board is attached, start 202 * the board with the given board flags, the board flags config, 203 * or the default cold start flag. If the board start was 204 * successful, set board attributes if any attribute configs were 205 * found. 206 * Parameters: 207 * name - (IN) board name to start, or NULL to probe 208 * flagidx - (IN) start flag 209 * Configs: 210 * board_name 211 * board_flags 212 * board_<attr> 213 * Returns: 214 * CMD_OK - success 215 * CMD_FAIL - failed 216 */ 217 STATIC cmd_result_t 218 board_cmd_start(char *name, int flagidx) 219 { 220 int rv, cmd_rv, num_attr, i; 221 uint32 flags = 0; 222 board_attribute_t *attr; 223 #if !defined(NO_SAL_APPL) 224 char config_name[SAL_CONFIG_STR_MAX]; 225 #else 226 char config_name[128]; 227 #endif 228 229 cmd_rv = CMD_FAIL; 230 attr = NULL; 231 232 #if !defined(NO_SAL_APPL) 233 if (name == NULL || sal_strlen(name) == 0) { 234 /* if there's a config board_name, use that name */ 235 name = sal_config_get(spn_BOARD_NAME); 236 } 237 #endif 238 239 if (name == NULL || sal_strlen(name) == 0) { 240 /* probe */ 241 name = board_probe(); 242 if (name == NULL) { 243 cli_out("Board probe failed\n"); 244 goto fail; 245 } 246 } else { 247 /* find */ 248 if (!board_find(name)) { 249 cli_out("Cannot find board '%s'\n", name); 250 goto fail; 251 } 252 } 253 254 /* attach */ 255 rv = board_attach(name); 256 if (BCM_FAILURE(rv)) { 257 cli_out("Cannot attach board '%s':%s (%d)\n", 258 name, bcm_errmsg(rv), rv); 259 goto fail; 260 } 261 262 /* start */ 263 if (flagidx < 0) { 264 char *flagstr = NULL; 265 266 #if !defined(NO_SAL_APPL) 267 flagstr = sal_config_get(spn_BOARD_FLAGS); 268 #endif 269 /* if there's a board_flags argument, use that, otherwise 270 default to 'cold boot' */ 271 272 if (flagstr) { 273 if (isint(flagstr)) { 274 flags = parse_integer(flagstr); 275 } else { 276 cli_out("Could not parse board_flags=%s\n",flagstr); 277 goto fail; 278 } 279 } else { 280 flags = board_cmd_flag_value[0]; 281 } 282 } 283 284 rv = board_start(flags); 285 if (BCM_FAILURE(rv)) { 286 cli_out("Cannot start %s(%08x):%s (%d)\n", 287 name, flags, bcm_errmsg(rv), rv); 288 board_detach(); 289 goto fail; 290 } 291 292 /* Go though the writable attributes, and see if there are 293 any matching configs. If there are, then set those 294 attributes */ 295 296 rv = board_attributes_get(0, NULL, &num_attr); 297 if (BCM_FAILURE(rv)) { 298 cli_out("Cannot get board attributes for %s:%s (%d)\n", 299 name, bcm_errmsg(rv), rv); 300 goto fail; 301 } 302 303 attr = sal_alloc(num_attr * sizeof(board_attribute_t), 304 "board_cmd_start"); 305 306 if (attr == NULL) { 307 cli_out("Cannot alloc memory for attributes\n"); 308 goto fail; 309 } 310 311 rv = board_attributes_get(num_attr, attr, &num_attr); 312 if (BCM_FAILURE(rv)) { 313 cli_out("Cannot get board attributes for %s:%s (%d)\n", 314 name, bcm_errmsg(rv), rv); 315 goto fail; 316 } 317 318 /* Set board attributes if matching config variables are found. 319 Set variables for all attributes. 320 */ 321 for (i=0; i<num_attr; i++) { 322 sal_sprintf(config_name, "board_%s", attr[i].name); 323 #if !defined(NO_SAL_APPL) 324 if (attr[i].set) { 325 char *value; 326 327 value = sal_config_get(config_name); 328 if (value) { 329 if (isint(value)) { 330 rv = board_attribute_set(config_name, 331 parse_integer(value)); 332 if (BCM_FAILURE(rv)) { 333 cli_out("Cannot set board attribute %s=%s:%s (%d)\n", 334 config_name, value, bcm_errmsg(rv), rv); 335 goto fail; 336 } 337 } else { 338 cli_out("Could not parse %s=%s\n", 339 config_name, value); 340 goto fail; 341 } 342 } 343 } 344 #endif 345 if (attr[i].get) { 346 int int_value; 347 char int_value_str[STRBUF]; 348 349 rv = board_attribute_get(config_name, &int_value); 350 if (BCM_SUCCESS(rv)) { 351 sal_sprintf(int_value_str, "%d", int_value); 352 if (var_set(config_name, int_value_str, FALSE, FALSE) < 0) { 353 goto fail; 354 } 355 } 356 } 357 } 358 359 /* Set board variables */ 360 if (var_set("board_name", board_name(), FALSE, FALSE) < 0) { 361 goto fail; 362 } 363 364 if (var_set(board_name(), "1", FALSE, FALSE) < 0) { 365 goto fail; 366 } 367 368 cmd_rv = CMD_OK; 369 370 fail: 371 if (attr) { 372 sal_free(attr); 373 } 374 375 return cmd_rv; 376 } 377 378 /* 379 * Function: 380 * board_cmd_register 381 * Purpose: 382 * Register a builtin driver of the given name 383 * Parameters: 384 * name - (IN) board driver to register 385 * Returns: 386 * CMD_OK - success 387 * CMD_FAIL - failed 388 */ 389 STATIC cmd_result_t 390 board_cmd_register(char *name) 391 { 392 board_driver_t **driver, *add; 393 int count, i; 394 int rv, cmd_rv = CMD_FAIL; 395 396 driver = NULL; 397 398 rv = board_driver_builtins_get(0, NULL, &count); 399 400 if (BCM_FAILURE(rv)) { 401 cli_out("board_driver_builtins_get: %s (%d)\n", bcm_errmsg(rv), rv); 402 goto fail; 403 } 404 405 driver = sal_alloc(count * sizeof(board_driver_t *), "board_cmd"); 406 407 if (!driver) { 408 cli_out("Out of memory\n"); 409 goto fail; 410 } 411 412 rv = board_driver_builtins_get(count, driver, &count); 413 if (BCM_FAILURE(rv)) { 414 cli_out("board_driver_builtins_get: %s (%d)\n", bcm_errmsg(rv), rv); 415 goto fail; 416 } 417 418 add = NULL; 419 for (i=0; i<count; i++) { 420 421 if (!sal_strcmp(name, driver[i]->name)) { 422 add = driver[i]; 423 break; 424 } 425 } 426 427 if (add) { 428 int rv; 429 430 rv = board_driver_add(add); 431 if (BCM_SUCCESS(rv)) { 432 cmd_rv = CMD_OK; 433 } else { 434 cli_out("Cannot add board driver %s:%s (%d)\n", 435 name, bcm_errmsg(rv), rv); 436 } 437 } else { 438 cli_out("Board driver %s not found\n", name); 439 } 440 441 fail: 442 if (driver) { 443 sal_free(driver); 444 } 445 446 return cmd_rv; 447 } 448 449 /* 450 * Function: 451 * board_cmd_unregister 452 * Purpose: 453 * Register a driver of the given name 454 * Parameters: 455 * name - (IN) board driver to unregister 456 * Returns: 457 * CMD_OK - success 458 * CMD_FAIL - failed 459 */ 460 STATIC cmd_result_t 461 board_cmd_unregister(char *name) 462 { 463 board_driver_t **driver, *del; 464 int count, i; 465 int rv, cmd_rv = CMD_FAIL; 466 467 rv = board_drivers_get(0, NULL, &count); 468 if (BCM_FAILURE(rv)) { 469 cli_out("board_drivers_get: %s (%d)\n", bcm_errmsg(rv), rv); 470 return CMD_FAIL; 471 } 472 473 driver = sal_alloc(count * sizeof(board_driver_t *), "board_cmd"); 474 475 if (!driver) { 476 cli_out("Out of memory\n"); 477 return CMD_FAIL; 478 } 479 480 rv = board_drivers_get(count, driver, &count); 481 if (BCM_FAILURE(rv)) { 482 cli_out("board_drivers_get: %s (%d)\n", bcm_errmsg(rv), rv); 483 sal_free(driver); 484 return CMD_FAIL; 485 } 486 487 del = NULL; 488 for (i=0; i<count; i++) { 489 490 if (!sal_strcmp(name, driver[i]->name)) { 491 del = driver[i]; 492 break; 493 } 494 495 } 496 if (del) { 497 int rv; 498 499 rv = board_driver_delete(del); 500 if (BCM_SUCCESS(rv)) { 501 cmd_rv = CMD_OK; 502 } else { 503 cli_out("Cannot delete board driver %s:%s (%d)\n", 504 name, bcm_errmsg(rv), rv); 505 } 506 } else { 507 cli_out("Board driver %s not registered\n", name); 508 } 509 510 sal_free(driver); 511 return cmd_rv; 512 } 513 514 /* 515 * Function: 516 * board_cmd_attr_print 517 * Purpose: 518 * Print short or long information about a board attribute 519 * Parameters: 520 * attr - (IN) attribute to print 521 * full - (IN) TRUE if full information is to be printed 522 * Returns: 523 * BCM_E_NONE - success 524 * BCM_E_XXX - failed 525 */ 526 STATIC int 527 board_cmd_attr_print(board_attribute_t *attr, int full) 528 { 529 int value, rv; 530 char valstr[STRBUF], *spacer, *units; 531 532 rv = board_attribute_get(attr->name, &value); 533 534 if (BCM_SUCCESS(rv)) { 535 536 /* print according to attribute format */ 537 sal_sprintf(valstr, attr->format ? attr->format : "%d", value); 538 539 if (full) { 540 /* get units if applicable */ 541 if (attr->units) { 542 spacer = " "; 543 units = attr->units; 544 } else { 545 spacer = units = ""; 546 } 547 548 /* display attribute */ 549 cli_out(" %-10s [%s]=%s%s%s\n", 550 attr->name, 551 ATTR_ACCESS(attr->set), 552 valstr, 553 spacer, 554 units); 555 } else { 556 cli_out("%s\n", valstr); 557 } 558 } else { 559 cli_out(" %s: %s (%d)\n", attr->name, bcm_errmsg(rv), rv); 560 } 561 562 return rv; 563 } 564 565 /* 566 * Function: 567 * board_cmd_attribute_list 568 * Purpose: 569 * Print arributes for the current board 570 * Parameters: 571 * name - (IN) Specific attribute to print, or NULL for all attributes 572 * Returns: 573 * CMD_OK - success 574 * CMD_FAIL - failed 575 */ 576 STATIC cmd_result_t 577 board_cmd_attribute_list(char *name) 578 { 579 board_attribute_t *attr; 580 int rv, count, i; 581 582 rv = board_attributes_get(0, NULL, &count); 583 if (BCM_FAILURE(rv)) { 584 cli_out("board_attributes_get: %s (%d)\n", bcm_errmsg(rv), rv); 585 return CMD_FAIL; 586 } 587 588 attr = sal_alloc(count * sizeof(board_attribute_t), "board_cmd"); 589 590 if (!attr) { 591 cli_out("Out of memory\n"); 592 return CMD_FAIL; 593 } 594 595 rv = board_attributes_get(count, attr, &count); 596 if (BCM_FAILURE(rv)) { 597 cli_out("board_attributes_get: %s (%d)\n", bcm_errmsg(rv), rv); 598 sal_free(attr); 599 return CMD_FAIL; 600 } 601 602 for (i=0; i<count; i++) { 603 if (name == NULL || !sal_strcmp(name, attr[i].name)) { 604 board_cmd_attr_print(&attr[i], TRUE); 605 } 606 } 607 608 sal_free(attr); 609 return CMD_OK; 610 } 611 612 /* 613 * Function: 614 * board_cmd_attribute_set 615 * Purpose: 616 * Set the attribute of the given name to the given value 617 * Parameters: 618 * name - (IN) attribute name 619 * value - (IN) value 620 * Returns: 621 * CMD_OK - success 622 * CMD_FAIL - failed 623 */ 624 STATIC cmd_result_t 625 board_cmd_attribute_set(char *name, char *value) 626 { 627 if (isint(value)) { 628 return CMD_SUCCESS(board_attribute_set(name, parse_integer(value))); 629 } 630 631 return CMD_FAIL; 632 } 633 634 #define MAX_CALL 4 635 #define MAX_NAME 16 636 637 /* 638 * Function: 639 * board_cmd_devport_name 640 * Purpose: 641 * Pretty print a gport DEVPORT name into a circular buffer. This 642 * intended to allow multiple calls to this function from printfs. 643 * Parameters: 644 * gport - (IN) gport to print 645 * Returns: 646 * static string name of port 647 */ 648 STATIC char * 649 board_cmd_devport_name(bcm_gport_t gport) 650 { 651 int unit; 652 bcm_port_t port; 653 char *s; 654 static char name[MAX_CALL][MAX_NAME]; 655 static int idx; 656 657 unit = BCM_GPORT_DEVPORT_DEVID_GET(gport); 658 port = BCM_GPORT_DEVPORT_PORT_GET(gport); 659 s = name[idx++]; 660 if (idx >= MAX_CALL) { 661 idx = 0; 662 } 663 if (bcm_unit_valid(unit) && port >= 0) { 664 sal_sprintf(s, "%d:%s", unit, bcm_port_name(unit, port)); 665 } else { 666 sal_sprintf(s, "%08x", gport); 667 } 668 return s; 669 } 670 671 /* 672 * Function: 673 * board_cmd_connection_print 674 * Purpose: 675 * Pretty print a board connection 676 * Parameters: 677 * connection - (IN) connection to print 678 * Returns: 679 * void 680 */ 681 STATIC void 682 board_cmd_connection_print(board_connection_t *connection) 683 { 684 if (connection->to != BCM_GPORT_TYPE_NONE) { 685 cli_out(" %8s -> %-8s\n", 686 board_cmd_devport_name(connection->from), 687 board_cmd_devport_name(connection->to)); 688 } else { 689 cli_out(" %s [stack]\n", board_cmd_devport_name(connection->from)); 690 } 691 } 692 693 /* 694 * Function: 695 * board_cmd_connection_list 696 * Purpose: 697 * List all connections for the current board 698 * Parameters: 699 * none 700 * Returns: 701 * CMD_OK - success 702 * CMD_FAIL - failed 703 */ 704 STATIC cmd_result_t 705 board_cmd_connection_list(void) 706 { 707 board_connection_t *conn; 708 int count, i; 709 710 if (BCM_FAILURE(board_connections_get(0, NULL, &count))) { 711 return CMD_FAIL; 712 } 713 714 conn = sal_alloc(count * sizeof(board_connection_t), "board_cmd"); 715 716 if (!conn) { 717 return CMD_FAIL; 718 } 719 720 if (BCM_FAILURE(board_connections_get(count, conn, &count))) { 721 sal_free(conn); 722 return CMD_FAIL; 723 } 724 725 for (i=0; i<count; i++) { 726 board_cmd_connection_print(&conn[i]); 727 } 728 729 sal_free(conn); 730 return CMD_OK; 731 } 732 733 /* 734 * Function: 735 * board_cmd_show 736 * Purpose: 737 * Print all information about the current board 738 * Parameters: 739 * none 740 * Returns: 741 * CMD_OK - success 742 * CMD_FAIL - failed 743 */ 744 STATIC cmd_result_t 745 board_cmd_show(void) 746 { 747 cli_out("Name:\n %s\n", S(board_name())); 748 cli_out("Description:\n %s\n", S(board_description())); 749 cli_out("Attributes:\n"); 750 board_cmd_attribute_list(NULL); 751 cli_out("Connections:\n"); 752 board_cmd_connection_list(); 753 return CMD_OK; 754 } 755 756 757 /* 758 * Function: 759 * board_cmd 760 * Purpose: 761 * Board Diag shell command handler 762 * Parameters: 763 * unit - (IN) current diag shell unit 764 * args - arglist 765 * Returns: 766 * CMD_OK - success 767 * CMD_FAIL - failed 768 */ 769 cmd_result_t 770 board_cmd(int unit, args_t *args) 771 { 772 char *subcmd; 773 int sublen; 774 int rv, cmd_rv; 775 static int init; 776 parse_table_t pt; 777 778 if (!init) { 779 rv = board_init(); 780 if (BCM_FAILURE(rv)) { 781 cli_out("board_init failed:%s (%d)\n", bcm_errmsg(rv), rv); 782 return CMD_FAIL; 783 } 784 rv = board_driver_builtins_add(); 785 if (BCM_FAILURE(rv)) { 786 cli_out("board_driver_builtins_add failed:%s (%d)\n", 787 bcm_errmsg(rv), rv); 788 return CMD_FAIL; 789 } 790 init=TRUE; 791 } 792 793 if ((subcmd = ARG_GET(args)) == NULL) { 794 return board_cmd_show(); 795 } 796 797 sublen=sal_strlen(subcmd); 798 if (sal_strncasecmp(subcmd, "show", sublen) == 0) { 799 return board_cmd_show(); 800 801 } else if (sal_strncasecmp(subcmd, "select", sublen) == 0) { 802 char *name; 803 int flagidx; 804 805 name=NULL; 806 flagidx=-1; 807 /* if flags are numeric, add to flag multi list */ 808 809 if (ARG_CNT(args) > 0) { 810 board_cmd_parse_numeric_start_flag(args); 811 parse_table_init(unit, &pt); 812 parse_table_add(&pt, "Name", PQ_STRING, 0, &name, 0); 813 parse_table_add(&pt, "Flags", PQ_DFL | PQ_MULTI, 0, &flagidx, 814 board_cmd_flag_list); 815 816 if (parse_arg_eq(args, &pt)) { 817 cli_out("select name:%s flag:%08x\n", 818 S(name), board_cmd_flag_value[flagidx]); 819 } else { 820 return CMD_USAGE; 821 } 822 } else { 823 name = ""; 824 } 825 return board_cmd_start(name, flagidx); 826 827 } else if (sal_strncasecmp(subcmd, "detach", sublen) == 0) { 828 cli_out("detach\n"); 829 rv = board_detach(); 830 return CMD_SUCCESS(rv); 831 832 } else if (sal_strncasecmp(subcmd, "list", sublen) == 0) { 833 return board_cmd_list(); 834 } else if (sal_strncasecmp(subcmd, "register", sublen) == 0) { 835 char *builtin; 836 837 builtin = ARG_CUR(args); 838 if (builtin != NULL && 839 sal_strncasecmp(builtin, "builtin", sal_strlen(builtin)) == 0) { 840 ARG_NEXT(args); 841 cli_out("register builtin\n"); 842 rv = board_driver_builtins_add(); 843 return CMD_SUCCESS(rv); 844 } else { 845 char *name; 846 847 name=NULL; 848 parse_table_init(unit, &pt); 849 parse_table_add(&pt, "Name", PQ_STRING, 0, &name, 0); 850 if (parse_arg_eq(args, &pt)) { 851 cmd_rv = board_cmd_register(name); 852 } else { 853 cmd_rv = CMD_USAGE; 854 } 855 } 856 return cmd_rv; 857 } else if (sal_strncasecmp(subcmd, "unregister", sublen) == 0) { 858 char *name; 859 860 name=NULL; 861 parse_table_init(unit, &pt); 862 parse_table_add(&pt, "Name", PQ_STRING, 0, &name, 0); 863 if (parse_arg_eq(args, &pt)) { 864 cmd_rv = board_cmd_unregister(name); 865 } else { 866 cmd_rv = CMD_USAGE; 867 } 868 return cmd_rv; 869 } else if (sal_strncasecmp(subcmd, "attribute", sublen) == 0) { 870 char *name, *value; 871 872 name = ARG_CUR(args); 873 if (name == NULL) { 874 cmd_rv = board_cmd_attribute_list(NULL); 875 } else { 876 value = sal_strchr(name, '='); 877 878 if (!value) { 879 board_cmd_attribute_list(name); 880 } else { 881 *value='\0'; 882 value++; 883 board_cmd_attribute_set(name, value); 884 } 885 ARG_NEXT(args); 886 } 887 return CMD_OK; 888 } else if (sal_strncasecmp(subcmd, "clear", sublen) == 0) { 889 cli_out("clear\n"); 890 return CMD_OK; 891 } else { 892 cli_out("Subcommand not found: %s\n", subcmd); 893 return CMD_USAGE; 894 } 895 896 return CMD_OK; 897 } 898 899 #endif /* INCLUDE_BAORD */