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

dma.c (20865B)


      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: 	dma.c
      8  * Purpose: 	Commands for low-level DMA-able memory control
      9  */
     10 
     11 #include <sal/types.h>
     12 
     13 #include <soc/cm.h>
     14 #include <soc/dma.h>
     15 #include <soc/error.h>
     16 #include <shared/bsl.h>
     17 #include <appl/diag/parse.h>
     18 #include <appl/diag/system.h>
     19 
     20 #define CMD_ESW_DMA_LADDR      "dma_laddr"
     21 #define CMD_ESW_DMA_PADDR      "dma_paddr"
     22 #define CMD_ESW_DMA_SIZE       "dma_size"
     23 #define CMD_ESW_DMA_COUNT      "dma_count"
     24 #define CMD_ESW_DMA_BYTES      "dma_bytes"
     25 #define CMD_ESW_DMA_SHORTS     "dma_shorts"
     26 #define CMD_ESW_DMA_WORDS      "dma_words"
     27 #define CMD_ESW_DMA_DV         "dma_dv_laddr"
     28 #define CMD_ESW_DMA_DCB        "dma_dcb_laddr"
     29 #define CMD_ESW_DMA_DCB_COUNT  "dma_dcb_count"
     30 #define CMD_ESW_DMA_DCB_SIZE   "dma_dcb_size"
     31 
     32 char cmd_esw_dma_usage[] =
     33 #ifdef COMPILER_STRING_CONST_LIMIT
     34     "Usage: dma <option> [args...]\n"
     35 #else
     36     "Usages:\n\t"
     37     "\n\t"
     38     "  dma alloc [b|h|w] <count> [name]\n\t"
     39     "            Allocate DMA-able memory (you can add region name)\n\t"
     40     "  dma free  [<laddr>]\n\t"
     41     "            Free DMA-able memory\n\t"
     42     "  dma l2p   [<laddr>]\n\t"
     43     "            Convert logical (CPU) address into a physical (bus) address\n\t"
     44     "  dma p2l   [<paddr>]\n\t"
     45     "            Convert physical (bus) address into a logical (CPU) address\n\t"
     46     "  dma flush [b|h|w] [<laddr> [<count>]]\n\t"
     47     "            Flush the cache corresponding to the DMA-able memory region\n\t"
     48     "  dma inval [b|h|w] [<laddr> [<count>]]\n\t"
     49     "            Invalidate the cache corresponding to the DMA-able memory region\n\t"
     50     "  dma load  <laddr> <hex data>\n\t"
     51     "            Fill DMA-able memory with provided hex data\n\t"
     52     "  dma fill  [b|h|w] <laddr> <count> <value>\n\t"
     53     "            Fill DMA-able memory with provided value\n\t"
     54     "  dma edit  [b|h|w] [<laddr>]\n\t"
     55     "            Interactive memory editing\n\t"
     56     "  dma dvalloc [r|t] <dcb_count>\n\t"
     57     "            Allocate a DMA Vector (DV) with dcb_count DCBs\n\t"
     58     "  dma dvfree dv_addr\n\t"
     59     "            Free a DV together with the allocated DCBs\n\t"
     60     "  dma addrx <dv_laddr> <buf_laddr> <bytes>\n\t"
     61     "            Add an RX DCB to the DV chain\n\t"
     62     "  dma dcbdump [r|t] $dcb_laddr\n\t"
     63     "            Dump the memory as a DCB\n\t"
     64     "\nNote:\n\t"
     65     "The following variables contain the results of the subcommands and\n\t"
     66     "be used as default arguments:\n\t\t"
     67     "$" CMD_ESW_DMA_LADDR "\t -- the logical  address of DMA-able memory\n\t\t"
     68     "$" CMD_ESW_DMA_PADDR "\t -- the physical address of DMA-able memory\n\t\t"
     69     "$" CMD_ESW_DMA_SIZE  "\t -- the size of the element (b, h, or w)\n\t\t"
     70     "$" CMD_ESW_DMA_COUNT "\t -- the number of elements (bytes, shorts, words)\n\t\t"
     71     "$" CMD_ESW_DMA_BYTES "\t -- number of bytes in the allocated region\n\t\t"
     72     "$" CMD_ESW_DMA_SHORTS"\t -- number of shorts in the allocated region\n\t\t"
     73     "$" CMD_ESW_DMA_WORDS "\t -- number of words in the allocated region\n\t\t"
     74     "$" CMD_ESW_DMA_DV    "\t -- the logical address of the allocated \n\t\t"
     75                     "\t\t    DMA vector (DV)\n\t\t"
     76     "$" CMD_ESW_DMA_DCB   "\t -- the logical address of allocated DCB chain\n\t\t"
     77     "$" CMD_ESW_DMA_DCB_COUNT "\t -- number of DCBs in the allocated chain\n\t\t"
     78     "$" CMD_ESW_DMA_DCB_SIZE  "\t -- the size of a single DCB in bytes\n"
     79     "\n"
     80 #endif
     81 ;
     82 
     83 STATIC cmd_result_t
     84 cmd_esw_dma_get_size(int unit, args_t *a, int *size)
     85 {
     86     char *sz;
     87 
     88     if (size == NULL) {
     89         return CMD_FAIL;
     90     }
     91 
     92     if ((sz = ARG_GET(a)) != NULL) { 
     93         switch (sz[0]) {
     94         case 'b': case 'B': *size = 1; return CMD_OK;
     95         case 'h': case 'H': *size = 2; return CMD_OK;
     96         case 'w': case 'W': *size = 4; return CMD_OK;
     97         default: ARG_PREV(a);
     98         }
     99     }
    100      
    101     if ((sz = var_get(CMD_ESW_DMA_SIZE)) == NULL) {
    102         *size = 1;        /* Default are bytes */
    103         return CMD_OK; 
    104     } else {
    105         switch (sz[0]) {
    106         case 'b': case 'B': *size = 1; return CMD_OK;
    107         case 'h': case 'H': *size = 2; return CMD_OK;
    108         case 'w': case 'W': *size = 4; return CMD_OK;
    109         default:
    110             cli_out("Incorrect size specification <%s>\n", sz);
    111             return CMD_FAIL;
    112         }
    113     }
    114 
    115     return CMD_FAIL;
    116 }
    117 
    118 STATIC cmd_result_t
    119 cmd_esw_dma_get_count(int unit, args_t *a, int *count)
    120 {
    121     char *arg;
    122 
    123     if (count == NULL) {
    124         return CMD_FAIL;
    125     }
    126 
    127     /* Parse the number of bytes to allocate */
    128     if ((arg = ARG_GET(a)) == NULL &&
    129         (arg = var_get(CMD_ESW_DMA_COUNT)) == NULL) {
    130         return CMD_FAIL;
    131     }
    132 
    133     *count = parse_integer(arg);
    134 
    135     return CMD_OK;
    136  }
    137 
    138 STATIC void
    139 cmd_esw_dma_set_count_size(uint32 count, uint32 size)
    140 {
    141 
    142     var_unset(CMD_ESW_DMA_BYTES,  TRUE, FALSE, FALSE);
    143     var_unset(CMD_ESW_DMA_SHORTS, TRUE, FALSE, FALSE);
    144     var_unset(CMD_ESW_DMA_WORDS,  TRUE, FALSE, FALSE);
    145 
    146     switch (size) {
    147     case 1:
    148         var_set(CMD_ESW_DMA_SIZE, "b", TRUE, FALSE);
    149         var_set_integer(CMD_ESW_DMA_BYTES, count, TRUE, FALSE);
    150         break;
    151     case 2:
    152         var_set(CMD_ESW_DMA_SIZE, "h", TRUE, FALSE);
    153         var_set_integer(CMD_ESW_DMA_SHORTS, count, TRUE, FALSE);
    154         break;
    155     case 4:
    156         var_set(CMD_ESW_DMA_SIZE, "w", TRUE, FALSE);
    157         var_set_integer(CMD_ESW_DMA_WORDS, count, TRUE, FALSE);
    158         break;
    159     default:
    160         var_set(CMD_ESW_DMA_SIZE, "?", TRUE, FALSE);
    161         break;
    162     }
    163 
    164 }
    165 
    166 STATIC cmd_result_t
    167 cmd_esw_dma_get_laddr(int unit, args_t *a, void **laddr)
    168 {
    169     char *arg;
    170 
    171     if (laddr == NULL) {
    172         return CMD_FAIL;
    173     }
    174 
    175     /* Parse the logical address */
    176     if ((arg = ARG_GET(a)) == NULL &&
    177         (arg = var_get(CMD_ESW_DMA_LADDR)) == NULL) {
    178         return CMD_FAIL;
    179     }
    180 
    181     *laddr = (void *)parse_address(arg);
    182     
    183     return CMD_OK;
    184 }
    185 
    186 STATIC void
    187 cmd_esw_dma_set_laddr(void *laddr)
    188 {
    189     char buf[20];
    190 
    191     sal_sprintf(buf, "%p", laddr);
    192     var_set(CMD_ESW_DMA_LADDR, buf, TRUE, FALSE);
    193 }
    194 
    195 STATIC cmd_result_t
    196 cmd_esw_dma_get_paddr(int unit, args_t *a, uint32 *paddr)
    197 {
    198     char *arg;
    199 
    200     if (paddr == NULL) {
    201         return CMD_FAIL;
    202     }
    203 
    204     /* Parse the logical address */
    205     if ((arg = ARG_GET(a)) == NULL &&
    206         (arg = var_get(CMD_ESW_DMA_PADDR)) == NULL) {
    207         return CMD_FAIL;
    208     }
    209 
    210     *paddr = parse_address(arg);
    211     
    212     return CMD_OK;
    213 }
    214 
    215 STATIC void
    216 cmd_esw_dma_set_paddr(uint32 paddr)
    217 {
    218     char buf[20];
    219 
    220     sal_sprintf(buf, "0x%08x", paddr);
    221     var_set(CMD_ESW_DMA_PADDR, buf, TRUE, FALSE);
    222 }
    223 
    224 STATIC cmd_result_t
    225 cmd_esw_dma_get_dcb_count(int unit, args_t *a, int *dcb_count)
    226 {
    227     char *arg;
    228 
    229     if (dcb_count == NULL) {
    230         return CMD_FAIL;
    231     }
    232 
    233     /* Parse the number of bytes to allocate */
    234     if ((arg = ARG_GET(a)) == NULL &&
    235         (arg = var_get(CMD_ESW_DMA_DCB_COUNT)) == NULL) {
    236         return CMD_FAIL;
    237     }
    238 
    239     *dcb_count = parse_integer(arg);
    240 
    241     return CMD_OK;
    242 }
    243 
    244 STATIC cmd_result_t
    245 cmd_esw_dma_get_dv(int unit, args_t *a, dv_t  **laddr)
    246 {
    247    char *arg;
    248 
    249     if (laddr == NULL) {
    250         return CMD_FAIL;
    251     }
    252 
    253     /* Parse the logical address */
    254     if ((arg = ARG_GET(a)) == NULL &&
    255         (arg = var_get(CMD_ESW_DMA_DV)) == NULL) {
    256         return CMD_FAIL;
    257     }
    258 
    259     *laddr = (void *)parse_address(arg);
    260     
    261     return CMD_OK;
    262 }
    263 
    264 STATIC void
    265 cmd_esw_dma_set_dv(dv_t *dv, int dcb_size)
    266 {
    267     char buf[20];
    268 
    269     sal_sprintf(buf, "%p", (void *)dv);
    270     var_set(CMD_ESW_DMA_DV, buf, TRUE, FALSE);
    271 
    272     sal_sprintf(buf, "%p", dv->dv_dcb);
    273     var_set(CMD_ESW_DMA_DCB, buf, TRUE, FALSE);
    274 
    275     var_set_integer(CMD_ESW_DMA_DCB_COUNT, dv->dv_cnt, TRUE, FALSE);
    276     var_set_integer(CMD_ESW_DMA_DCB_SIZE,  dcb_size,   TRUE, FALSE);
    277 }
    278 
    279 /*
    280  * Subcommands 
    281  */
    282 
    283 STATIC cmd_result_t
    284 cmd_esw_dma_alloc(int unit, args_t *a)
    285 {
    286     char *arg;
    287     int   size;
    288     int   count;
    289     int   alloc_count;
    290     void *laddr;
    291 
    292     if (!sh_check_attached(ARG_CMD(a), unit)) {
    293         return CMD_FAIL;
    294     }
    295 
    296     if (cmd_esw_dma_get_size(unit, a, &size) != CMD_OK) {
    297         return CMD_USAGE;
    298     }
    299     
    300     
    301     if (cmd_esw_dma_get_count(unit, a, &count) != CMD_OK || count == 0) {
    302         return CMD_USAGE;
    303     }
    304     
    305    /* Get the region name if provided */
    306     arg = ARG_GET(a);
    307     
    308     /* Allocate DMA-able memory */
    309     alloc_count = size * count;
    310     laddr = soc_cm_salloc(unit, alloc_count, arg == NULL ? "diag-shell" : arg);
    311     if (laddr == NULL) {
    312         cli_out("Failed to allocate %d bytes of DMA-able memory\n", alloc_count);
    313         return CMD_FAIL;
    314     }
    315     
    316     /* Print the results and set the variable for others to reference */
    317     cli_out("Allocated %d bytes of DMA-able memory at address %p\n",
    318             alloc_count, laddr);
    319     
    320     cmd_esw_dma_set_laddr(laddr);
    321     cmd_esw_dma_set_count_size(count, size);
    322     
    323     return CMD_OK;
    324 }
    325 
    326 STATIC cmd_result_t
    327 cmd_esw_dma_free(int unit, args_t *a)
    328 {
    329     void *laddr = NULL;
    330     
    331     if (!sh_check_attached(ARG_CMD(a), unit)) {
    332         return CMD_FAIL;
    333     }
    334     
    335     if (cmd_esw_dma_get_laddr(unit, a, &laddr) != CMD_OK) 
    336         if (laddr == NULL) {
    337             return CMD_FAIL;
    338         }
    339     
    340     soc_cm_sfree(unit, laddr);
    341     
    342     return CMD_OK;
    343 }
    344 
    345 STATIC cmd_result_t
    346 cmd_esw_dma_l2p(int unit, args_t *a)
    347 {
    348     void  *laddr;
    349     uint32 paddr;
    350 
    351     if (!sh_check_attached(ARG_CMD(a), unit)) {
    352         return CMD_FAIL;
    353     }
    354 
    355     if (cmd_esw_dma_get_laddr(unit, a, &laddr) != CMD_OK) {
    356         return CMD_USAGE;
    357     }
    358 
    359     paddr = soc_cm_l2p(unit, laddr);
    360         
    361     cli_out("l2p(%p) = 0x%08x\n", laddr, paddr);
    362 
    363     cmd_esw_dma_set_paddr(paddr);
    364 
    365     return CMD_OK;
    366 }
    367 
    368 STATIC cmd_result_t
    369 cmd_esw_dma_p2l(int unit, args_t *a)
    370 {
    371     uint32  paddr;
    372     void   *laddr;
    373 
    374     if (!sh_check_attached(ARG_CMD(a), unit)) {
    375         return CMD_FAIL;
    376     }
    377 
    378     if (cmd_esw_dma_get_paddr(unit, a, &paddr) != CMD_OK) {
    379         return CMD_USAGE;
    380     }
    381 
    382     laddr   = soc_cm_p2l(unit, paddr);
    383         
    384     cli_out("p2l(0x%08x) = %p\n", paddr, laddr);
    385 
    386     cmd_esw_dma_set_laddr(laddr);
    387 
    388     return CMD_OK;
    389 }
    390 
    391 STATIC cmd_result_t
    392 cmd_esw_dma_flush(int unit, args_t *a)
    393 {
    394     int   size;
    395     int   count;
    396     void *laddr;
    397     int   flush_count;
    398     int   rv;
    399 
    400     if (!sh_check_attached(ARG_CMD(a), unit)) {
    401         return CMD_FAIL;
    402     }
    403 
    404     if (cmd_esw_dma_get_size(unit, a, &size) != CMD_OK) {
    405         return CMD_USAGE;
    406     }
    407         
    408     if (cmd_esw_dma_get_laddr(unit, a, &laddr) != CMD_OK) {
    409         return CMD_USAGE;
    410     }
    411 
    412     if (cmd_esw_dma_get_count(unit, a, &count) != CMD_OK) {
    413         return CMD_USAGE;
    414     }
    415     
    416     flush_count = size * count;
    417 
    418     rv = soc_cm_sflush(unit, laddr, flush_count);
    419     cli_out("Flushing %d bytes starting at %p: %s\n",
    420             flush_count, laddr, soc_errmsg(rv));
    421     if (SOC_FAILURE(rv)) {
    422         return CMD_FAIL;
    423     }
    424 
    425     return CMD_OK;
    426 }
    427 
    428 STATIC cmd_result_t
    429 cmd_esw_dma_inval(int unit, args_t *a)
    430 {
    431     int   size;
    432     int   count;
    433     void *laddr;
    434     int   inval_count;
    435     int   rv;
    436 
    437     if (!sh_check_attached(ARG_CMD(a), unit)) {
    438         return CMD_FAIL;
    439     }
    440 
    441     if (cmd_esw_dma_get_size(unit, a, &size) != CMD_OK) {
    442         return CMD_USAGE;
    443     }
    444         
    445     if (cmd_esw_dma_get_laddr(unit, a, &laddr) != CMD_OK) {
    446         return CMD_USAGE;
    447     }
    448 
    449     if (cmd_esw_dma_get_count(unit, a, &count) != CMD_OK) {
    450         return CMD_USAGE;
    451     }
    452     
    453     inval_count = size * count;
    454 
    455     rv = soc_cm_sinval(unit, laddr, inval_count);
    456     cli_out("Invalidating %d bytes starting at %p: %s\n",
    457             inval_count, laddr, soc_errmsg(rv));
    458     if (SOC_FAILURE(rv)) {
    459         return CMD_FAIL;
    460     }
    461 
    462     return CMD_OK;
    463 }
    464 
    465 STATIC cmd_result_t
    466 cmd_esw_dma_load(int unit, args_t *a)
    467 {
    468     void  *laddr_v;
    469     uint8 *laddr;
    470     char *cp;
    471     
    472         
    473     if (cmd_esw_dma_get_laddr(unit, a, &laddr_v) != CMD_OK) {
    474         return CMD_USAGE;
    475     }
    476 
    477     laddr = (uint8 *)laddr_v;
    478 
    479     while ((cp = ARG_GET(a)) != NULL) {
    480         while (*cp) {
    481             if (isspace((int)(*cp))) {
    482                 cp++;
    483             } else {
    484                 if (!isxdigit((unsigned)*cp) ||
    485                     !isxdigit((unsigned)*(cp+1))) {
    486                     cli_out("%s: Invalid character\n", ARG_CMD(a));
    487                     return(CMD_FAIL);
    488                 }
    489 
    490                 *laddr++ = (xdigit2i(*cp) << 4) | xdigit2i(*(cp + 1));
    491                 cp += 2;
    492             }
    493         }
    494     }
    495 
    496     return CMD_OK;
    497 }
    498 
    499 STATIC cmd_result_t
    500 cmd_esw_dma_fill(int unit, args_t *a)
    501 {
    502     char   *arg;
    503     int     size;
    504     void   *laddr;
    505     int     count;
    506     uint32  val;
    507     int     i;
    508 
    509     if (cmd_esw_dma_get_size(unit, a, &size) != CMD_OK) {
    510         cli_out("Incorrect size specification\n");
    511         return CMD_USAGE;
    512     }
    513         
    514     if (cmd_esw_dma_get_laddr(unit, a, &laddr) != CMD_OK) {
    515         cli_out("Invalid logical address specified\n");
    516         return CMD_USAGE;
    517     }
    518 
    519     if (cmd_esw_dma_get_count(unit, a, &count) != CMD_OK) {
    520         cli_out("Invalid count specified\n");
    521         return CMD_USAGE;
    522     }
    523     
    524     if ((arg = ARG_GET(a)) == NULL) {
    525         cli_out("No fill value specified\n");
    526         return CMD_USAGE;
    527     }
    528 
    529     val = parse_integer(arg);
    530 
    531     switch (size) {
    532     case 1:
    533         sal_memset(laddr, val, count);
    534         break;
    535     case 2:
    536         for(i=0; i < count; i++) {
    537             ((uint16 *)laddr)[i] = (uint16)val;
    538         }
    539         break;
    540     case 4:
    541         for(i=0; i < count; i++) {
    542             ((uint32 *)laddr)[i] = val;
    543         }
    544         break;
    545     default:
    546         return CMD_USAGE;
    547     }
    548 
    549     return CMD_OK;
    550 }
    551 
    552 STATIC cmd_result_t
    553 cmd_esw_dma_edit(int unit, args_t *a)
    554 {
    555     void   *laddr_v;
    556     uint8  *laddr;
    557     int     size;
    558     uint32  val;
    559     char    prompt[40];
    560     char    dfl_str[40];
    561 
    562     if (cmd_esw_dma_get_size(unit, a, &size) != CMD_OK) {
    563         return CMD_USAGE;
    564     }
    565         
    566     if (cmd_esw_dma_get_laddr(unit, a, &laddr_v) != CMD_OK) {
    567         return CMD_USAGE;
    568     }
    569 
    570     cli_out("Editing memory starting at %p\n", laddr_v);
    571     cli_out("Available commands:\n"
    572             "\t'.', 'q' -- Exit\n"
    573             "\t'-'      -- Go to the previous byte/word/halfword\n"
    574             "\t'<ENTER> -- Go to the next byte/word/halfword\n"
    575             "\t'b'      -- Edit bytes\n"
    576             "\t'h'      == Edit half-words\n"
    577             "\t'w'      -- Edit words\n\n");
    578 
    579     laddr = laddr_v;
    580 
    581     for (;;) {
    582         sal_sprintf(prompt, "%p ", (void *)laddr);
    583         switch (size) {
    584         case 1:
    585             val = *(uint8 *)laddr;
    586             sal_sprintf(dfl_str, "0x%02x", val);
    587             break;
    588         case 2:
    589             val = *(uint16 *)laddr;
    590             sal_sprintf(dfl_str, "0x%04x", val);
    591             break;
    592         case 4:
    593             val = *(uint32 *)laddr;
    594             sal_sprintf(dfl_str, "0x%08x", val);
    595             break;
    596         }
    597 
    598         if (sal_readline(prompt, prompt, sizeof(prompt), dfl_str) == 0 ||
    599             prompt[0] == 0) {
    600             cli_out("Aborted\n");
    601             break;
    602         }
    603 
    604         if (prompt[0] == '.' || prompt[0] == 'Q' || prompt[0] == 'q') {
    605             break;
    606         }
    607 
    608         switch (prompt[0]) {
    609         case '-':
    610             laddr -= size;
    611             continue;
    612             break;
    613         case 'W': 
    614         case 'w':
    615             size = 4;
    616             continue;
    617             break;
    618         case 'H': 
    619         case 'h':
    620             size = 2;
    621             continue;
    622             break;
    623         case 'B': 
    624         case 'b':
    625             size = 1;
    626             continue;
    627             break;
    628         default:
    629             val = parse_integer(prompt);
    630             break;
    631         }
    632             
    633         switch (size) {
    634         case 1:
    635             *(uint8 *)laddr = val;
    636             break;
    637         case 2:
    638             *(uint16 *)laddr = val;
    639             break;
    640         case 4:
    641             *(uint32 *)laddr = val;
    642             break;
    643         }
    644             
    645         laddr += size;
    646     }
    647 
    648     return CMD_OK;
    649 }
    650 
    651 cmd_result_t
    652 cmd_esw_dma_dv_alloc(int unit, args_t *a)
    653 {
    654     char  *arg;
    655     dvt_t  op;
    656     int    dcb_count;
    657     dv_t  *dv;
    658 
    659     if (!sh_check_attached(ARG_CMD(a), unit)) {
    660         return CMD_FAIL;
    661     }
    662 
    663     if ((arg = ARG_GET(a)) == NULL) {
    664         cli_out("DMA Vector (DV) type is not specified.\n");
    665         return CMD_USAGE;
    666     } else {
    667         switch (arg[0]) {
    668         case 'r': case 'R':
    669             op = DV_RX;
    670             break;
    671         case 't': case 'T':
    672             op = DV_TX;
    673             break;
    674         default:
    675             cli_out("Incorrect DV type <%s>. [r|t] expected.\n", arg);
    676             return CMD_USAGE;
    677         }
    678     }
    679 
    680     if (cmd_esw_dma_get_dcb_count(unit, a, &dcb_count) != CMD_OK) {
    681         return CMD_USAGE;
    682     }
    683 
    684     dv = soc_dma_dv_alloc(unit, op,  dcb_count);
    685     if (dv == NULL) {
    686         cli_out("Failed to allocate a DMA Vector (DV) with %d DCBs\n", 
    687                 dcb_count);
    688         return CMD_FAIL;
    689     } else {
    690     /*    coverity[noescape]    */
    691         cli_out("Allocated DMA Vector (DV) at %p. "
    692                 "%d DCBs (start %p, %d bytes)\n",
    693                 (void *)dv, dv->dv_cnt, (void *)dv->dv_dcb, SOC_DCB_SIZE(unit));
    694         cmd_esw_dma_set_dv(dv, SOC_DCB_SIZE(unit));
    695     }
    696 
    697     return CMD_OK;
    698 }
    699 
    700 cmd_result_t
    701 cmd_esw_dma_dcb_dump(int unit, args_t *a)
    702 {
    703     char  *arg;
    704 #if defined(BROADCOM_DEBUG)
    705     dvt_t  op;
    706 #endif
    707     dcb_t  *dcb_laddr;
    708 
    709     if (!sh_check_attached(ARG_CMD(a), unit)) {
    710         return CMD_FAIL;
    711     }
    712 
    713     if ((arg = ARG_GET(a)) == NULL) {
    714         cli_out("DCB type is not specified.\n");
    715         return CMD_USAGE;
    716     } else {
    717         switch (arg[0]) {
    718         case 'r': case 'R':
    719 #if defined(BROADCOM_DEBUG)
    720             op = DV_RX;
    721 #endif
    722             break;
    723         case 't': case 'T':
    724 #if defined(BROADCOM_DEBUG)
    725             op = DV_TX;
    726 #endif
    727             break;
    728         default:
    729             cli_out("Incorrect DCB type <%s>. [r|t] expected.\n", arg);
    730             return CMD_USAGE;
    731         }
    732     }
    733 
    734     if (cmd_esw_dma_get_laddr(unit, a, &dcb_laddr) != CMD_OK) {
    735         cli_out("Cannot get DCB address\n");
    736         return CMD_FAIL;
    737     }
    738 
    739 #ifdef BROADCOM_DEBUG
    740     cli_out("Dumping DCB at address %p:\n", dcb_laddr);
    741     SOC_DCB_DUMP(unit, dcb_laddr, "", (op == DV_TX) ? 1 : 0);
    742 #endif
    743 
    744     return CMD_OK;
    745 }
    746 
    747 cmd_result_t
    748 cmd_esw_dma_dv_free(int unit, args_t *a)
    749 {
    750     dv_t *dv;
    751 
    752     if (!sh_check_attached(ARG_CMD(a), unit)) {
    753         return CMD_FAIL;
    754     }
    755 
    756     if (cmd_esw_dma_get_dv(unit, a, &dv) != CMD_OK) {
    757         return CMD_FAIL;
    758     }
    759 
    760     soc_dma_dv_free(unit, dv);
    761 
    762     return CMD_OK;
    763 }
    764 
    765 cmd_result_t
    766 cmd_esw_dma_addrx(int unit, args_t *a)
    767 {
    768     void *laddr;
    769     dv_t *dv;
    770     int   count;
    771     int   rv;
    772 
    773     if (!sh_check_attached(ARG_CMD(a), unit)) {
    774         return CMD_FAIL;
    775     }
    776 
    777     if (cmd_esw_dma_get_dv(unit, a, &dv) != CMD_OK) {
    778         cli_out("Cannot get DV address\n");
    779         return CMD_FAIL;
    780     }
    781 
    782 
    783     if (cmd_esw_dma_get_laddr(unit, a, &laddr) != CMD_OK) {
    784         cli_out("Cannot get buffer address\n");
    785         return CMD_FAIL;
    786     }
    787 
    788     if (cmd_esw_dma_get_count(unit, a, &count) != CMD_OK) {
    789         cli_out("Cannot get buffer size\n");
    790         return CMD_FAIL;
    791     }
    792 
    793     rv = SOC_DCB_ADDRX(unit, dv,  (sal_vaddr_t)laddr, count, 0);
    794     
    795     cli_out("Added DCB to RX DV. %d DCB remaining\n", rv);
    796 
    797     return CMD_OK;
    798 }
    799 cmd_result_t
    800 cmd_esw_dma(int unit, args_t *a)
    801 {
    802     char    *subcmd;
    803     
    804     if ((subcmd = ARG_GET(a)) == NULL) {
    805         return CMD_USAGE;
    806     }
    807 
    808     if (sal_strcasecmp(subcmd, "alloc") == 0) {
    809         return cmd_esw_dma_alloc(unit, a);
    810     } else if (sal_strcasecmp(subcmd, "free") == 0) {
    811         return cmd_esw_dma_free(unit, a);
    812     } else if (sal_strcasecmp(subcmd, "l2p") == 0) {
    813         return cmd_esw_dma_l2p(unit, a);
    814     } else if (sal_strcasecmp(subcmd, "p2l") == 0) {
    815         return cmd_esw_dma_p2l(unit, a);
    816     } else if (sal_strcasecmp(subcmd, "flush") == 0) {
    817         return cmd_esw_dma_flush(unit, a);
    818     } else if (sal_strcasecmp(subcmd, "inval") == 0) {
    819         return cmd_esw_dma_inval(unit, a);
    820     } else if (sal_strcasecmp(subcmd, "fill") == 0) {
    821         return cmd_esw_dma_fill(unit, a);
    822     } else if (sal_strcasecmp(subcmd, "load") == 0) {
    823         return cmd_esw_dma_load(unit, a);
    824     } else if (sal_strcasecmp(subcmd, "edit") == 0) {
    825         return cmd_esw_dma_edit(unit, a);
    826     } else if (sal_strcasecmp(subcmd, "dvalloc") == 0) {
    827         return cmd_esw_dma_dv_alloc(unit, a);
    828     } else if (sal_strcasecmp(subcmd, "dvfree") == 0) {
    829         return cmd_esw_dma_dv_free(unit, a);
    830     } else if (sal_strcasecmp(subcmd, "dcbdump") == 0) {
    831         return cmd_esw_dma_dcb_dump(unit, a);
    832     } else if (sal_strcasecmp(subcmd, "addrx") == 0) {
    833         return cmd_esw_dma_addrx(unit, a);
    834     }
    835 
    836     cli_out("Unrecognized subcommand <%s>\n", subcmd);
    837 
    838     return CMD_USAGE;
    839 }