/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <npi_txdma.h>
#include <npi_tx_rd64.h>
#include <npi_tx_wr64.h>
#define TXDMA_WAIT_LOOP 10000
#define TXDMA_WAIT_MSEC 5
static npi_status_t npi_txdma_control_reset_wait(npi_handle_t handle,
uint8_t channel);
static npi_status_t npi_txdma_control_stop_wait(npi_handle_t handle,
uint8_t channel);
static npi_status_t npi_txdma_control_resume_wait(npi_handle_t handle,
uint8_t channel);
uint64_t tdc_dmc_offset[] = {
TX_RNG_CFIG_REG,
TX_RING_HDL_REG,
TX_RING_KICK_REG,
TX_ENT_MSK_REG,
TX_CS_REG,
TXDMA_MBH_REG,
TXDMA_MBL_REG,
TX_DMA_PRE_ST_REG,
TX_RNG_ERR_LOGH_REG,
TX_RNG_ERR_LOGL_REG,
TDMC_INTR_DBG_REG,
TX_CS_DBG_REG
};
const char *tdc_dmc_name[] = {
"TX_RNG_CFIG_REG",
"TX_RING_HDL_REG",
"TX_RING_KICK_REG",
"TX_ENT_MSK_REG",
"TX_CS_REG",
"TXDMA_MBH_REG",
"TXDMA_MBL_REG",
"TX_DMA_PRE_ST_REG",
"TX_RNG_ERR_LOGH_REG",
"TX_RNG_ERR_LOGL_REG",
"TDMC_INTR_DBG_REG",
"TX_CS_DBG_REG"
};
uint64_t tdc_fzc_offset [] = {
TX_LOG_PAGE_VLD_REG,
TX_LOG_PAGE_MASK1_REG,
TX_LOG_PAGE_VAL1_REG,
TX_LOG_PAGE_MASK2_REG,
TX_LOG_PAGE_VAL2_REG,
TX_LOG_PAGE_RELO1_REG,
TX_LOG_PAGE_RELO2_REG,
TX_LOG_PAGE_HDL_REG
};
const char *tdc_fzc_name [] = {
"TX_LOG_PAGE_VLD_REG",
"TX_LOG_PAGE_MASK1_REG",
"TX_LOG_PAGE_VAL1_REG",
"TX_LOG_PAGE_MASK2_REG",
"TX_LOG_PAGE_VAL2_REG",
"TX_LOG_PAGE_RELO1_REG",
"TX_LOG_PAGE_RELO2_REG",
"TX_LOG_PAGE_HDL_REG"
};
uint64_t tx_fzc_offset[] = {
TX_ADDR_MD_REG,
TDMC_INJ_PAR_ERR_REG,
TDMC_DBG_SEL_REG,
TDMC_TRAINING_REG,
TXC_PORT_DMA_ENABLE_REG,
TXC_DMA_MAX_BURST_REG
};
const char *tx_fzc_name[] = {
"TX_ADDR_MD_REG",
"TDMC_INJ_PAR_ERR_REG",
"TDMC_DBG_SEL_REG",
"TDMC_TRAINING_REG",
"TXC_PORT_DMA_ENABLE_REG",
"TXC_DMA_MAX_BURST_REG"
};
#define NUM_TDC_DMC_REGS (sizeof (tdc_dmc_offset) / sizeof (uint64_t))
#define NUM_TX_FZC_REGS (sizeof (tx_fzc_offset) / sizeof (uint64_t))
/*
* npi_txdma_dump_tdc_regs
* Dumps the contents of tdc csrs and fzc registers
*
* Input:
* tdc: TX DMA number
*
* return:
* NPI_SUCCESS
* NPI_FAILURE
* NPI_TXDMA_CHANNEL_INVALID
*
*/
npi_status_t
npi_txdma_dump_tdc_regs(npi_handle_t handle, uint8_t tdc)
{
uint64_t value, offset;
int num_regs, i;
ASSERT(TXDMA_CHANNEL_VALID(tdc));
if (!TXDMA_CHANNEL_VALID(tdc)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
"npi_txdma_dump_tdc_regs"
" Invalid TDC number %d \n",
tdc));
return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(tdc));
}
NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
"\nTXDMA DMC Register Dump for Channel %d\n",
tdc));
num_regs = NUM_TDC_DMC_REGS;
for (i = 0; i < num_regs; i++) {
TXDMA_REG_READ64(handle, tdc_dmc_offset[i], tdc, &value);
offset = NXGE_TXDMA_OFFSET(tdc_dmc_offset[i], handle.is_vraddr,
tdc);
NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, "0x%08llx "
"%s\t 0x%016llx \n",
offset, tdc_dmc_name[i],
value));
}
NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
"\n TXDMA Register Dump for Channel %d done\n", tdc));
return (NPI_SUCCESS);
}
/*
* npi_txdma_dump_fzc_regs
* Dumps the contents of tdc csrs and fzc registers
*
* Input:
* tdc: TX DMA number
*
* return:
* NPI_SUCCESS
* NPI_FAILURE
* NPI_TXDMA_CHANNEL_INVALID
*
*/
npi_status_t
npi_txdma_dump_fzc_regs(npi_handle_t handle)
{
uint64_t value;
int num_regs, i;
NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
"\nFZC_DMC Common Register Dump\n"));
num_regs = NUM_TX_FZC_REGS;
for (i = 0; i < num_regs; i++) {
#if defined(__i386)
NXGE_REG_RD64(handle, (uint32_t)tx_fzc_offset[i], &value);
#else
NXGE_REG_RD64(handle, tx_fzc_offset[i], &value);
#endif
NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, "0x%08llx "
"%s\t 0x%08llx \n",
tx_fzc_offset[i],
tx_fzc_name[i], value));
}
NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
"\n TXDMA FZC_DMC Register Dump Done \n"));
return (NPI_SUCCESS);
}
npi_status_t
npi_txdma_tdc_regs_zero(npi_handle_t handle, uint8_t tdc)
{
uint64_t value;
int num_regs, i;
ASSERT(TXDMA_CHANNEL_VALID(tdc));
if (!TXDMA_CHANNEL_VALID(tdc)) {
NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
"npi_txdma_tdc_regs_zero"
" InvaliInvalid TDC number %d \n",
tdc));
return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(tdc));
}
NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
"\nTXDMA DMC Register (zero) for Channel %d\n",
tdc));
num_regs = NUM_TDC_DMC_REGS;
value = 0;
for (i = 0; i < num_regs; i++) {
TXDMA_REG_WRITE64(handle, tdc_dmc_offset[i], tdc, value);
}
NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
"\nTXDMA FZC_DMC Register clear for Channel %d\n",
tdc));
NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
"\n TXDMA Register Clear to 0s for Channel %d done\n", tdc));
return (NPI_SUCCESS);
}
/*
* npi_txdma_address_mode32_set():
* This function is called to only support 32 bit addressing.
*
* Parameters:
* handle - NPI handle
* mode_enable - B_TRUE (enable 32 bit mode)
* B_FALSE (disable 32 bit mode)
*
* Return:
* NPI_SUCCESS - If set is complete successfully.
*
* Error:
* NONE
*/
npi_status_t
npi_txdma_mode32_set(npi_handle_t handle, boolean_t mode_enable)
{
tx_addr_md_t mode32;
mode32.value = 0;
if (mode_enable) {
mode32.bits.ldw.mode32 = 1;
} else {
mode32.bits.ldw.mode32 = 0;
}
NXGE_REG_WR64(handle, TX_ADDR_MD_REG, mode32.value);
return (NPI_SUCCESS);
}
/*
* npi_txdma_log_page_set():
* This function is called to configure a logical page
* (valid bit, mask, value, relocation).
*
* Parameters:
* handle - NPI handle
* cfgp - pointer to NPI defined data structure:
* - page valid
* - mask
* - value
* - relocation
* channel - hardware TXDMA channel from 0 to 23.
*
* Return:
* NPI_SUCCESS - If configurations are set successfully.
*
* Error:
* NPI_FAILURE -
* NPI_TXDMA_CHANNEL_INVALID -
* NPI_TXDMA_FUNC_INVALID -
* NPI_TXDMA_PAGE_INVALID -
*/
npi_status_t
npi_txdma_log_page_set(npi_handle_t handle, uint8_t channel,
p_dma_log_page_t cfgp)
{
log_page_vld_t vld;
int status;
uint64_t val;
dma_log_page_t cfg;
DMA_LOG_PAGE_FN_VALIDATE(channel, cfgp->page_num, cfgp->func_num,
status);
if (status) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_log_page_set"
" npi_status <0x%x>", status));
return (status);
}
TX_LOG_REG_WRITE64(handle, TX_LOG_PAGE_VLD_REG, channel, 0);
TX_LOG_REG_READ64(handle, TX_LOG_PAGE_VLD_REG, channel, &val);
NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL,
"\n==> npi_txdma_log_page_set: WRITE 0 and "
" READ back 0x%llx\n ", val));
vld.value = 0;
TX_LOG_REG_READ64(handle, TX_LOG_PAGE_VLD_REG, channel, &val);
val &= 0x3;
vld.value |= val;
vld.value = 0;
vld.bits.ldw.func = cfgp->func_num;
if (!cfgp->page_num) {
TX_LOG_REG_WRITE64(handle, TX_LOG_PAGE_MASK1_REG,
channel, (cfgp->mask & DMA_LOG_PAGE_MASK_MASK));
TX_LOG_REG_WRITE64(handle, TX_LOG_PAGE_VAL1_REG,
channel, (cfgp->value & DMA_LOG_PAGE_VALUE_MASK));
TX_LOG_REG_WRITE64(handle, TX_LOG_PAGE_RELO1_REG,
channel, (cfgp->reloc & DMA_LOG_PAGE_RELO_MASK));
} else {
TX_LOG_REG_WRITE64(handle, TX_LOG_PAGE_MASK2_REG,
channel, (cfgp->mask & DMA_LOG_PAGE_MASK_MASK));
TX_LOG_REG_WRITE64(handle, TX_LOG_PAGE_VAL2_REG,
channel, (cfgp->value & DMA_LOG_PAGE_VALUE_MASK));
TX_LOG_REG_WRITE64(handle, TX_LOG_PAGE_RELO2_REG,
channel, (cfgp->reloc & DMA_LOG_PAGE_RELO_MASK));
}
TX_LOG_REG_WRITE64(handle, TX_LOG_PAGE_VLD_REG, channel,
vld.value | (cfgp->valid << cfgp->page_num));
NPI_DEBUG_MSG((handle.function, NPI_REG_CTL,
"\n==> npi_txdma_log_page_set: vld value "
" 0x%llx function %d page_valid01 0x%x\n",
vld.value,
vld.bits.ldw.func,
(cfgp->valid << cfgp->page_num)));
cfg.page_num = 0;
cfg.func_num = 0;
(void) npi_txdma_log_page_get(handle, channel, &cfg);
cfg.page_num = 1;
(void) npi_txdma_log_page_get(handle, channel, &cfg);
return (status);
}
/*
* npi_txdma_log_page_get():
* This function is called to get a logical page
* (valid bit, mask, value, relocation).
*
* Parameters:
* handle - NPI handle
* cfgp - Get the following values (NPI defined structure):
* - page valid
* - mask
* - value
* - relocation
* channel - hardware TXDMA channel from 0 to 23.
*
* Return:
* NPI_SUCCESS - If configurations are read successfully.
*
* Error:
* NPI_FAILURE -
* NPI_TXDMA_CHANNEL_INVALID -
* NPI_TXDMA_FUNC_INVALID -
* NPI_TXDMA_PAGE_INVALID -
*/
npi_status_t
npi_txdma_log_page_get(npi_handle_t handle, uint8_t channel,
p_dma_log_page_t cfgp)
{
log_page_vld_t vld;
int status;
uint64_t val;
DMA_LOG_PAGE_VALIDATE(channel, cfgp->page_num, status);
if (status) {
NPI_ERROR_MSG((handle.function, NPI_REG_CTL,
" npi_txdma_log_page_get"
" npi_status <0x%x>", status));
return (status);
}
vld.value = 0;
vld.bits.ldw.func = cfgp->func_num;
TX_LOG_REG_READ64(handle, TX_LOG_PAGE_VLD_REG, channel, &val);
NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL,
"\n==> npi_txdma_log_page_get: read value "
" function %d value 0x%llx\n",
cfgp->func_num, val));
vld.value |= val;
cfgp->func_num = vld.bits.ldw.func;
if (!cfgp->page_num) {
TX_LOG_REG_READ64(handle, TX_LOG_PAGE_MASK1_REG, channel, &val);
cfgp->mask = val & DMA_LOG_PAGE_MASK_MASK;
TX_LOG_REG_READ64(handle, TX_LOG_PAGE_VAL1_REG, channel, &val);
cfgp->value = val & DMA_LOG_PAGE_VALUE_MASK;
TX_LOG_REG_READ64(handle, TX_LOG_PAGE_RELO1_REG, channel, &val);
cfgp->reloc = val & DMA_LOG_PAGE_RELO_MASK;
cfgp->valid = vld.bits.ldw.page0;
} else {
TX_LOG_REG_READ64(handle, TX_LOG_PAGE_MASK2_REG, channel, &val);
cfgp->mask = val & DMA_LOG_PAGE_MASK_MASK;
TX_LOG_REG_READ64(handle, TX_LOG_PAGE_VAL2_REG, channel, &val);
cfgp->value = val & DMA_LOG_PAGE_VALUE_MASK;
TX_LOG_REG_READ64(handle, TX_LOG_PAGE_RELO2_REG, channel, &val);
cfgp->reloc = val & DMA_LOG_PAGE_RELO_MASK;
cfgp->valid = vld.bits.ldw.page1;
}
return (status);
}
/*
* npi_txdma_log_page_handle_set():
* This function is called to program a page handle
* (bits [63:44] of a 64-bit address to generate
* a 64 bit address)
*
* Parameters:
* handle - NPI handle
* hdl_p - pointer to a logical page handle
* hardware data structure (log_page_hdl_t).
* channel - hardware TXDMA channel from 0 to 23.
*
* Return:
* NPI_SUCCESS - If configurations are set successfully.
*
* Error:
* NPI_FAILURE -
* NPI_TXDMA_CHANNEL_INVALID -
* NPI_TXDMA_FUNC_INVALID -
* NPI_TXDMA_PAGE_INVALID -
*/
npi_status_t
npi_txdma_log_page_handle_set(npi_handle_t handle, uint8_t channel,
p_log_page_hdl_t hdl_p)
{
int status = NPI_SUCCESS;
ASSERT(TXDMA_CHANNEL_VALID(channel));
if (!TXDMA_CHANNEL_VALID(channel)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_log_page_handle_set"
" Invalid Input: channel <0x%x>",
channel));
return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
}
TX_LOG_REG_WRITE64(handle, TX_LOG_PAGE_HDL_REG,
channel, hdl_p->value);
return (status);
}
/*
* npi_txdma_log_page_config():
* This function is called to IO operations on
* a logical page to set, get, clear
* valid bit, mask, value, relocation).
*
* Parameters:
* handle - NPI handle
* op_mode - OP_GET, OP_SET, OP_CLEAR
* type - NPI specific config type
* TXDMA_LOG_PAGE_MASK
* TXDMA_LOG_PAGE_VALUE
* TXDMA_LOG_PAGE_RELOC
* TXDMA_LOG_PAGE_VALID
* TXDMA_LOG_PAGE_ALL
* channel - hardware TXDMA channel from 0 to 23.
* cfgp - pointer to the NPI config structure.
* Return:
* NPI_SUCCESS - If configurations are read successfully.
*
* Error:
* NPI_FAILURE -
* NPI_TXDMA_OPCODE_INVALID -
* NPI_TXDMA_CHANNEL_INVALID -
* NPI_TXDMA_FUNC_INVALID -
* NPI_TXDMA_PAGE_INVALID -
*/
npi_status_t
npi_txdma_log_page_config(npi_handle_t handle, io_op_t op_mode,
txdma_log_cfg_t type, uint8_t channel,
p_dma_log_page_t cfgp)
{
int status = NPI_SUCCESS;
uint64_t val;
ASSERT(TXDMA_CHANNEL_VALID(channel));
if (!TXDMA_CHANNEL_VALID(channel)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_log_page_config"
" Invalid Input: channel <0x%x>",
channel));
return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
}
switch (op_mode) {
case OP_GET:
switch (type) {
case TXDMA_LOG_PAGE_ALL:
return (npi_txdma_log_page_get(handle, channel,
cfgp));
case TXDMA_LOG_PAGE_MASK:
if (!cfgp->page_num) {
TX_LOG_REG_READ64(handle, TX_LOG_PAGE_MASK1_REG,
channel, &val);
cfgp->mask = val & DMA_LOG_PAGE_MASK_MASK;
} else {
TX_LOG_REG_READ64(handle, TX_LOG_PAGE_MASK2_REG,
channel, &val);
cfgp->mask = val & DMA_LOG_PAGE_MASK_MASK;
}
break;
case TXDMA_LOG_PAGE_VALUE:
if (!cfgp->page_num) {
TX_LOG_REG_READ64(handle, TX_LOG_PAGE_VAL1_REG,
channel, &val);
cfgp->value = val & DMA_LOG_PAGE_VALUE_MASK;
} else {
TX_LOG_REG_READ64(handle, TX_LOG_PAGE_VAL2_REG,
channel, &val);
cfgp->value = val & DMA_LOG_PAGE_VALUE_MASK;
}
break;
case TXDMA_LOG_PAGE_RELOC:
if (!cfgp->page_num) {
TX_LOG_REG_READ64(handle, TX_LOG_PAGE_RELO1_REG,
channel, &val);
cfgp->reloc = val & DMA_LOG_PAGE_RELO_MASK;
} else {
TX_LOG_REG_READ64(handle, TX_LOG_PAGE_VAL2_REG,
channel, &val);
cfgp->reloc = val & DMA_LOG_PAGE_RELO_MASK;
}
break;
default:
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_log_page_config"
" Invalid Input: pageconfig <0x%x>",
type));
return (NPI_FAILURE |
NPI_TXDMA_OPCODE_INVALID(channel));
}
break;
case OP_SET:
case OP_CLEAR:
if (op_mode == OP_CLEAR) {
cfgp->valid = 0;
cfgp->mask = cfgp->func_num = 0;
cfgp->value = cfgp->reloc = 0;
}
switch (type) {
case TXDMA_LOG_PAGE_ALL:
return (npi_txdma_log_page_set(handle, channel,
cfgp));
case TXDMA_LOG_PAGE_MASK:
if (!cfgp->page_num) {
TX_LOG_REG_WRITE64(handle,
TX_LOG_PAGE_MASK1_REG, channel,
(cfgp->mask & DMA_LOG_PAGE_MASK_MASK));
} else {
TX_LOG_REG_WRITE64(handle,
TX_LOG_PAGE_MASK2_REG, channel,
(cfgp->mask & DMA_LOG_PAGE_MASK_MASK));
}
break;
case TXDMA_LOG_PAGE_VALUE:
if (!cfgp->page_num) {
TX_LOG_REG_WRITE64(handle,
TX_LOG_PAGE_VAL1_REG, channel,
(cfgp->value & DMA_LOG_PAGE_VALUE_MASK));
} else {
TX_LOG_REG_WRITE64(handle,
TX_LOG_PAGE_VAL2_REG, channel,
(cfgp->value & DMA_LOG_PAGE_VALUE_MASK));
}
break;
case TXDMA_LOG_PAGE_RELOC:
if (!cfgp->page_num) {
TX_LOG_REG_WRITE64(handle,
TX_LOG_PAGE_RELO1_REG, channel,
(cfgp->reloc & DMA_LOG_PAGE_RELO_MASK));
} else {
TX_LOG_REG_WRITE64(handle,
TX_LOG_PAGE_RELO2_REG, channel,
(cfgp->reloc & DMA_LOG_PAGE_RELO_MASK));
}
break;
default:
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_log_page_config"
" Invalid Input: pageconfig <0x%x>",
type));
return (NPI_FAILURE |
NPI_TXDMA_OPCODE_INVALID(channel));
}
break;
default:
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_log_page_config"
" Invalid Input: op <0x%x>",
op_mode));
return (NPI_FAILURE | NPI_TXDMA_OPCODE_INVALID(channel));
}
return (status);
}
/*
* npi_txdma_log_page_vld_config():
* This function is called to configure the logical
* page valid register.
*
* Parameters:
* handle - NPI handle
* op_mode - OP_GET: get valid page configuration
* OP_SET: set valid page configuration
* OP_UPDATE: update valid page configuration
* OP_CLEAR: reset both valid pages to
* not defined (0).
* channel - hardware TXDMA channel from 0 to 23.
* vld_p - pointer to hardware defined log page valid register.
* Return:
* NPI_SUCCESS - If set is complete successfully.
*
* Error:
* NPI_FAILURE -
* NPI_TXDMA_CHANNEL_INVALID -
* NPI_TXDMA_OPCODE_INVALID -
*/
npi_status_t
npi_txdma_log_page_vld_config(npi_handle_t handle, io_op_t op_mode,
uint8_t channel, p_log_page_vld_t vld_p)
{
int status = NPI_SUCCESS;
log_page_vld_t vld;
ASSERT(TXDMA_CHANNEL_VALID(channel));
if (!TXDMA_CHANNEL_VALID(channel)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_log_page_vld_config"
" Invalid Input: channel <0x%x>",
channel));
return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
}
switch (op_mode) {
case OP_GET:
TX_LOG_REG_READ64(handle, TX_LOG_PAGE_VLD_REG, channel,
&vld_p->value);
break;
case OP_SET:
TX_LOG_REG_WRITE64(handle, TX_LOG_PAGE_VLD_REG,
channel, vld_p->value);
break;
case OP_UPDATE:
TX_LOG_REG_READ64(handle, TX_LOG_PAGE_VLD_REG, channel,
&vld.value);
TX_LOG_REG_WRITE64(handle, TX_LOG_PAGE_VLD_REG,
channel, vld.value | vld_p->value);
break;
case OP_CLEAR:
TX_LOG_REG_WRITE64(handle, TX_LOG_PAGE_VLD_REG,
channel, 0);
break;
default:
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_log_pag_vld_cofig"
" Invalid Input: pagevld <0x%x>",
op_mode));
return (NPI_FAILURE | NPI_TXDMA_OPCODE_INVALID(channel));
}
return (status);
}
/*
* npi_txdma_channel_reset():
* This function is called to reset a transmit DMA channel.
* (This function is used to reset a channel and reinitialize
* all other bits except RST_STATE).
*
* Parameters:
* handle - NPI handle (virtualization flag must be defined).
* channel - logical TXDMA channel from 0 to 23.
* (If virtualization flag is not set, then
* logical channel is the same as the hardware
* channel number).
*
* Return:
* NPI_SUCCESS - If reset is complete successfully.
*
* Error:
* NPI_FAILURE -
* NPI_TXDMA_CHANNEL_INVALID -
* NPI_TXDMA_RESET_FAILED -
*/
npi_status_t
npi_txdma_channel_reset(npi_handle_t handle, uint8_t channel)
{
NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL,
" npi_txdma_channel_reset"
" RESETTING",
channel));
return (npi_txdma_channel_control(handle, TXDMA_RESET, channel));
}
/*
* npi_txdma_channel_init_enable():
* This function is called to start a transmit DMA channel after reset.
*
* Parameters:
* handle - NPI handle (virtualization flag must be defined).
* channel - logical TXDMA channel from 0 to 23.
* (If virtualization flag is not set, then
* logical channel is the same as the hardware
* channel number).
* Return:
* NPI_SUCCESS - If DMA channel is started successfully.
*
* Error:
* NPI_FAILURE -
* NPI_TXDMA_CHANNEL_INVALID -
*/
npi_status_t
npi_txdma_channel_init_enable(npi_handle_t handle, uint8_t channel)
{
return (npi_txdma_channel_control(handle, TXDMA_INIT_START, channel));
}
/*
* npi_txdma_channel_enable():
* This function is called to start a transmit DMA channel.
*
* Parameters:
* handle - NPI handle (virtualization flag must be defined).
* channel - logical TXDMA channel from 0 to 23.
* (If virtualization flag is not set, then
* logical channel is the same as the hardware
* channel number).
* Return:
* NPI_SUCCESS - If DMA channel is stopped successfully.
*
* Error:
* NPI_FAILURE -
* NPI_TXDMA_CHANNEL_INVALID -
*/
npi_status_t
npi_txdma_channel_enable(npi_handle_t handle, uint8_t channel)
{
return (npi_txdma_channel_control(handle, TXDMA_START, channel));
}
/*
* npi_txdma_channel_disable():
* This function is called to stop a transmit DMA channel.
*
* Parameters:
* handle - NPI handle (virtualization flag must be defined).
* channel - logical TXDMA channel from 0 to 23.
* (If virtualization flag is not set, then
* logical channel is the same as the hardware
* channel number).
* Return:
* NPI_SUCCESS - If DMA channel is stopped successfully.
*
* Error:
* NPI_FAILURE -
* NPI_TXDMA_CHANNEL_INVALID -
* NPI_TXDMA_STOP_FAILED -
*/
npi_status_t
npi_txdma_channel_disable(npi_handle_t handle, uint8_t channel)
{
return (npi_txdma_channel_control(handle, TXDMA_STOP, channel));
}
/*
* npi_txdma_channel_resume():
* This function is called to restart a transmit DMA channel.
*
* Parameters:
* handle - NPI handle (virtualization flag must be defined).
* channel - logical TXDMA channel from 0 to 23.
* (If virtualization flag is not set, then
* logical channel is the same as the hardware
* channel number).
* Return:
* NPI_SUCCESS - If DMA channel is stopped successfully.
*
* Error:
* NPI_FAILURE -
* NPI_TXDMA_CHANNEL_INVALID -
* NPI_TXDMA_RESUME_FAILED -
*/
npi_status_t
npi_txdma_channel_resume(npi_handle_t handle, uint8_t channel)
{
return (npi_txdma_channel_control(handle, TXDMA_RESUME, channel));
}
/*
* npi_txdma_channel_mmk_clear():
* This function is called to clear MMK bit.
*
* Parameters:
* handle - NPI handle (virtualization flag must be defined).
* channel - logical TXDMA channel from 0 to 23.
* (If virtualization flag is not set, then
* logical channel is the same as the hardware
* channel number).
* Return:
* NPI_SUCCESS - If MMK is reset successfully.
*
* Error:
* NPI_FAILURE -
* NPI_TXDMA_CHANNEL_INVALID -
*/
npi_status_t
npi_txdma_channel_mmk_clear(npi_handle_t handle, uint8_t channel)
{
return (npi_txdma_channel_control(handle, TXDMA_CLEAR_MMK, channel));
}
/*
* npi_txdma_channel_mbox_enable():
* This function is called to enable the mailbox update.
*
* Parameters:
* handle - NPI handle (virtualization flag must be defined).
* channel - logical TXDMA channel from 0 to 23.
* (If virtualization flag is not set, then
* logical channel is the same as the hardware
* channel number).
* Return:
* NPI_SUCCESS - If mailbox is enabled successfully.
*
* Error:
* NPI_HW_ERROR -
* NPI_FAILURE -
* NPI_TXDMA_CHANNEL_INVALID -
*/
npi_status_t
npi_txdma_channel_mbox_enable(npi_handle_t handle, uint8_t channel)
{
return (npi_txdma_channel_control(handle, TXDMA_MBOX_ENABLE, channel));
}
/*
* npi_txdma_channel_control():
* This function is called to control a transmit DMA channel
* for reset, start or stop.
*
* Parameters:
* handle - NPI handle (virtualization flag must be defined).
* control - NPI defined control type supported
* - TXDMA_INIT_RESET
* - TXDMA_INIT_START
* - TXDMA_RESET
* - TXDMA_START
* - TXDMA_STOP
* channel - logical TXDMA channel from 0 to 23.
* (If virtualization flag is not set, then
* logical channel is the same as the hardware
*
* Return:
* NPI_SUCCESS - If reset is complete successfully.
*
* Error:
* NPI_FAILURE -
* NPI_TXDMA_OPCODE_INVALID -
* NPI_TXDMA_CHANNEL_INVALID -
* NPI_TXDMA_RESET_FAILED -
* NPI_TXDMA_STOP_FAILED -
* NPI_TXDMA_RESUME_FAILED -
*/
npi_status_t
npi_txdma_channel_control(npi_handle_t handle, txdma_cs_cntl_t control,
uint8_t channel)
{
int status = NPI_SUCCESS;
tx_cs_t cs;
ASSERT(TXDMA_CHANNEL_VALID(channel));
if (!TXDMA_CHANNEL_VALID(channel)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_channel_control"
" Invalid Input: channel <0x%x>",
channel));
return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
}
switch (control) {
case TXDMA_INIT_RESET:
cs.value = 0;
TXDMA_REG_READ64(handle, TX_CS_REG, channel, &cs.value);
cs.bits.ldw.rst = 1;
TXDMA_REG_WRITE64(handle, TX_CS_REG, channel, cs.value);
return (npi_txdma_control_reset_wait(handle, channel));
case TXDMA_INIT_START:
cs.value = 0;
TXDMA_REG_WRITE64(handle, TX_CS_REG, channel, cs.value);
break;
case TXDMA_RESET:
/*
* Sets reset bit only (Hardware will reset all
* the RW bits but leave the RO bits alone.
*/
cs.value = 0;
cs.bits.ldw.rst = 1;
TXDMA_REG_WRITE64(handle, TX_CS_REG, channel, cs.value);
return (npi_txdma_control_reset_wait(handle, channel));
case TXDMA_START:
/* Enable the DMA channel */
TXDMA_REG_READ64(handle, TX_CS_REG, channel, &cs.value);
cs.bits.ldw.stop_n_go = 0;
TXDMA_REG_WRITE64(handle, TX_CS_REG, channel, cs.value);
break;
case TXDMA_STOP:
/* Disable the DMA channel */
TXDMA_REG_READ64(handle, TX_CS_REG, channel, &cs.value);
cs.bits.ldw.stop_n_go = 1;
TXDMA_REG_WRITE64(handle, TX_CS_REG, channel, cs.value);
status = npi_txdma_control_stop_wait(handle, channel);
if (status) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
"Cannot stop channel %d (TXC hung!)",
channel));
}
break;
case TXDMA_RESUME:
/* Resume the packet transmission after stopping */
TXDMA_REG_READ64(handle, TX_CS_REG, channel, &cs.value);
cs.value |= ~TX_CS_STOP_N_GO_MASK;
TXDMA_REG_WRITE64(handle, TX_CS_REG, channel, cs.value);
return (npi_txdma_control_resume_wait(handle, channel));
case TXDMA_CLEAR_MMK:
/* Write 1 to MK bit to clear the MMK bit */
TXDMA_REG_READ64(handle, TX_CS_REG, channel, &cs.value);
cs.bits.ldw.mk = 1;
TXDMA_REG_WRITE64(handle, TX_CS_REG, channel, cs.value);
break;
case TXDMA_MBOX_ENABLE:
/*
* Write 1 to MB bit to enable mailbox update
* (cleared to 0 by hardware after update).
*/
TXDMA_REG_READ64(handle, TX_CS_REG, channel, &cs.value);
cs.bits.ldw.mb = 1;
TXDMA_REG_WRITE64(handle, TX_CS_REG, channel, cs.value);
break;
default:
status = (NPI_FAILURE | NPI_TXDMA_OPCODE_INVALID(channel));
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_channel_control"
" Invalid Input: control <0x%x>",
control));
}
return (status);
}
/*
* npi_txdma_control_status():
* This function is called to operate on the control
* and status register.
*
* Parameters:
* handle - NPI handle
* op_mode - OP_GET: get hardware control and status
* OP_SET: set hardware control and status
* OP_UPDATE: update hardware control and status.
* OP_CLEAR: clear control and status register to 0s.
* channel - hardware TXDMA channel from 0 to 23.
* cs_p - pointer to hardware defined control and status
* structure.
* Return:
* NPI_SUCCESS - If set is complete successfully.
*
* Error:
* NPI_FAILURE -
* NPI_TXDMA_OPCODE_INVALID -
* NPI_TXDMA_CHANNEL_INVALID -
* NPI_TXDMA_FUNC_INVALID -
*/
npi_status_t
npi_txdma_control_status(npi_handle_t handle, io_op_t op_mode,
uint8_t channel, p_tx_cs_t cs_p)
{
int status = NPI_SUCCESS;
tx_cs_t txcs;
ASSERT(TXDMA_CHANNEL_VALID(channel));
if (!TXDMA_CHANNEL_VALID(channel)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_control_status"
" Invalid Input: channel <0x%x>",
channel));
return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
}
switch (op_mode) {
case OP_GET:
TXDMA_REG_READ64(handle, TX_CS_REG, channel, &cs_p->value);
break;
case OP_SET:
TXDMA_REG_WRITE64(handle, TX_CS_REG, channel, cs_p->value);
break;
case OP_UPDATE:
TXDMA_REG_READ64(handle, TX_CS_REG, channel, &txcs.value);
TXDMA_REG_WRITE64(handle, TX_CS_REG, channel,
cs_p->value | txcs.value);
break;
default:
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_control_status"
" Invalid Input: control <0x%x>",
op_mode));
return (NPI_FAILURE | NPI_TXDMA_OPCODE_INVALID(channel));
}
return (status);
}
/*
* npi_txdma_event_mask():
* This function is called to operate on the event mask
* register which is used for generating interrupts..
* and status register.
*
* Parameters:
* handle - NPI handle
* op_mode - OP_GET: get hardware event mask
* OP_SET: set hardware interrupt event masks
* OP_CLEAR: clear control and status register to 0s.
* channel - hardware TXDMA channel from 0 to 23.
* mask_p - pointer to hardware defined event mask
* structure.
* Return:
* NPI_SUCCESS - If set is complete successfully.
*
* Error:
* NPI_FAILURE -
* NPI_TXDMA_OPCODE_INVALID -
* NPI_TXDMA_CHANNEL_INVALID -
*/
npi_status_t
npi_txdma_event_mask(npi_handle_t handle, io_op_t op_mode,
uint8_t channel, p_tx_dma_ent_msk_t mask_p)
{
int status = NPI_SUCCESS;
tx_dma_ent_msk_t mask;
ASSERT(TXDMA_CHANNEL_VALID(channel));
if (!TXDMA_CHANNEL_VALID(channel)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_event_mask"
" Invalid Input: channel <0x%x>",
channel));
return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
}
switch (op_mode) {
case OP_GET:
TXDMA_REG_READ64(handle, TX_ENT_MSK_REG, channel,
&mask_p->value);
break;
case OP_SET:
TXDMA_REG_WRITE64(handle, TX_ENT_MSK_REG, channel,
mask_p->value);
break;
case OP_UPDATE:
TXDMA_REG_READ64(handle, TX_ENT_MSK_REG, channel, &mask.value);
TXDMA_REG_WRITE64(handle, TX_ENT_MSK_REG, channel,
mask_p->value | mask.value);
break;
default:
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_event_mask"
" Invalid Input: eventmask <0x%x>",
op_mode));
return (NPI_FAILURE | NPI_TXDMA_OPCODE_INVALID(channel));
}
return (status);
}
/*
* npi_txdma_event_mask_config():
* This function is called to operate on the event mask
* register which is used for generating interrupts..
* and status register.
*
* Parameters:
* handle - NPI handle
* op_mode - OP_GET: get hardware event mask
* OP_SET: set hardware interrupt event masks
* OP_CLEAR: clear control and status register to 0s.
* channel - hardware TXDMA channel from 0 to 23.
* cfgp - pointer to NPI defined event mask
* enum data type.
* Return:
* NPI_SUCCESS - If set is complete successfully.
*
* Error:
* NPI_FAILURE -
* NPI_TXDMA_OPCODE_INVALID -
* NPI_TXDMA_CHANNEL_INVALID -
*/
npi_status_t
npi_txdma_event_mask_config(npi_handle_t handle, io_op_t op_mode,
uint8_t channel, txdma_ent_msk_cfg_t *mask_cfgp)
{
int status = NPI_SUCCESS;
uint64_t configuration = *mask_cfgp;
uint64_t value;
ASSERT(TXDMA_CHANNEL_VALID(channel));
if (!TXDMA_CHANNEL_VALID(channel)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_event_mask_config"
" Invalid Input: channel <0x%x>",
channel));
return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
}
switch (op_mode) {
case OP_GET:
TXDMA_REG_READ64(handle, TX_ENT_MSK_REG, channel,
(uint64_t *)mask_cfgp);
break;
case OP_SET:
TXDMA_REG_WRITE64(handle, TX_ENT_MSK_REG, channel,
configuration);
break;
case OP_UPDATE:
TXDMA_REG_READ64(handle, TX_ENT_MSK_REG, channel, &value);
TXDMA_REG_WRITE64(handle, TX_ENT_MSK_REG, channel,
configuration | value);
break;
case OP_CLEAR:
TXDMA_REG_WRITE64(handle, TX_ENT_MSK_REG, channel,
CFG_TXDMA_MASK_ALL);
break;
default:
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_event_mask_config"
" Invalid Input: eventmask <0x%x>",
op_mode));
return (NPI_FAILURE | NPI_TXDMA_OPCODE_INVALID(channel));
}
return (status);
}
/*
* npi_txdma_event_mask_mk_out():
* This function is called to mask out the packet transmit marked event.
*
* Parameters:
* handle - NPI handle
* channel - hardware TXDMA channel from 0 to 23.
* enum data type.
* Return:
* NPI_SUCCESS - If set is complete successfully.
*
* Error:
* NPI_FAILURE -
* NPI_TXDMA_CHANNEL_INVALID -
*/
npi_status_t
npi_txdma_event_mask_mk_out(npi_handle_t handle, uint8_t channel)
{
uint64_t event_mask;
int status = NPI_SUCCESS;
ASSERT(TXDMA_CHANNEL_VALID(channel));
if (!TXDMA_CHANNEL_VALID(channel)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_event_mask_mk_out"
" Invalid Input: channel <0x%x>",
channel));
return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
}
TXDMA_REG_READ64(handle, TX_ENT_MSK_REG, channel, &event_mask);
TXDMA_REG_WRITE64(handle, TX_ENT_MSK_REG, channel,
event_mask & (~TX_ENT_MSK_MK_MASK));
return (status);
}
/*
* npi_txdma_event_mask_mk_in():
* This function is called to set the mask for the the packet marked event.
*
* Parameters:
* handle - NPI handle
* channel - hardware TXDMA channel from 0 to 23.
* enum data type.
* Return:
* NPI_SUCCESS - If set is complete successfully.
*
* Error:
* NPI_FAILURE -
* NPI_TXDMA_CHANNEL_INVALID -
*/
npi_status_t
npi_txdma_event_mask_mk_in(npi_handle_t handle, uint8_t channel)
{
uint64_t event_mask;
int status = NPI_SUCCESS;
ASSERT(TXDMA_CHANNEL_VALID(channel));
if (!TXDMA_CHANNEL_VALID(channel)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_event_mask_mk_in"
" Invalid Input: channel <0x%x>",
channel));
return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
}
TXDMA_REG_READ64(handle, TX_ENT_MSK_REG, channel, &event_mask);
TXDMA_REG_WRITE64(handle, TX_ENT_MSK_REG, channel,
event_mask | TX_ENT_MSK_MK_MASK);
return (status);
}
/*
* npi_txdma_ring_addr_set():
* This function is called to configure the transmit descriptor
* ring address and its size.
*
* Parameters:
* handle - NPI handle (virtualization flag must be defined
* if its register pointer is from the virtual region).
* channel - logical TXDMA channel from 0 to 23.
* (If virtualization flag is not set, then
* logical channel is the same as the hardware
* channel number).
* start_addr - starting address of the descriptor
* len - maximum length of the descriptor
* (in number of 64 bytes block).
* Return:
* NPI_SUCCESS - If set is complete successfully.
*
* Error:
* NPI_FAILURE -
* NPI_TXDMA_OPCODE_INVALID -
* NPI_TXDMA_CHANNEL_INVALID -
*/
npi_status_t
npi_txdma_ring_addr_set(npi_handle_t handle, uint8_t channel,
uint64_t start_addr, uint32_t len)
{
int status = NPI_SUCCESS;
tx_rng_cfig_t cfg;
ASSERT(TXDMA_CHANNEL_VALID(channel));
if (!TXDMA_CHANNEL_VALID(channel)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_ring_addr_set"
" Invalid Input: channel <0x%x>",
channel));
return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
}
cfg.value = ((start_addr & TX_RNG_CFIG_ADDR_MASK) |
(((uint64_t)len) << TX_RNG_CFIG_LEN_SHIFT));
TXDMA_REG_WRITE64(handle, TX_RNG_CFIG_REG, channel, cfg.value);
return (status);
}
/*
* npi_txdma_ring_config():
* This function is called to config a descriptor ring
* by using the hardware defined data.
*
* Parameters:
* handle - NPI handle (virtualization flag must be defined
* if its register pointer is from the virtual region).
* channel - logical TXDMA channel from 0 to 23.
* (If virtualization flag is not set, then
* logical channel is the same as the hardware
* channel number).
* op_mode - OP_GET: get transmit ring configuration
* OP_SET: set transmit ring configuration
* reg_data - pointer to hardware defined transmit ring
* configuration data structure.
* Return:
* NPI_SUCCESS - If set/get is complete successfully.
*
* Error:
* NPI_FAILURE -
* NPI_TXDMA_CHANNEL_INVALID -
*/
npi_status_t
npi_txdma_ring_config(npi_handle_t handle, io_op_t op_mode,
uint8_t channel, uint64_t *reg_data)
{
int status = NPI_SUCCESS;
ASSERT(TXDMA_CHANNEL_VALID(channel));
if (!TXDMA_CHANNEL_VALID(channel)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_ring_config"
" Invalid Input: channel <0x%x>",
channel));
return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
}
switch (op_mode) {
case OP_GET:
TXDMA_REG_READ64(handle, TX_RNG_CFIG_REG, channel, reg_data);
break;
case OP_SET:
TXDMA_REG_WRITE64(handle, TX_RNG_CFIG_REG, channel,
*reg_data);
break;
default:
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_ring_config"
" Invalid Input: ring_config <0x%x>",
op_mode));
return (NPI_FAILURE | NPI_TXDMA_OPCODE_INVALID(channel));
}
return (status);
}
/*
* npi_txdma_mbox_config():
* This function is called to config the mailbox address
*
* Parameters:
* handle - NPI handle (virtualization flag must be defined
* if its register pointer is from the virtual region).
* channel - logical TXDMA channel from 0 to 23.
* (If virtualization flag is not set, then
* logical channel is the same as the hardware
* channel number).
* op_mode - OP_GET: get the mailbox address
* OP_SET: set the mailbox address
* reg_data - pointer to the mailbox address.
* Return:
* NPI_SUCCESS - If set is complete successfully.
*
* Error:
* NPI_FAILURE -
* NPI_TXDMA_OPCODE_INVALID -
* NPI_TXDMA_CHANNEL_INVALID -
*/
npi_status_t
npi_txdma_mbox_config(npi_handle_t handle, io_op_t op_mode,
uint8_t channel, uint64_t *mbox_addr)
{
int status = NPI_SUCCESS;
txdma_mbh_t mh;
txdma_mbl_t ml;
ASSERT(TXDMA_CHANNEL_VALID(channel));
if (!TXDMA_CHANNEL_VALID(channel)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_mbox_config"
" Invalid Input: channel <0x%x>",
channel));
return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
}
mh.value = ml.value = 0;
switch (op_mode) {
case OP_GET:
TXDMA_REG_READ64(handle, TXDMA_MBH_REG, channel, &mh.value);
TXDMA_REG_READ64(handle, TXDMA_MBL_REG, channel, &ml.value);
*mbox_addr = ml.value;
*mbox_addr |= (mh.value << TXDMA_MBH_ADDR_SHIFT);
break;
case OP_SET:
ml.bits.ldw.mbaddr = ((*mbox_addr & TXDMA_MBL_MASK) >>
TXDMA_MBL_SHIFT);
TXDMA_REG_WRITE64(handle, TXDMA_MBL_REG, channel, ml.value);
mh.bits.ldw.mbaddr = ((*mbox_addr >> TXDMA_MBH_ADDR_SHIFT) &
TXDMA_MBH_MASK);
TXDMA_REG_WRITE64(handle, TXDMA_MBH_REG, channel, mh.value);
break;
default:
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_mbox_config"
" Invalid Input: mbox <0x%x>",
op_mode));
return (NPI_FAILURE | NPI_TXDMA_OPCODE_INVALID(channel));
}
return (status);
}
/*
* npi_txdma_desc_gather_set():
* This function is called to set up a transmit descriptor entry.
*
* Parameters:
* handle - NPI handle (register pointer is the
* descriptor address in memory).
* desc_p - pointer to a descriptor
* gather_index - which entry (starts from index 0 to 15)
* mark - mark bit (only valid if it is the first gather).
* ngathers - number of gather pointers to set to the first gather.
* dma_ioaddr - starting dma address of an IO buffer to write.
* (SAD)
* transfer_len - transfer len.
* Return:
* NPI_SUCCESS - If set is complete successfully.
*
* Error:
* NPI_FAILURE -
* NPI_TXDMA_OPCODE_INVALID -
* NPI_TXDMA_CHANNEL_INVALID -
* NPI_TXDMA_XFER_LEN_INVALID -
*/
npi_status_t
npi_txdma_desc_gather_set(npi_handle_t handle,
p_tx_desc_t desc_p, uint8_t gather_index,
boolean_t mark, uint8_t ngathers,
uint64_t dma_ioaddr, uint32_t transfer_len)
{
int status;
status = NPI_TXDMA_GATHER_INDEX(gather_index);
if (status) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_desc_gather_set"
" Invalid Input: gather_index <0x%x>",
gather_index));
return (status);
}
if (transfer_len > TX_MAX_TRANSFER_LENGTH) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_desc_gather_set"
" Invalid Input: tr_len <0x%x>",
transfer_len));
return (NPI_FAILURE | NPI_TXDMA_XFER_LEN_INVALID);
}
if (gather_index == 0) {
desc_p->bits.hdw.sop = 1;
desc_p->bits.hdw.mark = mark;
desc_p->bits.hdw.num_ptr = ngathers;
NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL,
"npi_txdma_gather_set: SOP len %d (%d)",
desc_p->bits.hdw.tr_len, transfer_len));
}
desc_p->bits.hdw.tr_len = transfer_len;
desc_p->bits.hdw.sad = dma_ioaddr >> 32;
desc_p->bits.ldw.sad = dma_ioaddr & 0xffffffff;
NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL,
"npi_txdma_gather_set: xfer len %d to set (%d)",
desc_p->bits.hdw.tr_len, transfer_len));
NXGE_MEM_PIO_WRITE64(handle, desc_p->value);
return (status);
}
/*
* npi_txdma_desc_sop_set():
* This function is called to set up the first gather entry.
*
* Parameters:
* handle - NPI handle (register pointer is the
* descriptor address in memory).
* desc_p - pointer to a descriptor
* mark - mark bit (only valid if it is the first gather).
* ngathers - number of gather pointers to set to the first gather.
* Return:
* NPI_SUCCESS - If set is complete successfully.
*
* Error:
*/
npi_status_t
npi_txdma_desc_gather_sop_set(npi_handle_t handle,
p_tx_desc_t desc_p,
boolean_t mark_mode,
uint8_t ngathers)
{
int status = NPI_SUCCESS;
desc_p->bits.hdw.sop = 1;
desc_p->bits.hdw.mark = mark_mode;
desc_p->bits.hdw.num_ptr = ngathers;
NXGE_MEM_PIO_WRITE64(handle, desc_p->value);
return (status);
}
npi_status_t
npi_txdma_desc_gather_sop_set_1(npi_handle_t handle,
p_tx_desc_t desc_p,
boolean_t mark_mode,
uint8_t ngathers,
uint32_t extra)
{
int status = NPI_SUCCESS;
desc_p->bits.hdw.sop = 1;
desc_p->bits.hdw.mark = mark_mode;
desc_p->bits.hdw.num_ptr = ngathers;
desc_p->bits.hdw.tr_len += extra;
NXGE_MEM_PIO_WRITE64(handle, desc_p->value);
return (status);
}
npi_status_t
npi_txdma_desc_set_xfer_len(npi_handle_t handle,
p_tx_desc_t desc_p,
uint32_t transfer_len)
{
int status = NPI_SUCCESS;
desc_p->bits.hdw.tr_len = transfer_len;
NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL,
"npi_set_xfer_len: len %d (%d)",
desc_p->bits.hdw.tr_len, transfer_len));
NXGE_MEM_PIO_WRITE64(handle, desc_p->value);
return (status);
}
npi_status_t
npi_txdma_desc_set_zero(npi_handle_t handle, uint16_t entries)
{
uint32_t offset;
int i;
/*
* Assume no wrapped around.
*/
offset = 0;
for (i = 0; i < entries; i++) {
NXGE_REG_WR64(handle, offset, 0);
offset += (i * TXDMA_DESC_SIZE);
}
return (NPI_SUCCESS);
}
npi_status_t
npi_txdma_desc_mem_get(npi_handle_t handle, uint16_t index,
p_tx_desc_t desc_p)
{
int status = NPI_SUCCESS;
npi_txdma_dump_desc_one(handle, desc_p, index);
return (status);
}
/*
* npi_txdma_desc_kick_reg_set():
* This function is called to kick the transmit to start transmission.
*
* Parameters:
* handle - NPI handle (virtualization flag must be defined).
* channel - logical TXDMA channel from 0 to 23.
* (If virtualization flag is not set, then
* logical channel is the same as the hardware
* channel number).
* tail_index - index into the transmit descriptor
* wrap - toggle bit to indicate if the tail index is
* wrapped around.
*
* Return:
* NPI_SUCCESS - If set is complete successfully.
*
* Error:
* NPI_FAILURE -
* NPI_TXDMA_CHANNEL_INVALID -
*/
npi_status_t
npi_txdma_desc_kick_reg_set(npi_handle_t handle, uint8_t channel,
uint16_t tail_index, boolean_t wrap)
{
int status = NPI_SUCCESS;
tx_ring_kick_t kick;
ASSERT(TXDMA_CHANNEL_VALID(channel));
if (!TXDMA_CHANNEL_VALID(channel)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_desc_kick_reg_set"
" Invalid Input: channel <0x%x>",
channel));
return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
}
NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL,
" npi_txdma_desc_kick_reg_set: "
" KICKING channel %d",
channel));
/* Toggle the wrap around bit */
kick.value = 0;
kick.bits.ldw.wrap = wrap;
kick.bits.ldw.tail = tail_index;
/* Kick start the Transmit kick register */
TXDMA_REG_WRITE64(handle, TX_RING_KICK_REG, channel, kick.value);
return (status);
}
/*
* npi_txdma_desc_kick_reg_get():
* This function is called to kick the transmit to start transmission.
*
* Parameters:
* handle - NPI handle (virtualization flag must be defined).
* channel - logical TXDMA channel from 0 to 23.
* (If virtualization flag is not set, then
* logical channel is the same as the hardware
* channel number).
* tail_index - index into the transmit descriptor
* wrap - toggle bit to indicate if the tail index is
* wrapped around.
*
* Return:
* NPI_SUCCESS - If get is complete successfully.
*
* Error:
* NPI_FAILURE -
* NPI_TXDMA_CHANNEL_INVALID -
*/
npi_status_t
npi_txdma_desc_kick_reg_get(npi_handle_t handle, uint8_t channel,
p_tx_ring_kick_t kick_p)
{
int status = NPI_SUCCESS;
ASSERT(TXDMA_CHANNEL_VALID(channel));
if (!TXDMA_CHANNEL_VALID(channel)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_desc_kick_reg_get"
" Invalid Input: channel <0x%x>",
channel));
return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
}
TXDMA_REG_READ64(handle, TX_RING_KICK_REG, channel, &kick_p->value);
return (status);
}
/*
* npi_txdma_ring_head_get():
* This function is called to get the transmit ring head index.
*
* Parameters:
* handle - NPI handle (virtualization flag must be defined).
* channel - logical TXDMA channel from 0 to 23.
* (If virtualization flag is not set, then
* logical channel is the same as the hardware
* channel number).
* hdl_p - pointer to the hardware defined transmit
* ring header data (head index and wrap bit).
*
* Return:
* NPI_SUCCESS - If get is complete successfully.
*
* Error:
* NPI_FAILURE -
* NPI_TXDMA_CHANNEL_INVALID -
*/
npi_status_t
npi_txdma_ring_head_get(npi_handle_t handle, uint8_t channel,
p_tx_ring_hdl_t hdl_p)
{
int status = NPI_SUCCESS;
ASSERT(TXDMA_CHANNEL_VALID(channel));
if (!TXDMA_CHANNEL_VALID(channel)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_ring_head_get"
" Invalid Input: channel <0x%x>",
channel));
return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
}
TXDMA_REG_READ64(handle, TX_RING_HDL_REG, channel, &hdl_p->value);
return (status);
}
/*ARGSUSED*/
npi_status_t
npi_txdma_channel_mbox_get(npi_handle_t handle, uint8_t channel,
p_txdma_mailbox_t mbox_p)
{
int status = NPI_SUCCESS;
return (status);
}
npi_status_t
npi_txdma_channel_pre_state_get(npi_handle_t handle, uint8_t channel,
p_tx_dma_pre_st_t prep)
{
int status = NPI_SUCCESS;
ASSERT(TXDMA_CHANNEL_VALID(channel));
if (!TXDMA_CHANNEL_VALID(channel)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_channel_pre_state_get"
" Invalid Input: channel <0x%x>",
channel));
return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
}
TXDMA_REG_READ64(handle, TX_DMA_PRE_ST_REG, channel, &prep->value);
return (status);
}
npi_status_t
npi_txdma_ring_error_get(npi_handle_t handle, uint8_t channel,
p_txdma_ring_errlog_t ring_errlog_p)
{
tx_rng_err_logh_t logh;
tx_rng_err_logl_t logl;
int status = NPI_SUCCESS;
ASSERT(TXDMA_CHANNEL_VALID(channel));
if (!TXDMA_CHANNEL_VALID(channel)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_ring_error_get"
" Invalid Input: channel <0x%x>",
channel));
return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
}
logh.value = 0;
TXDMA_REG_READ64(handle, TX_RNG_ERR_LOGH_REG, channel, &logh.value);
TXDMA_REG_READ64(handle, TX_RNG_ERR_LOGL_REG, channel, &logl.value);
ring_errlog_p->logh.bits.ldw.err = logh.bits.ldw.err;
ring_errlog_p->logh.bits.ldw.merr = logh.bits.ldw.merr;
ring_errlog_p->logh.bits.ldw.errcode = logh.bits.ldw.errcode;
ring_errlog_p->logh.bits.ldw.err_addr = logh.bits.ldw.err_addr;
ring_errlog_p->logl.bits.ldw.err_addr = logl.bits.ldw.err_addr;
return (status);
}
npi_status_t
npi_txdma_inj_par_error_clear(npi_handle_t handle)
{
NXGE_REG_WR64(handle, TDMC_INJ_PAR_ERR_REG, 0);
return (NPI_SUCCESS);
}
npi_status_t
npi_txdma_inj_par_error_set(npi_handle_t handle, uint32_t err_bits)
{
tdmc_inj_par_err_t inj;
inj.value = 0;
inj.bits.ldw.inject_parity_error = (err_bits & TDMC_INJ_PAR_ERR_MASK);
NXGE_REG_WR64(handle, TDMC_INJ_PAR_ERR_REG, inj.value);
return (NPI_SUCCESS);
}
npi_status_t
npi_txdma_inj_par_error_update(npi_handle_t handle, uint32_t err_bits)
{
tdmc_inj_par_err_t inj;
inj.value = 0;
NXGE_REG_RD64(handle, TDMC_INJ_PAR_ERR_REG, &inj.value);
inj.value |= (err_bits & TDMC_INJ_PAR_ERR_MASK);
NXGE_REG_WR64(handle, TDMC_INJ_PAR_ERR_REG, inj.value);
return (NPI_SUCCESS);
}
npi_status_t
npi_txdma_inj_par_error_get(npi_handle_t handle, uint32_t *err_bits)
{
tdmc_inj_par_err_t inj;
inj.value = 0;
NXGE_REG_RD64(handle, TDMC_INJ_PAR_ERR_REG, &inj.value);
*err_bits = (inj.value & TDMC_INJ_PAR_ERR_MASK);
return (NPI_SUCCESS);
}
npi_status_t
npi_txdma_dbg_sel_set(npi_handle_t handle, uint8_t dbg_sel)
{
tdmc_dbg_sel_t dbg;
dbg.value = 0;
dbg.bits.ldw.dbg_sel = (dbg_sel & TDMC_DBG_SEL_MASK);
NXGE_REG_WR64(handle, TDMC_DBG_SEL_REG, dbg.value);
return (NPI_SUCCESS);
}
npi_status_t
npi_txdma_training_vector_set(npi_handle_t handle, uint32_t training_vector)
{
tdmc_training_t vec;
vec.value = 0;
vec.bits.ldw.vec = training_vector;
NXGE_REG_WR64(handle, TDMC_TRAINING_REG, vec.value);
return (NPI_SUCCESS);
}
/*
* npi_txdma_dump_desc_one(npi_handle_t handle, p_tx_desc_t desc_p,
* int desc_index)
*
* Dumps the contents of transmit descriptors.
*
* Parameters:
* handle - NPI handle (register pointer is the
* descriptor address in memory).
* desc_p - pointer to place the descriptor contents
* desc_index - descriptor index
*
*/
/*ARGSUSED*/
void
npi_txdma_dump_desc_one(npi_handle_t handle, p_tx_desc_t desc_p, int desc_index)
{
tx_desc_t desc, *desp;
#ifdef NXGE_DEBUG
uint64_t sad;
int xfer_len;
#endif
NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL,
"\n==> npi_txdma_dump_desc_one: dump "
" desc_p $%p descriptor entry %d\n",
desc_p, desc_index));
desc.value = 0;
desp = ((desc_p != NULL) ? desc_p : (p_tx_desc_t)&desc);
desp->value = NXGE_MEM_PIO_READ64(handle);
#ifdef NXGE_DEBUG
sad = (desp->value & TX_PKT_DESC_SAD_MASK);
xfer_len = ((desp->value & TX_PKT_DESC_TR_LEN_MASK) >>
TX_PKT_DESC_TR_LEN_SHIFT);
#endif
NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL, "\n\t: value 0x%llx\n"
"\t\tsad $%p\ttr_len %d len %d\tnptrs %d\tmark %d sop %d\n",
desp->value,
sad,
desp->bits.hdw.tr_len,
xfer_len,
desp->bits.hdw.num_ptr,
desp->bits.hdw.mark,
desp->bits.hdw.sop));
NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL,
"\n<== npi_txdma_dump_desc_one: Done \n"));
}
/*ARGSUSED*/
void
npi_txdma_dump_hdr(npi_handle_t handle, p_tx_pkt_header_t hdrp)
{
NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL,
"\n==> npi_txdma_dump_hdr: dump\n"));
NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL,
"\n\t: value 0x%llx\n"
"\t\tpkttype 0x%x\tip_ver %d\tllc %d\tvlan %d \tihl %d\n"
"\t\tl3start %d\tl4start %d\tl4stuff %d\n"
"\t\txferlen %d\tpad %d\n",
hdrp->value,
hdrp->bits.hdw.cksum_en_pkt_type,
hdrp->bits.hdw.ip_ver,
hdrp->bits.hdw.llc,
hdrp->bits.hdw.vlan,
hdrp->bits.hdw.ihl,
hdrp->bits.hdw.l3start,
hdrp->bits.hdw.l4start,
hdrp->bits.hdw.l4stuff,
hdrp->bits.ldw.tot_xfer_len,
hdrp->bits.ldw.pad));
NPI_DEBUG_MSG((handle.function, NPI_TDC_CTL,
"\n<== npi_txdma_dump_hdr: Done \n"));
}
npi_status_t
npi_txdma_inj_int_error_set(npi_handle_t handle, uint8_t channel,
p_tdmc_intr_dbg_t erp)
{
int status = NPI_SUCCESS;
ASSERT(TXDMA_CHANNEL_VALID(channel));
if (!TXDMA_CHANNEL_VALID(channel)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_txdma_inj_int_error_set"
" Invalid Input: channel <0x%x>",
channel));
return (NPI_FAILURE | NPI_TXDMA_CHANNEL_INVALID(channel));
}
TXDMA_REG_WRITE64(handle, TDMC_INTR_DBG_REG, channel, erp->value);
return (status);
}
/*
* Static functions start here.
*/
static npi_status_t
npi_txdma_control_reset_wait(npi_handle_t handle, uint8_t channel)
{
tx_cs_t txcs;
int loop = 0;
do {
NXGE_DELAY(TXDMA_WAIT_MSEC);
TXDMA_REG_READ64(handle, TX_CS_REG, channel, &txcs.value);
if (!txcs.bits.ldw.rst) {
return (NPI_SUCCESS);
}
loop++;
} while (loop < TXDMA_WAIT_LOOP);
if (loop == TXDMA_WAIT_LOOP) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
"npi_txdma_control_reset_wait: RST bit not "
"cleared to 0 txcs.bits 0x%llx", txcs.value));
return (NPI_FAILURE | NPI_TXDMA_RESET_FAILED);
}
return (NPI_SUCCESS);
}
static npi_status_t
npi_txdma_control_stop_wait(npi_handle_t handle, uint8_t channel)
{
tx_cs_t txcs;
int loop = 0;
do {
NXGE_DELAY(TXDMA_WAIT_MSEC);
TXDMA_REG_READ64(handle, TX_CS_REG, channel, &txcs.value);
if (txcs.bits.ldw.sng_state) {
return (NPI_SUCCESS);
}
loop++;
} while (loop < TXDMA_WAIT_LOOP);
if (loop == TXDMA_WAIT_LOOP) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
"npi_txdma_control_stop_wait: SNG_STATE not "
"set to 1 txcs.bits 0x%llx", txcs.value));
return (NPI_FAILURE | NPI_TXDMA_STOP_FAILED);
}
return (NPI_SUCCESS);
}
static npi_status_t
npi_txdma_control_resume_wait(npi_handle_t handle, uint8_t channel)
{
tx_cs_t txcs;
int loop = 0;
do {
NXGE_DELAY(TXDMA_WAIT_MSEC);
TXDMA_REG_READ64(handle, TX_CS_REG, channel, &txcs.value);
if (!txcs.bits.ldw.sng_state) {
return (NPI_SUCCESS);
}
loop++;
} while (loop < TXDMA_WAIT_LOOP);
if (loop == TXDMA_WAIT_LOOP) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
"npi_txdma_control_resume_wait: sng_state not "
"set to 0 txcs.bits 0x%llx", txcs.value));
return (NPI_FAILURE | NPI_TXDMA_RESUME_FAILED);
}
return (NPI_SUCCESS);
}