openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

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)*/