sysconf.c (18651B)
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 8 9 #include <sal/types.h> 10 #include <sal/core/libc.h> 11 #include <shared/alloc.h> 12 #include <shared/bsl.h> 13 #include <sal/core/spl.h> 14 #include <sal/appl/pci.h> 15 #include <sal/appl/sal.h> 16 #include <sal/appl/config.h> 17 #include <sal/appl/io.h> 18 19 #include <soc/debug.h> 20 #include <soc/cmext.h> 21 #include <soc/drv.h> 22 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_XGS3_SWITCH_SUPPORT) 23 #include <soc/rcpu.h> 24 #endif /* defined(BCM_RCPU_SUPPORT) && defined(BCM_XGS3_SWITCH_SUPPORT) */ 25 #include <bcm/init.h> 26 #include <appl/diag/system.h> 27 #include <appl/diag/sysconf.h> 28 #if defined(BCM_DFE_SUPPORT) || defined(BCM_PETRA_SUPPORT) 29 #if defined(INCLUDE_INTR) 30 #include <appl/dcmn/interrupts/interrupt_handler.h> 31 #endif 32 #endif 33 #include <ibde.h> 34 #include <soc/util.h> 35 36 extern int bde_create(void); /* provide by configuration/socdiag */ 37 extern int soc_phy_fw_acquire_default(const char *file_name, uint8 **fw, int *fw_len); 38 extern int soc_phy_fw_release_default(const char *dev_name, uint8 *fw, int fw_len); 39 40 /* SOC Configuration Manager Device Vectors */ 41 42 static char * 43 _sysconf_get_property(const char *property) 44 { 45 #ifndef NO_SAL_APPL 46 return sal_config_get(property); 47 #else 48 return NULL; 49 #endif 50 } 51 52 static char * 53 _config_var_get(soc_cm_dev_t *dev, const char *property) 54 { 55 COMPILER_REFERENCE(dev); 56 57 return _sysconf_get_property(property); 58 } 59 60 static void 61 _write(soc_cm_dev_t *dev, uint32 addr, uint32 data) 62 { 63 bde->write(dev->dev, addr, data); 64 } 65 66 static uint32 67 _read(soc_cm_dev_t *dev, uint32 addr) 68 { 69 return bde->read(dev->dev, addr); 70 } 71 72 static void 73 _write_null(soc_cm_dev_t *dev, uint32 addr, uint32 data) 74 { 75 return; 76 } 77 78 static uint32 79 _read_null(soc_cm_dev_t *dev, uint32 addr) 80 { 81 return 0; 82 } 83 84 static void * 85 _salloc(soc_cm_dev_t *dev, int size, const char *name) 86 { 87 COMPILER_REFERENCE(name); 88 return bde->salloc(dev->dev, size, name); 89 } 90 91 static void 92 _sfree(soc_cm_dev_t *dev, void *ptr) 93 { 94 bde->sfree(dev->dev, ptr); 95 } 96 97 static int 98 _sflush(soc_cm_dev_t *dev, void *addr, int length) 99 { 100 return (bde->sflush) ? bde->sflush(dev->dev, addr, length) : 0; 101 } 102 103 static int 104 _sinval(soc_cm_dev_t *dev, void *addr, int length) 105 { 106 return (bde->sinval) ? bde->sinval(dev->dev, addr, length) : 0; 107 } 108 109 static sal_paddr_t 110 _l2p(soc_cm_dev_t *dev, void *addr) 111 { 112 return (bde->l2p) ? bde->l2p(dev->dev, addr) : 0; 113 } 114 115 static void* 116 _p2l(soc_cm_dev_t *dev, sal_paddr_t addr) 117 { 118 return (bde->p2l) ? bde->p2l(dev->dev, addr) : 0; 119 } 120 121 static void 122 _iproc_write(soc_cm_dev_t *dev, uint32 addr, uint32 data) 123 { 124 bde->iproc_write(dev->dev, addr, data); 125 } 126 127 static uint32 128 _iproc_read(soc_cm_dev_t *dev, uint32 addr) 129 { 130 return bde->iproc_read(dev->dev, addr); 131 } 132 133 static int 134 _interrupt_connect(soc_cm_dev_t *dev, soc_cm_isr_func_t handler, void *data) 135 { 136 return bde->interrupt_connect(dev->dev, handler, data); 137 } 138 139 static int 140 _interrupt_disconnect(soc_cm_dev_t *dev) 141 { 142 return bde->interrupt_disconnect(dev->dev); 143 } 144 145 static int 146 _interrupt_connect_null(soc_cm_dev_t *dev, soc_cm_isr_func_t handler, void *data) 147 { 148 return 0; 149 } 150 151 static int 152 _interrupt_disconnect_null(soc_cm_dev_t *dev) 153 { 154 return 0; 155 } 156 157 static void 158 _pci_conf_write(soc_cm_dev_t *dev, uint32 addr, uint32 data) 159 { 160 bde->pci_conf_write(dev->dev, addr, data); 161 } 162 163 static uint32 164 _pci_conf_read(soc_cm_dev_t *dev, uint32 addr) 165 { 166 return bde->pci_conf_read(dev->dev, addr); 167 } 168 169 static int 170 _spi_read(soc_cm_dev_t *dev, uint32 addr, uint8 *buf, int len) 171 { 172 return (bde->spi_read) ? bde->spi_read(dev->dev, addr, buf, len) : -1; 173 } 174 175 static int 176 _spi_write(soc_cm_dev_t *dev, uint32 addr, uint8 *buf, int len) 177 { 178 return (bde->spi_write) ? bde->spi_write(dev->dev, addr, buf, len) : -1; 179 } 180 181 static int 182 _i2c_device_read(soc_cm_dev_t *dev, uint32 addr, uint32 *value) 183 { 184 return (bde->i2c_device_read) ? bde->i2c_device_read(dev->dev, addr, value) : -1; 185 } 186 187 static int 188 _i2c_device_write(soc_cm_dev_t *dev, uint32 addr, uint32 value) 189 { 190 return (bde->i2c_device_write) ? bde->i2c_device_write(dev->dev, addr, value) : -1; 191 } 192 193 /* 194 * Function: 195 * sysconf_chip_override 196 * Purpose: 197 * For driver testing only, allow properties to override the PCI 198 * device ID/rev ID for a particular unit to specified values. 199 * Parameters: 200 * unit - Unit number 201 * devID, revID - (IN, OUT) original PCI ID info 202 */ 203 204 void 205 sysconf_chip_override(int unit, uint16 *devID, uint8 *revID) 206 { 207 char prop[64], *s; 208 209 if ((*devID == BCM88670_DEVICE_ID) && (*revID == QMX_A0_REV_ID)) 210 { 211 *devID = QMX_DEVICE_ID; 212 } 213 214 sal_sprintf(prop, "pci_override_dev.%d", unit); 215 216 if ((s = _sysconf_get_property(prop)) == NULL) { 217 s = _sysconf_get_property("pci_override_dev"); 218 } 219 220 if (s != NULL) { 221 *devID = sal_ctoi(s, 0); 222 } 223 224 sal_sprintf(prop, "pci_override_rev.%d", unit); 225 226 if ((s = _sysconf_get_property(prop)) == NULL) { 227 s = _sysconf_get_property("pci_override_rev"); 228 } 229 230 if (s != NULL) { 231 *revID = sal_ctoi(s, 0); 232 } 233 234 if (SAL_BOOT_BCMSIM && *devID == 0xb260) 235 { 236 *devID = 0xb460; 237 } 238 } 239 240 /* 241 * _setup_bus 242 * 243 * Utility routine used by sysconf_probe 244 */ 245 246 static int 247 _setup_bus(int unit) 248 { 249 uint16 driverDevID; 250 uint8 driverRevID; 251 const ibde_dev_t *dev = bde->get_dev(unit); 252 char *bus_type; 253 uint8 revID = dev->rev; 254 255 #if defined(BCM_ENDURO_SUPPORT) 256 /* 257 * For Enduro, read revision ID from CMIC instead of PCIe config space. 258 */ 259 if (!SAL_BOOT_BCMSIM && 260 ((dev->device == BCM56132_DEVICE_ID) || 261 (dev->device == BCM56134_DEVICE_ID) || 262 (dev->device == BCM56320_DEVICE_ID) || 263 (dev->device == BCM56321_DEVICE_ID) || 264 (dev->device == BCM56331_DEVICE_ID) || 265 (dev->device == BCM56333_DEVICE_ID) || 266 (dev->device == BCM56334_DEVICE_ID) || 267 (dev->device == BCM56338_DEVICE_ID) || 268 (dev->device == BCM56230_DEVICE_ID) || 269 (dev->device == BCM56231_DEVICE_ID))) { 270 revID = (bde->read(unit, CMIC_REVID_DEVID) >> 16) & 0xff; 271 } 272 #endif /* BCM_ENDURO_SUPPORT */ 273 274 soc_cm_get_id_driver(dev->device, revID, 275 &driverDevID, &driverRevID); 276 277 switch(bde->get_dev_type(unit) & BDE_DEV_BUS_TYPE_MASK) 278 { 279 case BDE_PCI_DEV_TYPE: 280 bus_type = "PCI"; 281 break; 282 case BDE_SPI_DEV_TYPE: 283 bus_type = "SPI"; 284 break; 285 case BDE_EB_DEV_TYPE: 286 bus_type = "EB"; 287 break; 288 case BDE_ICS_DEV_TYPE: 289 bus_type = "ICS"; 290 break; 291 case (BDE_SPI_DEV_TYPE|BDE_EB_DEV_TYPE) : 292 bus_type = "SPI/EB"; 293 break; 294 case BDE_ET_DEV_TYPE: 295 bus_type = "ETH"; 296 break; 297 case BDE_EMMI_DEV_TYPE: 298 bus_type = "EMMI"; 299 break; 300 case BDE_AXI_DEV_TYPE: 301 bus_type = "AXI"; 302 break; 303 case BDE_I2C_DEV_TYPE: 304 bus_type = "I2C"; 305 break; 306 default: 307 cli_out("Error : Unknow bus type 0x%x !!\n", 308 bde->get_dev_type(unit) & BDE_DEV_BUS_TYPE_MASK); 309 return -1; 310 } 311 312 cli_out("%s unit %d: " 313 "Dev 0x%04x, Rev 0x%02x, Chip %s, Driver %s\n", 314 bus_type, unit, 315 dev->device, revID, 316 soc_cm_get_device_name(dev->device, revID), 317 soc_cm_get_device_name(driverDevID, driverRevID)); 318 319 /* 320 * Sanity check to ensure first CMIC register is accessible. 321 */ 322 323 if (dev->base_address) { 324 #ifndef __KERNEL__ 325 if (sal_memory_check((uint32)dev->base_address) < 0) { 326 cli_out("sysconf_probe: unable to probe address 0x%x\n", 327 (uint32)dev->base_address); 328 return -1; 329 } 330 #endif 331 } 332 333 return 0; 334 } 335 336 337 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_XGS3_SWITCH_SUPPORT) 338 339 #ifdef BCM_CMICM_SUPPORT 340 static uint32 341 _rcpu_read(soc_cm_dev_t *dev, uint32 addr) 342 { 343 return soc_rcpu_cmic_read(dev->dev, addr); 344 } 345 346 static void 347 _rcpu_write(soc_cm_dev_t *dev, uint32 addr, uint32 data) 348 { 349 soc_rcpu_cmic_write(dev->dev, addr, data); 350 } 351 #endif /* BCM_CMICM_SUPPORT */ 352 353 static void 354 _rcpu_config_get(int unit, soc_rcpu_cfg_t *cfg) 355 { 356 char *str; 357 char prop[64]; 358 359 sal_sprintf(prop, "rcpu_lmac.%d", unit); 360 str = _sysconf_get_property(prop); 361 if (str != NULL) { 362 (void)parse_macaddr(str, cfg->dst_mac); 363 } else { 364 str = DEFAULT_RCPU_DST_MAC; 365 (void)parse_macaddr(str, cfg->dst_mac); 366 cfg->dst_mac[5] = unit; 367 } 368 369 sal_sprintf(prop, "rcpu_src_mac.%d", unit); 370 str = _sysconf_get_property(prop); 371 if (str != NULL) { 372 (void)parse_macaddr(str, cfg->src_mac); 373 } else { 374 str = DEFAULT_RCPU_SRC_MAC; 375 (void)parse_macaddr(str, cfg->dst_mac); 376 } 377 378 cfg->tpid = DEFAULT_RCPU_TPID; 379 380 sal_sprintf(prop, "rcpu_vlan.%d", unit); 381 str = _sysconf_get_property(prop); 382 if (str != NULL) { 383 cfg->vlan = sal_ctoi(str, 0); 384 } else { 385 cfg->vlan = DEFAULT_RCPU_VLAN; 386 } 387 388 sal_sprintf(prop, "rcpu_port.%d", unit); 389 str = _sysconf_get_property(prop); 390 if (str != NULL) { 391 cfg->port = sal_ctoi(str, 0); 392 } else { 393 cfg->port = -1; 394 } 395 396 cfg->ether_type = DEFAULT_RCPU_ETHER_TYPE; 397 cfg->signature = DEFAULT_RCPU_SIGNATURE; 398 } 399 #endif /* BCM_RCPU_SUPPORT && BCM_XGS3_SWITCH_SUPPORT */ 400 401 /* 402 * sysconf_probe 403 * 404 * Searches for known devices and creates Configuration Manager instances. 405 */ 406 407 int sysconf_probe_done; 408 409 int 410 sysconf_probe(void) 411 { 412 int u; 413 #ifndef NDEBUG 414 int cm_dev = 0; 415 #endif /* !NDEBUG*/ 416 uint16 devID; 417 uint8 revID; 418 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_XGS3_SWITCH_SUPPORT) 419 soc_rcpu_cfg_t *rcpu_cfg = NULL; 420 #endif 421 if (sysconf_probe_done) { 422 cli_out("sysconf_probe: cannot probe more than once\n"); 423 return -1; 424 } 425 426 427 /* 428 * Initialize system BDE 429 */ 430 if (bde_create()) { 431 return -1; 432 } 433 434 /* Iterate over device */ 435 for (u = 0; u < bde->num_devices(BDE_ALL_DEVICES) && u < SOC_MAX_NUM_DEVICES; u++) { 436 const ibde_dev_t *dev = bde->get_dev(u); 437 devID = dev->device; 438 revID = dev->rev; 439 440 #if defined(BCM_ENDURO_SUPPORT) 441 /* 442 * For Enduro, read revision ID from CMIC instead of PCIe config space. 443 */ 444 if (!SAL_BOOT_BCMSIM && 445 ((devID == BCM56132_DEVICE_ID) || (devID == BCM56134_DEVICE_ID) || 446 (devID == BCM56320_DEVICE_ID) || (devID == BCM56321_DEVICE_ID) || 447 (devID == BCM56331_DEVICE_ID) || (devID == BCM56333_DEVICE_ID) || 448 (devID == BCM56334_DEVICE_ID) || (devID == BCM56338_DEVICE_ID) || 449 (devID == BCM56230_DEVICE_ID) || (devID == BCM56231_DEVICE_ID))) { 450 uint32 config = 0; 451 int big_pio, big_packet, big_other; 452 453 bde->pci_bus_features(u, &big_pio, &big_packet, &big_other); 454 455 if (big_pio) { 456 config |= ES_BIG_ENDIAN_PIO; 457 } 458 if (big_packet) { 459 config |= ES_BIG_ENDIAN_DMA_PACKET; 460 } 461 if (big_other) { 462 config |= ES_BIG_ENDIAN_DMA_OTHER; 463 } 464 465 bde->write(u, CMIC_ENDIAN_SELECT, config); 466 revID = (bde->read(u, CMIC_REVID_DEVID) >> 16) & 0xff; 467 } 468 #endif /* BCM_ENDURO_SUPPORT */ 469 470 sysconf_chip_override(u, &devID, &revID); 471 472 if (soc_cm_device_supported(devID, revID) < 0) { 473 /* Not a switch chip; continue probing other devices */ 474 cli_out("warning: device 0x%x revision 0x%x is not supported\n", (unsigned)devID, (unsigned)revID); 475 return 0; 476 } 477 478 if (_setup_bus(u) < 0) { 479 /* 480 * Error message already printed; continue probing other 481 * devices 482 */ 483 return 0; 484 } 485 486 /* 487 * Create a device handle, but don't initialize yet. This 488 * sneakily relies upon the fact that the cm handle = bde 489 * handle, which will probably get me into trouble some day. 490 * Since this is really just a minimal port to support the BDE 491 * interface, I'm hoping it will get rewritten more than this. 492 */ 493 #ifndef NDEBUG 494 cm_dev = 495 #endif /* !NDEBUG*/ 496 soc_cm_device_create(devID, revID, NULL); 497 498 assert(cm_dev >= 0); 499 assert(cm_dev == u); 500 sysconf_probe_done++; 501 } 502 503 504 505 506 if(_sysconf_get_property("extra_unit_min") && 507 _sysconf_get_property("extra_unit_max")) { 508 509 int u, min, max; 510 511 min = sal_ctoi(_sysconf_get_property("extra_unit_min"), 0); 512 max = sal_ctoi(_sysconf_get_property("extra_unit_max"), 0); 513 514 for(u = min; u <= max; u++) { 515 char prop[64]; 516 uint16 devid = 0; 517 uint8 revid; 518 sal_sprintf(prop, "extra_unit.%d", u); 519 if(_sysconf_get_property(prop)) { 520 sysconf_chip_override(u, &devid, &revid); 521 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_XGS3_SWITCH_SUPPORT) 522 sal_sprintf(prop, "rcpu_only.%d", u); 523 if(_sysconf_get_property(prop) && 524 (1 == sal_ctoi(_sysconf_get_property(prop), 0))) { 525 rcpu_cfg = (soc_rcpu_cfg_t *)sal_alloc(sizeof(soc_rcpu_cfg_t), 526 "SYSCONF RCPU"); 527 _rcpu_config_get(u, rcpu_cfg); 528 soc_cm_device_create(devid, revid, rcpu_cfg); 529 } else 530 #endif /* defined(BCM_RCPU_SUPPORT) && defined(BCM_XGS3_SWITCH_SUPPORT) */ 531 { 532 soc_cm_device_create(devid, revid, NULL); 533 } 534 } 535 } 536 } 537 538 return 0; 539 } 540 541 int 542 sysconf_attach(int unit) 543 { 544 /* Ready to install into configuration manager */ 545 soc_cm_device_vectors_t vectors; 546 char prop[64]; 547 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_XGS3_SWITCH_SUPPORT) 548 char *s; 549 #endif /* BCM_RCPU_SUPPORT && BCM_XGS3_SWITCH_SUPPORT */ 550 551 sal_memset(&vectors, 0, sizeof(soc_cm_device_vectors_t)); 552 /* 553 * Install extra devices separately to void calls to the BDE. 554 */ 555 sal_sprintf(prop, "extra_unit.%d", unit); 556 if(_sysconf_get_property(prop)) { 557 vectors.config_var_get = _config_var_get; 558 vectors.interrupt_connect = _interrupt_connect_null; 559 vectors.interrupt_disconnect= _interrupt_disconnect_null; 560 vectors.base_address = 0; 561 vectors.read = _read_null; 562 vectors.write = _write_null; 563 vectors.pci_conf_read = _pci_conf_read; 564 vectors.pci_conf_write = _pci_conf_write; 565 vectors.salloc = _salloc; 566 vectors.sfree = _sfree; 567 vectors.sinval = _sinval; 568 vectors.sflush = _sflush; 569 vectors.l2p = _l2p; 570 vectors.p2l = _p2l; 571 vectors.bus_type = 0; 572 vectors.i2c_device_read = _i2c_device_read; 573 vectors.i2c_device_write = _i2c_device_write; 574 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_XGS3_SWITCH_SUPPORT) 575 sal_sprintf(prop, "rcpu_only.%d", unit); 576 s = _sysconf_get_property(prop); 577 if(NULL != s && (1 == sal_ctoi(s, 0))) { 578 vectors.bus_type = SOC_RCPU_DEV_TYPE; 579 #ifdef BCM_CMICM_SUPPORT 580 vectors.read = _rcpu_read; 581 vectors.write = _rcpu_write; 582 #endif /* BCM_CMICM_SUPPORT */ 583 #ifdef BCM_OOB_RCPU_SUPPORT 584 sal_sprintf(prop, "rcpu_use_oob.%d", unit); 585 s = _sysconf_get_property(prop); 586 if(NULL != s && (1 == sal_ctoi(s, 0))) { 587 vectors.rcpu_tp = &rcpu_oob_trans_ptr; 588 } else 589 #endif /* BCM_OOB_RCPU_SUPPORT */ 590 { 591 vectors.rcpu_tp = &rcpu_trans_ptr; 592 } 593 } 594 #endif /* BCM_RCPU_SUPPORT && BCM_XGS3_SWITCH_SUPPORT */ 595 596 if (soc_cm_device_init(unit, &vectors) < 0) { 597 cli_out("sysconf_attach: bcm device init failed\n"); 598 return -1; 599 } 600 return 0; 601 } 602 603 /* Proceed with BDE device initialization */ 604 605 assert(unit >= 0 && unit < bde->num_devices(BDE_ALL_DEVICES)); 606 607 bde->pci_bus_features(unit, &vectors.big_endian_pio, 608 &vectors.big_endian_packet, 609 &vectors.big_endian_other); 610 vectors.config_var_get = _config_var_get; 611 vectors.interrupt_connect = _interrupt_connect; 612 vectors.interrupt_disconnect= _interrupt_disconnect; 613 #if defined(PCI_DECOUPLED) || defined(BCM_ICS) 614 vectors.base_address = 0; 615 #else 616 vectors.base_address = bde->get_dev(unit)->base_address; 617 #endif 618 vectors.read = _read; 619 vectors.write = _write; 620 vectors.pci_conf_read = _pci_conf_read; 621 vectors.pci_conf_write = _pci_conf_write; 622 vectors.salloc = _salloc; 623 vectors.sfree = _sfree; 624 vectors.sinval = _sinval; 625 vectors.sflush = _sflush; 626 vectors.l2p = _l2p; 627 vectors.p2l = _p2l; 628 vectors.iproc_read = _iproc_read; 629 vectors.iproc_write = _iproc_write; 630 vectors.bus_type = bde->get_dev_type(unit); 631 vectors.spi_read = _spi_read; 632 vectors.spi_write = _spi_write; 633 vectors.i2c_device_read = _i2c_device_read; 634 vectors.i2c_device_write = _i2c_device_write; 635 if (soc_cm_device_init(unit, &vectors) < 0) { 636 cli_out("sysconf_attach: bcm device init failed\n"); 637 return -1; 638 } 639 return 0; 640 } 641 642 int 643 sysconf_detach(int unit) 644 { 645 #ifdef BCM_RCPU_SUPPORT 646 assert(unit >= 0 && unit < soc_cm_get_num_devices()); 647 #else 648 assert(unit >= 0 && unit < bde->num_devices(BDE_ALL_DEVICES)); 649 #endif 650 #if (defined(BCM_DFE_SUPPORT) || defined(BCM_PETRA_SUPPORT)) && defined(INCLUDE_INTR) 651 if ((SOC_IS_FE1600(unit)) || (SOC_IS_ARAD(unit))){ 652 interrupt_handler_appl_deinit(unit); 653 } 654 #endif 655 if (!bcm_attach_check(unit)) { 656 if (bcm_detach(unit) < 0) { 657 cli_out("sysconf_detach: bcm detach failed\n"); 658 return -1; 659 } 660 } 661 662 /* COVERITY 663 * Intentional stack usage 664 */ 665 /* coverity[stack_use_return : FALSE] */ 666 /* coverity[stack_use_callee_max : FALSE] */ 667 /* coverity[stack_use_overflow : FALSE] */ 668 if (soc_cm_device_destroy(unit) < 0) { 669 cli_out("sysconf_detach: soc_cm_device_destroy failed\n"); 670 return -1; 671 } 672 sysconf_probe_done--; 673 674 return 0; 675 } 676 677 int 678 sysconf_init(void) 679 { 680 soc_phy_fw_init(); 681 soc_phy_fw_acquire = soc_phy_fw_acquire_default; 682 soc_phy_fw_release = soc_phy_fw_release_default; 683 684 return soc_cm_init(); 685 }