13dec9fcdSqs148142 /*
23dec9fcdSqs148142 * CDDL HEADER START
33dec9fcdSqs148142 *
43dec9fcdSqs148142 * The contents of this file are subject to the terms of the
53dec9fcdSqs148142 * Common Development and Distribution License (the "License").
63dec9fcdSqs148142 * You may not use this file except in compliance with the License.
73dec9fcdSqs148142 *
83dec9fcdSqs148142 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93dec9fcdSqs148142 * or http://www.opensolaris.org/os/licensing.
103dec9fcdSqs148142 * See the License for the specific language governing permissions
113dec9fcdSqs148142 * and limitations under the License.
123dec9fcdSqs148142 *
133dec9fcdSqs148142 * When distributing Covered Code, include this CDDL HEADER in each
143dec9fcdSqs148142 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153dec9fcdSqs148142 * If applicable, add the following below this CDDL HEADER, with the
163dec9fcdSqs148142 * fields enclosed by brackets "[]" replaced with your own identifying
173dec9fcdSqs148142 * information: Portions Copyright [yyyy] [name of copyright owner]
183dec9fcdSqs148142 *
193dec9fcdSqs148142 * CDDL HEADER END
203dec9fcdSqs148142 */
213dec9fcdSqs148142 /*
223dec9fcdSqs148142 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
233dec9fcdSqs148142 * Use is subject to license terms.
243dec9fcdSqs148142 */
253dec9fcdSqs148142
263dec9fcdSqs148142 #pragma ident "%Z%%M% %I% %E% SMI"
273dec9fcdSqs148142
283dec9fcdSqs148142 #include <hpi_txdma.h>
29*fe930412Sqs148142 #include <hxge_impl.h>
303dec9fcdSqs148142
313dec9fcdSqs148142 #define TXDMA_WAIT_LOOP 10000
323dec9fcdSqs148142 #define TXDMA_WAIT_MSEC 5
333dec9fcdSqs148142
343dec9fcdSqs148142 static hpi_status_t hpi_txdma_control_reset_wait(hpi_handle_t handle,
353dec9fcdSqs148142 uint8_t channel);
363dec9fcdSqs148142
373dec9fcdSqs148142 hpi_status_t
hpi_txdma_log_page_handle_set(hpi_handle_t handle,uint8_t channel,tdc_page_handle_t * hdl_p)383dec9fcdSqs148142 hpi_txdma_log_page_handle_set(hpi_handle_t handle, uint8_t channel,
393dec9fcdSqs148142 tdc_page_handle_t *hdl_p)
403dec9fcdSqs148142 {
413dec9fcdSqs148142 int status = HPI_SUCCESS;
423dec9fcdSqs148142
433dec9fcdSqs148142 if (!TXDMA_CHANNEL_VALID(channel)) {
443dec9fcdSqs148142 HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
453dec9fcdSqs148142 " hpi_txdma_log_page_handle_set"
463dec9fcdSqs148142 " Invalid Input: channel <0x%x>", channel));
473dec9fcdSqs148142 return (HPI_FAILURE | HPI_TXDMA_CHANNEL_INVALID(channel));
483dec9fcdSqs148142 }
493dec9fcdSqs148142
503dec9fcdSqs148142 TXDMA_REG_WRITE64(handle, TDC_PAGE_HANDLE, channel, hdl_p->value);
513dec9fcdSqs148142
523dec9fcdSqs148142 return (status);
533dec9fcdSqs148142 }
543dec9fcdSqs148142
553dec9fcdSqs148142 hpi_status_t
hpi_txdma_channel_reset(hpi_handle_t handle,uint8_t channel)563dec9fcdSqs148142 hpi_txdma_channel_reset(hpi_handle_t handle, uint8_t channel)
573dec9fcdSqs148142 {
583dec9fcdSqs148142 HPI_DEBUG_MSG((handle.function, HPI_TDC_CTL,
593dec9fcdSqs148142 " hpi_txdma_channel_reset" " RESETTING", channel));
603dec9fcdSqs148142 return (hpi_txdma_channel_control(handle, TXDMA_RESET, channel));
613dec9fcdSqs148142 }
623dec9fcdSqs148142
633dec9fcdSqs148142 hpi_status_t
hpi_txdma_channel_init_enable(hpi_handle_t handle,uint8_t channel)643dec9fcdSqs148142 hpi_txdma_channel_init_enable(hpi_handle_t handle, uint8_t channel)
653dec9fcdSqs148142 {
663dec9fcdSqs148142 return (hpi_txdma_channel_control(handle, TXDMA_INIT_START, channel));
673dec9fcdSqs148142 }
683dec9fcdSqs148142
693dec9fcdSqs148142 hpi_status_t
hpi_txdma_channel_enable(hpi_handle_t handle,uint8_t channel)703dec9fcdSqs148142 hpi_txdma_channel_enable(hpi_handle_t handle, uint8_t channel)
713dec9fcdSqs148142 {
723dec9fcdSqs148142 return (hpi_txdma_channel_control(handle, TXDMA_START, channel));
733dec9fcdSqs148142 }
743dec9fcdSqs148142
753dec9fcdSqs148142 hpi_status_t
hpi_txdma_channel_disable(hpi_handle_t handle,uint8_t channel)763dec9fcdSqs148142 hpi_txdma_channel_disable(hpi_handle_t handle, uint8_t channel)
773dec9fcdSqs148142 {
783dec9fcdSqs148142 return (hpi_txdma_channel_control(handle, TXDMA_STOP, channel));
793dec9fcdSqs148142 }
803dec9fcdSqs148142
813dec9fcdSqs148142 hpi_status_t
hpi_txdma_channel_mbox_enable(hpi_handle_t handle,uint8_t channel)823dec9fcdSqs148142 hpi_txdma_channel_mbox_enable(hpi_handle_t handle, uint8_t channel)
833dec9fcdSqs148142 {
843dec9fcdSqs148142 return (hpi_txdma_channel_control(handle, TXDMA_MBOX_ENABLE, channel));
853dec9fcdSqs148142 }
863dec9fcdSqs148142
873dec9fcdSqs148142 hpi_status_t
hpi_txdma_channel_control(hpi_handle_t handle,txdma_cs_cntl_t control,uint8_t channel)883dec9fcdSqs148142 hpi_txdma_channel_control(hpi_handle_t handle, txdma_cs_cntl_t control,
893dec9fcdSqs148142 uint8_t channel)
903dec9fcdSqs148142 {
913dec9fcdSqs148142 int status = HPI_SUCCESS;
923dec9fcdSqs148142 tdc_stat_t cs;
933dec9fcdSqs148142 tdc_tdr_cfg_t cfg;
943dec9fcdSqs148142
953dec9fcdSqs148142 if (!TXDMA_CHANNEL_VALID(channel)) {
963dec9fcdSqs148142 HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
973dec9fcdSqs148142 " hpi_txdma_channel_control"
983dec9fcdSqs148142 " Invalid Input: channel <0x%x>", channel));
993dec9fcdSqs148142 return (HPI_FAILURE | HPI_TXDMA_CHANNEL_INVALID(channel));
1003dec9fcdSqs148142 }
1013dec9fcdSqs148142
1023dec9fcdSqs148142 switch (control) {
1033dec9fcdSqs148142 case TXDMA_INIT_RESET:
1043dec9fcdSqs148142 cfg.value = 0;
1053dec9fcdSqs148142 TXDMA_REG_READ64(handle, TDC_TDR_CFG, channel, &cfg.value);
1063dec9fcdSqs148142 cfg.bits.reset = 1;
1073dec9fcdSqs148142 TXDMA_REG_WRITE64(handle, TDC_TDR_CFG, channel, cfg.value);
1083dec9fcdSqs148142 return (hpi_txdma_control_reset_wait(handle, channel));
1093dec9fcdSqs148142
1103dec9fcdSqs148142 case TXDMA_INIT_START:
1113dec9fcdSqs148142 cfg.value = 0;
1123dec9fcdSqs148142 TXDMA_REG_READ64(handle, TDC_TDR_CFG, channel, &cfg.value);
1133dec9fcdSqs148142 cfg.bits.enable = 1;
1143dec9fcdSqs148142 TXDMA_REG_WRITE64(handle, TDC_TDR_CFG, channel, cfg.value);
1153dec9fcdSqs148142 break;
1163dec9fcdSqs148142
1173dec9fcdSqs148142 case TXDMA_RESET:
1183dec9fcdSqs148142 /*
1193dec9fcdSqs148142 * Sets reset bit only (Hardware will reset all the RW bits but
1203dec9fcdSqs148142 * leave the RO bits alone.
1213dec9fcdSqs148142 */
1223dec9fcdSqs148142 cfg.value = 0;
1233dec9fcdSqs148142 cfg.bits.reset = 1;
1243dec9fcdSqs148142 TXDMA_REG_WRITE64(handle, TDC_TDR_CFG, channel, cfg.value);
1253dec9fcdSqs148142 return (hpi_txdma_control_reset_wait(handle, channel));
1263dec9fcdSqs148142
1273dec9fcdSqs148142 case TXDMA_START:
1283dec9fcdSqs148142 /* Enable the DMA channel */
1293dec9fcdSqs148142 TXDMA_REG_READ64(handle, TDC_TDR_CFG, channel, &cfg.value);
1303dec9fcdSqs148142 cfg.bits.enable = 1;
1313dec9fcdSqs148142 TXDMA_REG_WRITE64(handle, TDC_TDR_CFG, channel, cfg.value);
1323dec9fcdSqs148142 break;
1333dec9fcdSqs148142
1343dec9fcdSqs148142 case TXDMA_STOP:
1353dec9fcdSqs148142 /* Disable the DMA channel */
1363dec9fcdSqs148142 TXDMA_REG_READ64(handle, TDC_TDR_CFG, channel, &cfg.value);
1373dec9fcdSqs148142 cfg.bits.enable = 0;
1383dec9fcdSqs148142 TXDMA_REG_WRITE64(handle, TDC_TDR_CFG, channel, cfg.value);
1393dec9fcdSqs148142 status = hpi_txdma_control_stop_wait(handle, channel);
1403dec9fcdSqs148142 if (status) {
1413dec9fcdSqs148142 HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
1423dec9fcdSqs148142 "Cannot stop channel %d (TXC hung!)", channel));
1433dec9fcdSqs148142 }
1443dec9fcdSqs148142 break;
1453dec9fcdSqs148142
1463dec9fcdSqs148142 case TXDMA_MBOX_ENABLE:
1473dec9fcdSqs148142 /*
1483dec9fcdSqs148142 * Write 1 to MB bit to enable mailbox update (cleared to 0 by
1493dec9fcdSqs148142 * hardware after update).
1503dec9fcdSqs148142 */
1513dec9fcdSqs148142 TXDMA_REG_READ64(handle, TDC_STAT, channel, &cs.value);
1523dec9fcdSqs148142 cs.bits.mb = 1;
1533dec9fcdSqs148142 TXDMA_REG_WRITE64(handle, TDC_STAT, channel, cs.value);
1543dec9fcdSqs148142 break;
1553dec9fcdSqs148142
1563dec9fcdSqs148142 default:
1573dec9fcdSqs148142 status = (HPI_FAILURE | HPI_TXDMA_OPCODE_INVALID(channel));
1583dec9fcdSqs148142 HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
1593dec9fcdSqs148142 " hpi_txdma_channel_control"
1603dec9fcdSqs148142 " Invalid Input: control <0x%x>", control));
1613dec9fcdSqs148142 }
1623dec9fcdSqs148142
1633dec9fcdSqs148142 return (status);
1643dec9fcdSqs148142 }
1653dec9fcdSqs148142
1663dec9fcdSqs148142 hpi_status_t
hpi_txdma_control_status(hpi_handle_t handle,io_op_t op_mode,uint8_t channel,tdc_stat_t * cs_p)1673dec9fcdSqs148142 hpi_txdma_control_status(hpi_handle_t handle, io_op_t op_mode, uint8_t channel,
1683dec9fcdSqs148142 tdc_stat_t *cs_p)
1693dec9fcdSqs148142 {
1703dec9fcdSqs148142 int status = HPI_SUCCESS;
1713dec9fcdSqs148142 tdc_stat_t txcs;
1723dec9fcdSqs148142
1733dec9fcdSqs148142 if (!TXDMA_CHANNEL_VALID(channel)) {
1743dec9fcdSqs148142 HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
1753dec9fcdSqs148142 " hpi_txdma_control_status"
1763dec9fcdSqs148142 " Invalid Input: channel <0x%x>", channel));
1773dec9fcdSqs148142 return (HPI_FAILURE | HPI_TXDMA_CHANNEL_INVALID(channel));
1783dec9fcdSqs148142 }
1793dec9fcdSqs148142 switch (op_mode) {
1803dec9fcdSqs148142 case OP_GET:
1813dec9fcdSqs148142 TXDMA_REG_READ64(handle, TDC_STAT, channel, &cs_p->value);
1823dec9fcdSqs148142 break;
1833dec9fcdSqs148142
1843dec9fcdSqs148142 case OP_SET:
1853dec9fcdSqs148142 TXDMA_REG_WRITE64(handle, TDC_STAT, channel, cs_p->value);
1863dec9fcdSqs148142 break;
1873dec9fcdSqs148142
1883dec9fcdSqs148142 case OP_UPDATE:
1893dec9fcdSqs148142 TXDMA_REG_READ64(handle, TDC_STAT, channel, &txcs.value);
1903dec9fcdSqs148142 TXDMA_REG_WRITE64(handle, TDC_STAT, channel,
1913dec9fcdSqs148142 cs_p->value | txcs.value);
1923dec9fcdSqs148142 break;
1933dec9fcdSqs148142
1943dec9fcdSqs148142 default:
1953dec9fcdSqs148142 HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
1963dec9fcdSqs148142 " hpi_txdma_control_status"
1973dec9fcdSqs148142 " Invalid Input: control <0x%x>", op_mode));
1983dec9fcdSqs148142 return (HPI_FAILURE | HPI_TXDMA_OPCODE_INVALID(channel));
1993dec9fcdSqs148142 }
2003dec9fcdSqs148142
2013dec9fcdSqs148142 return (status);
2023dec9fcdSqs148142 }
2033dec9fcdSqs148142
2043dec9fcdSqs148142 hpi_status_t
hpi_txdma_event_mask(hpi_handle_t handle,io_op_t op_mode,uint8_t channel,tdc_int_mask_t * mask_p)2053dec9fcdSqs148142 hpi_txdma_event_mask(hpi_handle_t handle, io_op_t op_mode, uint8_t channel,
2063dec9fcdSqs148142 tdc_int_mask_t *mask_p)
2073dec9fcdSqs148142 {
2083dec9fcdSqs148142 int status = HPI_SUCCESS;
2093dec9fcdSqs148142 tdc_int_mask_t mask;
2103dec9fcdSqs148142
2113dec9fcdSqs148142 if (!TXDMA_CHANNEL_VALID(channel)) {
2123dec9fcdSqs148142 HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
2133dec9fcdSqs148142 " hpi_txdma_event_mask Invalid Input: channel <0x%x>",
2143dec9fcdSqs148142 channel));
2153dec9fcdSqs148142 return (HPI_FAILURE | HPI_TXDMA_CHANNEL_INVALID(channel));
2163dec9fcdSqs148142 }
2173dec9fcdSqs148142 switch (op_mode) {
2183dec9fcdSqs148142 case OP_GET:
2193dec9fcdSqs148142 TXDMA_REG_READ64(handle, TDC_INT_MASK, channel, &mask_p->value);
2203dec9fcdSqs148142 break;
2213dec9fcdSqs148142
2223dec9fcdSqs148142 case OP_SET:
2233dec9fcdSqs148142 TXDMA_REG_WRITE64(handle, TDC_INT_MASK, channel, mask_p->value);
2243dec9fcdSqs148142 break;
2253dec9fcdSqs148142
2263dec9fcdSqs148142 case OP_UPDATE:
2273dec9fcdSqs148142 TXDMA_REG_READ64(handle, TDC_INT_MASK, channel, &mask.value);
2283dec9fcdSqs148142 TXDMA_REG_WRITE64(handle, TDC_INT_MASK, channel,
2293dec9fcdSqs148142 mask_p->value | mask.value);
2303dec9fcdSqs148142 break;
2313dec9fcdSqs148142
2323dec9fcdSqs148142 default:
2333dec9fcdSqs148142 HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
2343dec9fcdSqs148142 " hpi_txdma_event_mask Invalid Input: eventmask <0x%x>",
2353dec9fcdSqs148142 op_mode));
2363dec9fcdSqs148142 return (HPI_FAILURE | HPI_TXDMA_OPCODE_INVALID(channel));
2373dec9fcdSqs148142 }
2383dec9fcdSqs148142
2393dec9fcdSqs148142 return (status);
2403dec9fcdSqs148142 }
2413dec9fcdSqs148142
2423dec9fcdSqs148142 hpi_status_t
hpi_txdma_ring_config(hpi_handle_t handle,io_op_t op_mode,uint8_t channel,uint64_t * reg_data)2433dec9fcdSqs148142 hpi_txdma_ring_config(hpi_handle_t handle, io_op_t op_mode,
2443dec9fcdSqs148142 uint8_t channel, uint64_t *reg_data)
2453dec9fcdSqs148142 {
2463dec9fcdSqs148142 int status = HPI_SUCCESS;
2473dec9fcdSqs148142
2483dec9fcdSqs148142 if (!TXDMA_CHANNEL_VALID(channel)) {
2493dec9fcdSqs148142 HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
2503dec9fcdSqs148142 " hpi_txdma_ring_config"
2513dec9fcdSqs148142 " Invalid Input: channel <0x%x>", channel));
2523dec9fcdSqs148142 return (HPI_FAILURE | HPI_TXDMA_CHANNEL_INVALID(channel));
2533dec9fcdSqs148142 }
2543dec9fcdSqs148142 switch (op_mode) {
2553dec9fcdSqs148142 case OP_GET:
2563dec9fcdSqs148142 TXDMA_REG_READ64(handle, TDC_TDR_CFG, channel, reg_data);
2573dec9fcdSqs148142 break;
2583dec9fcdSqs148142
2593dec9fcdSqs148142 case OP_SET:
2603dec9fcdSqs148142 TXDMA_REG_WRITE64(handle, TDC_TDR_CFG, channel, *reg_data);
2613dec9fcdSqs148142 break;
2623dec9fcdSqs148142
2633dec9fcdSqs148142 default:
2643dec9fcdSqs148142 HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
2653dec9fcdSqs148142 " hpi_txdma_ring_config"
2663dec9fcdSqs148142 " Invalid Input: ring_config <0x%x>", op_mode));
2673dec9fcdSqs148142 return (HPI_FAILURE | HPI_TXDMA_OPCODE_INVALID(channel));
2683dec9fcdSqs148142 }
2693dec9fcdSqs148142
2703dec9fcdSqs148142 return (status);
2713dec9fcdSqs148142 }
2723dec9fcdSqs148142
2733dec9fcdSqs148142 hpi_status_t
hpi_txdma_mbox_config(hpi_handle_t handle,io_op_t op_mode,uint8_t channel,uint64_t * mbox_addr)2743dec9fcdSqs148142 hpi_txdma_mbox_config(hpi_handle_t handle, io_op_t op_mode,
2753dec9fcdSqs148142 uint8_t channel, uint64_t *mbox_addr)
2763dec9fcdSqs148142 {
2773dec9fcdSqs148142 int status = HPI_SUCCESS;
2783dec9fcdSqs148142 tdc_mbh_t mh;
2793dec9fcdSqs148142 tdc_mbl_t ml;
2803dec9fcdSqs148142
2813dec9fcdSqs148142 if (!TXDMA_CHANNEL_VALID(channel)) {
2823dec9fcdSqs148142 HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
2833dec9fcdSqs148142 " hpi_txdma_mbox_config Invalid Input: channel <0x%x>",
2843dec9fcdSqs148142 channel));
2853dec9fcdSqs148142 return (HPI_FAILURE | HPI_TXDMA_CHANNEL_INVALID(channel));
2863dec9fcdSqs148142 }
2873dec9fcdSqs148142
2883dec9fcdSqs148142 mh.value = ml.value = 0;
2893dec9fcdSqs148142
2903dec9fcdSqs148142 switch (op_mode) {
2913dec9fcdSqs148142 case OP_GET:
2923dec9fcdSqs148142 TXDMA_REG_READ64(handle, TDC_MBH, channel, &mh.value);
2933dec9fcdSqs148142 TXDMA_REG_READ64(handle, TDC_MBL, channel, &ml.value);
2943dec9fcdSqs148142 *mbox_addr = ml.value;
2953dec9fcdSqs148142 *mbox_addr |= (mh.value << TDC_MBH_ADDR_SHIFT);
2963dec9fcdSqs148142
2973dec9fcdSqs148142 break;
2983dec9fcdSqs148142
2993dec9fcdSqs148142 case OP_SET:
3003dec9fcdSqs148142 ml.bits.mbaddr = ((*mbox_addr & TDC_MBL_MASK) >> TDC_MBL_SHIFT);
3013dec9fcdSqs148142 TXDMA_REG_WRITE64(handle, TDC_MBL, channel, ml.value);
3023dec9fcdSqs148142 mh.bits.mbaddr = ((*mbox_addr >> TDC_MBH_ADDR_SHIFT) &
3033dec9fcdSqs148142 TDC_MBH_MASK);
3043dec9fcdSqs148142 TXDMA_REG_WRITE64(handle, TDC_MBH, channel, mh.value);
3053dec9fcdSqs148142 break;
3063dec9fcdSqs148142
3073dec9fcdSqs148142 default:
3083dec9fcdSqs148142 HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
3093dec9fcdSqs148142 " hpi_txdma_mbox_config Invalid Input: mbox <0x%x>",
3103dec9fcdSqs148142 op_mode));
3113dec9fcdSqs148142 return (HPI_FAILURE | HPI_TXDMA_OPCODE_INVALID(channel));
3123dec9fcdSqs148142 }
3133dec9fcdSqs148142
3143dec9fcdSqs148142 return (status);
3153dec9fcdSqs148142 }
3163dec9fcdSqs148142
3173dec9fcdSqs148142 /*
3183dec9fcdSqs148142 * This function is called to set up a transmit descriptor entry.
3193dec9fcdSqs148142 */
3203dec9fcdSqs148142 hpi_status_t
hpi_txdma_desc_gather_set(hpi_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)3213dec9fcdSqs148142 hpi_txdma_desc_gather_set(hpi_handle_t handle, p_tx_desc_t desc_p,
3223dec9fcdSqs148142 uint8_t gather_index, boolean_t mark, uint8_t ngathers,
3233dec9fcdSqs148142 uint64_t dma_ioaddr, uint32_t transfer_len)
3243dec9fcdSqs148142 {
3253dec9fcdSqs148142 int status;
3263dec9fcdSqs148142
3273dec9fcdSqs148142 status = HPI_TXDMA_GATHER_INDEX(gather_index);
3283dec9fcdSqs148142 if (status) {
3293dec9fcdSqs148142 HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
3303dec9fcdSqs148142 " hpi_txdma_desc_gather_set"
3313dec9fcdSqs148142 " Invalid Input: gather_index <0x%x>", gather_index));
3323dec9fcdSqs148142 return (status);
3333dec9fcdSqs148142 }
3343dec9fcdSqs148142 if (transfer_len > TX_MAX_TRANSFER_LENGTH) {
3353dec9fcdSqs148142 HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
3363dec9fcdSqs148142 " hpi_txdma_desc_gather_set"
3373dec9fcdSqs148142 " Invalid Input: tr_len <0x%x>", transfer_len));
3383dec9fcdSqs148142 return (HPI_FAILURE | HPI_TXDMA_XFER_LEN_INVALID);
3393dec9fcdSqs148142 }
3403dec9fcdSqs148142 if (gather_index == 0) {
3413dec9fcdSqs148142 desc_p->bits.sop = 1;
3423dec9fcdSqs148142 desc_p->bits.mark = mark;
3433dec9fcdSqs148142 desc_p->bits.num_ptr = ngathers;
3443dec9fcdSqs148142 HPI_DEBUG_MSG((handle.function, HPI_TDC_CTL,
3453dec9fcdSqs148142 "hpi_txdma_gather_set: SOP len %d (%d)",
3463dec9fcdSqs148142 desc_p->bits.tr_len, transfer_len));
3473dec9fcdSqs148142 }
3483dec9fcdSqs148142 desc_p->bits.tr_len = transfer_len;
349*fe930412Sqs148142 desc_p->bits.sad = dma_ioaddr >> 32;
350*fe930412Sqs148142 desc_p->bits.sad_l = dma_ioaddr & 0xffffffff;
3513dec9fcdSqs148142
3523dec9fcdSqs148142 HPI_DEBUG_MSG((handle.function, HPI_TDC_CTL,
3533dec9fcdSqs148142 "hpi_txdma_gather_set: xfer len %d to set (%d)",
3543dec9fcdSqs148142 desc_p->bits.tr_len, transfer_len));
3553dec9fcdSqs148142
3563dec9fcdSqs148142 HXGE_MEM_PIO_WRITE64(handle, desc_p->value);
3573dec9fcdSqs148142
3583dec9fcdSqs148142 return (status);
3593dec9fcdSqs148142 }
3603dec9fcdSqs148142
3613dec9fcdSqs148142 hpi_status_t
hpi_txdma_desc_set_zero(hpi_handle_t handle,uint16_t entries)3623dec9fcdSqs148142 hpi_txdma_desc_set_zero(hpi_handle_t handle, uint16_t entries)
3633dec9fcdSqs148142 {
3643dec9fcdSqs148142 uint32_t offset;
3653dec9fcdSqs148142 int i;
3663dec9fcdSqs148142
3673dec9fcdSqs148142 /*
3683dec9fcdSqs148142 * Assume no wrapped around.
3693dec9fcdSqs148142 */
3703dec9fcdSqs148142 offset = 0;
3713dec9fcdSqs148142 for (i = 0; i < entries; i++) {
3723dec9fcdSqs148142 HXGE_REG_WR64(handle, offset, 0);
3733dec9fcdSqs148142 offset += (i * (sizeof (tx_desc_t)));
3743dec9fcdSqs148142 }
3753dec9fcdSqs148142
3763dec9fcdSqs148142 return (HPI_SUCCESS);
3773dec9fcdSqs148142 }
3783dec9fcdSqs148142
3793dec9fcdSqs148142 /*
3803dec9fcdSqs148142 * This function is called to get the transmit ring head index.
3813dec9fcdSqs148142 */
3823dec9fcdSqs148142 hpi_status_t
hpi_txdma_ring_head_get(hpi_handle_t handle,uint8_t channel,tdc_tdr_head_t * hdl_p)3833dec9fcdSqs148142 hpi_txdma_ring_head_get(hpi_handle_t handle, uint8_t channel,
3843dec9fcdSqs148142 tdc_tdr_head_t *hdl_p)
3853dec9fcdSqs148142 {
3863dec9fcdSqs148142 int status = HPI_SUCCESS;
3873dec9fcdSqs148142
3883dec9fcdSqs148142 if (!TXDMA_CHANNEL_VALID(channel)) {
3893dec9fcdSqs148142 HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
3903dec9fcdSqs148142 " hpi_txdma_ring_head_get"
3913dec9fcdSqs148142 " Invalid Input: channel <0x%x>", channel));
3923dec9fcdSqs148142 return (HPI_FAILURE | HPI_TXDMA_CHANNEL_INVALID(channel));
3933dec9fcdSqs148142 }
3943dec9fcdSqs148142 TXDMA_REG_READ64(handle, TDC_TDR_HEAD, channel, &hdl_p->value);
3953dec9fcdSqs148142
3963dec9fcdSqs148142 return (status);
3973dec9fcdSqs148142 }
3983dec9fcdSqs148142
3993dec9fcdSqs148142 /*
4003dec9fcdSqs148142 * Dumps the contents of transmit descriptors.
4013dec9fcdSqs148142 */
4023dec9fcdSqs148142 /*ARGSUSED*/
4033dec9fcdSqs148142 void
hpi_txdma_dump_desc_one(hpi_handle_t handle,p_tx_desc_t desc_p,int desc_index)4043dec9fcdSqs148142 hpi_txdma_dump_desc_one(hpi_handle_t handle, p_tx_desc_t desc_p, int desc_index)
4053dec9fcdSqs148142 {
4063dec9fcdSqs148142 tx_desc_t desc, *desp;
4073dec9fcdSqs148142
4083dec9fcdSqs148142 #ifdef HXGE_DEBUG
4093dec9fcdSqs148142 uint64_t sad;
4103dec9fcdSqs148142 int xfer_len;
4113dec9fcdSqs148142 #endif
4123dec9fcdSqs148142
4133dec9fcdSqs148142 HPI_DEBUG_MSG((handle.function, HPI_TDC_CTL,
4143dec9fcdSqs148142 "\n==> hpi_txdma_dump_desc_one: dump "
4153dec9fcdSqs148142 " desc_p $%p descriptor entry %d\n", desc_p, desc_index));
4163dec9fcdSqs148142 desc.value = 0;
4173dec9fcdSqs148142 desp = ((desc_p != NULL) ? desc_p : (p_tx_desc_t)&desc);
418*fe930412Sqs148142 HXGE_MEM_PIO_READ64(handle, &desp->value);
4193dec9fcdSqs148142 #ifdef HXGE_DEBUG
4203dec9fcdSqs148142 sad = desp->bits.sad;
421*fe930412Sqs148142 sad = (sad << 32) | desp->bits.sad_l;
4223dec9fcdSqs148142 xfer_len = desp->bits.tr_len;
4233dec9fcdSqs148142 #endif
4243dec9fcdSqs148142 HPI_DEBUG_MSG((handle.function, HPI_TDC_CTL, "\n\t: value 0x%llx\n"
4253dec9fcdSqs148142 "\t\tsad $%p\ttr_len %d len %d\tnptrs %d\tmark %d sop %d\n",
4263dec9fcdSqs148142 desp->value, sad, desp->bits.tr_len, xfer_len,
4273dec9fcdSqs148142 desp->bits.num_ptr, desp->bits.mark, desp->bits.sop));
4283dec9fcdSqs148142
4293dec9fcdSqs148142 HPI_DEBUG_MSG((handle.function, HPI_TDC_CTL,
4303dec9fcdSqs148142 "\n<== hpi_txdma_dump_desc_one: Done \n"));
4313dec9fcdSqs148142 }
4323dec9fcdSqs148142
4333dec9fcdSqs148142 /*
4343dec9fcdSqs148142 * Static functions start here.
4353dec9fcdSqs148142 */
4363dec9fcdSqs148142 static hpi_status_t
hpi_txdma_control_reset_wait(hpi_handle_t handle,uint8_t channel)4373dec9fcdSqs148142 hpi_txdma_control_reset_wait(hpi_handle_t handle, uint8_t channel)
4383dec9fcdSqs148142 {
4393dec9fcdSqs148142 tdc_tdr_cfg_t txcs;
4403dec9fcdSqs148142 int loop = 0;
4413dec9fcdSqs148142
4423dec9fcdSqs148142 txcs.value = 0;
4433dec9fcdSqs148142 do {
4443dec9fcdSqs148142 HXGE_DELAY(TXDMA_WAIT_MSEC);
4453dec9fcdSqs148142 TXDMA_REG_READ64(handle, TDC_TDR_CFG, channel, &txcs.value);
4463dec9fcdSqs148142
4473dec9fcdSqs148142 /*
4483dec9fcdSqs148142 * Reset completes when this bit is set to 1 by hw
4493dec9fcdSqs148142 */
4503dec9fcdSqs148142 if (txcs.bits.qst) {
4513dec9fcdSqs148142 return (HPI_SUCCESS);
4523dec9fcdSqs148142 }
4533dec9fcdSqs148142 loop++;
4543dec9fcdSqs148142 } while (loop < TXDMA_WAIT_LOOP);
4553dec9fcdSqs148142
4563dec9fcdSqs148142 if (loop == TXDMA_WAIT_LOOP) {
4573dec9fcdSqs148142 HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
4583dec9fcdSqs148142 "hpi_txdma_control_reset_wait: RST bit not "
4593dec9fcdSqs148142 "cleared to 0 txcs.bits 0x%llx", txcs.value));
4603dec9fcdSqs148142 return (HPI_FAILURE | HPI_TXDMA_RESET_FAILED);
4613dec9fcdSqs148142 }
4623dec9fcdSqs148142 return (HPI_SUCCESS);
4633dec9fcdSqs148142 }
4643dec9fcdSqs148142
465*fe930412Sqs148142 hpi_status_t
hpi_txdma_control_stop_wait(hpi_handle_t handle,uint8_t channel)4663dec9fcdSqs148142 hpi_txdma_control_stop_wait(hpi_handle_t handle, uint8_t channel)
4673dec9fcdSqs148142 {
4683dec9fcdSqs148142 tdc_tdr_cfg_t txcs;
4693dec9fcdSqs148142 int loop = 0;
4703dec9fcdSqs148142
4713dec9fcdSqs148142 do {
4723dec9fcdSqs148142 txcs.value = 0;
4733dec9fcdSqs148142 HXGE_DELAY(TXDMA_WAIT_MSEC);
4743dec9fcdSqs148142 TXDMA_REG_READ64(handle, TDC_TDR_CFG, channel, &txcs.value);
4753dec9fcdSqs148142 if (txcs.bits.qst) {
4763dec9fcdSqs148142 return (HPI_SUCCESS);
4773dec9fcdSqs148142 }
4783dec9fcdSqs148142 loop++;
4793dec9fcdSqs148142 } while (loop < TXDMA_WAIT_LOOP);
4803dec9fcdSqs148142
4813dec9fcdSqs148142 if (loop == TXDMA_WAIT_LOOP) {
4823dec9fcdSqs148142 HPI_ERROR_MSG((handle.function, HPI_ERR_CTL,
4833dec9fcdSqs148142 "hpi_txdma_control_stop_wait: SNG_STATE not "
4843dec9fcdSqs148142 "set to 1 txcs.bits 0x%llx", txcs.value));
4853dec9fcdSqs148142 return (HPI_FAILURE | HPI_TXDMA_STOP_FAILED);
4863dec9fcdSqs148142 }
4873dec9fcdSqs148142 return (HPI_SUCCESS);
4883dec9fcdSqs148142 }
489