external_stack.c (20256B)
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: external_stack.c 8 * 9 * Purpose: 10 * 11 * Functions: 12 * _bcm_ptp_external_stack_create 13 * _bcm_ptp_ext_stack_reset 14 * _bcm_ptp_ext_stack_start 15 * _bcm_ptp_write_pcishared_uint8_aligned_array 16 * 17 * esw_set_ext_stack_config_uint32 18 * esw_set_ext_stack_config_array 19 */ 20 21 #if defined(INCLUDE_PTP) 22 23 #include <soc/defs.h> 24 #include <soc/drv.h> 25 26 #include <sal/appl/io.h> 27 #include <sal/core/dpc.h> 28 29 #include <bcm/ptp.h> 30 #include <bcm_int/common/ptp.h> 31 #include <bcm/error.h> 32 33 #if defined(BCM_PTP_EXTERNAL_STACK_SUPPORT) 34 35 #include <soc/uc_msg.h> 36 37 /* Constants */ 38 #define FAULT_CHECK_US (100000) /* every .1 seconds */ 39 40 /* Event support (ToP OUT-OF-MEMORY).*/ 41 #define TOP_OOM_MSGDATA_SIZE_OCTETS (8) 42 #define TOP_OOM_MINIMUM_FREE_MEMORY_THRESHOLD_BYTES (1024) 43 #define TOP_OOM_ORDBLK_FREE_MEMORY_THRESHOLD_BYTES (1024) 44 45 /* For simplicity, a single FW-info structure. Need per-unit/per-stack 46 if multiple Keystone ToPs can be used simultaneously 47 */ 48 static _bcm_ptp_ext_fw_info_t top_fw_info; 49 50 extern int _bcm_ptp_write_ks_uint32(int idx, uint32 addr, uint32 val); 51 extern int _bcm_ptp_read_ks_uint32(int idx, uint32 addr, uint32 *value); 52 53 extern void _bcm_ptp_read_pcishared_uint8_aligned_array( 54 int pci_idx, 55 uint32 addr, 56 uint8 * array, 57 int array_len); 58 59 extern void _bcm_ptp_write_pcishared_uint8_aligned_array( 60 int pci_idx, 61 uint32 addr, 62 uint8 * array, 63 int array_len); 64 65 extern int _bcm_ptp_ext_stack_reset(int pci_idx); 66 67 /* 68 * Function: 69 * _bcm_ptp_external_stack_create 70 * Purpose: 71 * Create a PTP stack instance 72 * Parameters: 73 * unit - (IN) Unit number. 74 * ptp_info - (IN/OUT) Pointer to an PTP Stack Info structure 75 * Returns: 76 * BCM_E_... 77 * Notes: 78 */ 79 int 80 _bcm_ptp_external_stack_create( 81 int unit, 82 bcm_ptp_stack_info_t *info, 83 bcm_ptp_stack_id_t ptp_id) 84 { 85 _bcm_ptp_info_t *ptp_info_p; 86 _bcm_ptp_stack_info_t *stack_p; 87 uint32 tpidvlan; 88 89 SET_PTP_INFO; 90 if (!SOC_HAS_PTP_EXTERNAL_STACK_SUPPORT(unit)) { 91 return BCM_E_UNAVAIL; 92 } 93 94 stack_p = &ptp_info_p->stack_info[ptp_id]; 95 96 /* Set up dispatch for external transport */ 97 stack_p->transport_init = _bcm_ptp_external_transport_init; 98 stack_p->tx = _bcm_ptp_external_tx; 99 stack_p->tx_completion = _bcm_ptp_external_tx_completion; 100 stack_p->rx_free = _bcm_ptp_external_rx_response_free; 101 stack_p->transport_terminate = _bcm_ptp_external_transport_terminate; 102 103 /* Assuming that the unit has been locked by the caller */ 104 sal_memcpy(&stack_p->ext_info, info->ext_stack_info, sizeof(bcm_ptp_external_stack_info_t)); 105 106 /* Set the PCI read and write functions */ 107 stack_p->ext_info.cookie = INT_TO_PTR(ptp_id); 108 stack_p->ext_info.read_fn = &_bcm_ptp_read_pcishared_uint32; 109 stack_p->ext_info.write_fn = &_bcm_ptp_write_pcishared_uint32; 110 111 /* Config for Host <-> BCM53903 comms */ 112 esw_set_ext_stack_config_array(stack_p, CONFIG_HOST_OFFSET, stack_p->ext_info.host_mac, 6); 113 114 esw_set_ext_stack_config_array(stack_p, CONFIG_HOST_OFFSET + 8, stack_p->ext_info.top_mac, 6); 115 116 esw_set_ext_stack_config_uint32(stack_p, CONFIG_HOST_OFFSET + 16, stack_p->ext_info.host_ip_addr); 117 118 esw_set_ext_stack_config_uint32(stack_p, CONFIG_HOST_OFFSET + 20, stack_p->ext_info.top_ip_addr); 119 120 tpidvlan = 0x81000000 + ((int)(stack_p->ext_info.vlan_pri) << 13) + stack_p->ext_info.vlan; 121 122 esw_set_ext_stack_config_uint32(stack_p, CONFIG_HOST_OFFSET + 24, tpidvlan); 123 124 /* Config for BCM53903 that is currently hardwired on host side */ 125 /* outer / inner TPIDs for VLAN */ 126 esw_set_ext_stack_config_uint32(stack_p, CONFIG_VLAN_OFFSET, 0x91008100); 127 /* MPLS label ethertype */ 128 esw_set_ext_stack_config_uint32(stack_p, CONFIG_MPLS_OFFSET, 0x88470000); 129 130 #if 0 131 132 SOC_PBMP_PORT_ADD(pbmp, 0x03008000); 133 #endif 134 135 /* Set config for loaded firmware */ 136 _bcm_ptp_write_pcishared_uint8_aligned_array(ptp_id, CONFIG_BASE, stack_p->persistent_config, CONFIG_TOTAL_SIZE); 137 138 _bcm_ptp_ext_stack_start(ptp_id); 139 140 return BCM_E_NONE; 141 } 142 143 144 /* Set RCPU information for ToP processor and supply rule table. */ 145 int 146 _bcm_ptp_rcpu_configuration_set( 147 int unit, 148 bcm_ptp_stack_id_t ptp_id, 149 uint16 rcpu_ethertype, 150 uint16 rcpu_signature, 151 uint16 rcpu_tpid, 152 uint16 rcpu_vlan, 153 int top_port, 154 uint16 rcpu_reflected_ethertype, 155 bcm_mac_t switch_mac) 156 { 157 _bcm_ptp_info_t *ptp_info_p; 158 _bcm_ptp_stack_info_t *stack_p; 159 160 SET_PTP_INFO; 161 if (!SOC_HAS_PTP_EXTERNAL_STACK_SUPPORT(unit)) { 162 return BCM_E_UNAVAIL; 163 } 164 165 stack_p = &ptp_info_p->stack_info[ptp_id]; 166 167 esw_set_ext_stack_config_uint32(stack_p, CONFIG_RCPU_OFFSET + 0, rcpu_ethertype); 168 esw_set_ext_stack_config_uint32(stack_p, CONFIG_RCPU_OFFSET + 4, rcpu_signature); 169 esw_set_ext_stack_config_uint32(stack_p, CONFIG_RCPU_OFFSET + 8, rcpu_tpid); 170 esw_set_ext_stack_config_uint32(stack_p, CONFIG_RCPU_OFFSET + 12, rcpu_vlan); 171 esw_set_ext_stack_config_uint32(stack_p, CONFIG_RCPU_OFFSET + 16, top_port); 172 esw_set_ext_stack_config_uint32(stack_p, CONFIG_RCPU_OFFSET + 20, rcpu_reflected_ethertype); 173 esw_set_ext_stack_config_array(stack_p, CONFIG_RCPU_OFFSET + 24, switch_mac, 6); 174 175 return BCM_E_NONE; 176 } 177 178 179 int _bcm_ptp_ext_stack_reset(int pci_idx) 180 { 181 /*** Reset Core & ChipCommon in DMP ***/ 182 /* CPU Master DMP : soft reset : resetctrl (0x18103800) <- 0x1 (bit[0] <- 1 enter reset) */ 183 BCM_IF_ERROR_RETURN(_bcm_ptp_write_ks_uint32(pci_idx, 0x18103800, 1)); 184 /* ChipCommon Master DMP : soft reset : resetctrl (0x18100800) <- 0x1 (bit[0] <- 1 enter reset) */ 185 BCM_IF_ERROR_RETURN(_bcm_ptp_write_ks_uint32(pci_idx, 0x18100800, 1)); 186 187 /* delay 1ms */ 188 sal_usleep(1000); 189 190 /*** Enable Core & ChipCommon clocks and bring out of DMP reset ***/ 191 /* CPU Master DMP : enable clock : ioctrl (0x18103408) <- 0x1 (bit[0] <- 1 enable clock) */ 192 BCM_IF_ERROR_RETURN(_bcm_ptp_write_ks_uint32(pci_idx, 0x18103408, 1)); 193 /* CPU Master DMP : soft reset : resetctrl (0x18103800) <- 0x0 (bit[0] <- 0 exit reset) */ 194 BCM_IF_ERROR_RETURN(_bcm_ptp_write_ks_uint32(pci_idx, 0x18103800, 0)); 195 /* ChipCommon Master DMP : enable clock : ioctrl (0x18100408) <- 0x1 (bit[0] <- 1 enable clock) */ 196 BCM_IF_ERROR_RETURN(_bcm_ptp_write_ks_uint32(pci_idx, 0x18100408, 1)); 197 /* ChipCommon Master DMP : soft reset : resetctrl (0x18100800) <- 0x0 (bit[0] <- 1 exit reset) */ 198 BCM_IF_ERROR_RETURN(_bcm_ptp_write_ks_uint32(pci_idx, 0x18100800, 0)); 199 200 /*** Enable SOCRAM clocks and bring out of DMP reset ***/ 201 /* SOCRAM0 Slave DMP : enable clock : ioctrl (0x18107408) <- 0x1 (bit[0] <- 1 to enable clock) */ 202 BCM_IF_ERROR_RETURN(_bcm_ptp_write_ks_uint32(pci_idx, 0x18107408, 1)); 203 /* SOCRAM0 Slave DMP : enable clock : resetctrl (0x18107800) <- 0x0 (bit[0] <- 0 exit reset) */ 204 BCM_IF_ERROR_RETURN(_bcm_ptp_write_ks_uint32(pci_idx, 0x18107800, 0)); 205 206 /*** set MIPS resetvec to start of SOCRAM ***/ 207 /* Core Resetvec : set reset vector : resetvec (0x18003004) <- 0xb9000000 (start of SOCRAM) */ 208 BCM_IF_ERROR_RETURN(_bcm_ptp_write_ks_uint32(pci_idx, 0x18003004, 0xb9000000)); 209 210 /* MIPS Corecontrol : core soft reset : (0x18003000) <- 0x7 (bit[0] <- 1 force reset) */ 211 /* (bit[1] <- 1 alternate resetvec) */ 212 /* (bit[2] <- 1 HT clock) */ 213 _bcm_ptp_write_ks_uint32(pci_idx, 0x18003000, 7); 214 215 return BCM_E_NONE; 216 } 217 218 219 #define MAGIC_READ_VALUE 0xdeadc0de 220 221 int _bcm_ptp_ext_stack_start(int pci_idx) 222 { 223 int rv = BCM_E_NONE; 224 int boot_iter; 225 uint32 value = MAGIC_READ_VALUE; 226 227 /* MIPS Corecontrol : core soft reset : (0x18003000) <- 0x6 (bit[0] <- 0 leave reset) */ 228 /* (bit[1] <- 1 alternate resetvec) */ 229 /* (bit[2] <- 1 HT clock) */ 230 _bcm_ptp_write_ks_uint32(pci_idx, 0x18003000, 6); 231 232 for (boot_iter = 0; boot_iter < MAX_BOOT_ITER; ++boot_iter) { 233 _bcm_ptp_read_ks_uint32(pci_idx, BOOT_STATUS_ADDR, &value); 234 if (value != MAGIC_READ_VALUE) { 235 break; 236 } 237 238 /* delay 1 ms */ 239 sal_usleep(1000); 240 } 241 242 if (boot_iter == MAX_BOOT_ITER) { 243 rv = BCM_E_FAIL; 244 LOG_VERBOSE(BSL_LS_SOC_COMMON, 245 (BSL_META("external stack start failed"))); 246 } 247 248 return rv; 249 } 250 251 252 /* Set a value both on BCM53903 and in the persistent config used to reset BCM53903 after a load. */ 253 void 254 esw_set_ext_stack_config_uint32(_bcm_ptp_stack_info_t *stack_p, uint32 offset, uint32 value) 255 { 256 stack_p->ext_info.write_fn(stack_p->ext_info.cookie, CONFIG_BASE + offset, value); 257 _bcm_ptp_uint32_write(&stack_p->persistent_config[offset], value); 258 } 259 260 261 /* Set an array of values as above */ 262 void 263 esw_set_ext_stack_config_array(_bcm_ptp_stack_info_t* stack_p, uint32 offset, const uint8 * array, int len) 264 { 265 while (len--) { 266 _bcm_ptp_write_pcishared_uint8(&stack_p->ext_info, CONFIG_BASE + offset, *array); 267 stack_p->persistent_config[offset] = *array; 268 ++array; 269 ++offset; 270 } 271 } 272 273 274 void _bcm_ptp_write_pcishared_uint8_aligned_array(int pci_idx, uint32 addr, uint8 * array, int array_len) 275 { 276 while (array_len > 0) { 277 uint32 value = ( (((uint32)array[0]) << 24) | (((uint32)array[1]) << 16) | 278 (((uint32)array[2]) << 8) | (uint32)array[3] ); 279 _bcm_ptp_write_ks_uint32(pci_idx, addr, value); 280 array += 4; 281 array_len -= 4; 282 addr += 4; 283 } 284 } 285 286 287 void _bcm_ptp_read_pcishared_uint8_aligned_array(int pci_idx, uint32 addr, uint8 * array, int array_len) 288 { 289 while (array_len > 0) { 290 uint32 value; 291 _bcm_ptp_read_ks_uint32(pci_idx, addr, &value); 292 array[0] = ((value >> 24) & 0xff); 293 array[1] = ((value >> 16) & 0xff); 294 array[2] = ((value >> 8) & 0xff); 295 array[3] = ((value >> 0) & 0xff); 296 297 array += 4; 298 array_len -= 4; 299 addr += 4; 300 } 301 } 302 303 304 /* Get hardware timestamp and associated PTP time */ 305 int 306 _bcm_ptp_ext_stack_timestamp_get(int pci_idx, int event_id, soc_cmic_uc_ts_data_t *ts_data) 307 { 308 const uint32 timestamp_base = 0x19000c90; 309 const int max_iter = 100; 310 int iter = 0; 311 312 uint32 read_seconds_hi[2] = {0,0}, read_seconds_lo[2] = {0, 0}, read_nsec[2] = {0, 0}; 313 uint32 read_ts0[2] = {0, 0}, read_ts[2] = {0, 0}, read_prev_ts[2] = {0,0}; 314 315 if (event_id < 0 || event_id > 5) { 316 return BCM_E_PARAM; 317 } 318 319 do { 320 read_seconds_hi[1] = read_seconds_hi[0]; 321 read_seconds_lo[1] = read_seconds_lo[0]; 322 read_nsec[1] = read_nsec[0]; 323 read_ts0[1] = read_ts0[0]; 324 read_ts[1] = read_ts[0]; 325 read_prev_ts[1] = read_prev_ts[0]; 326 327 BCM_IF_ERROR_RETURN(_bcm_ptp_read_ks_uint32(pci_idx, timestamp_base, &read_seconds_hi[0])); 328 BCM_IF_ERROR_RETURN(_bcm_ptp_read_ks_uint32(pci_idx, timestamp_base + 0x04, &read_seconds_lo[0])); 329 BCM_IF_ERROR_RETURN(_bcm_ptp_read_ks_uint32(pci_idx, timestamp_base + 0x08, &read_nsec[0])); 330 BCM_IF_ERROR_RETURN(_bcm_ptp_read_ks_uint32(pci_idx, timestamp_base + 0x0c, &read_ts0[0])); 331 BCM_IF_ERROR_RETURN(_bcm_ptp_read_ks_uint32(pci_idx, timestamp_base + 0x10 + 4 * event_id, &read_ts[0])); 332 BCM_IF_ERROR_RETURN(_bcm_ptp_read_ks_uint32(pci_idx, timestamp_base + 0x28 + 4 * event_id, &read_prev_ts[0])); 333 } 334 while ((read_seconds_hi[0] != read_seconds_hi[1] || 335 read_seconds_lo[0] != read_seconds_lo[1] || 336 read_nsec[0] != read_nsec[1] || 337 read_ts0[0] != read_ts0[1] || 338 read_ts[0] != read_ts[1] || 339 read_prev_ts[0] != read_prev_ts[1]) 340 && (++iter < max_iter)); 341 342 ts_data->hwts = read_ts[0]; 343 ts_data->prev_hwts = read_prev_ts[0]; 344 345 /* the seconds/nsec time corresponds to the ts0 timestamp, so find the timestamp difference to apply to the PTP time */ 346 347 ts_data->time.seconds = ((((uint64)read_seconds_hi[0]) << 32) | (uint64)read_seconds_lo[0]); 348 { 349 uint64 one_billion = 1000000000; 350 int32 ts_minus_ts0 = read_ts[0] - read_ts0[0]; 351 int64 full_ns = (int64)(read_nsec[0]) + (int64)ts_minus_ts0; 352 353 if (full_ns < 0) { 354 full_ns += one_billion; 355 ts_data->time.seconds--; 356 } 357 358 if (full_ns >= one_billion) { 359 full_ns -= one_billion; 360 ts_data->time.seconds++; 361 } 362 363 ts_data->time.nanoseconds = (uint32)full_ns; 364 } 365 366 return (iter < max_iter) ? BCM_E_NONE : BCM_E_TIMEOUT; 367 } 368 369 370 /* Returns Boot status (1 == booted successfully) and fault status (0 == no fault) */ 371 int 372 _bcm_ptp_ext_stack_fault_status_get(int pci_idx, uint32 *boot_status, uint32 *fault_status) 373 { 374 BCM_IF_ERROR_RETURN(_bcm_ptp_read_ks_uint32(pci_idx, BOOT_STATUS_ADDR, boot_status)); 375 BCM_IF_ERROR_RETURN(_bcm_ptp_read_ks_uint32(pci_idx, FAULT_STATUS_ADDR, fault_status)); 376 377 return BCM_E_NONE; 378 } 379 380 381 /* Get low-level fault information, should be included with any crash bug reports */ 382 int 383 _bcm_ptp_ext_stack_fault_information_get(int pci_idx, int max_size, uint8 *fault_info, int *fault_info_size) 384 { 385 /* Note: may change in future, caller should not assume this size */ 386 const int fault_dump_size = 168; 387 *fault_info_size = fault_dump_size + sizeof(_bcm_ptp_ext_stack_processor_info_t); 388 389 if (max_size < *fault_info_size) { 390 return BCM_E_NONE; 391 } 392 393 if (!fault_info) { 394 return BCM_E_PARAM; 395 } 396 397 _bcm_ptp_read_pcishared_uint8_aligned_array(pci_idx, BOOT_STATUS_ADDR, fault_info, fault_dump_size); 398 399 BCM_IF_ERROR_RETURN( _bcm_ptp_ext_stack_processor_status_get( 400 pci_idx, (_bcm_ptp_ext_stack_processor_info_t*)((fault_info + fault_dump_size)))); 401 402 return BCM_E_NONE; 403 } 404 405 /* Get current and high-water-mark status of ToP processor, including memory 406 * usage and CPU core utilization. 407 */ 408 int 409 _bcm_ptp_ext_stack_processor_status_get(int pci_idx, _bcm_ptp_ext_stack_processor_info_t *info) 410 { 411 BCM_IF_ERROR_RETURN(_bcm_ptp_ext_stack_system_status_get(pci_idx, info)); 412 BCM_IF_ERROR_RETURN(_bcm_ptp_ext_stack_task_status_get(pci_idx, info)); 413 414 return BCM_E_NONE; 415 } 416 417 418 int 419 _bcm_ptp_ext_stack_task_status_get(int pci_idx, _bcm_ptp_ext_stack_processor_info_t *info) 420 { 421 const uint32 info_base = 0x19000bac; 422 const int stack_base_offset = 0x28; 423 const int stack_top_offset = 0x40; 424 425 const int max_tasks = 6; 426 const int max_reported_tasks = 10; /* in case max_tasks increases in the future, API has space to report more */ 427 int task; 428 uint32 cursor; 429 uint32 stack_base; 430 uint32 stack_top; 431 432 /* for any task slots that aren't filled, just report max uint */ 433 for (task = 0; task < max_reported_tasks; ++task) { 434 info->stack_free[task] = 0xffffffff; 435 } 436 437 for (task = 0; task < max_tasks; ++task) { 438 BCM_IF_ERROR_RETURN( _bcm_ptp_read_ks_uint32( 439 pci_idx, info_base + stack_base_offset + task * 4, &stack_base)); 440 441 stack_base &= 0x3fffffff; /* translate to physical memory address */ 442 if (stack_base != 0) { 443 /* there is a task in this slot. 444 * Walk through memory to find lowest point in stack with nonzero value */ 445 BCM_IF_ERROR_RETURN( _bcm_ptp_read_ks_uint32( 446 pci_idx, info_base + stack_top_offset + task * 4, &stack_top)); 447 448 stack_top &= 0x3fffffff; /* translate to physical memory address */ 449 for (cursor = stack_base; cursor < stack_top; cursor += 4) { 450 uint32 testval; 451 BCM_IF_ERROR_RETURN( _bcm_ptp_read_ks_uint32( 452 pci_idx, cursor, &testval)); 453 if (testval != 0) break; 454 } 455 456 info->stack_free[task] = (cursor - stack_base); 457 } 458 } 459 460 return BCM_E_NONE; 461 } 462 463 464 int 465 _bcm_ptp_ext_stack_system_status_get(int pci_idx, _bcm_ptp_ext_stack_processor_info_t *info) 466 { 467 const uint32 info_base = 0x19000bac; 468 const int subheap_offset = 0x58; 469 470 const int max_reported_tasks = 10; /* in case max_tasks increases in the future, API has space to report more */ 471 int task; 472 int heap; 473 const int max_heaps = 10; 474 475 BCM_IF_ERROR_RETURN(_bcm_ptp_read_ks_uint32(pci_idx, info_base + 0x00, &info->cpu_usage)); 476 BCM_IF_ERROR_RETURN(_bcm_ptp_read_ks_uint32(pci_idx, info_base + 0x04, &info->max_cpu_usage)); 477 BCM_IF_ERROR_RETURN(_bcm_ptp_read_ks_uint32(pci_idx, info_base + 0x08, &info->mem_free)); 478 BCM_IF_ERROR_RETURN(_bcm_ptp_read_ks_uint32(pci_idx, info_base + 0x0c, &info->min_mem_free)); 479 BCM_IF_ERROR_RETURN(_bcm_ptp_read_ks_uint32(pci_idx, info_base + 0x10, &info->tick_buffer)); 480 BCM_IF_ERROR_RETURN(_bcm_ptp_read_ks_uint32(pci_idx, info_base + 0x14, &info->min_tick_buffer)); 481 BCM_IF_ERROR_RETURN(_bcm_ptp_read_ks_uint32(pci_idx, info_base + 0x18, &info->one_sec_buffer)); 482 BCM_IF_ERROR_RETURN(_bcm_ptp_read_ks_uint32(pci_idx, info_base + 0x1c, &info->min_one_sec_buffer)); 483 BCM_IF_ERROR_RETURN(_bcm_ptp_read_ks_uint32(pci_idx, info_base + 0x20, &info->one_min_buffer)); 484 BCM_IF_ERROR_RETURN(_bcm_ptp_read_ks_uint32(pci_idx, info_base + 0x24, &info->min_one_min_buffer)); 485 486 /* just report uint_max since we aren't checking here */ 487 for (task = 0; task < max_reported_tasks; ++task) { 488 info->stack_free[task] = 0xffffffff; 489 } 490 491 for (heap = 0; heap < max_heaps; ++heap) { 492 BCM_IF_ERROR_RETURN(_bcm_ptp_read_ks_uint32(pci_idx, info_base + subheap_offset + heap * 4, &info->sub_heap_free[heap])); 493 } 494 495 return BCM_E_NONE; 496 } 497 498 499 /* Extract FW information from the READY event from the FW */ 500 int 501 _bcm_ptp_ext_fw_info_set(int unit, 502 bcm_ptp_stack_id_t ptp_id, 503 uint8 *data) 504 { 505 int i; 506 int descr_len; 507 int descr_limit_len; 508 509 sal_memset(top_fw_info.firmware_version,0,sizeof(top_fw_info.firmware_version)); 510 sal_memset(top_fw_info.servo_version,0,sizeof(top_fw_info.servo_version)); 511 512 /* 513 * Parse ToP ready event data. 514 * Octet 0...1 : Firmware version string length (N). 515 * Octet 2...N+1 : Firmware version. 516 * Octet N+2...N+3 : Servo version string length (P). 517 * Octet N+4...N+P+3 : Servo version. 518 * Octet N+P+4...N+P+7 : PTP stack timer frequency (Hz). 519 * Octet N+P+8 : Maximum number of PTP clocks (instances). 520 * Octet N+P+9 : Maximum number of PTP ports per PTP clock. 521 * Octet N+P+10 : Maximum number of unicast masters. 522 * Octet N+P+11 : Maximum number of unicast slaves. 523 * Octet N+P+12 : Maximum number of foreign master dataset entries (per port). 524 */ 525 i = 0; 526 descr_len = _bcm_ptp_uint16_read(data+i); 527 i += sizeof(uint16); 528 529 descr_limit_len = (descr_len < sizeof(top_fw_info.firmware_version)) ? 530 (descr_len) : (sizeof(top_fw_info.firmware_version)-1); 531 sal_memcpy(top_fw_info.firmware_version, data+i, descr_limit_len); 532 i += descr_len; 533 534 descr_len = _bcm_ptp_uint16_read(data+i); 535 i += sizeof(uint16); 536 537 descr_limit_len = (descr_len < sizeof(top_fw_info.servo_version)) ? 538 (descr_len) : (sizeof(top_fw_info.servo_version)-1); 539 sal_memcpy(top_fw_info.servo_version, data+i, descr_limit_len); 540 i += descr_len; 541 542 top_fw_info.ptp_stack_timer_hz = _bcm_ptp_uint32_read(data+i); 543 i += sizeof(uint32); 544 545 top_fw_info.ptp_clocks_max = data[i++]; 546 top_fw_info.ptp_ports_per_clock_max = data[i++]; 547 548 top_fw_info.unicast_masters_max = data[i++]; 549 top_fw_info.unicast_slaves_max = data[i++]; 550 top_fw_info.foreign_master_dataset_entries_max = data[i]; 551 552 return BCM_E_NONE; 553 } 554 555 int 556 _bcm_ptp_ext_fw_info_get( 557 int unit, 558 bcm_ptp_stack_id_t ptp_id, 559 _bcm_ptp_ext_fw_info_t *info) 560 { 561 *info = top_fw_info; 562 return BCM_E_NONE; 563 } 564 565 #endif /* defined(BCM_PTP_EXTERNAL_STACK_SUPPORT) */ 566 #endif /* defined(INCLUDE_PTP)*/