/* * 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 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #define RXDMA_RESET_TRY_COUNT 4 #define RXDMA_RESET_DELAY 5 #define RXDMA_OP_DISABLE 0 #define RXDMA_OP_ENABLE 1 #define RXDMA_OP_RESET 2 #define RCR_TIMEOUT_ENABLE 1 #define RCR_TIMEOUT_DISABLE 2 #define RCR_THRESHOLD 4 /* assume weight is in byte frames unit */ #define WEIGHT_FACTOR 3/2 uint64_t rdc_dmc_offset[] = { RXDMA_CFIG1_REG, RXDMA_CFIG2_REG, RBR_CFIG_A_REG, RBR_CFIG_B_REG, RBR_KICK_REG, RBR_STAT_REG, RBR_HDH_REG, RBR_HDL_REG, RCRCFIG_A_REG, RCRCFIG_B_REG, RCRSTAT_A_REG, RCRSTAT_B_REG, RCRSTAT_C_REG, RX_DMA_ENT_MSK_REG, RX_DMA_CTL_STAT_REG, RCR_FLSH_REG, RXMISC_DISCARD_REG }; const char *rdc_dmc_name[] = { "RXDMA_CFIG1", "RXDMA_CFIG2", "RBR_CFIG_A", "RBR_CFIG_B", "RBR_KICK", "RBR_STAT", "RBR_HDH", "RBR_HDL", "RCRCFIG_A", "RCRCFIG_B", "RCRSTAT_A", "RCRSTAT_B", "RCRSTAT_C", "RX_DMA_ENT_MSK", "RX_DMA_CTL_STAT", "RCR_FLSH", "RXMISC_DISCARD" }; uint64_t rdc_fzc_offset [] = { RX_LOG_PAGE_VLD_REG, RX_LOG_PAGE_MASK1_REG, RX_LOG_PAGE_VAL1_REG, RX_LOG_PAGE_MASK2_REG, RX_LOG_PAGE_VAL2_REG, RX_LOG_PAGE_RELO1_REG, RX_LOG_PAGE_RELO2_REG, RX_LOG_PAGE_HDL_REG, RDC_RED_PARA_REG, RED_DIS_CNT_REG }; const char *rdc_fzc_name [] = { "RX_LOG_PAGE_VLD", "RX_LOG_PAGE_MASK1", "RX_LOG_PAGE_VAL1", "RX_LOG_PAGE_MASK2", "RX_LOG_PAGE_VAL2", "RX_LOG_PAGE_RELO1", "RX_LOG_PAGE_RELO2", "RX_LOG_PAGE_HDL", "RDC_RED_PARA", "RED_DIS_CNT" }; /* * Dump the MEM_ADD register first so all the data registers * will have valid data buffer pointers. */ uint64_t rx_fzc_offset[] = { RX_DMA_CK_DIV_REG, DEF_PT0_RDC_REG, DEF_PT1_RDC_REG, DEF_PT2_RDC_REG, DEF_PT3_RDC_REG, RX_ADDR_MD_REG, PT_DRR_WT0_REG, PT_DRR_WT1_REG, PT_DRR_WT2_REG, PT_DRR_WT3_REG, PT_USE0_REG, PT_USE1_REG, PT_USE2_REG, PT_USE3_REG, RED_RAN_INIT_REG, RX_ADDR_MD_REG, RDMC_PRE_PAR_ERR_REG, RDMC_SHA_PAR_ERR_REG, RDMC_MEM_DATA4_REG, RDMC_MEM_DATA3_REG, RDMC_MEM_DATA2_REG, RDMC_MEM_DATA1_REG, RDMC_MEM_DATA0_REG, RDMC_MEM_ADDR_REG, RX_CTL_DAT_FIFO_STAT_REG, RX_CTL_DAT_FIFO_MASK_REG, RX_CTL_DAT_FIFO_STAT_DBG_REG, RDMC_TRAINING_VECTOR_REG, }; const char *rx_fzc_name[] = { "RX_DMA_CK_DIV", "DEF_PT0_RDC", "DEF_PT1_RDC", "DEF_PT2_RDC", "DEF_PT3_RDC", "RX_ADDR_MD", "PT_DRR_WT0", "PT_DRR_WT1", "PT_DRR_WT2", "PT_DRR_WT3", "PT_USE0", "PT_USE1", "PT_USE2", "PT_USE3", "RED_RAN_INIT", "RX_ADDR_MD", "RDMC_PRE_PAR_ERR", "RDMC_SHA_PAR_ERR", "RDMC_MEM_DATA4", "RDMC_MEM_DATA3", "RDMC_MEM_DATA2", "RDMC_MEM_DATA1", "RDMC_MEM_DATA0", "RDMC_MEM_ADDR", "RX_CTL_DAT_FIFO_STAT", "RX_CTL_DAT_FIFO_MASK", "RDMC_TRAINING_VECTOR_REG", "RX_CTL_DAT_FIFO_STAT_DBG_REG" }; npi_status_t npi_rxdma_cfg_rdc_ctl(npi_handle_t handle, uint8_t rdc, uint8_t op); npi_status_t npi_rxdma_cfg_rdc_rcr_ctl(npi_handle_t handle, uint8_t rdc, uint8_t op, uint16_t param); /* * npi_rxdma_dump_rdc_regs * Dumps the contents of rdc csrs and fzc registers * * Input: * handle: opaque handle interpreted by the underlying OS * rdc: RX DMA number * * return: * NPI_SUCCESS * NPI_RXDMA_RDC_INVALID * */ npi_status_t npi_rxdma_dump_rdc_regs(npi_handle_t handle, uint8_t rdc) { uint64_t value, offset; int num_regs, i; #ifdef NPI_DEBUG extern uint64_t npi_debug_level; uint64_t old_npi_debug_level = npi_debug_level; #endif ASSERT(RXDMA_CHANNEL_VALID(rdc)); if (!RXDMA_CHANNEL_VALID(rdc)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, "npi_rxdma_dump_rdc_regs" " Illegal RDC number %d \n", rdc)); return (NPI_RXDMA_RDC_INVALID); } #ifdef NPI_DEBUG npi_debug_level |= DUMP_ALWAYS; #endif num_regs = sizeof (rdc_dmc_offset) / sizeof (uint64_t); NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, "\nDMC Register Dump for Channel %d\n", rdc)); for (i = 0; i < num_regs; i++) { RXDMA_REG_READ64(handle, rdc_dmc_offset[i], rdc, &value); offset = NXGE_RXDMA_OFFSET(rdc_dmc_offset[i], handle.is_vraddr, rdc); NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, "%08llx %s\t %08llx \n", offset, rdc_dmc_name[i], value)); } NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, "\n Register Dump for Channel %d done\n", rdc)); #ifdef NPI_DEBUG npi_debug_level = old_npi_debug_level; #endif return (NPI_SUCCESS); } /* * npi_rxdma_dump_fzc_regs * Dumps the contents of rdc csrs and fzc registers * * Input: * handle: opaque handle interpreted by the underlying OS * * return: * NPI_SUCCESS */ npi_status_t npi_rxdma_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 = sizeof (rx_fzc_offset) / sizeof (uint64_t); for (i = 0; i < num_regs; i++) { NXGE_REG_RD64(handle, rx_fzc_offset[i], &value); NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, "0x%08llx %s\t 0x%08llx \n", rx_fzc_offset[i], rx_fzc_name[i], value)); } NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, "\n FZC_DMC Register Dump Done \n")); return (NPI_SUCCESS); } /* * per rdc config functions */ npi_status_t npi_rxdma_cfg_logical_page_disable(npi_handle_t handle, uint8_t rdc, uint8_t page_num) { log_page_vld_t page_vld; uint64_t valid_offset; ASSERT(RXDMA_CHANNEL_VALID(rdc)); if (!RXDMA_CHANNEL_VALID(rdc)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, "rxdma_cfg_logical_page_disable" " Illegal RDC number %d \n", rdc)); return (NPI_RXDMA_RDC_INVALID); } ASSERT(RXDMA_PAGE_VALID(page_num)); if (!RXDMA_PAGE_VALID(page_num)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, "rxdma_cfg_logical_page_disable" " Illegal page number %d \n", page_num)); return (NPI_RXDMA_PAGE_INVALID); } valid_offset = REG_FZC_RDC_OFFSET(RX_LOG_PAGE_VLD_REG, rdc); NXGE_REG_RD64(handle, valid_offset, &page_vld.value); if (page_num == 0) page_vld.bits.ldw.page0 = 0; if (page_num == 1) page_vld.bits.ldw.page1 = 0; NXGE_REG_WR64(handle, valid_offset, page_vld.value); return (NPI_SUCCESS); } npi_status_t npi_rxdma_cfg_logical_page(npi_handle_t handle, uint8_t rdc, dma_log_page_t *pg_cfg) { log_page_vld_t page_vld; log_page_mask_t page_mask; log_page_value_t page_value; log_page_relo_t page_reloc; uint64_t value_offset, reloc_offset, mask_offset; uint64_t valid_offset; value_offset = 0; reloc_offset = 0; mask_offset = 0; ASSERT(RXDMA_CHANNEL_VALID(rdc)); if (!RXDMA_CHANNEL_VALID(rdc)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " rxdma_cfg_logical_page" " Illegal RDC number %d \n", rdc)); return (NPI_RXDMA_RDC_INVALID); } ASSERT(RXDMA_PAGE_VALID(pg_cfg->page_num)); if (!RXDMA_PAGE_VALID(pg_cfg->page_num)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " rxdma_cfg_logical_page" " Illegal page number %d \n", pg_cfg->page_num)); return (NPI_RXDMA_PAGE_INVALID); } valid_offset = REG_FZC_RDC_OFFSET(RX_LOG_PAGE_VLD_REG, rdc); NXGE_REG_RD64(handle, valid_offset, &page_vld.value); if (!pg_cfg->valid) { if (pg_cfg->page_num == 0) page_vld.bits.ldw.page0 = 0; if (pg_cfg->page_num == 1) page_vld.bits.ldw.page1 = 0; NXGE_REG_WR64(handle, valid_offset, page_vld.value); return (NPI_SUCCESS); } if (pg_cfg->page_num == 0) { mask_offset = REG_FZC_RDC_OFFSET(RX_LOG_PAGE_MASK1_REG, rdc); value_offset = REG_FZC_RDC_OFFSET(RX_LOG_PAGE_VAL1_REG, rdc); reloc_offset = REG_FZC_RDC_OFFSET(RX_LOG_PAGE_RELO1_REG, rdc); page_vld.bits.ldw.page0 = 1; } if (pg_cfg->page_num == 1) { mask_offset = REG_FZC_RDC_OFFSET(RX_LOG_PAGE_MASK2_REG, rdc); value_offset = REG_FZC_RDC_OFFSET(RX_LOG_PAGE_VAL2_REG, rdc); reloc_offset = REG_FZC_RDC_OFFSET(RX_LOG_PAGE_RELO2_REG, rdc); page_vld.bits.ldw.page1 = 1; } page_vld.bits.ldw.func = pg_cfg->func_num; page_mask.value = 0; page_value.value = 0; page_reloc.value = 0; page_mask.bits.ldw.mask = pg_cfg->mask >> LOG_PAGE_ADDR_SHIFT; page_value.bits.ldw.value = pg_cfg->value >> LOG_PAGE_ADDR_SHIFT; page_reloc.bits.ldw.relo = pg_cfg->reloc >> LOG_PAGE_ADDR_SHIFT; NXGE_REG_WR64(handle, mask_offset, page_mask.value); NXGE_REG_WR64(handle, value_offset, page_value.value); NXGE_REG_WR64(handle, reloc_offset, page_reloc.value); /* enable the logical page */ NXGE_REG_WR64(handle, valid_offset, page_vld.value); return (NPI_SUCCESS); } npi_status_t npi_rxdma_cfg_logical_page_handle(npi_handle_t handle, uint8_t rdc, uint64_t page_handle) { uint64_t offset; log_page_hdl_t page_hdl; ASSERT(RXDMA_CHANNEL_VALID(rdc)); if (!RXDMA_CHANNEL_VALID(rdc)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, "rxdma_cfg_logical_page_handle" " Illegal RDC number %d \n", rdc)); return (NPI_RXDMA_RDC_INVALID); } page_hdl.value = 0; page_hdl.bits.ldw.handle = (uint32_t)page_handle; offset = REG_FZC_RDC_OFFSET(RX_LOG_PAGE_HDL_REG, rdc); NXGE_REG_WR64(handle, offset, page_hdl.value); return (NPI_SUCCESS); } /* * RX DMA functions */ npi_status_t npi_rxdma_cfg_rdc_ctl(npi_handle_t handle, uint8_t rdc, uint8_t op) { rxdma_cfig1_t cfg; uint32_t count = RXDMA_RESET_TRY_COUNT; uint32_t delay_time = RXDMA_RESET_DELAY; uint32_t error = NPI_RXDMA_ERROR_ENCODE(NPI_RXDMA_RESET_ERR, rdc); ASSERT(RXDMA_CHANNEL_VALID(rdc)); if (!RXDMA_CHANNEL_VALID(rdc)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, "npi_rxdma_cfg_rdc_ctl" " Illegal RDC number %d \n", rdc)); return (NPI_RXDMA_RDC_INVALID); } switch (op) { case RXDMA_OP_ENABLE: RXDMA_REG_READ64(handle, RXDMA_CFIG1_REG, rdc, &cfg.value); cfg.bits.ldw.en = 1; RXDMA_REG_WRITE64(handle, RXDMA_CFIG1_REG, rdc, cfg.value); NXGE_DELAY(delay_time); RXDMA_REG_READ64(handle, RXDMA_CFIG1_REG, rdc, &cfg.value); while ((count--) && (cfg.bits.ldw.qst == 0)) { NXGE_DELAY(delay_time); RXDMA_REG_READ64(handle, RXDMA_CFIG1_REG, rdc, &cfg.value); } if (cfg.bits.ldw.qst == 0) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " npi_rxdma_cfg_rdc_ctl" " RXDMA_OP_ENABLE Failed for RDC %d \n", rdc)); return (error); } break; case RXDMA_OP_DISABLE: RXDMA_REG_READ64(handle, RXDMA_CFIG1_REG, rdc, &cfg.value); cfg.bits.ldw.en = 0; RXDMA_REG_WRITE64(handle, RXDMA_CFIG1_REG, rdc, cfg.value); NXGE_DELAY(delay_time); RXDMA_REG_READ64(handle, RXDMA_CFIG1_REG, rdc, &cfg.value); while ((count--) && (cfg.bits.ldw.qst == 0)) { NXGE_DELAY(delay_time); RXDMA_REG_READ64(handle, RXDMA_CFIG1_REG, rdc, &cfg.value); } if (cfg.bits.ldw.qst == 0) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " npi_rxdma_cfg_rdc_ctl" " RXDMA_OP_DISABLE Failed for RDC %d \n", rdc)); return (error); } break; case RXDMA_OP_RESET: cfg.value = 0; cfg.bits.ldw.rst = 1; RXDMA_REG_WRITE64(handle, RXDMA_CFIG1_REG, rdc, cfg.value); NXGE_DELAY(delay_time); RXDMA_REG_READ64(handle, RXDMA_CFIG1_REG, rdc, &cfg.value); while ((count--) && (cfg.bits.ldw.rst)) { NXGE_DELAY(delay_time); RXDMA_REG_READ64(handle, RXDMA_CFIG1_REG, rdc, &cfg.value); } if (count == 0) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " npi_rxdma_cfg_rdc_ctl" " Reset Failed for RDC %d \n", rdc)); return (error); } break; default: return (NPI_RXDMA_SW_PARAM_ERROR); } return (NPI_SUCCESS); } npi_status_t npi_rxdma_cfg_rdc_enable(npi_handle_t handle, uint8_t rdc) { return (npi_rxdma_cfg_rdc_ctl(handle, rdc, RXDMA_OP_ENABLE)); } npi_status_t npi_rxdma_cfg_rdc_disable(npi_handle_t handle, uint8_t rdc) { return (npi_rxdma_cfg_rdc_ctl(handle, rdc, RXDMA_OP_DISABLE)); } npi_status_t npi_rxdma_cfg_rdc_reset(npi_handle_t handle, uint8_t rdc) { return (npi_rxdma_cfg_rdc_ctl(handle, rdc, RXDMA_OP_RESET)); } /* * npi_rxdma_cfg_default_port_rdc() * Set the default rdc for the port * * Inputs: * handle: register handle interpreted by the underlying OS * portnm: Physical Port Number * rdc: RX DMA Channel number * * Return: * NPI_SUCCESS * NPI_RXDMA_RDC_INVALID * NPI_RXDMA_PORT_INVALID * */ npi_status_t npi_rxdma_cfg_default_port_rdc(npi_handle_t handle, uint8_t portnm, uint8_t rdc) { uint64_t offset; def_pt_rdc_t cfg; ASSERT(RXDMA_CHANNEL_VALID(rdc)); if (!RXDMA_CHANNEL_VALID(rdc)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, "rxdma_cfg_default_port_rdc" " Illegal RDC number %d \n", rdc)); return (NPI_RXDMA_RDC_INVALID); } ASSERT(RXDMA_PORT_VALID(portnm)); if (!RXDMA_PORT_VALID(portnm)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, "rxdma_cfg_default_port_rdc" " Illegal Port number %d \n", portnm)); return (NPI_RXDMA_PORT_INVALID); } offset = DEF_PT_RDC_REG(portnm); cfg.value = 0; cfg.bits.ldw.rdc = rdc; NXGE_REG_WR64(handle, offset, cfg.value); return (NPI_SUCCESS); } npi_status_t npi_rxdma_cfg_rdc_rcr_ctl(npi_handle_t handle, uint8_t rdc, uint8_t op, uint16_t param) { rcrcfig_b_t rcr_cfgb; ASSERT(RXDMA_CHANNEL_VALID(rdc)); if (!RXDMA_CHANNEL_VALID(rdc)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, "rxdma_cfg_rdc_rcr_ctl" " Illegal RDC number %d \n", rdc)); return (NPI_RXDMA_RDC_INVALID); } RXDMA_REG_READ64(handle, RCRCFIG_B_REG, rdc, &rcr_cfgb.value); switch (op) { case RCR_TIMEOUT_ENABLE: rcr_cfgb.bits.ldw.timeout = (uint8_t)param; rcr_cfgb.bits.ldw.entout = 1; break; case RCR_THRESHOLD: rcr_cfgb.bits.ldw.pthres = param; break; case RCR_TIMEOUT_DISABLE: rcr_cfgb.bits.ldw.entout = 0; break; default: NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, "rxdma_cfg_rdc_rcr_ctl" " Illegal opcode %x \n", op)); return (NPI_RXDMA_OPCODE_INVALID(rdc)); } RXDMA_REG_WRITE64(handle, RCRCFIG_B_REG, rdc, rcr_cfgb.value); return (NPI_SUCCESS); } npi_status_t npi_rxdma_cfg_rdc_rcr_timeout_disable(npi_handle_t handle, uint8_t rdc) { return (npi_rxdma_cfg_rdc_rcr_ctl(handle, rdc, RCR_TIMEOUT_DISABLE, 0)); } npi_status_t npi_rxdma_cfg_rdc_rcr_threshold(npi_handle_t handle, uint8_t rdc, uint16_t rcr_threshold) { return (npi_rxdma_cfg_rdc_rcr_ctl(handle, rdc, RCR_THRESHOLD, rcr_threshold)); } npi_status_t npi_rxdma_cfg_rdc_rcr_timeout(npi_handle_t handle, uint8_t rdc, uint8_t rcr_timeout) { return (npi_rxdma_cfg_rdc_rcr_ctl(handle, rdc, RCR_TIMEOUT_ENABLE, rcr_timeout)); } /* * npi_rxdma_cfg_rdc_ring() * Configure The RDC channel Rcv Buffer Ring */ npi_status_t npi_rxdma_cfg_rdc_ring(npi_handle_t handle, uint8_t rdc, rdc_desc_cfg_t *rdc_desc_cfg, boolean_t new_off) { rbr_cfig_a_t cfga; rbr_cfig_b_t cfgb; rxdma_cfig1_t cfg1; rxdma_cfig2_t cfg2; rcrcfig_a_t rcr_cfga; rcrcfig_b_t rcr_cfgb; ASSERT(RXDMA_CHANNEL_VALID(rdc)); if (!RXDMA_CHANNEL_VALID(rdc)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, "rxdma_cfg_rdc_ring" " Illegal RDC number %d \n", rdc)); return (NPI_RXDMA_RDC_INVALID); } cfga.value = 0; cfgb.value = 0; cfg1.value = 0; cfg2.value = 0; if (rdc_desc_cfg->mbox_enable == 1) { cfg1.bits.ldw.mbaddr_h = (rdc_desc_cfg->mbox_addr >> 32) & 0xfff; cfg2.bits.ldw.mbaddr = ((rdc_desc_cfg->mbox_addr & RXDMA_CFIG2_MBADDR_L_MASK) >> RXDMA_CFIG2_MBADDR_L_SHIFT); /* * Only after all the configurations are set, then * enable the RDC or else configuration fatal error * will be returned (especially if the Hypervisor * set up the logical pages with non-zero values. * This NPI function only sets up the configuration. */ } if (rdc_desc_cfg->full_hdr == 1) cfg2.bits.ldw.full_hdr = 1; if (new_off) { if (RXDMA_RF_BUFF_OFFSET_VALID(rdc_desc_cfg->offset)) { switch (rdc_desc_cfg->offset) { case SW_OFFSET_NO_OFFSET: case SW_OFFSET_64: case SW_OFFSET_128: case SW_OFFSET_192: cfg2.bits.ldw.offset = rdc_desc_cfg->offset; cfg2.bits.ldw.offset256 = 0; break; case SW_OFFSET_256: case SW_OFFSET_320: case SW_OFFSET_384: case SW_OFFSET_448: cfg2.bits.ldw.offset = rdc_desc_cfg->offset & 0x3; cfg2.bits.ldw.offset256 = 1; break; default: cfg2.bits.ldw.offset = SW_OFFSET_NO_OFFSET; cfg2.bits.ldw.offset256 = 0; } } else { cfg2.bits.ldw.offset = SW_OFFSET_NO_OFFSET; cfg2.bits.ldw.offset256 = 0; } } else { if (RXDMA_BUFF_OFFSET_VALID(rdc_desc_cfg->offset)) { cfg2.bits.ldw.offset = rdc_desc_cfg->offset; } else { cfg2.bits.ldw.offset = SW_OFFSET_NO_OFFSET; } } /* rbr config */ cfga.value = (rdc_desc_cfg->rbr_addr & (RBR_CFIG_A_STDADDR_MASK | RBR_CFIG_A_STDADDR_BASE_MASK)); if ((rdc_desc_cfg->rbr_len < RBR_DEFAULT_MIN_LEN) || (rdc_desc_cfg->rbr_len > RBR_DEFAULT_MAX_LEN)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, "npi_rxdma_cfg_rdc_ring" " Illegal RBR Queue Length %d \n", rdc_desc_cfg->rbr_len)); return (NPI_RXDMA_ERROR_ENCODE(NPI_RXDMA_RBRSIZE_INVALID, rdc)); } cfga.bits.hdw.len = rdc_desc_cfg->rbr_len; NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL, "npi_rxdma_cfg_rdc_ring" " CFGA 0x%llx hdw.len %d (RBR LEN %d)\n", cfga.value, cfga.bits.hdw.len, rdc_desc_cfg->rbr_len)); if (rdc_desc_cfg->page_size == SIZE_4KB) cfgb.bits.ldw.bksize = RBR_BKSIZE_4K; else if (rdc_desc_cfg->page_size == SIZE_8KB) cfgb.bits.ldw.bksize = RBR_BKSIZE_8K; else if (rdc_desc_cfg->page_size == SIZE_16KB) cfgb.bits.ldw.bksize = RBR_BKSIZE_16K; else if (rdc_desc_cfg->page_size == SIZE_32KB) cfgb.bits.ldw.bksize = RBR_BKSIZE_32K; else { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, "rxdma_cfg_rdc_ring" " blksize: Illegal buffer size %d \n", rdc_desc_cfg->page_size)); return (NPI_RXDMA_BUFSIZE_INVALID); } if (rdc_desc_cfg->valid0) { if (rdc_desc_cfg->size0 == SIZE_256B) cfgb.bits.ldw.bufsz0 = RBR_BUFSZ0_256B; else if (rdc_desc_cfg->size0 == SIZE_512B) cfgb.bits.ldw.bufsz0 = RBR_BUFSZ0_512B; else if (rdc_desc_cfg->size0 == SIZE_1KB) cfgb.bits.ldw.bufsz0 = RBR_BUFSZ0_1K; else if (rdc_desc_cfg->size0 == SIZE_2KB) cfgb.bits.ldw.bufsz0 = RBR_BUFSZ0_2K; else { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " rxdma_cfg_rdc_ring" " blksize0: Illegal buffer size %x \n", rdc_desc_cfg->size0)); return (NPI_RXDMA_BUFSIZE_INVALID); } cfgb.bits.ldw.vld0 = 1; } else { cfgb.bits.ldw.vld0 = 0; } if (rdc_desc_cfg->valid1) { if (rdc_desc_cfg->size1 == SIZE_1KB) cfgb.bits.ldw.bufsz1 = RBR_BUFSZ1_1K; else if (rdc_desc_cfg->size1 == SIZE_2KB) cfgb.bits.ldw.bufsz1 = RBR_BUFSZ1_2K; else if (rdc_desc_cfg->size1 == SIZE_4KB) cfgb.bits.ldw.bufsz1 = RBR_BUFSZ1_4K; else if (rdc_desc_cfg->size1 == SIZE_8KB) cfgb.bits.ldw.bufsz1 = RBR_BUFSZ1_8K; else { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " rxdma_cfg_rdc_ring" " blksize1: Illegal buffer size %x \n", rdc_desc_cfg->size1)); return (NPI_RXDMA_BUFSIZE_INVALID); } cfgb.bits.ldw.vld1 = 1; } else { cfgb.bits.ldw.vld1 = 0; } if (rdc_desc_cfg->valid2) { if (rdc_desc_cfg->size2 == SIZE_2KB) cfgb.bits.ldw.bufsz2 = RBR_BUFSZ2_2K; else if (rdc_desc_cfg->size2 == SIZE_4KB) cfgb.bits.ldw.bufsz2 = RBR_BUFSZ2_4K; else if (rdc_desc_cfg->size2 == SIZE_8KB) cfgb.bits.ldw.bufsz2 = RBR_BUFSZ2_8K; else if (rdc_desc_cfg->size2 == SIZE_16KB) cfgb.bits.ldw.bufsz2 = RBR_BUFSZ2_16K; else { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " rxdma_cfg_rdc_ring" " blksize2: Illegal buffer size %x \n", rdc_desc_cfg->size2)); return (NPI_RXDMA_BUFSIZE_INVALID); } cfgb.bits.ldw.vld2 = 1; } else { cfgb.bits.ldw.vld2 = 0; } rcr_cfga.value = (rdc_desc_cfg->rcr_addr & (RCRCFIG_A_STADDR_MASK | RCRCFIG_A_STADDR_BASE_MASK)); if ((rdc_desc_cfg->rcr_len < RCR_DEFAULT_MIN_LEN) || (rdc_desc_cfg->rcr_len > NXGE_RCR_MAX)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " rxdma_cfg_rdc_ring" " Illegal RCR Queue Length %d \n", rdc_desc_cfg->rcr_len)); return (NPI_RXDMA_ERROR_ENCODE(NPI_RXDMA_RCRSIZE_INVALID, rdc)); } rcr_cfga.bits.hdw.len = rdc_desc_cfg->rcr_len; rcr_cfgb.value = 0; if (rdc_desc_cfg->rcr_timeout_enable == 1) { /* check if the rcr timeout value is valid */ if (RXDMA_RCR_TO_VALID(rdc_desc_cfg->rcr_timeout)) { rcr_cfgb.bits.ldw.timeout = rdc_desc_cfg->rcr_timeout; rcr_cfgb.bits.ldw.entout = 1; } else { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " rxdma_cfg_rdc_ring" " Illegal RCR Timeout value %d \n", rdc_desc_cfg->rcr_timeout)); rcr_cfgb.bits.ldw.entout = 0; } } else { rcr_cfgb.bits.ldw.entout = 0; } /* check if the rcr threshold value is valid */ if (RXDMA_RCR_THRESH_VALID(rdc_desc_cfg->rcr_threshold)) { rcr_cfgb.bits.ldw.pthres = rdc_desc_cfg->rcr_threshold; } else { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " rxdma_cfg_rdc_ring" " Illegal RCR Threshold value %d \n", rdc_desc_cfg->rcr_threshold)); rcr_cfgb.bits.ldw.pthres = 1; } /* now do the actual HW configuration */ RXDMA_REG_WRITE64(handle, RXDMA_CFIG1_REG, rdc, cfg1.value); RXDMA_REG_WRITE64(handle, RXDMA_CFIG2_REG, rdc, cfg2.value); RXDMA_REG_WRITE64(handle, RBR_CFIG_A_REG, rdc, cfga.value); RXDMA_REG_WRITE64(handle, RBR_CFIG_B_REG, rdc, cfgb.value); RXDMA_REG_WRITE64(handle, RCRCFIG_A_REG, rdc, rcr_cfga.value); RXDMA_REG_WRITE64(handle, RCRCFIG_B_REG, rdc, rcr_cfgb.value); return (NPI_SUCCESS); } /* * npi_rxdma_red_discard_stat_get * Gets the current discrad count due RED * The counter overflow bit is cleared, if it has been set. * * Inputs: * handle: opaque handle interpreted by the underlying OS * rdc: RX DMA Channel number * cnt: Ptr to structure to write current RDC discard stat * * Return: * NPI_SUCCESS * NPI_RXDMA_RDC_INVALID * */ npi_status_t npi_rxdma_red_discard_stat_get(npi_handle_t handle, uint8_t rdc, rx_disc_cnt_t *cnt) { uint64_t offset; ASSERT(RXDMA_CHANNEL_VALID(rdc)); if (!RXDMA_CHANNEL_VALID(rdc)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " npi_rxdma_red_discard_stat_get" " Illegal RDC Number %d \n", rdc)); return (NPI_RXDMA_RDC_INVALID); } offset = RDC_RED_RDC_DISC_REG(rdc); NXGE_REG_RD64(handle, offset, &cnt->value); if (cnt->bits.ldw.oflow) { NPI_DEBUG_MSG((handle.function, NPI_ERR_CTL, " npi_rxdma_red_discard_stat_get" " Counter overflow for channel %d ", " ..... clearing \n", rdc)); cnt->bits.ldw.oflow = 0; NXGE_REG_WR64(handle, offset, cnt->value); cnt->bits.ldw.oflow = 1; } return (NPI_SUCCESS); } /* * npi_rxdma_red_discard_oflow_clear * Clear RED discard counter overflow bit * * Inputs: * handle: opaque handle interpreted by the underlying OS * rdc: RX DMA Channel number * * Return: * NPI_SUCCESS * NPI_RXDMA_RDC_INVALID * */ npi_status_t npi_rxdma_red_discard_oflow_clear(npi_handle_t handle, uint8_t rdc) { uint64_t offset; rx_disc_cnt_t cnt; ASSERT(RXDMA_CHANNEL_VALID(rdc)); if (!RXDMA_CHANNEL_VALID(rdc)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " npi_rxdma_red_discard_oflow_clear" " Illegal RDC Number %d \n", rdc)); return (NPI_RXDMA_RDC_INVALID); } offset = RDC_RED_RDC_DISC_REG(rdc); NXGE_REG_RD64(handle, offset, &cnt.value); if (cnt.bits.ldw.oflow) { NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL, " npi_rxdma_red_discard_oflow_clear" " Counter overflow for channel %d ", " ..... clearing \n", rdc)); cnt.bits.ldw.oflow = 0; NXGE_REG_WR64(handle, offset, cnt.value); } return (NPI_SUCCESS); } /* * npi_rxdma_misc_discard_stat_get * Gets the current discrad count for the rdc due to * buffer pool empty * The counter overflow bit is cleared, if it has been set. * * Inputs: * handle: opaque handle interpreted by the underlying OS * rdc: RX DMA Channel number * cnt: Ptr to structure to write current RDC discard stat * * Return: * NPI_SUCCESS * NPI_RXDMA_RDC_INVALID * */ npi_status_t npi_rxdma_misc_discard_stat_get(npi_handle_t handle, uint8_t rdc, rx_disc_cnt_t *cnt) { ASSERT(RXDMA_CHANNEL_VALID(rdc)); if (!RXDMA_CHANNEL_VALID(rdc)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " npi_rxdma_misc_discard_stat_get" " Illegal RDC Number %d \n", rdc)); return (NPI_RXDMA_RDC_INVALID); } RXDMA_REG_READ64(handle, RXMISC_DISCARD_REG, rdc, &cnt->value); if (cnt->bits.ldw.oflow) { NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL, " npi_rxdma_misc_discard_stat_get" " Counter overflow for channel %d ", " ..... clearing \n", rdc)); cnt->bits.ldw.oflow = 0; RXDMA_REG_WRITE64(handle, RXMISC_DISCARD_REG, rdc, cnt->value); cnt->bits.ldw.oflow = 1; } return (NPI_SUCCESS); } /* * npi_rxdma_red_discard_oflow_clear * Clear RED discard counter overflow bit * clear the overflow bit for buffer pool empty discrad counter * for the rdc * * Inputs: * handle: opaque handle interpreted by the underlying OS * rdc: RX DMA Channel number * * Return: * NPI_SUCCESS * NPI_RXDMA_RDC_INVALID * */ npi_status_t npi_rxdma_misc_discard_oflow_clear(npi_handle_t handle, uint8_t rdc) { rx_disc_cnt_t cnt; ASSERT(RXDMA_CHANNEL_VALID(rdc)); if (!RXDMA_CHANNEL_VALID(rdc)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " npi_rxdma_misc_discard_oflow_clear" " Illegal RDC Number %d \n", rdc)); return (NPI_RXDMA_RDC_INVALID); } RXDMA_REG_READ64(handle, RXMISC_DISCARD_REG, rdc, &cnt.value); if (cnt.bits.ldw.oflow) { NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL, " npi_rxdma_misc_discard_oflow_clear" " Counter overflow for channel %d ", " ..... clearing \n", rdc)); cnt.bits.ldw.oflow = 0; RXDMA_REG_WRITE64(handle, RXMISC_DISCARD_REG, rdc, cnt.value); } return (NPI_SUCCESS); } /* * npi_rxdma_ring_perr_stat_get * Gets the current RDC Memory parity error * The counter overflow bit is cleared, if it has been set. * * Inputs: * handle: opaque handle interpreted by the underlying OS * pre_log: Structure to write current RDC Prefetch memory * Parity Error stat * sha_log: Structure to write current RDC Shadow memory * Parity Error stat * * Return: * NPI_SUCCESS * */ npi_status_t npi_rxdma_ring_perr_stat_get(npi_handle_t handle, rdmc_par_err_log_t *pre_log, rdmc_par_err_log_t *sha_log) { uint64_t pre_offset, sha_offset; rdmc_par_err_log_t clr; int clr_bits = 0; pre_offset = RDMC_PRE_PAR_ERR_REG; sha_offset = RDMC_SHA_PAR_ERR_REG; NXGE_REG_RD64(handle, pre_offset, &pre_log->value); NXGE_REG_RD64(handle, sha_offset, &sha_log->value); clr.value = pre_log->value; if (pre_log->bits.ldw.err) { NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL, " npi_rxdma_ring_perr_stat_get" " PRE ERR Bit set ..... clearing \n")); clr.bits.ldw.err = 0; clr_bits++; } if (pre_log->bits.ldw.merr) { NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL, " npi_rxdma_ring_perr_stat_get" " PRE MERR Bit set ..... clearing \n")); clr.bits.ldw.merr = 0; clr_bits++; } if (clr_bits) { NXGE_REG_WR64(handle, pre_offset, clr.value); } clr_bits = 0; clr.value = sha_log->value; if (sha_log->bits.ldw.err) { NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL, " npi_rxdma_ring_perr_stat_get" " SHA ERR Bit set ..... clearing \n")); clr.bits.ldw.err = 0; clr_bits++; } if (sha_log->bits.ldw.merr) { NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL, " npi_rxdma_ring_perr_stat_get" " SHA MERR Bit set ..... clearing \n")); clr.bits.ldw.merr = 0; clr_bits++; } if (clr_bits) { NXGE_REG_WR64(handle, sha_offset, clr.value); } return (NPI_SUCCESS); } /* * npi_rxdma_ring_perr_stat_clear * Clear RDC Memory Parity Error counter overflow bits * * Inputs: * handle: opaque handle interpreted by the underlying OS * Return: * NPI_SUCCESS * */ npi_status_t npi_rxdma_ring_perr_stat_clear(npi_handle_t handle) { uint64_t pre_offset, sha_offset; rdmc_par_err_log_t clr; int clr_bits = 0; pre_offset = RDMC_PRE_PAR_ERR_REG; sha_offset = RDMC_SHA_PAR_ERR_REG; NXGE_REG_RD64(handle, pre_offset, &clr.value); if (clr.bits.ldw.err) { NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL, " npi_rxdma_ring_perr_stat_get" " PRE ERR Bit set ..... clearing \n")); clr.bits.ldw.err = 0; clr_bits++; } if (clr.bits.ldw.merr) { NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL, " npi_rxdma_ring_perr_stat_get" " PRE MERR Bit set ..... clearing \n")); clr.bits.ldw.merr = 0; clr_bits++; } if (clr_bits) { NXGE_REG_WR64(handle, pre_offset, clr.value); } clr_bits = 0; NXGE_REG_RD64(handle, sha_offset, &clr.value); if (clr.bits.ldw.err) { NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL, " npi_rxdma_ring_perr_stat_get" " SHA ERR Bit set ..... clearing \n")); clr.bits.ldw.err = 0; clr_bits++; } if (clr.bits.ldw.merr) { NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL, " npi_rxdma_ring_perr_stat_get" " SHA MERR Bit set ..... clearing \n")); clr.bits.ldw.merr = 0; clr_bits++; } if (clr_bits) { NXGE_REG_WR64(handle, sha_offset, clr.value); } return (NPI_SUCCESS); } /* * Access the RDMC Memory: used for debugging */ npi_status_t npi_rxdma_rdmc_memory_io(npi_handle_t handle, rdmc_mem_access_t *data, uint8_t op) { uint64_t d0_offset, d1_offset, d2_offset, d3_offset, d4_offset; uint64_t addr_offset; rdmc_mem_addr_t addr; rdmc_mem_data_t d0, d1, d2, d3, d4; d0.value = 0; d1.value = 0; d2.value = 0; d3.value = 0; d4.value = 0; addr.value = 0; if ((data->location != RDMC_MEM_ADDR_PREFETCH) && (data->location != RDMC_MEM_ADDR_SHADOW)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " npi_rxdma_rdmc_memory_io" " Illegal memory Type %x \n", data->location)); return (NPI_RXDMA_OPCODE_INVALID(0)); } addr_offset = RDMC_MEM_ADDR_REG; addr.bits.ldw.addr = data->addr; addr.bits.ldw.pre_shad = data->location; d0_offset = RDMC_MEM_DATA0_REG; d1_offset = RDMC_MEM_DATA1_REG; d2_offset = RDMC_MEM_DATA2_REG; d3_offset = RDMC_MEM_DATA3_REG; d4_offset = RDMC_MEM_DATA4_REG; if (op == RDMC_MEM_WRITE) { d0.bits.ldw.data = data->data[0]; d1.bits.ldw.data = data->data[1]; d2.bits.ldw.data = data->data[2]; d3.bits.ldw.data = data->data[3]; d4.bits.ldw.data = data->data[4]; NXGE_REG_WR64(handle, addr_offset, addr.value); NXGE_REG_WR64(handle, d0_offset, d0.value); NXGE_REG_WR64(handle, d1_offset, d1.value); NXGE_REG_WR64(handle, d2_offset, d2.value); NXGE_REG_WR64(handle, d3_offset, d3.value); NXGE_REG_WR64(handle, d4_offset, d4.value); } if (op == RDMC_MEM_READ) { NXGE_REG_WR64(handle, addr_offset, addr.value); NXGE_REG_RD64(handle, d4_offset, &d4.value); NXGE_REG_RD64(handle, d3_offset, &d3.value); NXGE_REG_RD64(handle, d2_offset, &d2.value); NXGE_REG_RD64(handle, d1_offset, &d1.value); NXGE_REG_RD64(handle, d0_offset, &d0.value); data->data[0] = d0.bits.ldw.data; data->data[1] = d1.bits.ldw.data; data->data[2] = d2.bits.ldw.data; data->data[3] = d3.bits.ldw.data; data->data[4] = d4.bits.ldw.data; } else { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " npi_rxdma_rdmc_memory_io" " Illegal opcode %x \n", op)); return (NPI_RXDMA_OPCODE_INVALID(0)); } return (NPI_SUCCESS); } /* * system wide conf functions */ npi_status_t npi_rxdma_cfg_clock_div_set(npi_handle_t handle, uint16_t count) { uint64_t offset; rx_dma_ck_div_t clk_div; offset = RX_DMA_CK_DIV_REG; clk_div.value = 0; clk_div.bits.ldw.cnt = count; NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL, " npi_rxdma_cfg_clock_div_set: add 0x%llx " "handle 0x%llx value 0x%llx", handle.regp, handle.regh, clk_div.value)); NXGE_REG_WR64(handle, offset, clk_div.value); return (NPI_SUCCESS); } npi_status_t npi_rxdma_cfg_red_rand_init(npi_handle_t handle, uint16_t init_value) { uint64_t offset; red_ran_init_t rand_reg; offset = RED_RAN_INIT_REG; rand_reg.value = 0; rand_reg.bits.ldw.init = init_value; rand_reg.bits.ldw.enable = 1; NXGE_REG_WR64(handle, offset, rand_reg.value); return (NPI_SUCCESS); } npi_status_t npi_rxdma_cfg_red_rand_disable(npi_handle_t handle) { uint64_t offset; red_ran_init_t rand_reg; offset = RED_RAN_INIT_REG; NXGE_REG_RD64(handle, offset, &rand_reg.value); rand_reg.bits.ldw.enable = 0; NXGE_REG_WR64(handle, offset, rand_reg.value); return (NPI_SUCCESS); } npi_status_t npi_rxdma_cfg_32bitmode_enable(npi_handle_t handle) { uint64_t offset; rx_addr_md_t md_reg; offset = RX_ADDR_MD_REG; md_reg.value = 0; md_reg.bits.ldw.mode32 = 1; NXGE_REG_WR64(handle, offset, md_reg.value); return (NPI_SUCCESS); } npi_status_t npi_rxdma_cfg_32bitmode_disable(npi_handle_t handle) { uint64_t offset; rx_addr_md_t md_reg; offset = RX_ADDR_MD_REG; md_reg.value = 0; NXGE_REG_WR64(handle, offset, md_reg.value); return (NPI_SUCCESS); } npi_status_t npi_rxdma_cfg_ram_access_enable(npi_handle_t handle) { uint64_t offset; rx_addr_md_t md_reg; offset = RX_ADDR_MD_REG; NXGE_REG_RD64(handle, offset, &md_reg.value); md_reg.bits.ldw.ram_acc = 1; NXGE_REG_WR64(handle, offset, md_reg.value); return (NPI_SUCCESS); } npi_status_t npi_rxdma_cfg_ram_access_disable(npi_handle_t handle) { uint64_t offset; rx_addr_md_t md_reg; offset = RX_ADDR_MD_REG; NXGE_REG_RD64(handle, offset, &md_reg.value); md_reg.bits.ldw.ram_acc = 0; NXGE_REG_WR64(handle, offset, md_reg.value); return (NPI_SUCCESS); } npi_status_t npi_rxdma_cfg_port_ddr_weight(npi_handle_t handle, uint8_t portnm, uint32_t weight) { pt_drr_wt_t wt_reg; uint64_t offset; ASSERT(RXDMA_PORT_VALID(portnm)); if (!RXDMA_PORT_VALID(portnm)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " rxdma_cfg_port_ddr_weight" " Illegal Port Number %d \n", portnm)); return (NPI_RXDMA_PORT_INVALID); } offset = PT_DRR_WT_REG(portnm); wt_reg.value = 0; wt_reg.bits.ldw.wt = weight; NXGE_REG_WR64(handle, offset, wt_reg.value); return (NPI_SUCCESS); } npi_status_t npi_rxdma_port_usage_get(npi_handle_t handle, uint8_t portnm, uint32_t *blocks) { pt_use_t use_reg; uint64_t offset; ASSERT(RXDMA_PORT_VALID(portnm)); if (!RXDMA_PORT_VALID(portnm)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " rxdma_port_usage_get" " Illegal Port Number %d \n", portnm)); return (NPI_RXDMA_PORT_INVALID); } offset = PT_USE_REG(portnm); NXGE_REG_RD64(handle, offset, &use_reg.value); *blocks = use_reg.bits.ldw.cnt; return (NPI_SUCCESS); } npi_status_t npi_rxdma_cfg_wred_param(npi_handle_t handle, uint8_t rdc, rdc_red_para_t *wred_params) { rdc_red_para_t wred_reg; uint64_t offset; ASSERT(RXDMA_CHANNEL_VALID(rdc)); if (!RXDMA_CHANNEL_VALID(rdc)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " rxdma_cfg_wred_param" " Illegal RDC Number %d \n", rdc)); return (NPI_RXDMA_RDC_INVALID); } /* * need to update RDC_RED_PARA_REG as well as bit defs in * the hw header file */ offset = RDC_RED_RDC_PARA_REG(rdc); NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL, " npi_rxdma_cfg_wred_param: " "set RED_PARA: passed value 0x%llx " "win 0x%x thre 0x%x sync 0x%x thre_sync 0x%x", wred_params->value, wred_params->bits.ldw.win, wred_params->bits.ldw.thre, wred_params->bits.ldw.win_syn, wred_params->bits.ldw.thre_sync)); wred_reg.value = 0; wred_reg.bits.ldw.win = wred_params->bits.ldw.win; wred_reg.bits.ldw.thre = wred_params->bits.ldw.thre; wred_reg.bits.ldw.win_syn = wred_params->bits.ldw.win_syn; wred_reg.bits.ldw.thre_sync = wred_params->bits.ldw.thre_sync; NXGE_REG_WR64(handle, offset, wred_reg.value); NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL, "set RED_PARA: value 0x%llx " "win 0x%x thre 0x%x sync 0x%x thre_sync 0x%x", wred_reg.value, wred_reg.bits.ldw.win, wred_reg.bits.ldw.thre, wred_reg.bits.ldw.win_syn, wred_reg.bits.ldw.thre_sync)); return (NPI_SUCCESS); } /* * npi_rxdma_rdc_table_config() * Configure/populate the RDC table * * Inputs: * handle: register handle interpreted by the underlying OS * table: RDC Group Number * map: A bitmap of the RDCs to populate with. * count: A count of the RDCs expressed in . * * Notes: * This function assumes that we are not using the TCAM, but are * hashing all fields of the incoming ethernet packet! * * Return: * NPI_SUCCESS * NPI_RXDMA_TABLE_INVALID * */ npi_status_t npi_rxdma_rdc_table_config( npi_handle_t handle, uint8_t table, dc_map_t rdc_map, int count) { int8_t set[NXGE_MAX_RDCS]; int i, cursor; rdc_tbl_t rdc_tbl; uint64_t offset; ASSERT(RXDMA_TABLE_VALID(table)); if (!RXDMA_TABLE_VALID(table)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " npi_rxdma_cfg_rdc_table" " Illegal RDC Table Number %d \n", table)); return (NPI_RXDMA_TABLE_INVALID); } if (count == 0) /* This shouldn't happen */ return (NPI_SUCCESS); for (i = 0, cursor = 0; i < NXGE_MAX_RDCS; i++) { if ((1 << i) & rdc_map) { set[cursor++] = (int8_t)i; if (cursor == count) break; } } rdc_tbl.value = 0; offset = REG_RDC_TABLE_OFFSET(table); /* Now write ( NXGE_MAX_RDCS / count ) sets of RDC numbers. */ for (i = 0, cursor = 0; i < NXGE_MAX_RDCS; i++) { rdc_tbl.bits.ldw.rdc = set[cursor++]; NXGE_REG_WR64(handle, offset, rdc_tbl.value); offset += sizeof (rdc_tbl.value); if (cursor == count) cursor = 0; } /* * Here is what the resulting table looks like with: * * 0 1 2 3 4 5 6 7 8 9 a b c d e f * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * |v |w |x |y |z |v |w |x |y |z |v |w |x |y |z |v | 5 RDCs * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * |w |x |y |z |w |x |y |z |w |x |y |z |w |x |y |z | 4 RDCs * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * |x |y |z |x |y |z |x |y |z |x |y |z |x |y |z |x | 3 RDCs * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * |x |y |x |y |x |y |x |y |x |y |x |y |x |y |x |y | 2 RDCs * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * |x |x |x |x |x |x |x |x |x |x |x |x |x |x |x |x | 1 RDC * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ return (NPI_SUCCESS); } npi_status_t npi_rxdma_cfg_rdc_table_default_rdc(npi_handle_t handle, uint8_t table, uint8_t rdc) { uint64_t offset; rdc_tbl_t tbl_reg; tbl_reg.value = 0; ASSERT(RXDMA_TABLE_VALID(table)); if (!RXDMA_TABLE_VALID(table)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " npi_rxdma_cfg_rdc_table" " Illegal RDC table Number %d \n", rdc)); return (NPI_RXDMA_TABLE_INVALID); } offset = REG_RDC_TABLE_OFFSET(table); tbl_reg.bits.ldw.rdc = rdc; NXGE_REG_WR64(handle, offset, tbl_reg.value); return (NPI_SUCCESS); } npi_status_t npi_rxdma_dump_rdc_table(npi_handle_t handle, uint8_t table) { uint64_t offset; int tbl_offset; uint64_t value; ASSERT(RXDMA_TABLE_VALID(table)); if (!RXDMA_TABLE_VALID(table)) { NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, " npi_rxdma_dump_rdc_table" " Illegal RDC Rable Number %d \n", table)); return (NPI_RXDMA_TABLE_INVALID); } NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, "\n Register Dump for RDC Table %d \n", table)); offset = REG_RDC_TABLE_OFFSET(table); for (tbl_offset = 0; tbl_offset < NXGE_MAX_RDCS; tbl_offset++) { NXGE_REG_RD64(handle, offset, &value); NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, " 0x%08llx 0x%08llx \n", offset, value)); offset += 8; } NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL, "\n Register Dump for RDC Table %d done\n", table)); return (NPI_SUCCESS); } npi_status_t npi_rxdma_rdc_rbr_stat_get(npi_handle_t handle, uint8_t rdc, rbr_stat_t *rbr_stat) { ASSERT(RXDMA_CHANNEL_VALID(rdc)); if (!RXDMA_CHANNEL_VALID(rdc)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " rxdma_rdc_rbr_stat_get" " Illegal RDC Number %d \n", rdc)); return (NPI_RXDMA_RDC_INVALID); } RXDMA_REG_READ64(handle, RBR_STAT_REG, rdc, &rbr_stat->value); return (NPI_SUCCESS); } /* * npi_rxdma_rdc_rbr_head_get * Gets the current rbr head pointer. * * Inputs: * handle: opaque handle interpreted by the underlying OS * rdc: RX DMA Channel number * hdptr ptr to write the rbr head value * * Return: * NPI_SUCCESS * NPI_RXDMA_RDC_INVALID */ npi_status_t npi_rxdma_rdc_rbr_head_get(npi_handle_t handle, uint8_t rdc, addr44_t *hdptr) { rbr_hdh_t hh_ptr; rbr_hdl_t hl_ptr; ASSERT(RXDMA_CHANNEL_VALID(rdc)); if (!RXDMA_CHANNEL_VALID(rdc)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " rxdma_rdc_rbr_head_get" " Illegal RDC Number %d \n", rdc)); return (NPI_RXDMA_RDC_INVALID); } hh_ptr.value = 0; hl_ptr.value = 0; RXDMA_REG_READ64(handle, RBR_HDH_REG, rdc, &hh_ptr.value); RXDMA_REG_READ64(handle, RBR_HDL_REG, rdc, &hl_ptr.value); hdptr->bits.ldw = hl_ptr.bits.ldw.head_l << 2; hdptr->bits.hdw = hh_ptr.bits.ldw.head_h; return (NPI_SUCCESS); } npi_status_t npi_rxdma_rdc_rcr_qlen_get(npi_handle_t handle, uint8_t rdc, uint16_t *rcr_qlen) { rcrstat_a_t stats; ASSERT(RXDMA_CHANNEL_VALID(rdc)); if (!RXDMA_CHANNEL_VALID(rdc)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " rxdma_rdc_rcr_qlen_get" " Illegal RDC Number %d \n", rdc)); return (NPI_RXDMA_RDC_INVALID); } RXDMA_REG_READ64(handle, RCRSTAT_A_REG, rdc, &stats.value); *rcr_qlen = stats.bits.ldw.qlen; NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL, " rxdma_rdc_rcr_qlen_get" " RDC %d qlen %x qlen %x\n", rdc, *rcr_qlen, stats.bits.ldw.qlen)); return (NPI_SUCCESS); } npi_status_t npi_rxdma_rdc_rcr_tail_get(npi_handle_t handle, uint8_t rdc, addr44_t *tail_addr) { rcrstat_b_t th_ptr; rcrstat_c_t tl_ptr; ASSERT(RXDMA_CHANNEL_VALID(rdc)); if (!RXDMA_CHANNEL_VALID(rdc)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " rxdma_rdc_rcr_tail_get" " Illegal RDC Number %d \n", rdc)); return (NPI_RXDMA_RDC_INVALID); } th_ptr.value = 0; tl_ptr.value = 0; RXDMA_REG_READ64(handle, RCRSTAT_B_REG, rdc, &th_ptr.value); RXDMA_REG_READ64(handle, RCRSTAT_C_REG, rdc, &tl_ptr.value); tail_addr->bits.ldw = tl_ptr.bits.ldw.tlptr_l << 3; tail_addr->bits.hdw = th_ptr.bits.ldw.tlptr_h; NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL, " rxdma_rdc_rcr_tail_get" " RDC %d rcr_tail %llx tl %x\n", rdc, tl_ptr.value, tl_ptr.bits.ldw.tlptr_l)); return (NPI_SUCCESS); } /* * npi_rxdma_rxctl_fifo_error_intr_set * Configure The RX ctrl fifo error interrupt generation * * Inputs: * handle: opaque handle interpreted by the underlying OS * mask: rx_ctl_dat_fifo_mask_t specifying the errors * valid fields in rx_ctl_dat_fifo_mask_t structure are: * zcp_eop_err, ipp_eop_err, id_mismatch. If a field is set * to 1, we will enable interrupt generation for the * corresponding error condition. In the hardware, the bit(s) * have to be cleared to enable interrupt. * * Return: * NPI_SUCCESS * */ npi_status_t npi_rxdma_rxctl_fifo_error_intr_set(npi_handle_t handle, rx_ctl_dat_fifo_mask_t *mask) { uint64_t offset; rx_ctl_dat_fifo_mask_t intr_mask; offset = RX_CTL_DAT_FIFO_MASK_REG; NXGE_REG_RD64(handle, offset, &intr_mask.value); if (mask->bits.ldw.ipp_eop_err) { intr_mask.bits.ldw.ipp_eop_err = 0; } if (mask->bits.ldw.zcp_eop_err) { intr_mask.bits.ldw.zcp_eop_err = 0; } if (mask->bits.ldw.id_mismatch) { intr_mask.bits.ldw.id_mismatch = 0; } NXGE_REG_WR64(handle, offset, intr_mask.value); return (NPI_SUCCESS); } /* * npi_rxdma_rxctl_fifo_error_stat_get * Read The RX ctrl fifo error Status * * Inputs: * handle: opaque handle interpreted by the underlying OS * stat: rx_ctl_dat_fifo_stat_t to read the errors to * valid fields in rx_ctl_dat_fifo_stat_t structure are: * zcp_eop_err, ipp_eop_err, id_mismatch. * Return: * NPI_SUCCESS * */ npi_status_t npi_rxdma_rxctl_fifo_error_intr_get(npi_handle_t handle, rx_ctl_dat_fifo_stat_t *stat) { uint64_t offset = RX_CTL_DAT_FIFO_STAT_REG; NXGE_REG_RD64(handle, offset, &stat->value); return (NPI_SUCCESS); } npi_status_t npi_rxdma_rdc_rcr_pktread_update(npi_handle_t handle, uint8_t channel, uint16_t pkts_read) { rx_dma_ctl_stat_t cs; uint16_t min_read = 0; ASSERT(RXDMA_CHANNEL_VALID(channel)); if (!RXDMA_CHANNEL_VALID(channel)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " npi_rxdma_rdc_rcr_pktread_update ", " channel %d", channel)); return (NPI_FAILURE | NPI_RXDMA_CHANNEL_INVALID(channel)); } if ((pkts_read < min_read) && (pkts_read > 512)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " npi_rxdma_rdc_rcr_pktread_update ", " pkts %d out of bound", pkts_read)); return (NPI_RXDMA_OPCODE_INVALID(pkts_read)); } RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel, &cs.value); cs.bits.ldw.pktread = pkts_read; RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG, channel, cs.value); return (NPI_SUCCESS); } npi_status_t npi_rxdma_rdc_rcr_bufread_update(npi_handle_t handle, uint8_t channel, uint16_t bufs_read) { rx_dma_ctl_stat_t cs; uint16_t min_read = 0; ASSERT(RXDMA_CHANNEL_VALID(channel)); if (!RXDMA_CHANNEL_VALID(channel)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " npi_rxdma_rdc_rcr_bufread_update ", " channel %d", channel)); return (NPI_FAILURE | NPI_RXDMA_CHANNEL_INVALID(channel)); } if ((bufs_read < min_read) && (bufs_read > 512)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " npi_rxdma_rdc_rcr_bufread_update ", " bufs read %d out of bound", bufs_read)); return (NPI_RXDMA_OPCODE_INVALID(bufs_read)); } RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel, &cs.value); cs.bits.ldw.ptrread = bufs_read; RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG, channel, cs.value); return (NPI_SUCCESS); } npi_status_t npi_rxdma_rdc_rcr_read_update(npi_handle_t handle, uint8_t channel, uint16_t pkts_read, uint16_t bufs_read) { rx_dma_ctl_stat_t cs; ASSERT(RXDMA_CHANNEL_VALID(channel)); if (!RXDMA_CHANNEL_VALID(channel)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " npi_rxdma_rdc_rcr_read_update ", " channel %d", channel)); return (NPI_FAILURE | NPI_RXDMA_CHANNEL_INVALID(channel)); } NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL, " npi_rxdma_rdc_rcr_read_update " " bufs read %d pkt read %d", bufs_read, pkts_read)); RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel, &cs.value); NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL, " npi_rxdma_rdc_rcr_read_update: " " value: 0x%llx bufs read %d pkt read %d", cs.value, cs.bits.ldw.ptrread, cs.bits.ldw.pktread)); cs.bits.ldw.pktread = pkts_read; cs.bits.ldw.ptrread = bufs_read; RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG, channel, cs.value); RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel, &cs.value); NPI_DEBUG_MSG((handle.function, NPI_RDC_CTL, " npi_rxdma_rdc_rcr_read_update: read back after update " " value: 0x%llx bufs read %d pkt read %d", cs.value, cs.bits.ldw.ptrread, cs.bits.ldw.pktread)); return (NPI_SUCCESS); } /* * npi_rxdma_channel_mex_set(): * This function is called to arm the DMA channel with * mailbox updating capability. Software needs to rearm * for each update by writing to the control and status register. * * Parameters: * handle - NPI handle (virtualization flag must be defined). * channel - logical RXDMA 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 enable channel with mailbox update * is completed successfully. * * Error: * NPI error status code */ npi_status_t npi_rxdma_channel_mex_set(npi_handle_t handle, uint8_t channel) { return (npi_rxdma_channel_control(handle, RXDMA_MEX_SET, channel)); } /* * npi_rxdma_channel_rcrto_clear(): * This function is called to reset RCRTO bit to 0. * * Parameters: * handle - NPI handle (virtualization flag must be defined). * channel - logical RXDMA 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 * * Error: * NPI error status code */ npi_status_t npi_rxdma_channel_rcrto_clear(npi_handle_t handle, uint8_t channel) { return (npi_rxdma_channel_control(handle, RXDMA_RCRTO_CLEAR, channel)); } /* * npi_rxdma_channel_pt_drop_pkt_clear(): * This function is called to clear the port drop packet bit (debug). * * Parameters: * handle - NPI handle (virtualization flag must be defined). * channel - logical RXDMA 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 * * Error: * NPI error status code */ npi_status_t npi_rxdma_channel_pt_drop_pkt_clear(npi_handle_t handle, uint8_t channel) { return (npi_rxdma_channel_control(handle, RXDMA_PT_DROP_PKT_CLEAR, channel)); } /* * npi_rxdma_channel_wred_drop_clear(): * This function is called to wred drop bit (debug only). * * Parameters: * handle - NPI handle (virtualization flag must be defined). * channel - logical RXDMA 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 * * Error: * NPI error status code */ npi_status_t npi_rxdma_channel_wred_dop_clear(npi_handle_t handle, uint8_t channel) { return (npi_rxdma_channel_control(handle, RXDMA_WRED_DROP_CLEAR, channel)); } /* * npi_rxdma_channel_rcr_shfull_clear(): * This function is called to clear RCR shadow full bit. * * Parameters: * handle - NPI handle (virtualization flag must be defined). * channel - logical RXDMA 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 * * Error: * NPI error status code */ npi_status_t npi_rxdma_channel_rcr_shfull_clear(npi_handle_t handle, uint8_t channel) { return (npi_rxdma_channel_control(handle, RXDMA_RCR_SFULL_CLEAR, channel)); } /* * npi_rxdma_channel_rcrfull_clear(): * This function is called to clear RCR full bit. * * Parameters: * handle - NPI handle (virtualization flag must be defined). * channel - logical RXDMA 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 * * Error: * NPI error status code */ npi_status_t npi_rxdma_channel_rcr_full_clear(npi_handle_t handle, uint8_t channel) { return (npi_rxdma_channel_control(handle, RXDMA_RCR_FULL_CLEAR, channel)); } npi_status_t npi_rxdma_channel_rbr_empty_clear(npi_handle_t handle, uint8_t channel) { return (npi_rxdma_channel_control(handle, RXDMA_RBR_EMPTY_CLEAR, channel)); } npi_status_t npi_rxdma_channel_cs_clear_all(npi_handle_t handle, uint8_t channel) { return (npi_rxdma_channel_control(handle, RXDMA_CS_CLEAR_ALL, channel)); } /* * npi_rxdma_channel_control(): * This function is called to control a receive DMA channel * for arming the channel with mailbox updates, resetting * various event status bits (control and status register). * * Parameters: * handle - NPI handle (virtualization flag must be defined). * control - NPI defined control type supported: * - RXDMA_MEX_SET * - RXDMA_RCRTO_CLEAR * - RXDMA_PT_DROP_PKT_CLEAR * - RXDMA_WRED_DROP_CLEAR * - RXDMA_RCR_SFULL_CLEAR * - RXDMA_RCR_FULL_CLEAR * - RXDMA_RBR_PRE_EMPTY_CLEAR * - RXDMA_RBR_EMPTY_CLEAR * channel - logical RXDMA channel from 0 to 23. * (If virtualization flag is not set, then * logical channel is the same as the hardware. * Return: * NPI_SUCCESS * * Error: * NPI error status code */ npi_status_t npi_rxdma_channel_control(npi_handle_t handle, rxdma_cs_cntl_t control, uint8_t channel) { rx_dma_ctl_stat_t cs; ASSERT(RXDMA_CHANNEL_VALID(channel)); if (!RXDMA_CHANNEL_VALID(channel)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, " npi_rxdma_channel_control", " channel", channel)); return (NPI_FAILURE | NPI_RXDMA_CHANNEL_INVALID(channel)); } switch (control) { case RXDMA_MEX_SET: RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel, &cs.value); cs.bits.hdw.mex = 1; RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG, channel, cs.value); break; case RXDMA_RCRTO_CLEAR: RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel, &cs.value); cs.bits.hdw.rcrto = 0; RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG, channel, cs.value); break; case RXDMA_PT_DROP_PKT_CLEAR: RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel, &cs.value); cs.bits.hdw.port_drop_pkt = 0; RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG, channel, cs.value); break; case RXDMA_WRED_DROP_CLEAR: RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel, &cs.value); cs.bits.hdw.wred_drop = 0; RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG, channel, cs.value); break; case RXDMA_RCR_SFULL_CLEAR: RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel, &cs.value); cs.bits.hdw.rcr_shadow_full = 0; RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG, channel, cs.value); break; case RXDMA_RCR_FULL_CLEAR: RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel, &cs.value); cs.bits.hdw.rcrfull = 0; RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG, channel, cs.value); break; case RXDMA_RBR_PRE_EMPTY_CLEAR: RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel, &cs.value); cs.bits.hdw.rbr_pre_empty = 0; RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG, channel, cs.value); break; case RXDMA_RBR_EMPTY_CLEAR: RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel, &cs.value); cs.bits.hdw.rbr_empty = 1; RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG, channel, cs.value); break; case RXDMA_CS_CLEAR_ALL: cs.value = 0; RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG, channel, cs.value); break; default: NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, "npi_rxdma_channel_control", "control", control)); return (NPI_FAILURE | NPI_RXDMA_OPCODE_INVALID(channel)); } return (NPI_SUCCESS); } /* * npi_rxdma_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 RXDMA channel from 0 to 23. * cs_p - pointer to hardware defined control and status * structure. * Return: * NPI_SUCCESS * * Error: * NPI error status code */ npi_status_t npi_rxdma_control_status(npi_handle_t handle, io_op_t op_mode, uint8_t channel, p_rx_dma_ctl_stat_t cs_p) { int status = NPI_SUCCESS; rx_dma_ctl_stat_t cs; ASSERT(RXDMA_CHANNEL_VALID(channel)); if (!RXDMA_CHANNEL_VALID(channel)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, "npi_rxdma_control_status", "channel", channel)); return (NPI_FAILURE | NPI_RXDMA_CHANNEL_INVALID(channel)); } switch (op_mode) { case OP_GET: RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel, &cs_p->value); break; case OP_SET: RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG, channel, cs_p->value); break; case OP_UPDATE: RXDMA_REG_READ64(handle, RX_DMA_CTL_STAT_REG, channel, &cs.value); RXDMA_REG_WRITE64(handle, RX_DMA_CTL_STAT_REG, channel, cs_p->value | cs.value); break; default: NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, "npi_rxdma_control_status", "control", op_mode)); return (NPI_FAILURE | NPI_RXDMA_OPCODE_INVALID(channel)); } return (status); } /* * npi_rxdma_event_mask(): * This function is called to operate on the event mask * register which is used for generating interrupts. * * 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 RXDMA channel from 0 to 23. * mask_p - pointer to hardware defined event mask * structure. * Return: * NPI_SUCCESS - If set is complete successfully. * * Error: * NPI error status code */ npi_status_t npi_rxdma_event_mask(npi_handle_t handle, io_op_t op_mode, uint8_t channel, p_rx_dma_ent_msk_t mask_p) { int status = NPI_SUCCESS; rx_dma_ent_msk_t mask; ASSERT(RXDMA_CHANNEL_VALID(channel)); if (!RXDMA_CHANNEL_VALID(channel)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, "npi_rxdma_event_mask", "channel", channel)); return (NPI_FAILURE | NPI_RXDMA_CHANNEL_INVALID(channel)); } switch (op_mode) { case OP_GET: RXDMA_REG_READ64(handle, RX_DMA_ENT_MSK_REG, channel, &mask_p->value); break; case OP_SET: RXDMA_REG_WRITE64(handle, RX_DMA_ENT_MSK_REG, channel, mask_p->value); break; case OP_UPDATE: RXDMA_REG_READ64(handle, RX_DMA_ENT_MSK_REG, channel, &mask.value); RXDMA_REG_WRITE64(handle, RX_DMA_ENT_MSK_REG, channel, mask_p->value | mask.value); break; default: NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, "npi_rxdma_event_mask", "eventmask", op_mode)); return (NPI_FAILURE | NPI_RXDMA_OPCODE_INVALID(channel)); } return (status); } /* * npi_rxdma_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 RXDMA channel from 0 to 23. * mask_cfgp - pointer to NPI defined event mask * enum data type. * Return: * NPI_SUCCESS - If set is complete successfully. * * Error: * NPI error status code */ npi_status_t npi_rxdma_event_mask_config(npi_handle_t handle, io_op_t op_mode, uint8_t channel, rxdma_ent_msk_cfg_t *mask_cfgp) { int status = NPI_SUCCESS; uint64_t configuration = *mask_cfgp; uint64_t value; ASSERT(RXDMA_CHANNEL_VALID(channel)); if (!RXDMA_CHANNEL_VALID(channel)) { NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, "npi_rxdma_event_mask_config", "channel", channel)); return (NPI_FAILURE | NPI_RXDMA_CHANNEL_INVALID(channel)); } switch (op_mode) { case OP_GET: RXDMA_REG_READ64(handle, RX_DMA_ENT_MSK_REG, channel, (uint64_t *)mask_cfgp); break; case OP_SET: RXDMA_REG_WRITE64(handle, RX_DMA_ENT_MSK_REG, channel, configuration); break; case OP_UPDATE: RXDMA_REG_READ64(handle, RX_DMA_ENT_MSK_REG, channel, &value); RXDMA_REG_WRITE64(handle, RX_DMA_ENT_MSK_REG, channel, configuration | value); break; case OP_CLEAR: RXDMA_REG_WRITE64(handle, RX_DMA_ENT_MSK_REG, channel, CFG_RXDMA_MASK_ALL); break; default: NPI_ERROR_MSG((handle.function, NPI_ERR_CTL, "npi_rxdma_event_mask_config", "eventmask", op_mode)); return (NPI_FAILURE | NPI_RXDMA_OPCODE_INVALID(channel)); } return (status); }