xref: /titanic_50/usr/src/uts/common/io/hxge/hpi_txdma.c (revision fe930412c257f961ae67039de3b164b83717976a)
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