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

txrx.c (58541B)


      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  * socdiag tx (transmit) and rx (receive) commands
      8  */
      9 
     10 #include <sal/types.h>
     11 #include <sal/core/time.h>
     12 #include <sal/core/thread.h>
     13 #include <sal/core/libc.h>
     14 #include <sal/appl/sal.h>
     15 #include <sal/appl/io.h>
     16 #include <shared/bsl.h>
     17 #include <soc/types.h>
     18 #include <soc/debug.h>
     19 #include <soc/cm.h>
     20 #include <soc/higig.h>
     21 #include <soc/dma.h>
     22 #include <soc/dcb.h>
     23 #include <soc/drv.h>
     24 
     25 #ifdef __KERNEL__
     26 #include <linux/kernel.h>
     27 #include <linux/net.h>
     28 #include <linux/in.h>
     29 #else
     30 #include <stdlib.h>
     31 #include <sys/types.h>
     32 #include <sys/socket.h>
     33 #include <netinet/in.h>
     34 #endif
     35 
     36 #include <bcm/tx.h>
     37 #include <bcm/pkt.h>
     38 #include <bcm/rx.h>
     39 #include <bcm/port.h>
     40 #include <bcm/error.h>
     41 #include <bcm/stack.h>
     42 
     43 #include <appl/diag/system.h>
     44 #include <appl/diag/dport.h>
     45 #include <appl/diag/visibility.h>
     46 
     47 #if defined(BCM_BRADLEY_SUPPORT)
     48 #include <soc/bradley.h>
     49 #endif
     50 #if defined(BCM_ESW_SUPPORT)
     51 #include <bcm_int/common/multicast.h>
     52 #endif
     53 
     54 #if defined(BCM_XGS_SUPPORT) && defined(BCM_CPU_TX_PROC_SUPPORT)
     55 #include <soc/proc_hdr.h>
     56 #endif
     57 
     58 /* These modes must correspond with the order of strings below */
     59 #define ENCAP_IEEE      0
     60 #define ENCAP_HIGIG     1
     61 #define ENCAP_B5632     2
     62 #define ENCAP_HIGIG2    3 /* Note: no BCM_PORT_ENCAP_ equivalent */
     63 #define ENCAP_RAW       4 /* Note: no BCM_PORT_ENCAP_ equivalent */
     64 #define ENCAP_COUNT     5 /* Number of CLI encapsulation modes */
     65 
     66 static char *hdr_modes[] = {
     67     "Ieee",
     68     "Higig",
     69     "B5632",
     70     "Higig2",
     71     "Raw",
     72     NULL};
     73 
     74 typedef struct xd_s {                   /* TX/RX description */
     75     int         xd_unit;                /* Unit # */
     76     int         xd_tx_unit;             /* TX device */
     77     int         xd_ppsm;                /* true --> per port src macs */
     78     enum {
     79         XD_IDLE,                        /* Not doing anything */
     80         XD_RUNNING,                     /* Running */
     81         XD_STOP                         /* Stop requested */
     82     }           xd_state;
     83     uint32      xd_tot_cnt;             /* # to send/receive */
     84     uint32      xd_cur_cnt;             /* # sent/received */
     85     int         xd_pkt_len;             /* Packet length */
     86     char        *xd_file;               /* File name of packet data */
     87     sal_mac_addr_t  xd_mac_dst;         /* Destination mac address */
     88     sal_mac_addr_t  xd_mac_src;         /* Source mac address */
     89     sal_mac_addr_t  xd_mac_src_base;    /* Source mac address for pps */
     90                                         /* port source mac */
     91     uint32      xd_mac_dst_inc;         /* Destination mac increment */
     92     uint32      xd_mac_src_inc;         /* Source mac increment */
     93     uint32      xd_pat;                 /* XMIT pattern */
     94     uint32      xd_pat_inc;             /* Pattern Increment */
     95     int         xd_pat_random;          /* Use Random Pattern */
     96     pbmp_t      xd_ppsm_pbm;            /* Saved port bit map for per */
     97                                         /* port source mac */
     98     uint32      xd_vlan;                /* vlan id (0 if untagged) */
     99     uint32      xd_prio;                /* vlan prio */
    100     uint32      xd_prio_int;            /* Internal priority */
    101     uint32      xd_cong_int;            /* Internal congestion */
    102     uint32      xd_crc;
    103 
    104     /* Packet info is now in bcm_pkt_t structure */
    105     bcm_pkt_t   pkt_info;
    106 
    107     /* XGS Header Fields.  Most are in pkt_info */
    108     int         hdr_mode;               /* Mode type */
    109     int         ether_pkt;              /* Use Ethernet packet */
    110     uint32      w0,w1,w2,w3,w4;         /* Raw mode words */
    111     uint32      xd_hg_dmod;             /* Higig Dest Mod */
    112     uint32      xd_hg_dport;            /* Higig Dest Port */
    113     uint32      xd_hg_smod;             /* Higig Src Mod */
    114     uint32      xd_hg_sport;            /* Higig Src Port */
    115     uint32      xd_hg_opcode;           /* Higig Opcode */
    116     uint32      xd_hg_cos;              /* Higig Class of Service */
    117     uint32      xd_hg_pfm;              /* Higig Port Filtering Mode */
    118 #ifdef BCM_HIGIG2_SUPPORT
    119     uint32      xd_hg_mgid;             /* Higig2 Multicast Group ID */
    120     uint32      xd_hg_lbid;             /* Higig2 Load Balancing ID */
    121     uint32      xd_hg_dp;               /* Higig2 Drop Precendece */
    122 #endif /* BCM_HIGIG2_SUPPORT */
    123     uint32      xd_s_portid;            /* BCM5632 Source port ID */
    124     uint32      xd_d_portid;            /* BCM5632 Destination port ID */
    125     uint32      xd_length;              /* BCM5632 Length Field */
    126     uint32      xd_start;               /* BCM5632 Start Field */
    127     int         xd_untag;               /* FB/ER Send Untagged */
    128     int         xd_purge;               /* FB/ER Send Purge */
    129     char        *xd_data;               /* packet data */
    130 #if defined(BCM_TRIUMPH3_SUPPORT)
    131     int         xd_rpl_type;            /* replacement type */
    132     int         xd_rpl_offset;          /* replacement offset */
    133     int         xd_lm_ctr_index;          /* LM counter Index */
    134 #endif
    135 
    136 #ifdef BCM_INSTRUMENTATION_SUPPORT
    137     int         xd_vis_options;
    138     int         xd_vis_sport;
    139 #endif /* BCM_INSTRUMENTATION_SUPPORT */
    140 #ifdef BCM_CPU_TX_PROC_SUPPORT
    141     int         xd_ph_destination_type; /* CPU TX Proc Destination type */
    142     int         xd_ph_destination;      /* CPU TX Proc Destination */
    143     int         xd_ph_destination_port; /* CPU TX Proc Destination Port */
    144     int         xd_ph_source_port;      /* CPU TX Proc Source Port */
    145     int         xd_ph_routed_pkt;       /* CPU TX Proc Routed Packet */
    146     int         xd_ph_qos_fields_valid; /* CPU TX Proc QoS Fields Valid */
    147     int         xd_ph_dp;               /* CPU TX Proc Drop Precedence */
    148     int         xd_ph_mcast_lb_index_valid; /* CPU TX Proc Mcast LB index valid */
    149     int         xd_ph_mcast_lb_index;       /* CPU TX Proc Mcast LB index */
    150     int         xd_ph_ecmp_group_index;     /* CPU TX Proc Group index */
    151     int         xd_ph_ecmp_member_index;    /* CPU TX Proc Member index */
    152 #endif /* BCM_CPU_TX_PROC_SUPPORT */
    153     int         xd_mc_qtype;            /*To MC queue(SOBMH) */
    154     int         xd_rqe_q_num;            /*RQE Queue num(SOBMH) */
    155     int         xd_link_down_tx;         /* Allow tx to link down port */
    156 } xd_t;
    157 
    158 static xd_t     *xd_units[SOC_MAX_NUM_DEVICES];
    159 
    160 #define _XD_INIT(unit, xd) do { \
    161         if (xd_units[unit] == NULL) \
    162             _xd_init(unit); \
    163         if (xd_units[unit] == NULL) \
    164             return CMD_FAIL; \
    165         xd = xd_units[unit]; } while (0)
    166 
    167 #define XD_FILE(xd)     ((xd)->xd_file != NULL && (xd)->xd_file[0] != 0)
    168 #define XD_STRING(xd)   ((xd)->xd_data != NULL && (xd)->xd_data[0] != 0)
    169 
    170 #define UNTAGGED_PACKET_LENGTH         1024
    171 
    172 #if  defined(BCM_HIGIG2_SUPPORT) || defined(BCM_CPU_TX_PROC_SUPPORT)
    173 STATIC char *drop_precedence[] = {
    174     "Green", "Red", "Invalid", "Yellow", NULL
    175 };
    176 #endif /* BCM_HIGIG2_SUPPORT ||  BCM_CPU_TX_PROC_SUPPORT */
    177 
    178 #define XD_PRIO_INT_INVALID 0xffffffff 
    179 #define XD_CONG_INT_INVALID 0xffffffff
    180 
    181 #if  defined(BCM_CPU_TX_PROC_SUPPORT)
    182 #define XD_DEST_TYPE_INVALID 0xff
    183 #endif
    184 
    185 STATIC void
    186 _xd_init(int unit)
    187 {
    188     xd_t        *xd;
    189     int         port;
    190     sal_mac_addr_t default_mac_src ={ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
    191     sal_mac_addr_t default_mac_dst ={ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15 };
    192     bcm_port_config_t pcfg;
    193 
    194     if (bcm_port_config_get(unit, &pcfg) != BCM_E_NONE) {
    195         cli_out("WARNING: bcm ports not initialized\n");
    196         return;
    197     }
    198 
    199     xd = xd_units[unit];
    200     if (xd == NULL) {
    201         xd = sal_alloc(sizeof(xd_t), "xd");
    202         if (xd == NULL) {
    203             cli_out("WARNING: xd memory allocation failed\n");
    204             return;
    205         }
    206         sal_memset(xd, 0, sizeof(xd_t));
    207     }
    208 #ifdef  BCM_XGS_SUPPORT
    209     if (SOC_IS_SHADOW(unit)) {
    210         xd->xd_hg_smod = 0;
    211     } else 
    212     if (bcm_stk_my_modid_get(unit, (int *)&xd->xd_hg_smod) < 0 ) {
    213         cli_out("WARNING: getting my_modid failed\n");
    214         if (xd_units[unit] == NULL) {
    215             sal_free(xd);
    216         }
    217         /* coverity[leaked_storage : FALSE] */
    218         return;
    219     }
    220     xd->xd_hg_dmod      = 0;
    221     xd->xd_hg_dport     = 0;
    222     xd->xd_hg_opcode    = SOC_HIGIG_OP_CPU;
    223     BCM_PBMP_ITER(pcfg.cpu, port) {
    224         xd->xd_hg_sport = port;
    225         break;
    226     }
    227     xd->xd_hg_pfm       = 0;
    228 #endif  /* BCM_XGS_SUPPORT */
    229     
    230     /* get the encapsulation of the first higig port or default to IEEE */
    231     xd->hdr_mode = ENCAP_IEEE;
    232     BCM_PBMP_ITER(pcfg.stack_ext, port) {
    233         if (bcm_port_encap_get(unit, port, &xd->hdr_mode) < 0) {
    234             xd->hdr_mode = ENCAP_IEEE;
    235         }
    236         break;
    237     }
    238 
    239     xd->xd_unit         = unit;
    240     xd->xd_tx_unit      = unit;
    241     xd->xd_state        = XD_IDLE;
    242     xd->xd_file         = NULL;
    243     xd->xd_data         = NULL;
    244     xd->xd_pkt_len      = 68;
    245     xd->xd_pat          = 0x12345678;
    246     xd->xd_pat_inc      = 1;
    247     xd->xd_pat_random   = 0;
    248     BCM_PBMP_ASSIGN(xd->pkt_info.tx_pbmp, pcfg.all);
    249 #if defined(BCM_XGS3_SWITCH_SUPPORT)
    250     if (SOC_IS_XGS3_SWITCH(xd->xd_unit)) {
    251         SOC_PBMP_CLEAR(xd->pkt_info.tx_pbmp);
    252     }
    253 #endif /* BCM_XGS3_SWITCH_SUPPORT */
    254     BCM_PBMP_ASSIGN(xd->xd_ppsm_pbm, pcfg.all);
    255     xd->xd_vlan         = 0x1;
    256     xd->xd_prio         = 0;
    257     xd->xd_prio_int     = XD_PRIO_INT_INVALID;
    258     xd->xd_cong_int     = XD_CONG_INT_INVALID;
    259     xd->xd_ppsm         = 0;
    260 
    261 #if defined(BCM_CPU_TX_PROC_SUPPORT)
    262     xd->xd_ph_destination_type = XD_DEST_TYPE_INVALID;
    263 #endif
    264 
    265     ENET_SET_MACADDR(xd->xd_mac_dst, default_mac_dst);
    266     ENET_SET_MACADDR(xd->xd_mac_src, default_mac_src);
    267     xd->xd_crc      = 1;                /* Re-gen CRC by default */
    268 
    269     if (xd->pkt_info.pkt_data) { /* Has been setup before */
    270         soc_cm_sfree(unit, xd->pkt_info._pkt_data.data);
    271         xd->pkt_info.pkt_data = NULL;
    272     }
    273     xd->pkt_info.flags = 0;
    274 
    275     if ((xd->pkt_info._pkt_data.data = (uint8 *)soc_cm_salloc(unit,
    276                                                               xd->xd_pkt_len,
    277                                                               "xd tx")) == NULL) {
    278         cli_out("WARNING: xd tx packet memory allocation failed\n");
    279         xd->pkt_info.pkt_data = NULL;
    280         xd->pkt_info._pkt_data.len = 0;
    281     } else {
    282         xd->pkt_info.pkt_data = &xd->pkt_info._pkt_data;
    283         xd->pkt_info.blk_count = 1;
    284         xd->pkt_info._pkt_data.len = xd->xd_pkt_len;
    285     }
    286 
    287     xd_units[unit] = xd;
    288 }
    289 
    290 bcm_pkt_t *
    291 txrx_pkt_alloc(int unit, int nblocks, int *sizes, int flags)
    292 {
    293     bcm_pkt_t *pkt;
    294     int i, j;
    295 
    296     if (!(pkt = sal_alloc(sizeof(bcm_pkt_t), "txrx pkt"))) {
    297         return NULL;
    298     }
    299 
    300     pkt->blk_count = nblocks;
    301     if (nblocks == 1) {
    302         pkt->pkt_data = &pkt->_pkt_data;
    303     } else {
    304         if (!(pkt->pkt_data = sal_alloc(sizeof(bcm_pkt_blk_t) * nblocks,
    305                                         "tx pdata"))) {
    306             sal_free(pkt);
    307             return NULL;
    308         }
    309     }
    310 
    311     for (i = 0; i < nblocks; i++) {
    312         pkt->pkt_data[i].len = sizes[i];
    313         if (!(pkt->pkt_data[i].data = soc_cm_salloc(unit, sizes[i],
    314                                                     "txrx data"))) {
    315             for (j = 0; j < i; j++) {
    316                 soc_cm_sfree(unit, pkt->pkt_data[j].data);
    317             }
    318             if (nblocks > 1) {
    319                 sal_free(pkt->pkt_data);
    320             }
    321             sal_free(pkt);
    322             return NULL;
    323         }
    324     }
    325 
    326     pkt->unit = unit;
    327     pkt->flags = flags;
    328     return pkt;
    329 }
    330 
    331 void
    332 txrx_pkt_free(int unit, bcm_pkt_t *pkt)
    333 {
    334     int i;
    335 
    336     for (i = 0; i < pkt->blk_count; i++) {
    337         soc_cm_sfree(unit, pkt->pkt_data[i].data);
    338     }
    339 
    340     if (pkt->pkt_data != &pkt->_pkt_data) {
    341         sal_free(pkt->pkt_data);
    342     }
    343 
    344     sal_free(pkt);
    345 }
    346 
    347 cmd_result_t
    348 tx_parse(int u, args_t *a, xd_t *xd)
    349 /*
    350  * Function:    txrx_parse
    351  * Purpose:     Parse input parameters into a xd structure.
    352  * Parameters:  u - unit #.
    353  *              a - pointer to arguments
    354  *              xd - pointer to xd structure to fill in.
    355  * Returns:     0 - success, -1 failed.
    356  */
    357 {
    358     char *crc_list[] = {"None", "Recompute", "Append", NULL};
    359     parse_table_t       pt;
    360     int                 min_len, tagged;
    361 
    362     /* First arg is count */
    363 
    364     if (!ARG_CNT(a) || !isint(ARG_CUR(a))) {
    365         return(CMD_USAGE);
    366     }
    367 
    368     _XD_INIT(u, xd);
    369 
    370     xd->xd_tot_cnt = parse_integer(ARG_GET(a));
    371 
    372     parse_table_init(u, &pt);
    373 
    374     /* Add XGS Ethernet/BCM5632/HIGIG Options */
    375     if (xd->hdr_mode == ENCAP_IEEE) {
    376         if (SOC_IS_XGS3_SWITCH(u)) {
    377             parse_table_add(&pt, "Untagged", PQ_DFL|PQ_BOOL, 0,
    378                             &xd->xd_untag, NULL);
    379             parse_table_add(&pt, "HGSrcMod",        PQ_DFL|PQ_INT,  0,
    380                             &xd->xd_hg_smod,            NULL);
    381         }
    382         xd->pkt_info.flags &= (~(BCM_TX_HG_READY));
    383     } else if (xd->hdr_mode == ENCAP_HIGIG ||
    384                xd->hdr_mode == ENCAP_HIGIG2) {
    385         if (SOC_IS_XGS_FABRIC(u) || SOC_IS_XGS3_SWITCH(u)) {
    386             xd->pkt_info.flags |= (BCM_TX_HG_READY);
    387         }
    388         parse_table_add(&pt, "HGDestMod",       PQ_DFL|PQ_INT,  0,
    389                         &xd->xd_hg_dmod,            NULL);
    390         parse_table_add(&pt, "HGDestPort",      PQ_DFL|PQ_INT,  0,
    391                         &xd->xd_hg_dport, NULL);
    392         parse_table_add(&pt, "HGOpcode",        PQ_DFL|PQ_INT,  0,
    393                         &xd->xd_hg_opcode,          NULL);
    394         parse_table_add(&pt, "HGSrcMod",        PQ_DFL|PQ_INT,  0,
    395                         &xd->xd_hg_smod,            NULL);
    396         parse_table_add(&pt, "HGSrcPort",       PQ_DFL|PQ_INT,  0,
    397                         &xd->xd_hg_sport, NULL);
    398         parse_table_add(&pt, "PFM",             PQ_DFL|PQ_INT,  0,
    399                         &xd->xd_hg_pfm, NULL);
    400         parse_table_add(&pt, "EthernetPacket",  PQ_DFL|PQ_BOOL, 0,
    401                         &xd->ether_pkt,             NULL);
    402 #ifdef BCM_HIGIG2_SUPPORT
    403         if (xd->hdr_mode == ENCAP_HIGIG2 &&
    404             soc_feature(u, soc_feature_higig2)) {
    405             /* Map traffic class to internal priority */
    406             parse_table_add(&pt, "TrafficClass",     PQ_DFL|PQ_INT,     0,
    407                             &xd->xd_prio_int, NULL);
    408             parse_table_add(&pt, "McastGroupID",     PQ_DFL|PQ_INT,     0,
    409                             &xd->xd_hg_mgid, NULL);
    410             parse_table_add(&pt, "LoadBalID",        PQ_DFL|PQ_INT,     0,
    411                             &xd->xd_hg_lbid, NULL);
    412             parse_table_add(&pt, "DropPrecedence",   PQ_DFL|PQ_MULTI,   0,
    413                             &xd->xd_hg_dp, drop_precedence);
    414         }
    415 #endif /* BCM_HIGIG2_SUPPORT */
    416     } else if (xd->hdr_mode == ENCAP_B5632) {
    417         parse_table_add(&pt, "SourcePortID",    PQ_DFL|PQ_INT,  0,
    418                         &xd->xd_s_portid,           NULL);
    419         parse_table_add(&pt, "DestPortID",      PQ_DFL|PQ_INT,  0,
    420                         &xd->xd_d_portid,           NULL);
    421         parse_table_add(&pt, "Start",   PQ_DFL|PQ_INT,0,
    422                         &xd->xd_start, NULL);
    423         parse_table_add(&pt, "Length",  PQ_DFL|PQ_INT,0,
    424                             &xd->xd_length, NULL);
    425     } else if (xd->hdr_mode == ENCAP_RAW) {
    426         parse_table_add(&pt, "Word0",   PQ_DFL|PQ_INT,0,
    427                         &xd->w0, NULL);
    428         parse_table_add(&pt, "Word1",   PQ_DFL|PQ_INT,0,
    429                         &xd->w1, NULL);
    430         parse_table_add(&pt, "Word2",   PQ_DFL|PQ_INT,0,
    431                         &xd->w2, NULL);
    432 
    433 #if defined(BCM_HIGIG2_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
    434         if (soc_feature(u, soc_feature_higig2) || SOC_IS_TOMAHAWK3(u)) {
    435             parse_table_add(&pt, "Word3",   PQ_DFL|PQ_INT,0,
    436                             &xd->w3, NULL);
    437             parse_table_add(&pt, "Word4",   PQ_DFL|PQ_INT,0,
    438                             &xd->w4, NULL);
    439         }
    440 #endif /* BCM_HIGIG2_SUPPORT */
    441     }
    442 
    443     parse_table_add(&pt, "TXUnit", PQ_DFL|PQ_INT, 0, &xd->xd_tx_unit, NULL);
    444     parse_table_add(&pt, "PortBitMap",      PQ_DFL|PQ_PBMP|PQ_BCM, 0,
    445                     &xd->pkt_info.tx_pbmp,      NULL);
    446 
    447 #ifdef BCM_INSTRUMENTATION_SUPPORT
    448     parse_table_add(&pt, "VisibilityOptions",    PQ_DFL|PQ_INT,  0,
    449                     &xd->xd_vis_options,         NULL);
    450     parse_table_add(&pt, "VisibilitySourcePort",    PQ_DFL|PQ_PORT,  0,
    451                     &xd->xd_vis_sport,           NULL);
    452 #endif /* BCM_INSTRUMENTATION_SUPPORT */
    453 
    454 #ifdef BCM_CPU_TX_PROC_SUPPORT
    455     if (soc_feature(u, soc_feature_cpu_tx_proc)) {
    456         parse_table_add(&pt, "TxProcMhDestinationType",              PQ_DFL|PQ_INT,    0,
    457                         &xd->xd_ph_destination_type,                 NULL);
    458         parse_table_add(&pt, "TxProcMhSourcePort",                   PQ_DFL|PQ_PORT,   0,
    459                         &xd->xd_ph_source_port,                      NULL);
    460         parse_table_add(&pt, "TxProcMhDestinationPort",              PQ_DFL|PQ_PORT,   0,
    461                         &xd->xd_ph_destination_port,                 NULL);
    462         parse_table_add(&pt, "TxProcMhDestination",                  PQ_DFL|PQ_INT,    0,
    463                         &xd->xd_ph_destination,                      NULL);
    464         parse_table_add(&pt, "TxProcMhMcastLbIndexValid",            PQ_DFL|PQ_BOOL,   0,
    465                         &xd->xd_ph_mcast_lb_index_valid,             NULL);
    466         parse_table_add(&pt, "TxProcMhMcastLbIndex",                 PQ_DFL|PQ_INT,    0,
    467                         &xd->xd_ph_mcast_lb_index,                   NULL);
    468         parse_table_add(&pt, "TxProcMhQosFieldsValid",               PQ_DFL|PQ_BOOL,   0,
    469                         &xd->xd_ph_qos_fields_valid,                 NULL);
    470         parse_table_add(&pt, "TxProcMhDropPrecedence",               PQ_DFL|PQ_MULTI,  0,
    471                         &xd->xd_ph_dp,                               drop_precedence);
    472         parse_table_add(&pt, "TxProcMhInternalPriority",             PQ_DFL|PQ_INT,    0,
    473                         &xd->xd_prio_int,                            NULL);
    474         parse_table_add(&pt, "TxProcMhInternalCongestion",           PQ_DFL|PQ_INT,    0,
    475                         &xd->xd_cong_int,                            NULL);
    476         parse_table_add(&pt, "TxProcMhRoutedPkt",                    PQ_DFL|PQ_BOOL,   0,
    477                         &xd->xd_ph_routed_pkt,                       NULL);
    478         parse_table_add(&pt, "TxProcMhEcmpGroup",                    PQ_DFL|PQ_INT,    0,
    479                         &xd->xd_ph_ecmp_group_index,                 NULL);
    480         parse_table_add(&pt, "TxProcMhEcmpMember",                   PQ_DFL|PQ_INT,    0,
    481                         &xd->xd_ph_ecmp_member_index,                NULL);
    482     }
    483 #endif /* BCM_CPU_TX_PROC_SUPPORT */
    484 
    485     if (!SOC_IS_XGS_FABRIC(u)) {
    486         parse_table_add(&pt, "UntagBitMap", PQ_DFL|PQ_PBMP|PQ_BCM, 0,
    487                         &xd->pkt_info.tx_upbmp,         NULL);
    488     }
    489 
    490     if (!SOC_IS_XGS3_SWITCH(u)) {
    491         if (SOC_IS_XGS_SWITCH(u)) {
    492             parse_table_add(&pt, "L3BitMap",    PQ_DFL|PQ_PBMP|PQ_BCM, 0,
    493                             &xd->pkt_info.tx_l3pbmp,    NULL);
    494         }
    495     }
    496 
    497     parse_table_add(&pt, "DATA",        PQ_DFL|PQ_STRING,0,
    498                     &xd->xd_data,           NULL);
    499     parse_table_add(&pt, "Filename",    PQ_DFL|PQ_STRING,0,
    500                     &xd->xd_file,           NULL);
    501     parse_table_add(&pt, "Length",      PQ_DFL|PQ_INT,  0,
    502                     &xd->xd_pkt_len,    NULL);
    503     parse_table_add(&pt, "VLantag",     PQ_DFL|PQ_HEX,  0,
    504                     &xd->xd_vlan,           NULL);
    505     parse_table_add(&pt, "VlanPrio",    PQ_DFL|PQ_INT,  0,
    506                     &xd->xd_prio,           NULL);
    507     parse_table_add(&pt, "PrioInt",     PQ_DFL|PQ_INT,  0,
    508                     &xd->xd_prio_int,       NULL);
    509     parse_table_add(&pt, "Pattern",     PQ_DFL|PQ_HEX,  0,
    510                     &xd->xd_pat,            NULL);
    511     parse_table_add(&pt, "PatternInc",  PQ_DFL|PQ_INT,  0,
    512                     &xd->xd_pat_inc,    NULL);
    513     parse_table_add(&pt, "PatternRandom", PQ_DFL|PQ_BOOL, 0,
    514                     &xd->xd_pat_random,    NULL);
    515     parse_table_add(&pt, "PerPortSrcMac",PQ_DFL|PQ_INT, 0,
    516                     &xd->xd_ppsm,    NULL);
    517     parse_table_add(&pt, "SourceMac",   PQ_DFL|PQ_MAC,  0,
    518                     &xd->xd_mac_src,    NULL);
    519     parse_table_add(&pt, "SourceMacInc",PQ_DFL|PQ_INT,  0,
    520                     &xd->xd_mac_src_inc,NULL);
    521     parse_table_add(&pt, "DestMac",     PQ_DFL|PQ_MAC,  0,
    522                     &xd->xd_mac_dst,    NULL);
    523     parse_table_add(&pt, "DestMacInc",  PQ_DFL|PQ_INT,  0,
    524                     &xd->xd_mac_dst_inc,NULL);
    525     parse_table_add(&pt, "LinkDownTX",        PQ_DFL|PQ_INT,  0,
    526                     &xd->xd_link_down_tx,       NULL);
    527 #if defined(BCM_XGS3_SWITCH_SUPPORT)
    528     if (SOC_IS_XGS3_SWITCH(u)) {
    529         parse_table_add(&pt, "PurGe", PQ_DFL|PQ_BOOL, 0,
    530                         &xd->xd_purge, NULL);
    531         parse_table_add(&pt, "McQType",       PQ_DFL|PQ_BOOL,   0,
    532                         &xd->xd_mc_qtype, NULL);
    533     }
    534 #endif /* BCM_XGS3_SWITCH_SUPPORT */
    535     parse_table_add(&pt, "COSqueue",        PQ_DFL|PQ_INT,  0,
    536                     &xd->xd_hg_cos, NULL);
    537     parse_table_add(&pt, "CRC",         PQ_DFL|PQ_MULTI,0,
    538                     &xd->xd_crc,            crc_list);
    539     parse_table_add(&pt, "RQEnum",       PQ_DFL|PQ_INT,  0,
    540                     &xd->xd_rqe_q_num, NULL);
    541 #if defined(BCM_TRIUMPH3_SUPPORT)
    542     parse_table_add(&pt, "RplType",        PQ_DFL|PQ_INT,  0,
    543                     &xd->xd_rpl_type, NULL);
    544     parse_table_add(&pt, "RplOffset",      PQ_DFL|PQ_INT,  0,
    545                     &xd->xd_rpl_offset, NULL);
    546     parse_table_add(&pt, "LmCtrIdx",       PQ_DFL|PQ_INT,  0,
    547                     &xd->xd_lm_ctr_index, NULL);
    548 #endif /* BCM_TRIUMPH3_SUPPORT */
    549 
    550     if (SOC_IS_XGS_FABRIC(u)) {
    551         SOC_PBMP_PORT_REMOVE(xd->pkt_info.tx_pbmp, CMIC_PORT(u));
    552     }
    553 
    554     /* Parse remaining arguments */
    555     if (0 > parse_arg_eq(a, &pt)) {
    556         cli_out("%s: Error: Invalid option or malformed expression: %s\n",
    557                 ARG_CMD(a), ARG_CUR(a));
    558         parse_arg_eq_done(&pt);
    559         return(CMD_FAIL);
    560     }
    561     {
    562         char *xfile = NULL, *xdata = NULL;
    563         if (xd->xd_file) {
    564             xfile = sal_strdup(xd->xd_file);
    565         }
    566         if (xd->xd_data) {
    567             xdata = sal_strdup(xd->xd_data);
    568         }
    569         parse_arg_eq_done(&pt);
    570         xd->xd_file = xfile;
    571         xd->xd_data = xdata;
    572     }
    573 
    574     if (SOC_IS_XGS12_FABRIC(u)) {
    575         tagged = TRUE;
    576         min_len = ((xd->hdr_mode == ENCAP_HIGIG) ? 60 : 64);
    577         if (xd->hdr_mode == ENCAP_HIGIG) {
    578             BCM_PKT_HGHDR_REQUIRE(&xd->pkt_info);
    579         }
    580     } else {
    581         tagged = (xd->xd_vlan != 0);
    582         min_len = (tagged ? 68 : 64);
    583     }
    584 
    585 #if defined(BCM_XGS3_SWITCH_SUPPORT)
    586     if (SOC_IS_XGS3_SWITCH(u)) {
    587         if (SOC_PBMP_IS_NULL(xd->pkt_info.tx_pbmp)) { 
    588             xd->pkt_info.flags |= (BCM_TX_ETHER); /* Mapped mode */
    589             if (xd->ether_pkt) {
    590                 xd->pkt_info.flags &= (~BCM_TX_HG_READY);
    591             }
    592         } else {
    593             xd->pkt_info.flags &= (~BCM_TX_ETHER); /* Raw mode */
    594         }
    595 
    596         if (xd->hdr_mode == ENCAP_RAW) {
    597             if (xd->w0 != 0) {
    598                 xd->pkt_info.flags |= (BCM_TX_HG_READY);
    599             } else {
    600                 xd->pkt_info.flags &= (~BCM_TX_HG_READY);
    601             }
    602         }
    603     }
    604 #endif /* BCM_XGS3_SWITCH_SUPPORT */
    605 
    606     if (!XD_FILE(xd) && !XD_STRING(xd) && !tagged) {
    607         cli_out("%s: Warning: Sending untagged packets from CPU "
    608                 "not recommended\n",
    609                 ARG_CMD(a));
    610     }
    611 
    612     if (!XD_FILE(xd) && !XD_STRING(xd) && xd->xd_pkt_len < min_len) {
    613         cli_out("%s: Warning: Length %d too small for %s packet (min %d)\n",
    614                 ARG_CMD(a),
    615                 xd->xd_pkt_len,
    616                 tagged ? "tagged" : "untagged",
    617                 min_len);
    618     }
    619 
    620     if (xd->xd_hg_cos > NUM_COS(xd->xd_unit)-1 && 
    621         xd->xd_hg_cos != 14 && xd->xd_hg_cos != 15 && 
    622         !SOC_IS_TR_VL(xd->xd_unit)) {
    623         cli_out("%s: Error: Invalid COS queue %d, must be < %d\n", ARG_CMD(a),
    624                 xd->xd_hg_cos, NUM_COS(xd->xd_unit));
    625         return(CMD_FAIL);
    626     }
    627 
    628     if (xd->xd_untag) {
    629         xd->xd_vlan = 0;
    630     }
    631 
    632     return CMD_OK;
    633 }
    634 
    635 /*
    636  * Function:    _tx_first_pbm(pbmp_t pbm)
    637  * Purpose:     Get the first port in a bitmap.
    638  * Parameters:  pbm -- the port bitmap
    639  *              rpbm -- (OUT) port bitmap with only one port set.
    640  */
    641 STATIC void
    642 _tx_first_pbm(int unit, bcm_pbmp_t pbm, bcm_pbmp_t *rpbm)
    643 {
    644     soc_port_t p, dport;
    645 
    646     COMPILER_REFERENCE(unit);
    647 
    648     BCM_PBMP_CLEAR(*rpbm);
    649     /* coverity[overrun-local] */
    650     DPORT_BCM_PBMP_ITER(unit, pbm, dport, p) {
    651         LOG_INFO(BSL_LS_APPL_TX,
    652                  (BSL_META_U(unit,
    653                              "First to port %d\n"), p));
    654         /* coverity[overrun-local] */
    655         BCM_PBMP_PORT_ADD(*rpbm, p);
    656         return;
    657     }
    658 
    659     LOG_INFO(BSL_LS_APPL_TX,
    660              (BSL_META_U(unit,
    661                          "Warning: first pbm null\n")));
    662 }
    663 
    664 /*
    665  * Function:    int _tx_next_port(pbmp_t *newpbm, pbmp_t allpbm)
    666  * Purpose:     Get the first port in a bitmap.
    667  * Parameters:  *newpbm -- the current port bitmap (one port)
    668  *                         set to next port
    669  *              allpbm  -- all ports being iterated over.
    670  * Returns:     0 if okay.  1 if reset to first port in allpbm
    671  */
    672 STATIC int
    673 _tx_next_port(int unit, bcm_pbmp_t *newpbm, bcm_pbmp_t allpbm)
    674 {
    675     soc_port_t p, dport;
    676     soc_port_t np, ndport;
    677     int found = FALSE;
    678     char pfmt[SOC_PBMP_FMT_LEN];
    679 
    680     /* coverity[overrun-local] */
    681     DPORT_BCM_PBMP_ITER(unit, *newpbm, ndport, np) {
    682         /* coverity[overrun-local] */
    683         DPORT_BCM_PBMP_ITER(unit, allpbm, dport, p) {
    684             if (found) {
    685                 LOG_INFO(BSL_LS_APPL_TX,
    686                          (BSL_META_U(unit,
    687                                      "Next to port %d\n"), p));
    688                 BCM_PBMP_CLEAR(*newpbm);
    689                 BCM_PBMP_PORT_ADD(*newpbm, p);
    690                 return 0;
    691             }
    692             if (np == p) found = TRUE;
    693         }
    694     }
    695 
    696     /* If we get here, must be resetting. */
    697     _tx_first_pbm(unit, allpbm, newpbm);
    698     LOG_INFO(BSL_LS_APPL_TX,
    699              (BSL_META_U(unit,
    700                          "Resetting to pbm %s\n"), SOC_PBMP_FMT(*newpbm, pfmt)));
    701     return 1;
    702 }
    703 
    704 #define TX_LOAD_MAX             4096
    705 
    706 #ifndef NO_FILEIO
    707 
    708 /* Discard the rest of the line */
    709 STATIC int
    710 _discard_line(FILE *fp)
    711 {
    712     int c;
    713     do {
    714         if ((c = sal_fgetc(fp)) == EOF) {
    715 	    return c;
    716 	}
    717     } while (c != '\n');
    718     return c;
    719 }
    720 
    721 STATIC int
    722 tx_load_byte(FILE *fp, uint8 *byte)
    723 {
    724     int         c, d;
    725 
    726     do {
    727         if ((c = sal_fgetc(fp)) == EOF) {
    728             return -1;
    729 	}
    730 	else if (c == '#') {
    731 	    if((c = _discard_line(fp)) == EOF) {
    732 	        return -1;
    733 	    }
    734 	}
    735     } while (!isxdigit(c));
    736 
    737     do {
    738         if ((d = sal_fgetc(fp)) == EOF) {
    739             return -1;
    740 	}
    741 	else if (d == '#') {
    742 	    if((d = _discard_line(fp)) == EOF) {
    743 	        return -1;
    744 	    }
    745 	}
    746     } while (!isxdigit(d));
    747 
    748     *byte = (xdigit2i(c) << 4) | xdigit2i(d);
    749 
    750     return 0;
    751 }
    752 
    753 STATIC uint8 *
    754 tx_load_packet(int unit, char *fname, int *length)
    755 {
    756     uint8               *p;
    757     FILE                *fp;
    758     int                 i;
    759 
    760     if ((p = soc_cm_salloc(unit, TX_LOAD_MAX, "tx_packet")) == NULL)
    761         return p;
    762 
    763     if ((fp = sal_fopen(fname, "r")) == NULL) {
    764         soc_cm_sfree(unit, p);
    765         return NULL;
    766     }
    767 
    768     for (i = 0; i < TX_LOAD_MAX; i++) {
    769         if (tx_load_byte(fp, &p[i]) < 0)
    770             break;
    771     }
    772 
    773     *length = i;
    774 
    775     sal_fclose(fp);
    776 
    777     return p;
    778 }
    779 #endif /* NO_FILEIO */
    780 
    781 /* If data was read from file, extract to XD structure */
    782 STATIC void
    783 check_pkt_fields(xd_t *xd)
    784 {
    785     enet_hdr_t        *ep;              /* Ethernet packet header */
    786     bcm_pkt_t      *pkt_info = &xd->pkt_info;
    787 
    788     ep = (enet_hdr_t *)BCM_PKT_IEEE(pkt_info);
    789 
    790     if (XD_FILE(xd) || XD_STRING(xd)) { /* Loaded from file or string */
    791         /* Also set parameters to file data so incrementing works */
    792 
    793         ENET_COPY_MACADDR(&ep->en_dhost, xd->xd_mac_dst);
    794         ENET_COPY_MACADDR(&ep->en_shost, xd->xd_mac_src);
    795 
    796         if (!ENET_TAGGED(ep)) {
    797             cli_out("Warning:  Untagged packet read from file for tx.\n");
    798             xd->xd_vlan = VLAN_ID_NONE;
    799         } else {
    800             xd->xd_vlan = VLAN_CTRL_ID(bcm_ntohs(ep->en_tag_ctrl));
    801             xd->xd_prio = VLAN_CTRL_PRIO(bcm_ntohs(ep->en_tag_ctrl));
    802         }
    803     } else {
    804         if (xd->xd_vlan) {                      /* Tagged format */
    805             ep->en_tag_ctrl = bcm_htons(VLAN_CTRL(xd->xd_prio, 0, xd->xd_vlan));
    806             ep->en_tag_len	= bcm_htons(xd->xd_pkt_len - ENET_TAGGED_HDR_LEN - ENET_CHECKSUM_LEN);
    807             ep->en_tag_tpid = bcm_htons(0x8100);
    808         } else {                                /* Untagged format */
    809             cli_out("Warning:  Sending untagged packet.\n");
    810 		ep->en_untagged_len = bcm_htons(xd->xd_pkt_len - ENET_UNTAGGED_HDR_LEN - ENET_CHECKSUM_LEN);
    811         }
    812         ENET_SET_MACADDR(ep->en_dhost, xd->xd_mac_dst);
    813         ENET_SET_MACADDR(ep->en_shost, xd->xd_mac_src);
    814     }
    815 }
    816 
    817 #ifdef  BCM_XGS_SUPPORT
    818 STATIC int
    819 _tx_hghdr_setup(bcm_pkt_t *pkt, int sop)
    820 {
    821     soc_higig_hdr_t *xgh = (soc_higig_hdr_t *)pkt->_higig;
    822     int unit = pkt->unit;
    823     uint32 vlan_val;
    824 
    825     sal_memset(xgh, 0, sizeof(pkt->_higig));
    826     soc_higig_field_set(unit, xgh, HG_start, sop);
    827     soc_higig_field_set(unit, xgh, HG_hgi, SOC_HIGIG_HGI);
    828     soc_higig_field_set(unit, xgh, HG_opcode, pkt->opcode);
    829     soc_higig_field_set(unit, xgh, HG_hdr_format,
    830                         SOC_HIGIG_HDR_DEFAULT);
    831 
    832     vlan_val = BCM_PKT_VLAN_CONTROL(pkt);
    833     soc_higig_field_set(unit, xgh, HG_vlan_tag, vlan_val);
    834     soc_higig_field_set(unit, xgh, HG_dst_mod, pkt->dest_mod);
    835     soc_higig_field_set(unit, xgh, HG_dst_port, pkt->dest_port);
    836     soc_higig_field_set(unit, xgh, HG_src_mod, pkt->src_mod);
    837     soc_higig_field_set(unit, xgh, HG_src_port, pkt->src_port);
    838     soc_higig_field_set(unit, xgh, HG_pfm, pkt->pfm);
    839     soc_higig_field_set(unit, xgh, HG_cos, pkt->prio_int);
    840 
    841     return BCM_E_NONE;
    842 }
    843 
    844 #if defined(BCM_HIGIG2_SUPPORT)
    845 
    846 STATIC int
    847 _tx_hg2hdr_setup(bcm_pkt_t *pkt, int sop, 
    848     uint32      xd_hg_mgid,             /* Higig2 Multicast Group ID */
    849     uint32      xd_hg_lbid,             /* Higig2 Load Balancing ID */
    850     uint32      xd_hg_dp                /* Higig2 Drop Precendece */
    851 )
    852 {
    853     soc_higig2_hdr_t *xgh = (soc_higig2_hdr_t *)pkt->_higig;
    854     int unit = pkt->unit, multicast = 0, mc_index_offset = 0, mc_index = 0;
    855     uint32 vlan_val;
    856 #if defined(BCM_BRADLEY_SUPPORT)
    857     int bcast_size, mcast_size, ipmc_size;
    858 #endif
    859 
    860     sal_memset(xgh, 0, sizeof(pkt->_higig));
    861     soc_higig2_field_set(unit, xgh, HG_start, sop);
    862     soc_higig2_field_set(unit, xgh, HG_hgi, SOC_HIGIG_HGI);
    863     soc_higig2_field_set(unit, xgh, HG_opcode, pkt->opcode);
    864     soc_higig2_field_set(unit, xgh, HG_hdr_format,
    865                         SOC_HIGIG_HDR_DEFAULT);
    866 
    867     vlan_val = BCM_PKT_VLAN_CONTROL(pkt);
    868     soc_higig2_field_set(unit, xgh, HG_vlan_tag, vlan_val);
    869     soc_higig2_field_set(unit, xgh, HG_dst_mod, pkt->dest_mod);
    870     soc_higig2_field_set(unit, xgh, HG_dst_port, pkt->dest_port);
    871     soc_higig2_field_set(unit, xgh, HG_src_mod, pkt->src_mod);
    872     soc_higig2_field_set(unit, xgh, HG_src_port, pkt->src_port);
    873     soc_higig2_field_set(unit, xgh, HG_pfm, pkt->pfm);
    874     soc_higig2_field_set(unit, xgh, HG_cos, pkt->prio_int);
    875 
    876     multicast = ((pkt->opcode == SOC_HIGIG_OP_CPU) ||
    877                  (pkt->opcode == SOC_HIGIG_OP_UC)) ? 0 : pkt->opcode;
    878     if (multicast) {
    879         soc_higig2_field_set(unit, xgh, HG_mcst, 1);
    880 
    881 
    882         mc_index_offset = 0;
    883 
    884 #if defined(BCM_BRADLEY_SUPPORT)
    885         /* Higig2 has different ranges for different multicast types */
    886         BCM_IF_ERROR_RETURN
    887             (soc_hbx_higig2_mcast_sizes_get(unit, &bcast_size, &mcast_size,
    888                                             &ipmc_size));
    889         switch (multicast) {
    890         case SOC_HIGIG_OP_IPMC:
    891             mc_index_offset += mcast_size;
    892             /* Fall thru */
    893         case SOC_HIGIG_OP_MC:
    894             mc_index_offset += bcast_size;
    895             /* Fall thru */
    896         case SOC_HIGIG_OP_BC:
    897             break;
    898         default:
    899             /* Unknown opcode */
    900             return BCM_E_PARAM;
    901         }
    902 #endif
    903         mc_index = _BCM_MULTICAST_ID_GET(xd_hg_mgid);
    904         soc_higig2_field_set(unit, xgh, HG_mgid,
    905                              mc_index + mc_index_offset);
    906  
    907     }
    908 
    909     soc_higig2_field_set(unit, xgh, HG_lbid, xd_hg_lbid);
    910     soc_higig2_field_set(unit, xgh, HG_dp,   xd_hg_dp);
    911 
    912     return BCM_E_NONE;
    913 }
    914 #endif /* BCM_HIGIG2_SUPPORT */
    915 
    916 STATIC void
    917 add_higig_hdr(xd_t *xd, bcm_pkt_t *pkt_info)
    918 {
    919     soc_bcm5632_hdr_t *b5632h;          /* BCM5632 header */
    920     uint32 temp_raw;
    921     uint8 *ptr;
    922     uint8 *ext_ptr;
    923 
    924     switch(xd->hdr_mode) {
    925     case ENCAP_HIGIG:       /* HiGig header */
    926         _tx_hghdr_setup(pkt_info, SOC_HIGIG_START);
    927         break;
    928 
    929 #ifdef BCM_HIGIG2_SUPPORT
    930     case ENCAP_HIGIG2:      /* HiGig2 header */
    931         if (xd->hdr_mode == ENCAP_HIGIG2 &&
    932             soc_feature(xd->xd_unit, soc_feature_higig2)) {
    933             _tx_hg2hdr_setup(pkt_info, SOC_HIGIG2_START,
    934                 xd->xd_hg_mgid,
    935                 xd->xd_hg_lbid,
    936                 xd->xd_hg_dp);
    937         } else {
    938             cli_out("Warning:  Higig2 not supported by device\n");
    939         }
    940         break;
    941 #endif /* BCM_HIGIG2_SUPPORT */
    942 
    943     case ENCAP_B5632:      /* 5632 header */
    944         b5632h = (soc_bcm5632_hdr_t*)BCM_PKT_HG_HDR(pkt_info);
    945 
    946         sal_memset(b5632h, 0, sizeof (soc_bcm5632_hdr_t));
    947         b5632h->overlay1.s_portid = xd->xd_s_portid;
    948         b5632h->overlay1.d_portid = xd->xd_d_portid;
    949         b5632h->overlay1.start = xd->xd_start;
    950         b5632h->overlay1.length_hi = xd->xd_length >> 8;
    951         b5632h->overlay1.length_lo = xd->xd_length & 0xff;
    952         break;
    953 
    954     case ENCAP_RAW:        /* Raw HIGIG */
    955         ptr = (uint8 *)BCM_PKT_HG_HDR(pkt_info);
    956         ext_ptr = (uint8 *)BCM_PKT_EXT_HG_HDR(pkt_info);
    957 
    958         /* Convert to network byte order */
    959         temp_raw = soc_htonl(xd->w0);
    960         sal_memcpy(ptr,   (void*)&temp_raw, sizeof(uint32));
    961         temp_raw = soc_htonl(xd->w1);
    962         sal_memcpy(ptr+4, (void*)&temp_raw, sizeof(uint32));
    963         temp_raw = soc_htonl(xd->w2);
    964         sal_memcpy(ptr+8, (void*)&temp_raw, sizeof(uint32));
    965 #ifdef BCM_HIGIG2_SUPPORT
    966         if (soc_feature(xd->xd_unit, soc_feature_higig2)) {
    967             temp_raw = soc_htonl(xd->w3);
    968             sal_memcpy(ptr+12, (void*)&temp_raw, sizeof(uint32));
    969             temp_raw = soc_htonl(xd->w4);
    970             sal_memcpy(ext_ptr, (void*)&temp_raw, sizeof(uint32));
    971         }
    972 #endif /* BCM_HIGIG2_SUPPORT */
    973         break;
    974 
    975     default:          /* Error */
    976         cli_out("Warning:  Unknown HG header format: %d\n", xd->hdr_mode);
    977         break;
    978     }
    979 }
    980 
    981 /* Set up the XGS information needed for the DCB */
    982 STATIC void
    983 add_xgs_info(xd_t *xd, bcm_pkt_t *pkt)
    984 {
    985     pkt->dest_mod = xd->xd_hg_dmod;
    986     pkt->dest_port = xd->xd_hg_dport;
    987     pkt->src_mod = xd->xd_hg_smod;
    988     pkt->src_port = xd->xd_hg_sport;
    989     pkt->flags &= ~(BCM_TX_SRC_MOD | BCM_TX_SRC_PORT);
    990     if (xd->xd_link_down_tx) {
    991         pkt->flags |= BCM_TX_LINKDOWN_TRANSMIT;
    992     } else {
    993         pkt->flags &= ~BCM_TX_LINKDOWN_TRANSMIT;
    994     }
    995     if (!xd->ether_pkt) {
    996         pkt->flags |= BCM_TX_SRC_PORT;
    997         pkt->flags |= BCM_TX_SRC_MOD;
    998     }
    999     pkt->opcode = xd->xd_hg_opcode;
   1000     pkt->cos = xd->xd_hg_cos;
   1001     pkt->rqe_q_num = xd->xd_rqe_q_num;
   1002     pkt->flags &= ~BCM_TX_PRIO_INT;
   1003     if (xd->xd_prio_int != XD_PRIO_INT_INVALID) {
   1004         pkt->prio_int = xd->xd_prio_int;
   1005         pkt->flags |= BCM_TX_PRIO_INT;
   1006     } else {
   1007         /* For now, internal priority matches COS (or v.v.) */
   1008         pkt->prio_int = xd->xd_hg_cos;
   1009     }
   1010     pkt->pfm = xd->xd_hg_pfm;
   1011 }
   1012 
   1013 /*
   1014  * Function:
   1015  *      setup_higig_tx
   1016  * Purpose:
   1017  *      Setup the hercules packet for tx
   1018  * Parameters:
   1019  *      xd         - transmit descriptor
   1020  *      pkt_data   - Raw data to transmit
   1021  * Returns:
   1022  *      BCM_E_XXX
   1023  * Notes:
   1024  */
   1025 
   1026 STATIC void
   1027 setup_higig_tx(xd_t *xd)
   1028 {
   1029     bcm_pkt_t      *pkt_info = &xd->pkt_info;
   1030     
   1031     pkt_info->unit = xd->xd_unit;
   1032     /* Use raw higig header from pkt_info structure */
   1033     if (BCM_PKT_TX_HG_READY(pkt_info)) {
   1034         add_xgs_info(xd, pkt_info);
   1035         add_higig_hdr(xd, pkt_info);
   1036     } else if (SOC_IS_XGS_SWITCH(xd->xd_unit)) { /* Set HG info members */
   1037         add_xgs_info(xd, pkt_info);
   1038         if (SOC_IS_XGS3_SWITCH(xd->xd_unit)) {
   1039             /* Ethernet mode TX. Remove TX properties */
   1040             pkt_info->flags &= (~(BCM_TX_PKT_PROP_ANY));
   1041 
   1042         }
   1043     } else {
   1044         /* Always get cos from higig info structure */
   1045         pkt_info->cos = xd->xd_hg_cos;
   1046     }
   1047 }
   1048 
   1049 #ifdef BCM_CPU_TX_PROC_SUPPORT
   1050 /*
   1051  * Function:
   1052  *      setup_cpu_tx_proc
   1053  * Purpose:
   1054  *      Setup packet for cpu tx proc
   1055  * Parameters:
   1056  *      xd         - transmit descriptor
   1057  * Returns:
   1058  *      BCM_E_XXX
   1059  * Notes:
   1060  */
   1061 STATIC void
   1062 setup_cpu_tx_proc(xd_t *xd)
   1063 {
   1064     bcm_pkt_t      *pkt_info = &xd->pkt_info;
   1065 
   1066     pkt_info->unit = xd->xd_unit;
   1067 
   1068     if (xd->xd_ph_destination_type <= SOC_TX_PROC_OP_VLAN_FLOOD) {
   1069         xd->pkt_info.flags2 |= BCM_PKT_F2_CPU_TX_PROC;
   1070         xd->pkt_info.flags &= (~BCM_TX_ETHER);
   1071         pkt_info->txprocmh_destination_type = xd->xd_ph_destination_type;
   1072         pkt_info->rx_port = xd->xd_ph_source_port;
   1073     }
   1074 
   1075     if (xd->xd_ph_qos_fields_valid) {
   1076         pkt_info->txprocmh_qos_fields_valid = xd->xd_ph_qos_fields_valid;
   1077         pkt_info->color = xd->xd_ph_dp;
   1078         pkt_info->flags &= ~BCM_TX_PRIO_INT;
   1079         if (xd->xd_prio_int != XD_PRIO_INT_INVALID) {
   1080             pkt_info->prio_int = xd->xd_prio_int;
   1081             pkt_info->flags |= BCM_TX_PRIO_INT;
   1082         }
   1083 
   1084         pkt_info->flags2 &= ~BCM_PKT_F2_CONG_INT;
   1085         if (xd->xd_cong_int != XD_CONG_INT_INVALID) {
   1086             pkt_info->txprocmh_congestion_int = xd->xd_cong_int;
   1087             pkt_info->flags2 |= BCM_PKT_F2_CONG_INT;
   1088         }
   1089     }
   1090 
   1091     if (xd->xd_ph_destination_type == SOC_TX_PROC_OP_DGPP) {
   1092         pkt_info->txprocmh_destination = xd->xd_ph_destination_port;
   1093     } else {
   1094         pkt_info->txprocmh_destination = xd->xd_ph_destination;
   1095     }
   1096 
   1097     if ((xd->xd_ph_destination_type == SOC_TX_PROC_OP_ECMP_MEMBER) ||
   1098             (xd->xd_ph_destination_type == SOC_TX_PROC_OP_ECMP)) {
   1099         pkt_info->txprocmh_ecmp_group_index = xd->xd_ph_ecmp_group_index;
   1100     }
   1101 
   1102     if (xd->xd_ph_destination_type == SOC_TX_PROC_OP_ECMP_MEMBER) {
   1103         pkt_info->txprocmh_ecmp_member_index = xd->xd_ph_ecmp_member_index;
   1104     }
   1105 
   1106     if (xd->xd_ph_routed_pkt) {
   1107         pkt_info->flags |= BCM_PKT_F_ROUTED;
   1108     }
   1109 
   1110     if (xd->xd_ph_mcast_lb_index_valid) {
   1111         pkt_info->txprocmh_mcast_lb_index_valid = xd->xd_ph_mcast_lb_index_valid;
   1112         pkt_info->txprocmh_mcast_lb_index       = xd->xd_ph_mcast_lb_index;
   1113     }
   1114 }
   1115 #endif /* BCM_CPU_TX_PROC_SUPPORT */
   1116 
   1117 #endif  /* BCM_XGS_SUPPORT */
   1118 
   1119 /* parsing string given by user as packet payload */
   1120 STATIC uint8 *
   1121 parse_data_packet_payload(int unit, char *packet_data, int *length)
   1122 {
   1123     uint8               *p;
   1124     char                 tmp, data_iter;
   1125     int                  data_len, i, j, pkt_len, data_base;
   1126 
   1127     /* If string data starts with 0x or 0X, skip it */
   1128     if ((packet_data[0] == '0')
   1129         && (packet_data[1] == 'x' || packet_data[1] == 'X')) {
   1130         data_base = 2;
   1131     } else {
   1132         data_base = 0;
   1133     }
   1134 
   1135     data_len = strlen(packet_data) - data_base;
   1136     pkt_len = (data_len + 1) / 2;
   1137     if (pkt_len < UNTAGGED_PACKET_LENGTH) {
   1138         pkt_len = UNTAGGED_PACKET_LENGTH;
   1139     }
   1140 
   1141     p = soc_cm_salloc(unit, pkt_len, "tx_string_packet");
   1142     if (p == NULL) {
   1143         return p;
   1144     }
   1145     sal_memset(p, 0, pkt_len);
   1146     /* Convert char to value */
   1147     i = j = 0;
   1148     while (j < data_len) {
   1149         data_iter = packet_data[data_base + j];
   1150         if (('0' <= data_iter) && (data_iter <= '9')) {
   1151             tmp = data_iter - '0';
   1152         } else if (('a' <= data_iter) && (data_iter <= 'f')) {
   1153             tmp = data_iter - 'a' + 10;
   1154         } else if (('A' <= data_iter) && (data_iter <= 'F')) {
   1155             tmp = data_iter - 'A' + 10;
   1156         } else if (data_iter == ' ') {
   1157             ++j;
   1158             continue;
   1159         } else {
   1160             soc_cm_sfree(unit, p);
   1161             return NULL;
   1162         }
   1163 
   1164         /* String input is in 4b unit. Below we're filling in 8b:
   1165            offset is /2, and we shift by 4b if the input char is odd */
   1166         p[i / 2] |= tmp << (((i + 1) % 2) * 4);
   1167         ++i;
   1168         ++j;
   1169     }
   1170 
   1171     *length = i / 2 + 4; /* pad for crc */
   1172     return p;
   1173 }
   1174 
   1175 STATIC cmd_result_t
   1176 do_tx(xd_t *xd)
   1177 /*
   1178  * Function:    do_tx
   1179  * Purpose:     Perform actual work for a TX operation.
   1180  * Parameters:  xd - pointer to XD structure already filled in.
   1181  * Returns:     CMD_xxx
   1182  */
   1183 {
   1184     uint8             *pkt_data;        /* Packet */
   1185     uint8             *payload;         /* data - packet payload */
   1186     enet_hdr_t        *ep;              /* Ethernet packet header */
   1187     bcm_pkt_t         *pkt_info = &xd->pkt_info;
   1188     int                rv = BCM_E_INTERNAL;
   1189     int                payload_len;
   1190 
   1191     pkt_data = NULL;
   1192 
   1193     /* Allocate the packet; use tx_load if reading from file */
   1194     if (XD_FILE(xd)) {
   1195 #ifdef NO_FILEIO
   1196         cli_out("no filesystem\n");
   1197         return CMD_FAIL;
   1198 #else
   1199         if ((pkt_data = tx_load_packet(xd->xd_unit,
   1200                                 xd->xd_file, &xd->xd_pkt_len)) == NULL) {
   1201             cli_out("Unable to load packet from file %s\n", xd->xd_file);
   1202             return CMD_FAIL;
   1203         }
   1204         cli_out("Packet from file: %s, length=%d\n", xd->xd_file, xd->xd_pkt_len);
   1205 #endif
   1206     } else if (XD_STRING(xd)) {
   1207         /* use parse_data_packet_payload if reading from user string input */
   1208         pkt_data = parse_data_packet_payload(xd->xd_unit, 
   1209                                              xd->xd_data, &xd->xd_pkt_len);
   1210         if (pkt_data == NULL) {
   1211             cli_out("Unable to allocate memory or Invalid inputs %s\n", xd->xd_data);
   1212             return CMD_FAIL;
   1213         }
   1214         cli_out("Packet from data=<>, length=%d\n", xd->xd_pkt_len);
   1215     }
   1216 
   1217     /* Make sure packet allocation size is right size */
   1218     if (pkt_info->pkt_data[0].len != xd->xd_pkt_len) {
   1219         soc_cm_sfree(xd->xd_unit, pkt_info->pkt_data[0].data);
   1220         if ((pkt_info->pkt_data[0].data = (uint8 *)
   1221              soc_cm_salloc(xd->xd_unit, xd->xd_pkt_len, "TX")) == NULL) {
   1222             if (pkt_data) { /* free packet buffer */
   1223                 soc_cm_sfree(xd->xd_unit, pkt_data);
   1224             }
   1225             cli_out("Unable to allocate packet memory\n");
   1226             return(CMD_FAIL);
   1227         }
   1228         pkt_info->pkt_data[0].len = xd->xd_pkt_len;
   1229     }
   1230 
   1231     sal_memset(pkt_info->pkt_data[0].data, 0, pkt_info->pkt_data[0].len);
   1232     if (pkt_data) { /* Data was read from file.  Copy into pkt_info */
   1233         sal_memcpy(pkt_info->pkt_data[0].data, pkt_data, xd->xd_pkt_len);
   1234         soc_cm_sfree(xd->xd_unit, pkt_data);
   1235     }
   1236 
   1237     /* Setup the packet */
   1238     pkt_info->flags &= ~BCM_TX_CRC_FLD;
   1239     pkt_info->flags |= (xd->xd_crc==1 ? BCM_TX_CRC_REGEN : 0) |
   1240         (xd->xd_crc==2 ? BCM_TX_CRC_APPEND: 0);
   1241 
   1242     pkt_info->flags &= ~BCM_TX_NO_PAD;
   1243     if (xd->xd_pkt_len < (xd->xd_vlan != 0 ? 68 : 64)) {
   1244         pkt_info->flags |= BCM_TX_NO_PAD;
   1245     }
   1246 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   1247     pkt_info->flags &= (~(BCM_TX_PURGE));
   1248     if (xd->xd_purge) {
   1249         pkt_info->flags |= BCM_TX_PURGE;
   1250     }
   1251 
   1252     pkt_info->flags2 &= ~BCM_PKT_F2_MC_QUEUE;
   1253     if (xd->xd_mc_qtype) {
   1254         pkt_info->flags2 |= BCM_PKT_F2_MC_QUEUE;
   1255     }
   1256 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   1257 
   1258     check_pkt_fields(xd);
   1259 
   1260 #ifdef  BCM_XGS_SUPPORT
   1261     /* Setup special headers and DMA data */
   1262     setup_higig_tx(xd);
   1263 #endif  /* BCM_XGS_SUPPORT */
   1264 
   1265 #ifdef BCM_CPU_TX_PROC_SUPPORT
   1266     if (soc_feature(xd->xd_unit, soc_feature_cpu_tx_proc)) {
   1267         setup_cpu_tx_proc(xd);
   1268     }
   1269 #endif  /* BCM_CPU_TX_PROC_SUPPORT */
   1270 
   1271     ep = (enet_hdr_t *)(pkt_info->pkt_data[0].data);
   1272 
   1273     payload = &pkt_info->pkt_data[0].data[sizeof(enet_hdr_t)];
   1274     payload_len = pkt_info->pkt_data[0].len - sizeof(enet_hdr_t) -
   1275         sizeof(uint32) /* CRC */;
   1276 
   1277     if (xd->xd_ppsm) { /* save base info. setup first port. */
   1278         LOG_INFO(BSL_LS_APPL_TX,
   1279                  (BSL_META_U(xd->xd_unit,
   1280                              "Per port source is active\n")));
   1281         xd->xd_ppsm_pbm = pkt_info->tx_pbmp;
   1282         _tx_first_pbm(xd->xd_unit, pkt_info->tx_pbmp, &pkt_info->tx_pbmp);
   1283         ENET_COPY_MACADDR(xd->xd_mac_src, xd->xd_mac_src_base);
   1284     }
   1285 
   1286 #if defined(BCM_TRIUMPH3_SUPPORT)
   1287     if(xd->xd_rpl_type) {
   1288         pkt_info->flags2 |= BCM_PKT_F2_REPLACEMENT_TYPE;
   1289         pkt_info->flags2 |= BCM_PKT_F2_REPLACEMENT_OFFSET;
   1290         pkt_info->oam_replacement_type = xd->xd_rpl_type;
   1291         pkt_info->oam_replacement_offset = xd->xd_rpl_offset;
   1292         if(xd->xd_lm_ctr_index) {
   1293             pkt_info->flags2 |= BCM_PKT_F2_LM_COUNTER_INDEX;
   1294             pkt_info->oam_lm_counter_index = xd->xd_lm_ctr_index;
   1295         }
   1296     }
   1297 #endif
   1298     /* XMIT all the required packets */
   1299     for (xd->xd_cur_cnt = 0;
   1300          xd->xd_cur_cnt < xd->xd_tot_cnt;
   1301          xd->xd_cur_cnt++) {
   1302 
   1303         if (xd->xd_state != XD_RUNNING) {
   1304             break;                      /* Abort */
   1305         }
   1306 
   1307         /*
   1308          * Generate pattern on first time through, or every time if
   1309          * pattern is incrementing.
   1310          */
   1311 
   1312         if (xd->xd_mac_dst_inc != 0) {
   1313             ENET_SET_MACADDR(ep->en_dhost, xd->xd_mac_dst);
   1314         }
   1315         if (xd->xd_mac_src_inc != 0) {
   1316             ENET_SET_MACADDR(ep->en_shost, xd->xd_mac_src);
   1317         }
   1318 
   1319         /* Store pattern */
   1320         if (!XD_FILE(xd) && !XD_STRING(xd) && xd->xd_pat_random) {
   1321             packet_random_store(payload, payload_len);
   1322         } else if (!XD_FILE(xd) && !XD_STRING(xd) &&
   1323                     (xd->xd_cur_cnt == 0 || xd->xd_pat_inc != 0)) {
   1324             xd->xd_pat =
   1325                 packet_store(payload, payload_len,
   1326                              xd->xd_pat, xd->xd_pat_inc);
   1327         }
   1328 
   1329 #ifdef BCM_INSTRUMENTATION_SUPPORT
   1330         if (xd->xd_vis_sport) {
   1331             rv = appl_visibility_trace(xd->xd_unit,
   1332                                        xd->xd_vis_options,
   1333                                        xd->xd_vis_sport,
   1334                                        pkt_info);
   1335         } else
   1336 #endif /* BCM_INSTRUMENTATION_SUPPORT */
   1337         {
   1338             rv = bcm_tx(xd->xd_tx_unit, pkt_info, NULL);
   1339         }
   1340         if (rv != BCM_E_NONE) {
   1341             cli_out("bcm_tx failed2: TX Unit %d: %s\n",
   1342                     xd->xd_tx_unit, bcm_errmsg(rv));
   1343             break;
   1344         }
   1345 
   1346         increment_macaddr(xd->xd_mac_dst, xd->xd_mac_dst_inc);
   1347         increment_macaddr(xd->xd_mac_src, xd->xd_mac_src_inc);
   1348 
   1349         if (xd->xd_ppsm) { /* per port source mac */
   1350             /* change xd_pbm to next port. reset src mac if at base port */
   1351             if (_tx_next_port(xd->xd_unit, &pkt_info->tx_pbmp,
   1352                               xd->xd_ppsm_pbm)) {
   1353                 LOG_INFO(BSL_LS_APPL_TX,
   1354                          (BSL_META_U(xd->xd_tx_unit,
   1355                                      "resetting mac\n")));
   1356                 ENET_COPY_MACADDR(xd->xd_mac_src_base, xd->xd_mac_src);
   1357             }
   1358         }
   1359     }
   1360 
   1361     if (xd->xd_ppsm) { /* Replace original params */
   1362         ENET_COPY_MACADDR(xd->xd_mac_src_base, xd->xd_mac_src);
   1363         pkt_info->tx_pbmp = xd->xd_ppsm_pbm;
   1364     }
   1365 
   1366     return(rv == BCM_E_NONE ? CMD_OK : CMD_FAIL);
   1367 }
   1368 
   1369 STATIC void
   1370 do_tx_start(void *xdv)
   1371 /*
   1372  * Function:    do_tx_start
   1373  * Purpose:     Wrapper function for a tx_start thread.
   1374  * Parameters:  xdv - pointer to xd structure for the unit under test.
   1375  * Returns:     Nothing, does not return.
   1376  */
   1377 {
   1378     cmd_result_t rv;
   1379     xd_t        *xd = (xd_t *)xdv;
   1380 
   1381     rv = do_tx(xd);
   1382 
   1383     cli_out("TX Completed %s: TX Requested(%d) Tx Sent(%d)\n",
   1384             rv == CMD_OK ?"successfully" : "with error",
   1385             xd->xd_tot_cnt, xd->xd_cur_cnt);
   1386     xd->xd_state = XD_IDLE;
   1387     sal_thread_exit(rv == CMD_OK ? 0 : 1);
   1388 }
   1389 
   1390 char cmd_rx_usage[] =
   1391     "Parameters: <count>\n\t"
   1392     "Wait for and received <count> packets from the CMIC. This command\n\t"
   1393     "is mostly obsolete, and PacketWatcher should be used.\n";
   1394 
   1395 cmd_result_t
   1396 cmd_rx(int u, args_t *a)
   1397 /*
   1398  * Function:    rx
   1399  * Purpose:     Perform simple RX
   1400  * Parameters:  u - unit number
   1401  *              a - arguments (expect "count");
   1402  * Returns:     CMD_XX
   1403  */
   1404 {
   1405     cmd_result_t rv = CMD_OK;
   1406     dv_t        *dv;
   1407     void        *p;                     /* Packet */
   1408     int         cnt, i;
   1409     pbmp_t      empty_pbm;
   1410 
   1411     if ((1 != ARG_CNT(a)) || !(isint(ARG_CUR(a)))) {
   1412         return(CMD_USAGE);
   1413     } else if (!sh_check_attached(ARG_CMD(a), u)) {
   1414         return(CMD_FAIL);
   1415     } else if (pw_running(u)) {
   1416         cli_out("%s: Error: Packetwatcher running\n", ARG_CMD(a));
   1417         return(CMD_FAIL);
   1418     }
   1419 
   1420     cnt = parse_integer(ARG_GET(a));
   1421 
   1422     if (!(dv = soc_dma_dv_alloc(u, DV_RX, 1))) {
   1423         cli_out("%s: failed to allocate DV\n", ARG_CMD(a));
   1424         return(CMD_FAIL);
   1425     }
   1426     if (!(p = soc_cm_salloc(u, 10240, "RX"))) {
   1427         cli_out("%s: failed to allocate packet memory\n", ARG_CMD(a));
   1428         soc_dma_dv_free(u, dv);
   1429         return(CMD_FAIL);
   1430     }
   1431 
   1432     SOC_PBMP_CLEAR(empty_pbm);
   1433     for (i = 0; i < cnt; i++) {
   1434         int     result;
   1435 
   1436         soc_dma_dv_reset(DV_RX, dv);
   1437         soc_dma_desc_add(dv, (sal_vaddr_t)p, 10240,
   1438                          empty_pbm, empty_pbm, empty_pbm, 0, NULL);
   1439         soc_dma_desc_end_packet(dv);
   1440 
   1441         if (0 > (result = soc_dma_wait(u, dv))) {
   1442             cli_out("%s: Dma Failed: %s\n", ARG_CMD(a), soc_errmsg(result));
   1443             rv = CMD_FAIL;
   1444             break;
   1445         }
   1446     }
   1447 
   1448     soc_dma_dv_free(u, dv);
   1449     soc_cm_sfree(u, p);
   1450     return(rv);
   1451 }
   1452 
   1453 cmd_result_t
   1454 cmd_esw_tx_count(int u, args_t *a)
   1455 /*
   1456  * Function:    tx_count
   1457  * Purpose:     Print out status of any currently running TX command.
   1458  * Parameters:  u - unit number.
   1459  *              a - arguments, none expected.
   1460  * Returns:     CMD_OK
   1461  */
   1462 {
   1463     xd_t        *xd;
   1464 
   1465     if (ARG_CNT(a)) {
   1466         return(CMD_USAGE);
   1467     }
   1468 
   1469     _XD_INIT(u, xd);
   1470     cli_out("TX (%sRunning) Transmit Req(%d) Sent(%d)\n",
   1471             xd->xd_state == XD_RUNNING ? "" : "Not-",
   1472             xd->xd_tot_cnt, xd->xd_cur_cnt);
   1473     return(CMD_OK);
   1474 }
   1475 
   1476 cmd_result_t
   1477 cmd_esw_tx_start(int u, args_t *a)
   1478 /*
   1479  * Function:    tx_start
   1480  * Purpose:     Start off a background TX thread.
   1481  * Parameters:  u - unit number
   1482  *              a - arguments.
   1483  * Returns:     CMD_XXX
   1484  */
   1485 {
   1486     cmd_result_t rv;
   1487     xd_t        *xd;
   1488 
   1489     if (!sh_check_attached(ARG_CMD(a), u)) {
   1490         return(CMD_FAIL);
   1491     }
   1492 
   1493     _XD_INIT(u, xd);
   1494     if (xd->xd_state == XD_RUNNING) {
   1495         cli_out("%s: Error: tx command running\n", ARG_CMD(a));
   1496         return(CMD_FAIL);
   1497     }
   1498 
   1499 #ifdef BROADCOM_DEBUG
   1500     if (ARG_CUR(a) && !sal_strcasecmp(_ARG_CUR(a), "show")) {
   1501         bcm_tx_show(u);
   1502         return CMD_OK;
   1503     }
   1504 #endif /* BROADCOM_DEBUG */
   1505 
   1506     if (CMD_OK != (rv = tx_parse(u, a, xd))) {
   1507         return(rv);
   1508     }
   1509 
   1510     /* BLOCK_CNTL_C */
   1511     xd->xd_state = XD_RUNNING;          /* Say GO */
   1512 
   1513     if (SAL_THREAD_ERROR == sal_thread_create("TX", SAL_THREAD_STKSZ, 100,
   1514                                               do_tx_start, (void *)xd)) {
   1515         cli_out("%s: Error: Failed to create background thread\n",ARG_CMD(a));
   1516         xd->xd_state = XD_IDLE;
   1517         rv = CMD_FAIL;
   1518     }
   1519     /* UN-BLOCK_CNTL_C */
   1520     return(rv);
   1521 }
   1522 
   1523 cmd_result_t
   1524 cmd_esw_tx_stop(int u, args_t *a)
   1525 /*
   1526  * Function:    tx_stop
   1527  * Purpose:     Stop a currently running TX command
   1528  * Parameters:  u - unit number.
   1529  *              a - arguments (none expected).
   1530  * Returns:     CMD_OK/CMD_USAGE/CMD_FAIL
   1531  */
   1532 {
   1533     xd_t        *xd;
   1534 
   1535     if (ARG_CNT(a)) {
   1536         return(CMD_USAGE);
   1537     } else if (!sh_check_attached(ARG_CMD(a), u)) {
   1538         return(CMD_FAIL);
   1539     }
   1540     _XD_INIT(u, xd);
   1541     if (XD_RUNNING != xd->xd_state) {
   1542         cli_out("%s: TX not currently running\n", ARG_CMD(a));
   1543         return(CMD_FAIL);
   1544     } else {
   1545         xd->xd_state = XD_STOP;
   1546         cli_out("%s: TX termination requested\n", ARG_CMD(a));
   1547         return(CMD_OK);
   1548     }
   1549 }
   1550 
   1551 cmd_result_t
   1552 cmd_esw_tx(int u, args_t *a)
   1553 /*
   1554  * Function:
   1555  * Purpose:
   1556  * Parameters:
   1557  * Returns:
   1558  */
   1559 {
   1560     xd_t *xd;
   1561     volatile cmd_result_t rv;
   1562     jmp_buf ctrl_c;
   1563 
   1564     if (!sh_check_attached(ARG_CMD(a), u)) {
   1565         return(CMD_FAIL);
   1566     }
   1567     _XD_INIT(u, xd);
   1568     if (xd->xd_state == XD_RUNNING) {
   1569         cli_out("%s: Error: already active\n", ARG_CMD(a));
   1570         return(CMD_FAIL);
   1571     }
   1572 
   1573     if (CMD_OK != (rv = tx_parse(u, a, xd))) {
   1574         return(rv);
   1575     }
   1576 
   1577 #ifndef NO_CTRL_C
   1578     if (!setjmp(ctrl_c)) {
   1579 #endif
   1580         sh_push_ctrl_c(&ctrl_c);
   1581         xd->xd_state = XD_RUNNING;      /* Say GO */
   1582         rv = do_tx(xd);
   1583 #ifndef NO_CTRL_C
   1584     } else {
   1585         rv = CMD_INTR;
   1586     }
   1587 #endif
   1588 
   1589     sh_pop_ctrl_c();
   1590     xd->xd_state = XD_IDLE;
   1591 
   1592     return(rv);
   1593 }
   1594 
   1595 /****************************************************************
   1596  *
   1597  * RX commands
   1598  */
   1599 
   1600 
   1601 cmd_result_t
   1602 cmd_esw_rx_init(int unit, args_t *args)
   1603 {
   1604     char *ch;
   1605     int override_unit;
   1606     int rv;
   1607 
   1608     if ((ch = ARG_GET(args)) == NULL) {
   1609         cli_out("RXINIT requires unit specification\n");
   1610         return CMD_USAGE;
   1611     }
   1612 
   1613     override_unit = strtoul(ch, NULL, 0);
   1614     rv = bcm_rx_init(override_unit);
   1615 
   1616     if (rv < 0) {
   1617         cli_out("ERROR:  bcm_rx_init(%d) returns %d: %s\n",
   1618                 override_unit, rv, bcm_errmsg(rv));
   1619         return CMD_FAIL;
   1620     }
   1621 
   1622     return CMD_OK;
   1623 }
   1624 
   1625 
   1626 char cmd_hdr_mode_usage[] =
   1627     "Parameters: [mode]\n"
   1628     "  With no mode, shows packet header mode of current unit.\n"
   1629     "  Although the header mode may be set for any device, \n"
   1630     "  it only has an effect for BCM5670 and related devices\n"
   1631     "  Supported modes are:\n"
   1632     "      Ieee   --  no encapusulation\n"
   1633     "      Higig  --  Use parsed HiGig header information\n"
   1634 #ifdef BCM_HIGIG2_SUPPORT
   1635     "      Higig2 --  Use parsed HiGig2 header information\n"
   1636 #endif /* BCM_HIGIG2_SUPPORT */
   1637     "      B5632  --  Use parsed BCM5632 header information\n"
   1638     "      Raw    --  Use 3 words of raw data for the header\n";
   1639 
   1640 cmd_result_t
   1641 cmd_hdr_mode(int unit, args_t *args)
   1642 /*
   1643  * Function:
   1644  * Purpose:
   1645  * Parameters:
   1646  * Returns:
   1647  */
   1648 {
   1649     xd_t *xd;
   1650     char *arg;
   1651     int i = -1;
   1652 
   1653     if (!sh_check_attached(ARG_CMD(args), unit)) {
   1654         return(CMD_FAIL);
   1655     }
   1656 
   1657     _XD_INIT(unit, xd);
   1658 
   1659     if ((arg = ARG_GET(args)) != NULL) {
   1660         for (i = 0; i < ENCAP_COUNT; i++) {
   1661             if (!sal_strcasecmp(arg, hdr_modes[i])) {
   1662                 xd->hdr_mode = i;
   1663                 break;
   1664             }
   1665         }
   1666     }
   1667 
   1668     if (xd->hdr_mode < 0 || xd->hdr_mode >= ENCAP_COUNT) {
   1669         cli_out("Current header mode for unit %d is invalid (%d).\n",
   1670                 unit, xd->hdr_mode);
   1671     } else {
   1672         cli_out("Current header mode for unit %d is%s %s (%d).\n",
   1673                 unit, (i != -1) ? " now" : "",
   1674                 hdr_modes[xd->hdr_mode], xd->hdr_mode);
   1675     }
   1676 
   1677     return (i < ENCAP_COUNT) ? CMD_OK : CMD_USAGE;
   1678 }
   1679 
   1680 /*
   1681  * Very simple test command for the SOC DMA ROM interface
   1682  */
   1683 char cmd_drt_usage[] =
   1684     "Parameters: [init|detach|rx|tx]\n"
   1685     "  init     - Calls soc_dma_rom_init() \n"
   1686     "  detach   - Calls soc_dma_rom_detach() \n" 
   1687     "  rx       - Calls soc_dma_rom_rx_poll() \n"
   1688     "             Dumps packet if available \n"
   1689     "  tx       - Simple packet transmit using soc_dma_rom_tx_start() \n"; 
   1690 
   1691 
   1692 cmd_result_t
   1693 cmd_drt(int unit, args_t *args)
   1694 {
   1695     char* arg; 
   1696     int rv; 
   1697 
   1698     if((arg = ARG_GET(args)) == NULL) {
   1699         return CMD_USAGE; 
   1700     }
   1701 
   1702     if(!sal_strcmp(arg, "init")) {
   1703         if((rv = soc_dma_rom_init(unit, 1600, 1, 1)) < 0) {
   1704             cli_out("soc_dma_rom_init() returned %d: %s\n",
   1705                     rv, soc_errmsg(rv)); 
   1706             return CMD_FAIL; 
   1707         }
   1708     }
   1709     else if(!sal_strcmp(arg, "detach")) {
   1710         if((rv = soc_dma_rom_detach(unit)) < 0) {
   1711             cli_out("soc_dma_rom_detach() returnd %d: %s\n",
   1712                     rv, soc_errmsg(rv)); 
   1713             return CMD_FAIL;
   1714         }
   1715     }
   1716     else if(!sal_strcmp(arg, "rx")) {
   1717         dcb_t* dcb; 
   1718         
   1719         if((rv=soc_dma_rom_rx_poll(unit, &dcb)) < 0) {
   1720             cli_out("soc_dma_rom_rx_poll() returned %d: %s\n",
   1721                     rv, soc_errmsg(rv)); 
   1722             return CMD_FAIL; 
   1723         }
   1724         
   1725         if(dcb) {
   1726             unsigned char* pkt; 
   1727             int len; 
   1728 
   1729             pkt = (unsigned char *)SOC_DCB_ADDR_GET(unit, dcb); 
   1730             len = SOC_DCB_XFERCOUNT_GET(unit, dcb); 
   1731             
   1732             soc_dma_dump_pkt(unit, "rx: ", pkt, len, TRUE); 
   1733 
   1734             soc_dma_rom_dcb_free(unit, dcb); 
   1735         }
   1736         else {
   1737             cli_out("no packet\n");          
   1738         }       
   1739     }
   1740     else if(!sal_strcmp(arg, "tx")) {
   1741         unsigned char _pkt[100] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
   1742                                     0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 
   1743                                     0x81, 0x00, 0x00, 0x01, 0x00, 0x00, 
   1744         }; 
   1745         dcb_t* dcb; 
   1746         unsigned char* p; 
   1747         int polls = 0; 
   1748         int done; 
   1749         
   1750         dcb = soc_dma_rom_dcb_alloc(unit, sizeof(_pkt)); 
   1751         
   1752         p = (unsigned char*)SOC_DCB_ADDR_GET(unit, dcb); 
   1753         sal_memcpy(p, _pkt, sizeof(_pkt)); 
   1754         
   1755         SOC_DCB_TX_L2PBM_SET(unit, dcb, PBMP_ALL(unit)); 
   1756         SOC_DCB_TX_UTPBM_SET(unit, dcb, PBMP_E_ALL(unit)); 
   1757 
   1758 #ifdef  BCM_XGS_SUPPORT
   1759         if (SOC_IS_XGS_SWITCH(unit)) {
   1760             SOC_DCB_TX_DESTPORT_SET(unit, dcb, 0);
   1761             SOC_DCB_TX_DESTMOD_SET(unit, dcb, 1); 
   1762             SOC_DCB_TX_OPCODE_SET(unit, dcb, SOC_HIGIG_OP_UC); 
   1763         }
   1764 #endif
   1765 
   1766         if ((rv = soc_dma_rom_tx_start(unit, dcb)) < 0) {
   1767             cli_out("soc_dma_rom_tx_start() returned %d: %s\n",
   1768                     rv, soc_errmsg(rv));         
   1769             soc_dma_rom_dcb_free(unit, dcb); 
   1770             return CMD_FAIL; 
   1771         }
   1772         
   1773         do {
   1774             soc_dma_rom_tx_poll(unit, &done);   
   1775             polls++;
   1776         } while(!done); 
   1777 
   1778         cli_out("tx done in %d polls\n", polls); 
   1779         soc_dma_rom_dcb_free(unit, dcb); 
   1780 
   1781     }
   1782     else {
   1783         return CMD_USAGE; 
   1784     }
   1785 
   1786     return CMD_OK; 
   1787 }
   1788 
   1789