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

rx.c (64818B)


      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:    rx.c
      8  *
      9  * Purpose: 
     10  *
     11  * Functions:
     12  *      _bcm_ptp_rx_init
     13  *      _bcm_ptp_rx_stack_create
     14  *      _bcm_ptp_rx_clock_create
     15  *      _bcm_ptp_external_rx_response_free
     16  *      _bcm_ptp_internal_rx_response_free
     17  *      _bcm_ptp_rx_response_flush
     18  *      _bcm_ptp_rx_response_get
     19  *      _bcm_ptp_rx_thread
     20  *      _bcm_ptp_rx_callback
     21  *      _bcm_ptp_rx_message_destination_port_get
     22  *      _bcm_ptp_rx_message_source_clock_identity_get
     23  *      _bcm_ptp_rx_message_length_get
     24  *      _bcm_ptp_register_management_callback
     25  *      _bcm_ptp_register_event_callback
     26  *      _bcm_ptp_register_signal_callback
     27  *      _bcm_ptp_register_peers_callback
     28  *      _bcm_ptp_register_fault_callback
     29  *      _bcm_ptp_unregister_management_callback
     30  *      _bcm_ptp_unregister_event_callback
     31  *      _bcm_ptp_unregister_signal_callback
     32  *      _bcm_ptp_unregister_peers_callback
     33  *      _bcm_ptp_event_message_monitor
     34  *      _bcm_ptp_signal_handler_default
     35  */
     36 
     37 #if defined(INCLUDE_PTP)
     38 
     39 #ifdef BCM_HIDE_DISPATCHABLE
     40 #undef BCM_HIDE_DISPATCHABLE
     41 #endif
     42 
     43 #include <shared/bsl.h>
     44 
     45 #include <soc/defs.h>
     46 #include <soc/drv.h>
     47 
     48 #include <bcm/pkt.h>
     49 #include <bcm/tx.h>
     50 #include <bcm/rx.h>
     51 #include <bcm/error.h>
     52 #include <bcm/ptp.h>
     53 #include <bcm_int/common/ptp.h>
     54 
     55 #if defined(BCM_PTP_INTERNAL_STACK_SUPPORT)
     56 #include <soc/uc_msg.h>
     57 #endif
     58 
     59 #include <soc/uc_dbg.h>
     60 
     61 #ifdef BCM_ESMC_EXTDPLL_SUPPORT
     62 #include <bcm_int/common/esmc.h>
     63 #endif /* BCM_ESMC_EXTDPLL_SUPPORT */
     64 
     65 #if !defined(BCM_PTP_RX_POLL_WAIT_USEC)
     66 #define BCM_PTP_RX_POLL_WAIT_USEC (1000)
     67 #endif
     68 
     69 void (*_bcm_ptp_arp_callback)(int unit, bcm_ptp_stack_id_t ptp_id,
     70                               int protocol, int src_addr_offset,
     71                               int payload_offset, int msg_len, uint8 *msg);
     72 
     73 #define PTP_SDK_VERSION         0x01000000
     74 #define PTP_UC_MIN_VERSION      0x01000000
     75 
     76 #define PTP_RX_PACKET_MIN_SIZE_OCTETS     (14)
     77 #define PTP_RX_TUNNEL_MSG_MIN_SIZE_OCTETS (11)
     78 #define PTP_RX_EVENT_MSG_MIN_SIZE_OCTETS  (2)
     79 #define PTP_RX_MGMT_MIN_SIZE              (0x64)
     80 #define PTP_RX_UDP_PAYLOAD_OFFSET         (46)
     81 
     82 /* PTP clock Rx data. */
     83 typedef struct _bcm_ptp_clock_rx_data_s {
     84     _bcm_ptp_sem_t response_ready;
     85     uint8 * volatile response_data;
     86     volatile int response_len;
     87 } _bcm_ptp_clock_rx_data_t;
     88 
     89 /* Stack PTP Rx data arrays. */
     90 typedef struct _bcm_ptp_stack_rx_array_s {
     91     _bcm_ptp_memstate_t memstate;
     92 
     93 #if defined(BCM_PTP_EXTERNAL_STACK_SUPPORT)
     94     bcm_mac_t host_mac;
     95     bcm_mac_t top_mac;
     96     int tpid;
     97     int vlan;
     98 #endif
     99 #if defined(BCM_PTP_INTERNAL_STACK_SUPPORT)
    100     sal_thread_t rx_thread;
    101     volatile int rx_thread_exit;
    102 #endif
    103 
    104     _bcm_ptp_clock_rx_data_t *clock_data;
    105 } _bcm_ptp_stack_rx_array_t;
    106 
    107 /* Unit PTP Rx data arrays. */
    108 typedef struct _bcm_ptp_unit_rx_array_s {
    109     _bcm_ptp_memstate_t memstate;
    110 
    111     bcm_ptp_cb management_cb;
    112     bcm_ptp_cb event_cb;
    113     bcm_ptp_cb signal_cb;
    114     bcm_ptp_cb fault_cb;
    115     bcm_ptp_cb peers_cb;
    116     uint8      *management_user_data;
    117     uint8      *event_user_data;
    118     uint8      *signal_user_data;
    119     uint8      *fault_user_data;
    120     uint8      *peers_user_data;
    121 
    122     _bcm_ptp_stack_rx_array_t *stack_array;
    123 } _bcm_ptp_unit_rx_array_t;
    124 
    125 static _bcm_ptp_unit_rx_array_t unit_rx_array[BCM_MAX_NUM_UNITS];
    126 
    127 
    128 
    129 int _bcm_ptp_most_recent_clock_num;
    130 int _bcm_ptp_most_recent_port;
    131 bcm_ptp_protocol_t _bcm_ptp_most_recent_protocol;
    132 int _bcm_ptp_most_recent_src_addr_offset;
    133 int _bcm_ptp_most_recent_msg_offset;
    134 
    135 #ifdef BCM_PTP_EXT_SERVO_SUPPORT
    136 extern bcm_ptp_mbox_tsevent_stats_t mbox_tsevent_stats;
    137 #endif /* BCM_PTP_EXT_SERVO_SUPPORT */
    138 
    139 #if defined(BCM_PTP_INTERNAL_STACK_SUPPORT)
    140 static void _bcm_ptp_rx_thread(void *arg);
    141 #endif
    142 
    143 #if defined(BCM_PTP_EXTERNAL_STACK_SUPPORT)
    144 bcm_rx_t _bcm_ptp_rx_callback(
    145     int unit,
    146     bcm_pkt_t *pkt,
    147     void *cookie);
    148 
    149 static int _bcm_ptp_rx_message_destination_port_get(
    150     uint8 *message,
    151     uint16 *dest_port);
    152 
    153 static int _bcm_ptp_rx_message_source_clock_identity_get(
    154     uint8 *message,
    155     bcm_ptp_clock_identity_t *clock_identity);
    156 
    157 static int _bcm_ptp_rx_message_length_get(
    158     uint8 *message,
    159     uint16 *message_len);
    160 
    161 #endif /* defined(BCM_PTP_EXTERNAL_STACK_SUPPORT) */
    162 
    163 #if defined(BCM_PTP_INTERNAL_STACK_SUPPORT) || defined(BCM_PTP_EXTERNAL_STACK_SUPPORT)
    164 STATIC int _bcm_ptp_event_message_monitor(
    165     int unit,
    166     bcm_ptp_stack_id_t ptp_id,
    167     int ev_data_len,
    168     uint8 *ev_data,
    169     int *ev_internal);
    170 #endif
    171 
    172 STATIC int _bcm_ptp_signal_handler_default(
    173     int unit,
    174     bcm_ptp_stack_id_t ptp_id,
    175     int clock_num,
    176     uint32 clock_port,
    177     bcm_ptp_cb_type_t type,
    178     bcm_ptp_cb_msg_t *msg,
    179     void *user_data);
    180 
    181 /*
    182  * Function:
    183  *      _bcm_ptp_rx_init
    184  * Purpose:
    185  *      Initialize the PTP Rx framework and data of a unit.
    186  * Parameters:
    187  *      unit - (IN) Unit number.
    188  * Returns:
    189  *      BCM_E_XXX
    190  * Notes:
    191  */
    192 int
    193 _bcm_ptp_rx_init(
    194     int unit)
    195 {
    196     int rv = BCM_E_UNAVAIL;
    197     _bcm_ptp_stack_rx_array_t *stack_p;
    198     int i;
    199 
    200     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT,
    201             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    202         return rv;
    203     }
    204 
    205     
    206     if (NULL == unit_rx_array[unit].stack_array) {
    207         stack_p = sal_alloc(PTP_MAX_STACKS_PER_UNIT*
    208                             sizeof(_bcm_ptp_stack_rx_array_t),"Unit Rx arrays");
    209     } else {
    210         stack_p = unit_rx_array[unit].stack_array;
    211     }
    212     if (!stack_p) {
    213         unit_rx_array[unit].memstate = PTP_MEMSTATE_FAILURE;
    214         return BCM_E_MEMORY;
    215     }
    216     SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostPtpRx, "%s: stack_p: %p\n", 
    217                           __FUNCTION__, stack_p));
    218 
    219     for (i = 0; i < PTP_MAX_STACKS_PER_UNIT; ++i) {
    220         stack_p[i].memstate = PTP_MEMSTATE_STARTUP;
    221     }
    222 
    223     unit_rx_array[unit].stack_array = stack_p;
    224     unit_rx_array[unit].memstate = PTP_MEMSTATE_INITIALIZED;
    225 
    226     unit_rx_array[unit].management_cb = NULL;
    227     unit_rx_array[unit].event_cb = NULL;
    228     unit_rx_array[unit].signal_cb = NULL;
    229     unit_rx_array[unit].fault_cb = NULL;
    230 
    231     unit_rx_array[unit].management_user_data = NULL;
    232     unit_rx_array[unit].event_user_data = NULL;
    233     unit_rx_array[unit].signal_user_data = NULL;
    234     unit_rx_array[unit].fault_user_data = NULL;
    235 
    236     /*
    237      * Add default callback function for tunneled PTP signaling messages
    238      */
    239     if (BCM_FAILURE(rv = _bcm_ptp_register_signal_callback(unit,
    240             _bcm_ptp_signal_handler_default, NULL))) {
    241         PTP_ERROR_FUNC("_bcm_ptp_register_signal_callback()");
    242     }
    243 
    244     return BCM_E_NONE;
    245 }
    246 
    247 /*
    248  * Function:
    249  *      _bcm_ptp_rx_init_detach
    250  * Purpose:
    251  *      Shut down the PTP Rx framework and data of a unit.
    252  * Parameters:
    253  *      unit - (IN) Unit number.
    254  * Returns:
    255  *      BCM_E_XXX
    256  * Notes:
    257  */
    258 int
    259 _bcm_ptp_rx_detach(
    260     int unit)
    261 {
    262     if(unit_rx_array[unit].stack_array) {
    263         unit_rx_array[unit].memstate = PTP_MEMSTATE_STARTUP;
    264         sal_free(unit_rx_array[unit].stack_array);
    265         unit_rx_array[unit].stack_array = NULL;
    266     }
    267     return BCM_E_NONE;
    268 }
    269 
    270 /*
    271  * Function:
    272  *      _bcm_ptp_rx_stack_create
    273  * Purpose:
    274  *      Create the PTP Rx data of a PTP stack.
    275  * Parameters:
    276  *      unit     - (IN) Unit number.
    277  *      ptp_id   - (IN) PTP stack ID.
    278  *      host_mac - (IN) Host MAC address.
    279  *      top_mac  - (IN) ToP MAC address.
    280  *      tpid     - (IN) TPID for Host <-> ToP Communication
    281  *      vlan     - (IN) VLAN for Host <-> ToP Communication
    282  * Returns:
    283  *      BCM_E_XXX
    284  * Notes:
    285  */
    286 int
    287 _bcm_ptp_rx_stack_create(
    288     int unit,
    289     bcm_ptp_stack_id_t ptp_id,
    290     bcm_mac_t *host_mac,
    291     bcm_mac_t *top_mac,
    292     int tpid,
    293     int vlan)
    294 {
    295     int rv = BCM_E_UNAVAIL;
    296     _bcm_ptp_clock_rx_data_t *data_p;
    297     int i;
    298 
    299     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
    300             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    301         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
    302         return rv;
    303     }
    304 
    305     if (unit_rx_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) {
    306         LOG_VERBOSE(BSL_LS_BCM_COMMON,
    307                     (BSL_META_U(unit,
    308                                 "PTP memory state not initialized\n")));
    309         return BCM_E_UNAVAIL;
    310     }
    311 
    312     data_p = sal_alloc(PTP_MAX_CLOCK_INSTANCES*
    313                        sizeof(_bcm_ptp_clock_rx_data_t),
    314                        "PTP stack Rx array");
    315 
    316     if (!data_p) {
    317         unit_rx_array[unit].stack_array[ptp_id].memstate =
    318             PTP_MEMSTATE_FAILURE;
    319         LOG_VERBOSE(BSL_LS_BCM_COMMON,
    320                     (BSL_META_U(unit,
    321                                 "PTP memory state error\n")));
    322         return BCM_E_MEMORY;
    323     }
    324 
    325     unit_rx_array[unit].stack_array[ptp_id].clock_data = data_p;
    326     unit_rx_array[unit].stack_array[ptp_id].memstate =
    327         PTP_MEMSTATE_INITIALIZED;
    328 
    329 #if defined(BCM_PTP_EXTERNAL_STACK_SUPPORT)
    330     if (SOC_HAS_PTP_EXTERNAL_STACK_SUPPORT(unit)) {
    331         sal_memcpy(unit_rx_array[unit].stack_array[ptp_id].host_mac, host_mac,
    332                    sizeof(bcm_mac_t));
    333 
    334         sal_memcpy(unit_rx_array[unit].stack_array[ptp_id].top_mac, top_mac,
    335                    sizeof(bcm_mac_t));
    336 
    337         unit_rx_array[unit].stack_array[ptp_id].tpid = tpid;
    338         unit_rx_array[unit].stack_array[ptp_id].vlan = vlan;
    339 
    340 #ifndef CUSTOMER_CALLBACK
    341         if (!bcm_rx_active(unit)) {
    342             if (BCM_FAILURE(rv = bcm_rx_cfg_init(unit))) {
    343                 PTP_ERROR_FUNC("bcm_rx_cfg_init()");
    344                 return rv;
    345             }
    346 
    347             if (BCM_FAILURE(rv = bcm_rx_start(unit, NULL))) {
    348                 PTP_ERROR_FUNC("bcm_rx_start()");
    349                 return rv;
    350             }
    351         }
    352 
    353         if (BCM_FAILURE(rv = bcm_rx_register(unit, "BCM_PTP_Rx", _bcm_ptp_rx_callback,
    354                                              BCM_RX_PRIO_MAX, (void*)ptp_id, BCM_RCO_F_ALL_COS))) {
    355             PTP_ERROR_FUNC("bcm_rx_register()");
    356             return rv;
    357         }
    358 #endif /* CUSTOMER_CALLBACK */
    359     }
    360 #endif /* defined(BCM_PTP_EXTERNAL_STACK_SUPPORT) */
    361 
    362 #if defined(BCM_PTP_INTERNAL_STACK_SUPPORT)
    363     if (SOC_HAS_PTP_INTERNAL_STACK_SUPPORT(unit)) {
    364         _bcm_ptp_stack_info_t *stack_p;
    365         _bcm_ptp_info_t *ptp_info_p;
    366 
    367         SET_PTP_INFO;
    368         stack_p = &ptp_info_p->stack_info[ptp_id];
    369 
    370         unit_rx_array[unit].stack_array[ptp_id].rx_thread_exit = FALSE;
    371 
    372         unit_rx_array[unit].stack_array[ptp_id].rx_thread = sal_thread_create("PTP Rx", SAL_THREAD_STKSZ,
    373                                 soc_property_get(unit, spn_UC_MSG_THREAD_PRI, 50) + 1,
    374                                 _bcm_ptp_rx_thread, stack_p);
    375         if (unit_rx_array[unit].stack_array[ptp_id].rx_thread == SAL_THREAD_ERROR) {
    376             rv = BCM_E_INTERNAL;
    377             PTP_ERROR_FUNC("sal_thread_create()");
    378             return rv;
    379         }
    380     }
    381 #endif
    382 
    383     for (i = 0; i < PTP_MAX_CLOCKS_PER_STACK; ++i) {
    384         if (BCM_FAILURE(rv = _bcm_ptp_rx_clock_create(unit, ptp_id, i))) {
    385             PTP_ERROR_FUNC("_bcm_ptp_rx_clock_create()");
    386             return rv;
    387         }
    388     }
    389 
    390     return rv;
    391 }
    392 
    393 int
    394 _bcm_ptp_rx_stack_destroy(
    395     int unit,
    396     bcm_ptp_stack_id_t ptp_id)
    397 {
    398     int rv = BCM_E_NONE;
    399     int i;
    400 
    401     if (unit_rx_array[unit].stack_array[ptp_id].memstate == PTP_MEMSTATE_FAILURE) {
    402         /* Initialization / allocation did not succeed before, so just reset the state */
    403         unit_rx_array[unit].stack_array[ptp_id].memstate = PTP_MEMSTATE_STARTUP;
    404         return BCM_E_NONE;
    405     }
    406 
    407     if (unit_rx_array[unit].stack_array[ptp_id].memstate != PTP_MEMSTATE_INITIALIZED) {
    408         return BCM_E_INIT;
    409     }
    410 
    411     for (i = 0; i < PTP_MAX_CLOCKS_PER_STACK; ++i) {
    412         if (BCM_FAILURE(rv = _bcm_ptp_rx_clock_destroy(unit, ptp_id, i))) {
    413             PTP_ERROR_FUNC("_bcm_ptp_rx_clock_create()");
    414             return rv;
    415         }
    416     }
    417 
    418 #if defined (BCM_PTP_EXTERNAL_STACK_SUPPORT)
    419 #ifndef CUSTOMER_CALLBACK
    420 
    421     if (BCM_FAILURE(rv = bcm_rx_unregister(unit, _bcm_ptp_rx_callback, BCM_RX_PRIO_MAX))) {
    422         PTP_ERROR_FUNC("bcm_rx_unregister()");
    423     }
    424 
    425 #endif /* CUSTOMER_CALLBACK */
    426 #endif /* BCM_PTP_EXTERNAL_STACK_SUPPORT */
    427 
    428 #if defined(BCM_PTP_INTERNAL_STACK_SUPPORT)
    429     if (SOC_HAS_PTP_INTERNAL_STACK_SUPPORT(unit)) {
    430         if (unit_rx_array[unit].stack_array[ptp_id].rx_thread != SAL_THREAD_ERROR) {
    431             unit_rx_array[unit].stack_array[ptp_id].rx_thread_exit = TRUE;
    432             /* allow thread to exit */
    433             for (i=0; i < 50; i++) {
    434                 if (unit_rx_array[unit].stack_array[ptp_id].rx_thread == SAL_THREAD_ERROR) {
    435                     break;
    436                 }
    437                 sal_usleep(10000);
    438             }
    439             if (unit_rx_array[unit].stack_array[ptp_id].rx_thread != SAL_THREAD_ERROR) {
    440                 PTP_ERROR("PTP RX thread did not exit gracefully\n");
    441             }
    442         }
    443     }
    444 #endif
    445 
    446     unit_rx_array[unit].stack_array[ptp_id].memstate = PTP_MEMSTATE_STARTUP;
    447     sal_free(unit_rx_array[unit].stack_array[ptp_id].clock_data);
    448     unit_rx_array[unit].stack_array[ptp_id].clock_data = 0;
    449 
    450     return rv;
    451 }
    452 
    453 /*
    454  * Function:
    455  *      _bcm_ptp_rx_clock_create
    456  * Purpose:
    457  *      Create the PTP Rx data of a PTP clock.
    458  * Parameters:
    459  *      unit      - (IN) Unit number.
    460  *      ptp_id    - (IN) PTP stack ID.
    461  *      clock_num - (IN) PTP clock number.
    462  * Returns:
    463  *      BCM_E_XXX
    464  * Notes:
    465  */
    466 int
    467 _bcm_ptp_rx_clock_create(
    468     int unit,
    469     bcm_ptp_stack_id_t ptp_id,
    470     int clock_num)
    471 {
    472     int rv = BCM_E_UNAVAIL;
    473 
    474     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num,
    475             PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    476         return rv;
    477     }
    478 
    479     if ((unit_rx_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) ||
    480         (unit_rx_array[unit].stack_array[ptp_id].memstate !=
    481             PTP_MEMSTATE_INITIALIZED)) {
    482         return BCM_E_UNAVAIL;
    483     }
    484 
    485     unit_rx_array[unit].stack_array[ptp_id].clock_data[clock_num].response_data = 0;
    486     unit_rx_array[unit].stack_array[ptp_id].clock_data[clock_num].response_len = 0;
    487 
    488     unit_rx_array[unit].stack_array[ptp_id].clock_data[clock_num].response_ready =
    489         _bcm_ptp_sem_create("BCM_PTP_resp", sal_sem_BINARY, 0);
    490 
    491     return rv;
    492 }
    493 
    494 /*
    495  * Function:
    496  *      _bcm_ptp_rx_clock_destroy
    497  * Purpose:
    498  *      Destroy the PTP Rx data of a PTP clock.
    499  * Parameters:
    500  *      unit      - (IN) Unit number.
    501  *      ptp_id    - (IN) PTP stack ID.
    502  *      clock_num - (IN) PTP clock number.
    503  * Returns:
    504  *      BCM_E_XXX
    505  * Notes:
    506  */
    507 int
    508 _bcm_ptp_rx_clock_destroy(
    509     int unit,
    510     bcm_ptp_stack_id_t ptp_id,
    511     int clock_num)
    512 {
    513     int rv = BCM_E_NONE;
    514 
    515     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num,
    516             PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    517         return rv;
    518     }
    519 
    520     if ((unit_rx_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) ||
    521         (unit_rx_array[unit].stack_array[ptp_id].memstate !=
    522             PTP_MEMSTATE_INITIALIZED)) {
    523         return BCM_E_UNAVAIL;
    524     }
    525 
    526     if (unit_rx_array[unit].stack_array[ptp_id].clock_data[clock_num].response_ready) {
    527         _bcm_ptp_sem_destroy(unit_rx_array[unit].stack_array[ptp_id].clock_data[clock_num].response_ready);
    528         unit_rx_array[unit].stack_array[ptp_id].clock_data[clock_num].response_ready = 0;
    529     }
    530 
    531     return rv;
    532 }
    533 
    534 
    535 /* External version */
    536 int
    537 _bcm_ptp_external_rx_response_free(int unit, int ptp_id, uint8 *resp_data)
    538 {
    539     return bcm_rx_free(unit, resp_data - PTP_RX_UDP_PAYLOAD_OFFSET);
    540 }
    541 
    542 /* Internal version */
    543 int
    544 _bcm_ptp_internal_rx_response_free(int unit, int ptp_id, uint8 *resp_data)
    545 {
    546     _bcm_ptp_stack_info_t *stack_p;
    547     _bcm_ptp_info_t *ptp_info_p;
    548     int i;
    549 
    550     SET_PTP_INFO;
    551     stack_p = &ptp_info_p->stack_info[ptp_id];
    552     for (i = 0; i < BCM_PTP_MAX_BUFFERS; ++i) {
    553         if (stack_p->int_state.mboxes->mbox[i].data == resp_data) {
    554             if (GET_MBOX_STATUS(stack_p, i) != MBOX_STATUS_PENDING_HOST) {
    555                 LOG_ERROR(BSL_LS_BCM_COMMON,
    556                           (BSL_META_U(unit,
    557                                       "Invalid mbox status on PTP rx response free (%d)\n"),
    558                            GET_MBOX_STATUS(stack_p, i)));
    559             }
    560             SET_MBOX_STATUS(stack_p, i, MBOX_STATUS_EMPTY);
    561             return BCM_E_NONE;
    562         }
    563     }
    564 
    565     LOG_ERROR(BSL_LS_BCM_COMMON,
    566               (BSL_META_U(unit,
    567                           "Invalid PTP rx response free (%p vs %p)\n"),
    568                (void *)resp_data, (void*)stack_p->int_state.mboxes->mbox[i-1].data));
    569 
    570     return BCM_E_NOT_FOUND;
    571 }
    572 
    573 
    574 /*
    575  * Function:
    576  *      _bcm_ptp_rx_response_flush
    577  * Purpose:
    578  *      Flush prior Rx response.
    579  * Parameters:
    580  *      unit       - (IN)  Unit number.
    581  *      ptp_id     - (IN)  PTP stack ID.
    582  *      clock_num  - (IN)  PTP clock number.
    583  * Returns:
    584  *      BCM_E_XXX
    585  * Notes:
    586  */
    587 int
    588 _bcm_ptp_rx_response_flush(
    589     int unit,
    590     bcm_ptp_stack_id_t ptp_id,
    591     int clock_num)
    592 {
    593     int rv = BCM_E_UNAVAIL;
    594     int spl;
    595 
    596     uint8 *prior_data;
    597     _bcm_ptp_stack_info_t *stack_p;
    598     _bcm_ptp_info_t *ptp_info_p;
    599 
    600     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num,
    601             PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    602         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
    603         return rv;
    604     }
    605 
    606     if ((unit_rx_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) ||
    607             (unit_rx_array[unit].stack_array[ptp_id].memstate !=
    608             PTP_MEMSTATE_INITIALIZED)) {
    609         LOG_VERBOSE(BSL_LS_BCM_COMMON,
    610                     (BSL_META_U(unit,
    611                                 "PTP memory state not initialized\n")));
    612         return BCM_E_UNAVAIL;
    613     }
    614 
    615     rv = _bcm_ptp_sem_take(unit_rx_array[unit].stack_array[ptp_id]
    616             .clock_data[clock_num].response_ready, sal_mutex_NOWAIT);
    617 
    618     if (rv == BCM_E_NONE) {
    619         LOG_WARN(BSL_LS_BCM_PTP,
    620             (BSL_META_U(unit,
    621             "PTP mbox flush found waiting sem.  Rx task blocked?\n")));
    622     } else {
    623         LOG_WARN(BSL_LS_BCM_PTP,
    624             (BSL_META_U(unit,
    625             "PTP mbox flush: no sem waiting.\n")));
    626     }
    627 
    628     /*
    629      * Flush response.
    630      * NOTICE: Response already waiting is unexpected.
    631      */
    632     /* Lock. */
    633     spl = sal_splhi();
    634 
    635     prior_data = unit_rx_array[unit].stack_array[ptp_id]
    636         .clock_data[clock_num].response_data;
    637 
    638     unit_rx_array[unit].stack_array[ptp_id]
    639         .clock_data[clock_num].response_data = 0;
    640 
    641     /* Unlock. */
    642     sal_spl(spl);
    643 
    644     SET_PTP_INFO;
    645     stack_p = &ptp_info_p->stack_info[ptp_id];
    646 
    647     if (prior_data) {
    648         stack_p->rx_free(unit, ptp_id, prior_data);
    649     }
    650 
    651     /* MBOX 0 is the one that has the response in it */
    652     SET_MBOX_STATUS(stack_p, 0, MBOX_STATUS_EMPTY);
    653 
    654     return rv;
    655 }
    656 
    657 /*
    658  * Function:
    659  *      _bcm_ptp_rx_response_get
    660  * Purpose:
    661  *      Get Rx response data for a PTP clock.
    662  * Parameters:
    663  *      unit       - (IN)  Unit number.
    664  *      ptp_id     - (IN)  PTP stack ID.
    665  *      clock_num  - (IN)  PTP clock number.
    666  *      usec       - (IN)  Semaphore timeout (usec).
    667  *      data       - (OUT) Response data.
    668  *      data_len   - (OUT) Response data size (octets).
    669  * Returns:
    670  *      BCM_E_XXX
    671  * Notes:
    672  */
    673 int
    674 _bcm_ptp_rx_response_get(
    675     int unit,
    676     bcm_ptp_stack_id_t ptp_id,
    677     int clock_num,
    678     int usec,
    679     uint8 **data,
    680     int *data_len)
    681 {
    682     int rv = BCM_E_UNAVAIL;
    683     int spl;
    684     sal_usecs_t expiration_time = sal_time_usecs() + usec;
    685 
    686     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num,
    687             PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    688         return rv;
    689     }
    690 
    691     if ((unit_rx_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) ||
    692             (unit_rx_array[unit].stack_array[ptp_id].memstate !=
    693             PTP_MEMSTATE_INITIALIZED)) {
    694         return BCM_E_UNAVAIL;
    695     }
    696 
    697     rv = BCM_E_FAIL;
    698     /* ptp_printf("Await resp @ %d\n", (int)sal_time_usecs()); */
    699 
    700     while (BCM_FAILURE(rv) && (int32) (sal_time_usecs() - expiration_time) < 0) {
    701         rv = _bcm_ptp_sem_take(unit_rx_array[unit].stack_array[ptp_id].clock_data[clock_num].response_ready, usec);
    702     }
    703     if (BCM_FAILURE(rv)) {
    704         LOG_VERBOSE(BSL_LS_BCM_COMMON,
    705                     (BSL_META_U(unit,
    706                                 "Failed management Tx to ToP\n")));
    707         PTP_ERROR_FUNC("_bcm_ptp_sem_take()");
    708         return rv;
    709     }
    710 
    711     /* Lock. */
    712     spl = sal_splhi();
    713 
    714     *data = unit_rx_array[unit].stack_array[ptp_id]
    715                .clock_data[clock_num].response_data;
    716 
    717     *data_len = unit_rx_array[unit].stack_array[ptp_id]
    718                     .clock_data[clock_num].response_len;
    719 
    720     unit_rx_array[unit].stack_array[ptp_id]
    721         .clock_data[clock_num].response_data = 0;
    722 
    723     /* Unlock. */
    724     sal_spl(spl);
    725 
    726     return rv;
    727 }
    728 
    729 
    730 #if defined(BCM_PTP_INTERNAL_STACK_SUPPORT)
    731 static void _bcm_ptp_rx_thread(void *arg)
    732 {
    733     _bcm_ptp_stack_info_t *stack_p = arg;
    734     int unit = stack_p->unit;
    735     bcm_ptp_stack_id_t ptp_id = stack_p->stack_id;
    736     int rv = 0;
    737     _bcm_ptp_stack_rx_array_t *stack_rx = &unit_rx_array[unit].stack_array[ptp_id];
    738     bcm_ptp_cb_msg_t cb_msg;
    739     int rx_thread_exit = 0;
    740 
    741     /* sal_usecs_t last_time = 0; */
    742     /* sal_usecs_t this_time = 0; */
    743 
    744     while (1) {
    745         int mbox;
    746         
    747         /* mos_msg_data_t rcv; */
    748         /* int rv = soc_cmic_uc_msg_receive(stack_p->unit, stack_p->int_state.core_num, MOS_MSG_CLASS_1588, &rcv, sal_sem_FOREVER); */
    749         /* if (rv) { */
    750         /*     /\* got error, so wait *\/ */
    751         /*     sal_usleep(100000); */
    752         /* } */
    753         /* The uc_msg is just a signal that there is a message somewhere to get, so look through all mboxes */
    754 
    755         /* rather than getting woken by soc_cmic_uc_msg_receive, just poll */
    756 
    757         /* Note:  on some SAL implementations, a short usleep is done by doing a 'yield' within a loop,
    758            rather than a true 'sleep'.  If no other tasks are using the CPU, this will effectively be a
    759            busy-wait, as the yield will immediately return.  This can make it appear that the PTP Rx thread
    760            is using a lot of CPU, though this is only because no other task is in a running state.
    761            To avoid this appearance of CPU load, the value of BCM_PTP_RX_POLL_WAIT_USEC can be increased
    762            via the Make.local file, e.g.:  CFGFLAGS += -DBCM_PTP_RX_POLL_WAIT_USEC=11000
    763         */
    764         sal_usleep(BCM_PTP_RX_POLL_WAIT_USEC);
    765 
    766         /* last_time = this_time; */
    767         /* this_time = sal_time_usecs(); */
    768 
    769         for (mbox = 0; mbox < BCM_PTP_MAX_BUFFERS; ++mbox) {
    770 
    771             if (stack_rx->rx_thread_exit || (_bcm_ptp_running(unit) != BCM_E_NONE)
    772                 || (stack_p->int_state.mboxes == NULL)) {
    773                 /* Existing the rx thread */
    774                 rx_thread_exit = 1;
    775                 break;
    776             }
    777 
    778             /* Invalidate cache for the shared memory before reading it */
    779             soc_cm_sinval(unit, (void*)&stack_p->int_state.mboxes->mbox[mbox].status, sizeof(stack_p->int_state.mboxes->mbox[mbox]));
    780 
    781             switch (soc_ntohl(stack_p->int_state.mboxes->mbox[mbox].status)) {
    782             case MBOX_STATUS_ATTN_HOST_TUNNEL: {
    783                 int cb_flags = 0;        
    784                 unsigned clock_num = soc_ntohl(stack_p->int_state.mboxes->mbox[mbox].clock_num);
    785                 int message_type = _bcm_ptp_uint16_read((uint8 *)stack_p->int_state.mboxes->mbox[mbox].data + MBOX_TUNNEL_MSG_TYPE_OFFSET);
    786                 int port_num = _bcm_ptp_uint16_read((uint8 *)stack_p->int_state.mboxes->mbox[mbox].data + MBOX_TUNNEL_PORT_NUM_OFFSET);
    787                 int protocol = _bcm_ptp_uint16_read((uint8 *)stack_p->int_state.mboxes->mbox[mbox].data + MBOX_TUNNEL_PROTOCOL_OFFSET);
    788                 int src_addr_offset = _bcm_ptp_uint16_read((uint8 *)stack_p->int_state.mboxes->mbox[mbox].data + MBOX_TUNNEL_SRC_ADDR_OFFS_OFFSET);
    789                 int ptp_offset = _bcm_ptp_uint16_read((uint8 *)stack_p->int_state.mboxes->mbox[mbox].data + MBOX_TUNNEL_PTP_OFFS_OFFSET);
    790                 uint8 * cb_data = (uint8 *)stack_p->int_state.mboxes->mbox[mbox].data + MBOX_TUNNEL_PACKET_OFFSET;
    791                 int cb_data_len = soc_ntohl(stack_p->int_state.mboxes->mbox[mbox].data_len) - MBOX_TUNNEL_PACKET_OFFSET;
    792 
    793                 bcm_ptp_clock_identity_t peer_clockIdentity;
    794                 bcm_ptp_clock_port_address_t peer_portAddress;
    795 
    796                 /* ptp_printf("Got Tunnel: MsgType:%d, Proto:%d Clk:%d\n", message_type, protocol, clock_num); */
    797                 SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostPtpRx,
    798                                      "Got Tunnel: MsgType:%d, Proto:%d Clk:%d\n",
    799                                      message_type, protocol, clock_num));
    800 
    801                 
    802                 _bcm_ptp_most_recent_clock_num = clock_num;
    803                 _bcm_ptp_most_recent_port = port_num;
    804                 _bcm_ptp_most_recent_protocol = protocol;
    805                 _bcm_ptp_most_recent_src_addr_offset = src_addr_offset;
    806                 _bcm_ptp_most_recent_msg_offset = ptp_offset;
    807                 cb_flags = 0;
    808 
    809                 if (message_type == bcmPTP_MESSAGE_TYPE_SIGNALING ||
    810                     message_type == bcmPTP_MESSAGE_TYPE_MANAGEMENT) {
    811                     /* Peer information for counts of Rx signaling and external management messages. */
    812                     sal_memcpy(peer_clockIdentity,
    813                                cb_data + ptp_offset + PTP_PTPHDR_SRCPORT_OFFSET_OCTETS,
    814                                sizeof(bcm_ptp_clock_identity_t));
    815 
    816                     peer_portAddress.addr_type = protocol;
    817                     sal_memset(peer_portAddress.address, 0, BCM_PTP_MAX_NETW_ADDR_SIZE);
    818                     switch (protocol) {
    819                     case bcmPTPUDPIPv4:
    820                         sal_memcpy(peer_portAddress.address,
    821                                    cb_data + src_addr_offset, PTP_IPV4_ADDR_SIZE_BYTES);
    822                         break;
    823                     case bcmPTPUDPIPv6:
    824                         sal_memcpy(peer_portAddress.address,
    825                                    cb_data + src_addr_offset, PTP_IPV6_ADDR_SIZE_BYTES);
    826                         break;
    827                     case bcmPTPIEEE8023:
    828                         sal_memcpy(peer_portAddress.address,
    829                                    cb_data + src_addr_offset, PTP_MAC_ADDR_SIZE_BYTES);
    830                         break;
    831                     default:
    832                         ;
    833                     }
    834                 }
    835 
    836                 switch (message_type) {
    837                 case bcmPTP_MESSAGE_TYPE_SIGNALING:
    838                     /* Peer dataset counts of Rx signaling messages. */
    839                     if (BCM_FAILURE(rv = _bcm_ptp_update_peer_counts(unit, ptp_id, clock_num, port_num,
    840                             &peer_clockIdentity, &peer_portAddress, 0, 0, 0, 0, 0, 0, 0, 1, 0, NULL))) {
    841                         SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostPtpRx,
    842                                              "Error in _bcm_ptp_update_peer_counts()\n"));
    843                         PTP_ERROR_FUNC("_bcm_ptp_update_peer_counts()");
    844                     }
    845 
    846                     if (unit_rx_array[unit].signal_cb) {
    847                         sal_memset(&cb_msg, 0, sizeof(bcm_ptp_cb_msg_t));
    848                         cb_msg.length = cb_data_len;
    849                         cb_msg.data = cb_data;
    850                         unit_rx_array[unit].signal_cb(unit, ptp_id, clock_num, port_num,
    851                                                       bcmPTPCallbackTypeSignal, &cb_msg, 
    852                                                       unit_rx_array[unit].signal_user_data);
    853                     }
    854                     break;
    855 
    856                 case bcmPTP_MESSAGE_TYPE_MANAGEMENT:
    857                     /* Peer dataset counts of Rx external management messages. */
    858                     if (BCM_FAILURE(rv = _bcm_ptp_update_peer_counts(unit, ptp_id, clock_num, port_num,
    859                             &peer_clockIdentity, &peer_portAddress, 0, 0, 0, 0, 0, 0, 1, 0, 0, NULL))) {
    860                         SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostPtpRx,
    861                                              "Error in _bcm_ptp_update_peer_counts()\n"));
    862                         PTP_ERROR_FUNC("_bcm_ptp_update_peer_counts()");
    863                     }
    864 
    865                     if (unit_rx_array[unit].management_cb) {
    866                         sal_memset(&cb_msg, 0, sizeof(bcm_ptp_cb_msg_t));
    867 
    868                         cb_msg.flags = cb_flags;
    869                         cb_msg.protocol = protocol;
    870                         cb_msg.src_addr_offset = src_addr_offset;
    871                         cb_msg.msg_offset = ptp_offset;
    872                         cb_msg.length = cb_data_len;
    873                         cb_msg.data = cb_data;
    874 
    875                         if (unit_rx_array[unit].management_cb(unit, ptp_id, clock_num, port_num,
    876                                                               bcmPTPCallbackTypeManagement, &cb_msg,
    877                                                               unit_rx_array[unit].management_user_data)
    878                             == bcmPTPCallbackAccept) {
    879                             if (BCM_FAILURE(rv =_bcm_ptp_tunnel_message_to_top(unit,
    880                                                      ptp_id, clock_num, port_num,
    881                                                      cb_data_len, cb_data, 1))) {
    882                                 PTP_ERROR_FUNC("_bcm_ptp_tunnel_message_to_top()");
    883                             }
    884                         }
    885                     }
    886                     break;
    887                 case bcmPTP_MESSAGE_TYPE_ARP:
    888                     if (_bcm_ptp_arp_callback) {
    889                         _bcm_ptp_arp_callback(unit, ptp_id, protocol, src_addr_offset, ptp_offset, cb_data_len, cb_data);
    890                     }
    891                     break;
    892 
    893                 case (0x0100):
    894                     
    895                     if (BCM_FAILURE(rv = bcm_esmc_rx(unit, ptp_id, port_num,
    896                             protocol, cb_data_len, cb_data))) {
    897                         PTP_ERROR_FUNC("bcm_esmc_rx()");
    898                     }
    899                     break;
    900 
    901                 default:
    902                     LOG_VERBOSE(BSL_LS_BCM_COMMON,
    903                                 (BSL_META_U(unit,
    904                                             "Improper PTP tunneled message type: %d in mbox %d\n"), message_type, mbox));
    905                     SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostPtpRx,
    906                         "Improper PTP tunneled message type: %d in mbox %d\n",
    907                         message_type, mbox));
    908                     break;
    909                 }
    910                 /* Free the mbox so the CMICm can use it again */
    911                 SET_MBOX_STATUS(stack_p, mbox, MBOX_STATUS_EMPTY);
    912 
    913                 break;
    914               }
    915 
    916             case MBOX_STATUS_ATTN_HOST_EVENT: {
    917                 
    918                 unsigned clock_num = soc_ntohl(stack_p->int_state.mboxes->mbox[mbox].clock_num);
    919                 int cb_flags = 0;
    920                 int cb_data_len = soc_ntohl(stack_p->int_state.mboxes->mbox[mbox].data_len);
    921                 uint8 *cb_data = (uint8 *)stack_p->int_state.mboxes->mbox[mbox].data;
    922                 int ev_internal = 0;
    923 #ifdef PTP_RX_CALLBACK_DEBUG
    924                 LOG_CLI((BSL_META_U(unit,
    925                     "Rx thread : Host event(%d)\n"), cb_data_len));
    926                 _bcm_ptp_dump_hex(cb_data, cb_data_len, 0);
    927 #endif
    928 
    929                 if (BCM_FAILURE(rv = _bcm_ptp_event_message_monitor(unit, ptp_id,
    930                         cb_data_len, cb_data, &ev_internal))) {
    931                         PTP_ERROR_FUNC("_bcm_ptp_event_message_monitor()");
    932                 }
    933 
    934                 if (unit_rx_array[unit].event_cb && !ev_internal) {
    935                     sal_memset(&cb_msg, 0, sizeof(bcm_ptp_cb_msg_t));
    936                     cb_msg.length = cb_data_len;
    937                     cb_msg.data = cb_data;
    938                     cb_msg.flags = cb_flags;
    939                     unit_rx_array[unit].event_cb(unit, ptp_id, clock_num,
    940                                                  PTP_CLOCK_PORT_NUMBER_DEFAULT,
    941                                                  bcmPTPCallbackTypeEvent, &cb_msg,
    942                                                  unit_rx_array[unit].event_user_data);
    943                 }
    944 
    945                 SET_MBOX_STATUS(stack_p, mbox, MBOX_STATUS_EMPTY);
    946                 SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostPtpRx, "Got HOST_EVENT in mbox %d\n", mbox));
    947                 break;
    948               }
    949 
    950             case MBOX_STATUS_ATTN_HOST_RESP: {
    951                 /* This really should only be in mbox 0, but here for generality */
    952                 int clock_num = soc_ntohl(stack_p->int_state.mboxes->mbox[mbox].clock_num);
    953 
    954                 /* ptp_printf("Got HOST_RESP in mbox %d\n", mbox); */
    955                 SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostPtpRx, "Got HOST_RESP in mbox %d\n", mbox));
    956 
    957                 stack_rx->clock_data[clock_num].response_data = (uint8 *)stack_p->int_state.mboxes->mbox[mbox].data;
    958                 stack_rx->clock_data[clock_num].response_len = soc_ntohl(stack_p->int_state.mboxes->mbox[mbox].data_len);
    959 
    960                 SET_MBOX_STATUS(stack_p, mbox, MBOX_STATUS_PENDING_HOST);
    961 
    962                 rv = _bcm_ptp_sem_give(stack_rx->clock_data[clock_num].response_ready);
    963                 if (BCM_FAILURE(rv)) {
    964                     PTP_ERROR_FUNC("_bcm_ptp_sem_give()");
    965                 }
    966                 break;
    967               }
    968              case MBOX_STATUS_ATTN_HOST_TIMESTAMPS: {
    969                 unsigned clock_num = soc_ntohl(stack_p->int_state.mboxes->mbox[mbox].clock_num);
    970                 int cb_data_len = soc_ntohl(stack_p->int_state.mboxes->mbox[mbox].data_len);
    971                 uint8 *cb_data = (uint8 *)stack_p->int_state.mboxes->mbox[mbox].data;
    972                 if (BCM_FAILURE(rv =_bcm_ptp_timestamp_queue_add(unit,
    973                                                      ptp_id, clock_num, cb_data_len, cb_data))) {
    974 #ifdef BCM_PTP_EXT_SERVO_SUPPORT
    975                    mbox_tsevent_stats.error_queue_add++;
    976 #endif /* BCM_PTP_EXT_SERVO_SUPPORT */
    977                    PTP_ERROR_FUNC("_bcm_ptp_queue_timestamp_message()");
    978                 } else {
    979 #ifdef BCM_PTP_EXT_SERVO_SUPPORT
    980                 mbox_tsevent_stats.event_queued++;
    981 #endif /* BCM_PTP_EXT_SERVO_SUPPORT */
    982                 }
    983                 SET_MBOX_STATUS(stack_p, mbox, MBOX_STATUS_EMPTY);
    984                 SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostPtpRx, "Got HOST_TIMESTAMPS_EVENT in mbox %d\n", mbox));
    985                 break;
    986               }
    987            }
    988         }
    989         /* exit the thread */
    990         if (rx_thread_exit) {
    991             break;
    992         }
    993     } /* while (1) loop */
    994 
    995     stack_rx->rx_thread = SAL_THREAD_ERROR;
    996     sal_thread_exit(0);
    997 }
    998 #endif  /* defined(BCM_PTP_INTERNAL_STACK_SUPPORT) */
    999 
   1000 #if defined(BCM_PTP_EXTERNAL_STACK_SUPPORT)
   1001 
   1002 bcm_rx_t
   1003 _bcm_ptp_rx_callback(
   1004     int unit,
   1005     bcm_pkt_t *pkt,
   1006     void *cookie)
   1007 {
   1008     int rv = BCM_E_UNAVAIL;
   1009     int spl;
   1010 
   1011     uint8 *prior_data;
   1012     uint16 udp_dest_port;
   1013     uint16 message_len;
   1014 
   1015     int wrapClockNumber;
   1016     int wrapPortNumber;
   1017     bcm_ptp_message_type_t wrapMessageType;
   1018     bcm_ptp_protocol_t wrapProtocol;
   1019     uint16 wrapSrcAddrOffset;
   1020     uint16 wrapPtpOffset;
   1021 
   1022     _bcm_ptp_stack_info_t *stack_p;
   1023     _bcm_ptp_info_t *ptp_info_p;
   1024     bcm_ptp_clock_identity_t cb_clock_identity;
   1025     bcm_ptp_stack_id_t cb_ptp_id = (bcm_ptp_stack_id_t)cookie;
   1026     int cb_clock_num;
   1027     uint32 cb_flags;
   1028     int ev_internal = 0;
   1029     int vlan, tpid;
   1030     int i = 0;
   1031 
   1032     bcm_ptp_clock_identity_t peer_clockIdentity;
   1033     bcm_ptp_clock_port_address_t peer_portAddress;
   1034 
   1035     bcm_ptp_cb_msg_t cb_msg;
   1036 
   1037     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT,
   1038             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   1039         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
   1040         return BCM_RX_NOT_HANDLED;
   1041     }
   1042 
   1043     if (unit_rx_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) {
   1044         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1045                     (BSL_META_U(unit,
   1046                                 "Rx unit data not initialized\n")));
   1047         return BCM_RX_NOT_HANDLED;
   1048     }
   1049 
   1050 #ifdef PTP_RX_CALLBACK_DEBUG
   1051     LOG_CLI((BSL_META_U(unit,
   1052                         "_bcm_ptp_rx_callback(%d,%d)\n"),
   1053              pkt->pkt_len, BCM_PKT_IEEE_LEN(pkt)));
   1054         _bcm_ptp_dump_hex(BCM_PKT_IEEE(pkt), BCM_PKT_IEEE_LEN(pkt), 0);
   1055 #endif
   1056 
   1057     if (pkt->pkt_data[0].len < pkt->pkt_len ||
   1058             pkt->pkt_len < PTP_RX_PACKET_MIN_SIZE_OCTETS) {
   1059         /*
   1060          * Ignore packet.
   1061          * NOTICE: inconsistent or incompatible packet length.
   1062          */
   1063         return BCM_RX_NOT_HANDLED;
   1064     }
   1065 
   1066     if (BCM_FAILURE(rv = _bcm_ptp_rx_message_length_get(BCM_PKT_IEEE(pkt),
   1067             &message_len))) {
   1068         PTP_ERROR_FUNC("_bcm_ptp_rx_message_length_get()");
   1069         return BCM_RX_NOT_HANDLED;
   1070     }
   1071 
   1072     /*
   1073      * Parse packet data.
   1074      */
   1075 
   1076     /** Get destination port from UDP header, which is a proxy for packet
   1077      * type and subsequent handling.
   1078      */
   1079     if (BCM_FAILURE(rv = _bcm_ptp_rx_message_destination_port_get(
   1080              BCM_PKT_IEEE(pkt), &udp_dest_port))) {
   1081         PTP_ERROR_FUNC("_bcm_ptp_rx_message_destination_port_get()");
   1082         return BCM_RX_NOT_HANDLED;
   1083     }
   1084 
   1085     switch (udp_dest_port) {
   1086     case (0x0140):
   1087         /* Response message. */
   1088 
   1089         /* Sanity / Security check: Validate VLAN & MAC information for this clock */
   1090         tpid = _bcm_ptp_uint16_read(BCM_PKT_IEEE(pkt) + 12);  /* 12: fixed offset for TPID/VLAN */
   1091 
   1092         /* Extract only vid, mask out Pri and CFI */
   1093         vlan =  (_bcm_ptp_uint16_read(BCM_PKT_IEEE(pkt) + 14) & 0x0FFF);
   1094 
   1095         if (tpid != unit_rx_array[unit].stack_array[cb_ptp_id].tpid ||
   1096             vlan != unit_rx_array[unit].stack_array[cb_ptp_id].vlan) {
   1097             /* This is a PTP message, but not from our stack (since it is on the wrong VLAN). */
   1098             return BCM_RX_NOT_HANDLED;
   1099         }
   1100 
   1101         if (pkt->pkt_len < PTP_RX_MGMT_MIN_SIZE) {
   1102             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1103                         (BSL_META_U(unit,
   1104                                     "Bad response len\n")));
   1105             return BCM_RX_NOT_HANDLED;
   1106         }
   1107 
   1108         /*
   1109          * Parse packet data.
   1110          * Lookup the unit number, PTP stack ID, and PTP clock number
   1111          * association of the packet based on the sender's PTP clock
   1112          * identity.
   1113          */
   1114         if (BCM_FAILURE(rv = _bcm_ptp_rx_message_source_clock_identity_get(
   1115                 BCM_PKT_IEEE(pkt), &cb_clock_identity))) {
   1116             PTP_ERROR_FUNC("_bcm_ptp_rx_message_source_clock_identity_get()");
   1117             return BCM_RX_NOT_HANDLED;
   1118         }
   1119 
   1120         if (BCM_FAILURE(rv = _bcm_ptp_clock_lookup(cb_clock_identity, unit,
   1121                                                    cb_ptp_id, &cb_clock_num))) {
   1122             /* Not from one of this stack's clocks, so leave it */
   1123             return BCM_RX_NOT_HANDLED;
   1124         }
   1125 
   1126         /*
   1127          * Ensure that Rx framework is initialized and Rx data structures are
   1128          * created for the requisite unit and PTP stack.
   1129          */
   1130         if ((unit_rx_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) ||
   1131                 (unit_rx_array[unit].stack_array[cb_ptp_id].memstate !=
   1132                 PTP_MEMSTATE_INITIALIZED)) {
   1133             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1134                         (BSL_META_U(unit,
   1135                                     "Rx unit/stack data not initialized\n")));
   1136             return BCM_RX_NOT_HANDLED;
   1137         }
   1138 
   1139         if (sal_memcmp(BCM_PKT_IEEE(pkt) + sizeof(bcm_mac_t),
   1140                        unit_rx_array[unit].stack_array[cb_ptp_id].top_mac,
   1141                        sizeof(bcm_mac_t)) != 0) {
   1142             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1143                         (BSL_META_U(unit,
   1144                                     "Bad response smac\n")));
   1145         }
   1146 
   1147         if (sal_memcmp(BCM_PKT_IEEE(pkt),
   1148                        unit_rx_array[unit].stack_array[cb_ptp_id].host_mac,
   1149                        sizeof(bcm_mac_t)) != 0) {
   1150             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1151                         (BSL_META_U(unit,
   1152                                     "Bad response dmac\n")));
   1153         }
   1154 
   1155         /* Lock. */
   1156         spl = sal_splhi();
   1157 
   1158         prior_data = unit_rx_array[unit].stack_array[cb_ptp_id]
   1159                                            .clock_data[cb_clock_num]
   1160                                            .response_data;
   1161 
   1162         unit_rx_array[unit].stack_array[cb_ptp_id]
   1163                               .clock_data[cb_clock_num]
   1164                               .response_data = pkt->pkt_data[0].data + PTP_RX_UDP_PAYLOAD_OFFSET;
   1165 
   1166         unit_rx_array[unit].stack_array[cb_ptp_id]
   1167                               .clock_data[cb_clock_num]
   1168                               .response_len =  pkt->pkt_len - PTP_RX_UDP_PAYLOAD_OFFSET;
   1169 
   1170         /* Unlock. */
   1171         sal_spl(spl);
   1172 
   1173         /*
   1174          * Free unclaimed response.
   1175          * NOTICE: If prior data exists, it must be freed.
   1176          */
   1177         if (prior_data) {
   1178             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1179                         (BSL_META_U(unit,
   1180                                     "Unclaimed response freed\n")));
   1181 
   1182             SET_PTP_INFO;
   1183             stack_p = &ptp_info_p->stack_info[cb_ptp_id];
   1184 
   1185             stack_p->rx_free(unit, cb_ptp_id, prior_data);
   1186         }
   1187 
   1188         rv = _bcm_ptp_sem_give(unit_rx_array[unit].stack_array[cb_ptp_id]
   1189                      .clock_data[cb_clock_num].response_ready);
   1190         if (BCM_FAILURE(rv)) {
   1191             PTP_ERROR_FUNC("_bcm_ptp_sem_give()");
   1192         }
   1193 
   1194         return BCM_RX_HANDLED_OWNED;
   1195         break;
   1196 
   1197     case (0x0141):
   1198         /* Forwarded (tunnel) message. */
   1199         if (message_len < PTP_RX_TUNNEL_MSG_MIN_SIZE_OCTETS) {
   1200             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1201                         (BSL_META_U(unit,
   1202                                     "Invalid (too-short) tunnel message received (0x%04x)\n"),
   1203                          message_len));
   1204             return BCM_RX_HANDLED;
   1205         }
   1206 
   1207         /*
   1208          * Parse wrapping header.
   1209          * Move cursor forward to "remove" wrapping header.
   1210          *
   1211          * NOTICE: Forwarded tunnel message prepends an 11-element header, which
   1212          *         includes PTP message and addressing metadata.
   1213          *         Wrapping Header Octet  0      : Instance number.
   1214          *         Wrapping Header Octets 1...2  : Local (receiving) port number.
   1215          *         Wrapping Header Octets 3...4  : Message type.
   1216          *         Wrapping Header Octets 5...6  : Ethertype.
   1217          *         Wrapping Header Octets 7...8  : Source address offset.
   1218          *         Wrapping Header Octets 9...10 : PTP payload offset.
   1219          */
   1220         i = PTP_PTPHDR_START_IDX;
   1221 
   1222         wrapClockNumber = *(BCM_PKT_IEEE(pkt) + i);
   1223         ++i;
   1224         --message_len;
   1225 
   1226         wrapPortNumber = _bcm_ptp_uint16_read(BCM_PKT_IEEE(pkt) + i);
   1227         i += sizeof(uint16);
   1228         message_len -= sizeof(uint16);
   1229 
   1230         wrapMessageType = _bcm_ptp_uint16_read(BCM_PKT_IEEE(pkt) + i);
   1231         i += sizeof(uint16);
   1232         message_len -= sizeof(uint16);
   1233 
   1234         wrapProtocol = _bcm_ptp_uint16_read(BCM_PKT_IEEE(pkt) + i);
   1235         i += sizeof(uint16);
   1236         message_len -= sizeof(uint16);
   1237 
   1238         wrapSrcAddrOffset = _bcm_ptp_uint16_read(BCM_PKT_IEEE(pkt) + i);
   1239         i += sizeof(uint16);
   1240         message_len -= sizeof(uint16);
   1241 
   1242         wrapPtpOffset = _bcm_ptp_uint16_read(BCM_PKT_IEEE(pkt) + i);
   1243         i += sizeof(uint16);
   1244         message_len -= sizeof(uint16);
   1245 
   1246         
   1247         _bcm_ptp_most_recent_clock_num = wrapClockNumber;
   1248         _bcm_ptp_most_recent_port = wrapPortNumber;
   1249         _bcm_ptp_most_recent_protocol = wrapProtocol;
   1250         _bcm_ptp_most_recent_src_addr_offset = wrapSrcAddrOffset;
   1251         _bcm_ptp_most_recent_msg_offset = wrapPtpOffset;
   1252 
   1253         /*
   1254          * Parse packet data.
   1255          * Lookup the unit number, PTP stack ID, and PTP clock number
   1256          * association of the packet based on the recipient's PTP clock
   1257          * identity.
   1258          */
   1259         if (wrapMessageType == bcmPTP_MESSAGE_TYPE_SIGNALING ||
   1260             wrapMessageType == bcmPTP_MESSAGE_TYPE_MANAGEMENT) {
   1261             /* PTP tunneled message. */
   1262             sal_memcpy(cb_clock_identity,
   1263                        BCM_PKT_IEEE(pkt) + i + wrapPtpOffset + PTP_PTPHDR_SIZE_OCTETS,
   1264                        sizeof(bcm_ptp_clock_identity_t));
   1265 
   1266             /* Peer information for counts of Rx signaling and external management messages. */
   1267             sal_memcpy(peer_clockIdentity,
   1268                        BCM_PKT_IEEE(pkt) + i + wrapPtpOffset + PTP_PTPHDR_SRCPORT_OFFSET_OCTETS,
   1269                        sizeof(bcm_ptp_clock_identity_t));
   1270 
   1271             peer_portAddress.addr_type = wrapProtocol;
   1272             sal_memset(peer_portAddress.address, 0, BCM_PTP_MAX_NETW_ADDR_SIZE);
   1273             switch (wrapProtocol) {
   1274             case bcmPTPUDPIPv4:
   1275                 sal_memcpy(peer_portAddress.address,
   1276                            BCM_PKT_IEEE(pkt) + i + wrapSrcAddrOffset, PTP_IPV4_ADDR_SIZE_BYTES);
   1277                 break;
   1278             case bcmPTPUDPIPv6:
   1279                 sal_memcpy(peer_portAddress.address,
   1280                            BCM_PKT_IEEE(pkt) + i + wrapSrcAddrOffset, PTP_IPV6_ADDR_SIZE_BYTES);
   1281                 break;
   1282             case bcmPTPIEEE8023:
   1283                 sal_memcpy(peer_portAddress.address,
   1284                            BCM_PKT_IEEE(pkt) + i + wrapSrcAddrOffset, PTP_MAC_ADDR_SIZE_BYTES);
   1285                 break;
   1286             default:
   1287                 ;
   1288             }
   1289         } else {
   1290             /* Non-PTP tunneled message (e.g. ARP). */
   1291 
   1292             
   1293             sal_memset(cb_clock_identity, 0xff, sizeof(bcm_ptp_clock_identity_t));
   1294         }
   1295 
   1296         if (BCM_FAILURE(rv = _bcm_ptp_clock_lookup(cb_clock_identity, unit,
   1297                                                    cb_ptp_id, &cb_clock_num))) {
   1298             /* Not from one of this stack's clocks, so leave it */
   1299             return BCM_RX_NOT_HANDLED;
   1300         }
   1301 
   1302         /*
   1303          * Ensure that Rx framework is initialized and Rx data structures are
   1304          * created for the requisite unit and PTP stack.
   1305          */
   1306         if ((unit_rx_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) ||
   1307                 (unit_rx_array[unit].stack_array[cb_ptp_id].memstate !=
   1308                 PTP_MEMSTATE_INITIALIZED)) {
   1309             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1310                         (BSL_META_U(unit,
   1311                                     "Rx unit/stack data not initialized\n")));
   1312             return BCM_RX_NOT_HANDLED;
   1313         }
   1314 
   1315         switch (wrapMessageType) {
   1316         case bcmPTP_MESSAGE_TYPE_SIGNALING:
   1317             /* Peer dataset counts of Rx signaling messages. */
   1318             if (BCM_FAILURE(rv = _bcm_ptp_update_peer_counts(unit, cb_ptp_id, wrapClockNumber, wrapPortNumber,
   1319                     &peer_clockIdentity, &peer_portAddress, 0, 0, 0, 0, 0, 0, 0, 1, 0, NULL))) {
   1320                 PTP_ERROR_FUNC("_bcm_ptp_update_peer_counts()");
   1321             }
   1322 
   1323             
   1324             cb_flags = 0;
   1325 
   1326             if (unit_rx_array[unit].signal_cb) {
   1327                 cb_msg.flags = cb_flags;
   1328                 cb_msg.protocol = wrapProtocol;
   1329                 cb_msg.src_addr_offset = wrapSrcAddrOffset;
   1330                 cb_msg.msg_offset = wrapPtpOffset;
   1331                 cb_msg.length = message_len;
   1332                 cb_msg.data = BCM_PKT_IEEE(pkt) + i;
   1333 
   1334                 unit_rx_array[unit].signal_cb(unit, cb_ptp_id,
   1335                     cb_clock_num, wrapPortNumber,
   1336                     bcmPTPCallbackTypeSignal, &cb_msg,
   1337                     unit_rx_array[unit].signal_user_data);
   1338             }
   1339             break;
   1340 
   1341         case bcmPTP_MESSAGE_TYPE_MANAGEMENT:
   1342             /* Peer dataset counts of Rx external management messages. */
   1343             if (BCM_FAILURE(rv = _bcm_ptp_update_peer_counts(unit, cb_ptp_id, wrapClockNumber, wrapPortNumber,
   1344                     &peer_clockIdentity, &peer_portAddress, 0, 0, 0, 0, 0, 0, 1, 0, 0, NULL))) {
   1345                 PTP_ERROR_FUNC("_bcm_ptp_update_peer_counts()");
   1346             }
   1347 
   1348             
   1349             cb_flags = 0;
   1350 
   1351             if (unit_rx_array[unit].management_cb) {
   1352                 cb_msg.flags = cb_flags;
   1353                 cb_msg.protocol = wrapProtocol;
   1354                 cb_msg.src_addr_offset = wrapSrcAddrOffset;
   1355                 cb_msg.msg_offset = wrapPtpOffset;
   1356                 cb_msg.length = message_len;
   1357                 cb_msg.data = BCM_PKT_IEEE(pkt) + i;
   1358 
   1359                 if (unit_rx_array[unit].management_cb(unit, cb_ptp_id,
   1360                         cb_clock_num, wrapPortNumber,
   1361                         bcmPTPCallbackTypeManagement, &cb_msg,
   1362                         unit_rx_array[unit].management_user_data) == bcmPTPCallbackAccept) {
   1363                     /* Tunnel message to ToP. */
   1364                     if (BCM_FAILURE(rv =_bcm_ptp_tunnel_message_to_top(unit,
   1365                             cb_ptp_id, cb_clock_num, wrapPortNumber,
   1366                             message_len, BCM_PKT_IEEE(pkt) + i, 1))) {
   1367                         PTP_ERROR_FUNC("_bcm_ptp_tunnel_message_to_top()");
   1368                     }
   1369                 }
   1370             }
   1371             break;
   1372 
   1373         case bcmPTP_MESSAGE_TYPE_ARP:
   1374             if (_bcm_ptp_arp_callback) {
   1375                 _bcm_ptp_arp_callback(unit, cb_ptp_id, wrapProtocol, wrapSrcAddrOffset,
   1376                     wrapPtpOffset, message_len, BCM_PKT_IEEE(pkt) + i);
   1377             }
   1378             break;
   1379 
   1380         default:
   1381             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1382                         (BSL_META_U(unit,
   1383                                     "Invalid tunnel message received: "
   1384                                     "unknown/unsupported type (0x%02x)\n"), wrapMessageType));
   1385         }
   1386         break;
   1387 
   1388     case (0x0142):
   1389         /* Event message. */
   1390         if (message_len < PTP_RX_EVENT_MSG_MIN_SIZE_OCTETS) {
   1391             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1392                         (BSL_META_U(unit,
   1393                                     "Invalid (too-short) event message received (0x%04x)\n"),
   1394                          message_len));
   1395             return BCM_RX_HANDLED;
   1396         }
   1397 
   1398         
   1399         cb_ptp_id = 0;
   1400         cb_clock_num = 0;
   1401         cb_flags = 0;
   1402 
   1403         if (BCM_FAILURE(rv = _bcm_ptp_event_message_monitor(unit, cb_ptp_id,
   1404                 message_len, BCM_PKT_IEEE(pkt) + PTP_PTPHDR_START_IDX, &ev_internal))) {
   1405                 PTP_ERROR_FUNC("_bcm_ptp_event_message_monitor()");
   1406         }
   1407 
   1408         if (unit_rx_array[unit].event_cb && !ev_internal) {
   1409             i = PTP_PTPHDR_START_IDX;
   1410 
   1411             cb_msg.flags = cb_flags;
   1412             cb_msg.protocol = bcmPTPUDPIPv4;
   1413             cb_msg.src_addr_offset = 0;
   1414             cb_msg.msg_offset = 0;
   1415             cb_msg.length = message_len;
   1416             cb_msg.data = BCM_PKT_IEEE(pkt) + i;
   1417 
   1418             unit_rx_array[unit].event_cb(unit, cb_ptp_id,
   1419                 cb_clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT,
   1420                 bcmPTPCallbackTypeEvent, &cb_msg,
   1421                 unit_rx_array[unit].event_user_data);
   1422         }
   1423 
   1424         break;
   1425 
   1426     default:
   1427 #ifdef PTP_RX_CALLBACK_DEBUG
   1428         LOG_CLI((BSL_META_U(unit,
   1429                             "UDP packet dst port 0x%04x not handled\n"), udp_dest_port));
   1430 #endif
   1431         return BCM_RX_NOT_HANDLED;
   1432     }
   1433 
   1434     return BCM_RX_HANDLED;
   1435 }
   1436 
   1437 
   1438 /*
   1439  * Function:
   1440  *      _bcm_ptp_rx_message_destination_port_get
   1441  * Purpose:
   1442  *      Get destination port number in UDP header.
   1443  * Parameters:
   1444  *      message   - (IN)  PTP management message.
   1445  *      dest_port - (OUT) Destination port number.
   1446  * Returns:
   1447  *      BCM_E_XXX
   1448  * Notes:
   1449  */
   1450 static int
   1451 _bcm_ptp_rx_message_destination_port_get(
   1452     uint8 *message,
   1453     uint16 *dest_port)
   1454 {
   1455     int i = PTP_UDPHDR_START_IDX + PTP_UDPHDR_DESTPORT_OFFSET_OCTETS;
   1456 
   1457     *dest_port = _bcm_ptp_uint16_read(message + i);
   1458     return BCM_E_NONE;
   1459 }
   1460 
   1461 
   1462 /*
   1463  * Function:
   1464  *      _bcm_ptp_rx_message_source_clock_identity_get
   1465  * Purpose:
   1466  *      Get PTP source clock identity in PTP common header.
   1467  * Parameters:
   1468  *      message        - (IN)  PTP management message.
   1469  *      clock_identity - (OUT) PTP source clock identity.
   1470  * Returns:
   1471  *      BCM_E_XXX
   1472  * Notes:
   1473  */
   1474 static int
   1475 _bcm_ptp_rx_message_source_clock_identity_get(
   1476     uint8 *message,
   1477     bcm_ptp_clock_identity_t *clock_identity)
   1478 {
   1479     int i = PTP_PTPHDR_START_IDX + PTP_PTPHDR_SRCPORT_OFFSET_OCTETS;
   1480 
   1481     sal_memcpy(clock_identity, message + i, sizeof(bcm_ptp_clock_identity_t));
   1482     return BCM_E_NONE;
   1483 }
   1484 
   1485 /*
   1486  * Function:
   1487  *      _bcm_ptp_rx_message_length_get
   1488  * Purpose:
   1489  *      Get the length of a message.
   1490  * Parameters:
   1491  *      message     - (IN)  PTP management message.
   1492  *      message_len - (OUT) Message length (octets).
   1493  * Returns:
   1494  *      BCM_E_XXX.
   1495  * Notes:
   1496  *      Message length is size of Rx packet excluding headers.
   1497  */
   1498 static int
   1499 _bcm_ptp_rx_message_length_get(
   1500     uint8 *message,
   1501     uint16 *message_len)
   1502 {
   1503     int i = PTP_UDPHDR_START_IDX + PTP_UDPHDR_MSGLEN_OFFSET_OCTETS;
   1504 
   1505     *message_len = _bcm_ptp_uint16_read(message + i) - PTP_UDPHDR_SIZE_OCTETS;
   1506     return BCM_E_NONE;
   1507 }
   1508 
   1509 #endif /* defined(BCM_PTP_EXTERNAL_STACK_SUPPORT) */
   1510 
   1511 /*
   1512  * Function:
   1513  *      _bcm_ptp_register_management_callback
   1514  * Purpose:
   1515  *      Register a management callback function
   1516  * Parameters:
   1517  *      unit - (IN) Unit number.
   1518  *      cb - (IN) A pointer to the callback function to call for the specified PTP events
   1519  *      user_data - (IN) Pointer to user data to supply in the callback
   1520  * Returns:
   1521  *      BCM_E_XXX.
   1522  * Notes:
   1523  *      The unit is already locked by the calling function
   1524  */
   1525 int
   1526 _bcm_ptp_register_management_callback(
   1527     int unit,
   1528     bcm_ptp_cb cb,
   1529     void *user_data)
   1530 {
   1531     int rv = BCM_E_UNAVAIL;
   1532 
   1533     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT,
   1534             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   1535         return rv;
   1536     }
   1537 
   1538     unit_rx_array[unit].management_cb = cb;
   1539     unit_rx_array[unit].management_user_data = user_data;
   1540 
   1541     return rv;
   1542 }
   1543 
   1544 /*
   1545  * Function:
   1546  *      _bcm_ptp_register_event_callback
   1547  * Purpose:
   1548  *      Register a event callback function
   1549  * Parameters:
   1550  *      unit - (IN) Unit number.
   1551  *      cb - (IN) A pointer to the callback function to call for the specified PTP events
   1552  *      user_data - (IN) Pointer to user data to supply in the callback
   1553  * Returns:
   1554  *      BCM_E_XXX.
   1555  * Notes:
   1556  *      The unit is already locked by the calling function
   1557  */
   1558 int
   1559 _bcm_ptp_register_event_callback(
   1560     int unit,
   1561     bcm_ptp_cb cb,
   1562     void *user_data)
   1563 {
   1564     int rv = BCM_E_UNAVAIL;
   1565 
   1566     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT,
   1567             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   1568         return rv;
   1569     }
   1570 
   1571     unit_rx_array[unit].event_cb = cb;
   1572     unit_rx_array[unit].event_user_data = user_data;
   1573 
   1574     return rv;
   1575 }
   1576 
   1577 /*
   1578  * Function:
   1579  *      _bcm_ptp_register_signal_callback
   1580  * Purpose:
   1581  *      Register a signal callback function
   1582  * Parameters:
   1583  *      unit - (IN) Unit number.
   1584  *      cb - (IN) A pointer to the callback function to call for the specified PTP events
   1585  *      user_data - (IN) Pointer to user data to supply in the callback
   1586  * Returns:
   1587  *      BCM_E_XXX.
   1588  * Notes:
   1589  *      The unit is already locked by the calling function
   1590  */
   1591 int
   1592 _bcm_ptp_register_signal_callback(
   1593     int unit,
   1594     bcm_ptp_cb cb,
   1595     void *user_data)
   1596 {
   1597     int rv = BCM_E_UNAVAIL;
   1598 
   1599     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT,
   1600             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   1601         return rv;
   1602     }
   1603 
   1604     unit_rx_array[unit].signal_cb = cb;
   1605     unit_rx_array[unit].signal_user_data = user_data;
   1606 
   1607     return rv;
   1608 }
   1609 
   1610 /*
   1611  * Function:
   1612  *      _bcm_ptp_register_peers_callback
   1613  * Purpose:
   1614  *      Register callback function to periodically get the peer counters
   1615  * Parameters:
   1616  *      unit - (IN) Unit number.
   1617  *      cb - (IN) A pointer to the callback function to call for the specified PTP events
   1618  *      user_data - (IN) Pointer to user data to supply in the callback
   1619  * Returns:
   1620  *      BCM_E_XXX.
   1621  * Notes:
   1622  *      The unit is already locked by the calling function
   1623  */
   1624 int
   1625 _bcm_ptp_register_peers_callback(
   1626     int unit,
   1627     bcm_ptp_cb cb,
   1628     void *user_data)
   1629 {
   1630     int rv = BCM_E_UNAVAIL;
   1631 
   1632     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT,
   1633             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   1634         return rv;
   1635     }
   1636 
   1637     unit_rx_array[unit].peers_cb = cb;
   1638     unit_rx_array[unit].peers_user_data = user_data;
   1639 
   1640     return rv;
   1641 }
   1642 
   1643 /*
   1644  * Function:
   1645  *      _bcm_ptp_register_fault_callback
   1646  * Purpose:
   1647  *      Register a fault callback function
   1648  * Parameters:
   1649  *      unit - (IN) Unit number.
   1650  *      cb - (IN) A pointer to the callback function to call for the specified PTP events
   1651  *      user_data - (IN) Pointer to user data to supply in the callback
   1652  * Returns:
   1653  *      BCM_E_XXX.
   1654  * Notes:
   1655  *      The unit is already locked by the calling function
   1656  */
   1657 int
   1658 _bcm_ptp_register_fault_callback(
   1659     int unit,
   1660     bcm_ptp_cb cb,
   1661     void *user_data)
   1662 {
   1663     int rv = BCM_E_UNAVAIL;
   1664 
   1665     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT,
   1666             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   1667         return rv;
   1668     }
   1669 
   1670     unit_rx_array[unit].fault_cb = cb;
   1671     unit_rx_array[unit].fault_user_data = user_data;
   1672 
   1673     return rv;
   1674 }
   1675 
   1676 /*
   1677  * Function:
   1678  *      _bcm_ptp_unregister_management_callback
   1679  * Purpose:
   1680  *      Unregister a management callback function
   1681  * Parameters:
   1682  *      unit - (IN) Unit number.
   1683  * Returns:
   1684  *      BCM_E_XXX.
   1685  * Notes:
   1686  *      The unit is already locked by the calling function
   1687  */
   1688 int
   1689 _bcm_ptp_unregister_management_callback(
   1690     int unit)
   1691 {
   1692     int rv = BCM_E_UNAVAIL;
   1693 
   1694     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT,
   1695             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   1696         return rv;
   1697     }
   1698 
   1699     unit_rx_array[unit].management_cb = NULL;
   1700     unit_rx_array[unit].management_user_data = NULL;
   1701 
   1702     return rv;
   1703 }
   1704 
   1705 /*
   1706  * Function:
   1707  *      _bcm_ptp_unregister_event_callback
   1708  * Purpose:
   1709  *      Unregister a event callback function
   1710  * Parameters:
   1711  *      unit - (IN) Unit number.
   1712  * Returns:
   1713  *      BCM_E_XXX.
   1714  * Notes:
   1715  *      The unit is already locked by the calling function
   1716  */
   1717 int
   1718 _bcm_ptp_unregister_event_callback(
   1719     int unit)
   1720 {
   1721     int rv = BCM_E_UNAVAIL;
   1722 
   1723     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT,
   1724             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   1725         return rv;
   1726     }
   1727 
   1728     unit_rx_array[unit].event_cb = NULL;
   1729     unit_rx_array[unit].event_user_data = NULL;
   1730 
   1731     return rv;
   1732 }
   1733 
   1734 /*
   1735  * Function:
   1736  *      _bcm_ptp_unregister_signal_callback
   1737  * Purpose:
   1738  *      Unregister a signal callback function
   1739  * Parameters:
   1740  *      unit - (IN) Unit number.
   1741  * Returns:
   1742  *      BCM_E_XXX.
   1743  * Notes:
   1744  *      The unit is already locked by the calling function
   1745  */
   1746 int
   1747 _bcm_ptp_unregister_signal_callback(
   1748     int unit)
   1749 {
   1750     int rv = BCM_E_UNAVAIL;
   1751 
   1752     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT,
   1753             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   1754         return rv;
   1755     }
   1756 
   1757     unit_rx_array[unit].signal_cb = NULL;
   1758     unit_rx_array[unit].signal_user_data = NULL;
   1759 
   1760     return rv;
   1761 }
   1762 
   1763 /*
   1764  * Function:
   1765  *      _bcm_ptp_unregister_peers_callback
   1766  * Purpose:
   1767  *      Unregister a check peers callback function
   1768  * Parameters:
   1769  *      unit - (IN) Unit number.
   1770  * Returns:
   1771  *      BCM_E_XXX.
   1772  * Notes:
   1773  *      The unit is already locked by the calling function
   1774  */
   1775 int
   1776 _bcm_ptp_unregister_peers_callback(
   1777     int unit)
   1778 {
   1779     int rv = BCM_E_UNAVAIL;
   1780 
   1781     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT,
   1782             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   1783         return rv;
   1784     }
   1785 
   1786     unit_rx_array[unit].peers_cb = NULL;
   1787     unit_rx_array[unit].peers_user_data = NULL;
   1788 
   1789     return rv;
   1790 }
   1791 
   1792 
   1793 /*
   1794  * Function:
   1795  *      _bcm_ptp_unregister_fault_callback
   1796  * Purpose:
   1797  *      Unregister a fault callback function
   1798  * Parameters:
   1799  *      unit - (IN) Unit number.
   1800  * Returns:
   1801  *      BCM_E_XXX.
   1802  * Notes:
   1803  *      The unit is already locked by the calling function
   1804  */
   1805 int
   1806 _bcm_ptp_unregister_fault_callback(
   1807     int unit)
   1808 {
   1809     int rv = BCM_E_UNAVAIL;
   1810 
   1811     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT,
   1812             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   1813         return rv;
   1814     }
   1815 
   1816     unit_rx_array[unit].fault_cb = NULL;
   1817     unit_rx_array[unit].fault_user_data = NULL;
   1818 
   1819     return rv;
   1820 }
   1821 
   1822 #if defined(BCM_PTP_INTERNAL_STACK_SUPPORT) || defined(BCM_PTP_EXTERNAL_STACK_SUPPORT)
   1823 /*
   1824  * Function:
   1825  *      _bcm_ptp_event_message_monitor
   1826  * Purpose:
   1827  *      Monitor incoming event messages and perform basic operations req'd
   1828  *      for maintenance of host caches.
   1829  * Parameters:
   1830  *      unit        - (IN)  Unit number.
   1831  *      ptp_id      - (IN)  PTP stack ID.
   1832  *      ev_data_len - (IN)  Event message data length (octets).
   1833  *      ev_data     - (IN)  Event message data.
   1834  *      ev_internal - (OUT) Internal-only event. Do not pass to event callbacks.
   1835  * Returns:
   1836  *      BCM_E_XXX - Function status.
   1837  * Notes:
   1838  */
   1839 STATIC int
   1840 _bcm_ptp_event_message_monitor(
   1841     int unit,
   1842     bcm_ptp_stack_id_t ptp_id,
   1843     int ev_data_len,
   1844     uint8 *ev_data,
   1845     int *ev_internal)
   1846 {
   1847     int rv;
   1848 
   1849     uint8 event_clock_num;
   1850     uint16 event_port_num;
   1851     _bcm_ptp_event_t event_code;
   1852     _bcm_ptp_port_state_t portState;
   1853 #ifdef BCM_ESMC_EXTDPLL_SUPPORT
   1854     int event_input_clock_num;
   1855 #endif
   1856 
   1857     int cursor = 0;
   1858 
   1859     event_code = (_bcm_ptp_event_t)_bcm_ptp_uint16_read(ev_data + cursor);
   1860     cursor += sizeof(uint16);
   1861 
   1862     if (event_code == _bcm_ptp_state_change_event) {
   1863         /* EVENT MONITOR: portState change. */
   1864         *ev_internal = 0;
   1865 
   1866         /* Extract clock number and port number of event. */
   1867         event_clock_num = ev_data[cursor++];
   1868         event_port_num = _bcm_ptp_uint16_read(ev_data + cursor);
   1869         cursor += sizeof(uint16);
   1870 
   1871         /* Advance cursor and extract portState of event. */
   1872         cursor += BCM_PTP_CLOCK_EUID_IEEE1588_SIZE + 2;
   1873         portState = (_bcm_ptp_port_state_t)ev_data[cursor];
   1874 
   1875         if (BCM_FAILURE(rv = _bcm_ptp_clock_cache_port_state_set(unit, ptp_id,
   1876                 event_clock_num, event_port_num, portState))) {
   1877             return rv;
   1878         }
   1879     } else if (event_code == _bcm_ptp_tdev_event) {
   1880         /* EVENT MONITOR: TDEV data analysis. */
   1881         *ev_internal = 1;
   1882 
   1883         if (BCM_FAILURE(rv = _bcm_ptp_ctdev_gateway(unit, ptp_id, PTP_CLOCK_NUMBER_DEFAULT,
   1884                 ev_data_len, ev_data))) {
   1885             return rv;
   1886         }
   1887 #if defined(BCM_PTP_EXTERNAL_STACK_SUPPORT)
   1888     } else if (event_code == _bcm_ptp_top_ready_event) {
   1889         _bcm_ptp_ext_fw_info_set(unit, ptp_id, ev_data + 2);
   1890 #endif
   1891 #ifdef BCM_ESMC_EXTDPLL_SUPPORT
   1892     } else if (event_code == _bcm_ptp_synce_loss_event) {
   1893         *ev_internal = 1;
   1894         event_input_clock_num = _bcm_ptp_uint16_read(ev_data + cursor);
   1895         bcm_extdpll_esmc_synce_event_handler(unit, ptp_id, event_input_clock_num);
   1896 #endif /* BCM_ESMC_EXTDPLL_SUPPORT */
   1897     }
   1898 
   1899     return BCM_E_NONE;
   1900 }
   1901 #endif
   1902 
   1903 /*
   1904  * Function:
   1905  *      _bcm_ptp_signal_handler_default
   1906  * Purpose:
   1907  *      Default forwarded (tunneled) PTP signaling message callback handler.
   1908  * Parameters:
   1909  *      unit       - (IN) Unit number.
   1910  *      stack_id   - (IN) PTP stack ID.
   1911  *      clock_num  - (IN) PTP clock number.
   1912  *      clock_port - (IN) PTP port number.
   1913  *      type       - (IN) Callback function type.
   1914  *      msg        - (IN) Callback message data.
   1915  *      user_data  - (IN) Callback user data.
   1916  * Returns:
   1917  *      BCM_E_XXX (if failure)
   1918  *      bcmPTPCallbackAccept (if success)
   1919  * Notes:
   1920  */
   1921 STATIC int
   1922 _bcm_ptp_signal_handler_default(
   1923     int unit,
   1924     bcm_ptp_stack_id_t ptp_id,
   1925     int clock_num, 
   1926     uint32 clock_port, 
   1927     bcm_ptp_cb_type_t type,
   1928     bcm_ptp_cb_msg_t *msg,
   1929     void *user_data)
   1930 {
   1931     int rv = BCM_E_UNAVAIL;
   1932     
   1933     int port_num = _bcm_ptp_most_recent_port;
   1934     bcm_ptp_protocol_t protocol = _bcm_ptp_most_recent_protocol;
   1935     int src_addr_offset = _bcm_ptp_most_recent_src_addr_offset;
   1936     int msg_offset = _bcm_ptp_most_recent_msg_offset;
   1937 
   1938     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
   1939             clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   1940         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
   1941         return rv;
   1942     }
   1943 
   1944 #ifdef PTP_RX_CALLBACK_DEBUG
   1945     LOG_CLI((BSL_META_U(unit,
   1946                         "Signaling callback (Unit = %d, PTP Stack = %d)\n"),
   1947              unit, ptp_id));
   1948     _bcm_ptp_dump_hex(msg->data, msg->length,0);
   1949 #endif
   1950 
   1951     return _bcm_ptp_process_incoming_signaling_msg(unit, ptp_id, clock_num, port_num, protocol, src_addr_offset,
   1952                                                    msg_offset, msg->length, msg->data);
   1953 }
   1954 
   1955 #endif /* defined(INCLUDE_PTP) */