108057504Sxy /*
208057504Sxy  * This file is provided under a CDDLv1 license.  When using or
308057504Sxy  * redistributing this file, you may do so under this license.
408057504Sxy  * In redistributing this file this license must be included
508057504Sxy  * and no other modification of this header file is permitted.
608057504Sxy  *
708057504Sxy  * CDDL LICENSE SUMMARY
808057504Sxy  *
9d5c3073dSchenlu chen - Sun Microsystems - Beijing China  * Copyright(c) 1999 - 2009 Intel Corporation. All rights reserved.
1008057504Sxy  *
1108057504Sxy  * The contents of this file are subject to the terms of Version
1208057504Sxy  * 1.0 of the Common Development and Distribution License (the "License").
1308057504Sxy  *
1408057504Sxy  * You should have received a copy of the License with this software.
1508057504Sxy  * You can obtain a copy of the License at
1608057504Sxy  *	http://www.opensolaris.org/os/licensing.
1708057504Sxy  * See the License for the specific language governing permissions
1808057504Sxy  * and limitations under the License.
1908057504Sxy  */
2008057504Sxy 
2108057504Sxy /*
220dc2366fSVenugopal Iyer  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23da14cebeSEric Cheng  * Use is subject to license terms.
2408057504Sxy  */
2508057504Sxy 
265c68564dSBryan Cantrill /*
2749b78600SRobert Mustacchi  * Copyright 2016 Joyent, Inc.
285c68564dSBryan Cantrill  */
295c68564dSBryan Cantrill 
3008057504Sxy /*
3108057504Sxy  * **********************************************************************
3208057504Sxy  *									*
3308057504Sxy  * Module Name:								*
3408057504Sxy  *   e1000g_tx.c							*
3508057504Sxy  *									*
3608057504Sxy  * Abstract:								*
3725f2d433Sxy  *   This file contains some routines that take care of Transmit,	*
3825f2d433Sxy  *   make the hardware to send the data pointed by the packet out	*
3925f2d433Sxy  *   on to the physical medium.						*
4008057504Sxy  *									*
4108057504Sxy  * **********************************************************************
4208057504Sxy  */
4308057504Sxy 
4408057504Sxy #include "e1000g_sw.h"
4508057504Sxy #include "e1000g_debug.h"
4608057504Sxy 
4708057504Sxy static boolean_t e1000g_send(struct e1000g *, mblk_t *);
4825f2d433Sxy static int e1000g_tx_copy(e1000g_tx_ring_t *,
49c7770590Smx     p_tx_sw_packet_t, mblk_t *, boolean_t);
5025f2d433Sxy static int e1000g_tx_bind(e1000g_tx_ring_t *,
5125f2d433Sxy     p_tx_sw_packet_t, mblk_t *);
524d737963Sxiangtao you - Sun Microsystems - Beijing China static boolean_t e1000g_retrieve_context(mblk_t *, context_data_t *, size_t);
53c7770590Smx static boolean_t e1000g_check_context(e1000g_tx_ring_t *, context_data_t *);
5408057504Sxy static int e1000g_fill_tx_ring(e1000g_tx_ring_t *, LIST_DESCRIBER *,
55c7770590Smx     context_data_t *);
56c7770590Smx static void e1000g_fill_context_descriptor(context_data_t *,
5708057504Sxy     struct e1000_context_desc *);
5825f2d433Sxy static int e1000g_fill_tx_desc(e1000g_tx_ring_t *,
5925f2d433Sxy     p_tx_sw_packet_t, uint64_t, size_t);
6008057504Sxy static uint32_t e1000g_fill_82544_desc(uint64_t Address, size_t Length,
6125f2d433Sxy     p_desc_array_t desc_array);
6225f2d433Sxy static int e1000g_tx_workaround_PCIX_82544(p_tx_sw_packet_t, uint64_t, size_t);
6325f2d433Sxy static int e1000g_tx_workaround_jumbo_82544(p_tx_sw_packet_t, uint64_t, size_t);
6408057504Sxy static void e1000g_82547_timeout(void *);
6508057504Sxy static void e1000g_82547_tx_move_tail(e1000g_tx_ring_t *);
6608057504Sxy static void e1000g_82547_tx_move_tail_work(e1000g_tx_ring_t *);
6708057504Sxy 
6825f2d433Sxy #ifndef E1000G_DEBUG
6908057504Sxy #pragma inline(e1000g_tx_copy)
7008057504Sxy #pragma inline(e1000g_tx_bind)
714d737963Sxiangtao you - Sun Microsystems - Beijing China #pragma inline(e1000g_retrieve_context)
72c7770590Smx #pragma inline(e1000g_check_context)
7308057504Sxy #pragma inline(e1000g_fill_tx_ring)
7408057504Sxy #pragma inline(e1000g_fill_context_descriptor)
7508057504Sxy #pragma inline(e1000g_fill_tx_desc)
7608057504Sxy #pragma inline(e1000g_fill_82544_desc)
7708057504Sxy #pragma inline(e1000g_tx_workaround_PCIX_82544)
7808057504Sxy #pragma inline(e1000g_tx_workaround_jumbo_82544)
7925f2d433Sxy #pragma inline(e1000g_free_tx_swpkt)
8008057504Sxy #endif
8108057504Sxy 
8208057504Sxy /*
8325f2d433Sxy  * e1000g_free_tx_swpkt	- free up the tx sw packet
8425f2d433Sxy  *
8525f2d433Sxy  * Unbind the previously bound DMA handle for a given
8625f2d433Sxy  * transmit sw packet. And reset the sw packet data.
8708057504Sxy  */
8808057504Sxy void
e1000g_free_tx_swpkt(register p_tx_sw_packet_t packet)8925f2d433Sxy e1000g_free_tx_swpkt(register p_tx_sw_packet_t packet)
9008057504Sxy {
9108057504Sxy 	switch (packet->data_transfer_type) {
9208057504Sxy 	case USE_BCOPY:
9308057504Sxy 		packet->tx_buf->len = 0;
9408057504Sxy 		break;
9508057504Sxy #ifdef __sparc
9608057504Sxy 	case USE_DVMA:
9708057504Sxy 		dvma_unload(packet->tx_dma_handle, 0, -1);
9808057504Sxy 		break;
9908057504Sxy #endif
10008057504Sxy 	case USE_DMA:
101fe62dec3SChen-Liang Xu 		(void) ddi_dma_unbind_handle(packet->tx_dma_handle);
10208057504Sxy 		break;
10308057504Sxy 	default:
10408057504Sxy 		break;
10508057504Sxy 	}
10608057504Sxy 
10708057504Sxy 	/*
10808057504Sxy 	 * The mblk has been stripped off the sw packet
10908057504Sxy 	 * and will be freed in a triggered soft intr.
11008057504Sxy 	 */
11108057504Sxy 	ASSERT(packet->mp == NULL);
11208057504Sxy 
11308057504Sxy 	packet->data_transfer_type = USE_NONE;
11408057504Sxy 	packet->num_mblk_frag = 0;
11508057504Sxy 	packet->num_desc = 0;
11608057504Sxy }
11708057504Sxy 
11808057504Sxy mblk_t *
e1000g_m_tx(void * arg,mblk_t * mp)11908057504Sxy e1000g_m_tx(void *arg, mblk_t *mp)
12008057504Sxy {
12108057504Sxy 	struct e1000g *Adapter = (struct e1000g *)arg;
12208057504Sxy 	mblk_t *next;
12308057504Sxy 
12408057504Sxy 	rw_enter(&Adapter->chip_lock, RW_READER);
12508057504Sxy 
126d5c3073dSchenlu chen - Sun Microsystems - Beijing China 	if ((Adapter->e1000g_state & E1000G_SUSPENDED) ||
127d5c3073dSchenlu chen - Sun Microsystems - Beijing China 	    !(Adapter->e1000g_state & E1000G_STARTED) ||
1289b6541b3Sgl 	    (Adapter->link_state != LINK_STATE_UP)) {
12908057504Sxy 		freemsgchain(mp);
13008057504Sxy 		mp = NULL;
13108057504Sxy 	}
13208057504Sxy 
13308057504Sxy 	while (mp != NULL) {
13408057504Sxy 		next = mp->b_next;
13508057504Sxy 		mp->b_next = NULL;
13608057504Sxy 
13708057504Sxy 		if (!e1000g_send(Adapter, mp)) {
13808057504Sxy 			mp->b_next = next;
13908057504Sxy 			break;
14008057504Sxy 		}
14108057504Sxy 
14208057504Sxy 		mp = next;
14308057504Sxy 	}
14408057504Sxy 
14508057504Sxy 	rw_exit(&Adapter->chip_lock);
14608057504Sxy 	return (mp);
14708057504Sxy }
14808057504Sxy 
14908057504Sxy /*
15025f2d433Sxy  * e1000g_send -  send packets onto the wire
15125f2d433Sxy  *
15225f2d433Sxy  * Called from e1000g_m_tx with an mblk ready to send. this
15325f2d433Sxy  * routine sets up the transmit descriptors and sends data to
15425f2d433Sxy  * the wire. It also pushes the just transmitted packet to
15525f2d433Sxy  * the used tx sw packet list.
15608057504Sxy  */
15708057504Sxy static boolean_t
e1000g_send(struct e1000g * Adapter,mblk_t * mp)15808057504Sxy e1000g_send(struct e1000g *Adapter, mblk_t *mp)
15908057504Sxy {
16025f2d433Sxy 	p_tx_sw_packet_t packet;
16108057504Sxy 	LIST_DESCRIBER pending_list;
16208057504Sxy 	size_t len;
16308057504Sxy 	size_t msg_size;
16408057504Sxy 	uint32_t frag_count;
16508057504Sxy 	int desc_count;
16608057504Sxy 	uint32_t desc_total;
16743a17687SMiles Xu, Sun Microsystems 	uint32_t bcopy_thresh;
16843a17687SMiles Xu, Sun Microsystems 	uint32_t hdr_frag_len;
169c7770590Smx 	boolean_t tx_undersize_flag;
17008057504Sxy 	mblk_t *nmp;
17108057504Sxy 	mblk_t *tmp;
17243a17687SMiles Xu, Sun Microsystems 	mblk_t *new_mp;
17343a17687SMiles Xu, Sun Microsystems 	mblk_t *pre_mp;
1741b5c080fSchangqing li - Sun Microsystems - Beijing China 	mblk_t *next_mp;
17508057504Sxy 	e1000g_tx_ring_t *tx_ring;
176c7770590Smx 	context_data_t cur_context;
17708057504Sxy 
17825f2d433Sxy 	tx_ring = Adapter->tx_ring;
17943a17687SMiles Xu, Sun Microsystems 	bcopy_thresh = Adapter->tx_bcopy_thresh;
18025f2d433Sxy 
18108057504Sxy 	/* Get the total size and frags number of the message */
182c7770590Smx 	tx_undersize_flag = B_FALSE;
18308057504Sxy 	frag_count = 0;
18408057504Sxy 	msg_size = 0;
18508057504Sxy 	for (nmp = mp; nmp; nmp = nmp->b_cont) {
18608057504Sxy 		frag_count++;
18708057504Sxy 		msg_size += MBLKL(nmp);
18808057504Sxy 	}
18908057504Sxy 
1904d737963Sxiangtao you - Sun Microsystems - Beijing China 	/* retrieve and compute information for context descriptor */
1914d737963Sxiangtao you - Sun Microsystems - Beijing China 	if (!e1000g_retrieve_context(mp, &cur_context, msg_size)) {
192c7770590Smx 		freemsg(mp);
193c7770590Smx 		return (B_TRUE);
194c7770590Smx 	}
195c7770590Smx 
196c7770590Smx 	/*
197c7770590Smx 	 * Make sure the packet is less than the allowed size
198c7770590Smx 	 */
199c7770590Smx 	if (!cur_context.lso_flag &&
200c7770590Smx 	    (msg_size > Adapter->max_frame_size - ETHERFCSL)) {
20108057504Sxy 		/*
20208057504Sxy 		 * For the over size packet, we'll just drop it.
20308057504Sxy 		 * So we return B_TRUE here.
20408057504Sxy 		 */
20525f2d433Sxy 		E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
20608057504Sxy 		    "Tx packet out of bound. length = %d \n", msg_size);
20725f2d433Sxy 		E1000G_STAT(tx_ring->stat_over_size);
20808057504Sxy 		freemsg(mp);
20908057504Sxy 		return (B_TRUE);
21008057504Sxy 	}
21108057504Sxy 
21208057504Sxy 	/*
21308057504Sxy 	 * Check and reclaim tx descriptors.
21408057504Sxy 	 * This low water mark check should be done all the time as
21508057504Sxy 	 * Transmit interrupt delay can produce Transmit interrupts little
21608057504Sxy 	 * late and that may cause few problems related to reaping Tx
21708057504Sxy 	 * Descriptors... As you may run short of them before getting any
21808057504Sxy 	 * transmit interrupt...
21908057504Sxy 	 */
220da14cebeSEric Cheng 	if (tx_ring->tbd_avail < DEFAULT_TX_NO_RESOURCE) {
22108057504Sxy 		(void) e1000g_recycle(tx_ring);
22247b7744cSyy 		E1000G_DEBUG_STAT(tx_ring->stat_recycle);
22308057504Sxy 
22447b7744cSyy 		if (tx_ring->tbd_avail < DEFAULT_TX_NO_RESOURCE) {
22547b7744cSyy 			E1000G_DEBUG_STAT(tx_ring->stat_lack_desc);
22647b7744cSyy 			goto tx_no_resource;
22747b7744cSyy 		}
22808057504Sxy 	}
22908057504Sxy 
23008057504Sxy 	/*
23108057504Sxy 	 * If the message size is less than the minimum ethernet packet size,
23208057504Sxy 	 * we'll use bcopy to send it, and padd it to 60 bytes later.
23308057504Sxy 	 */
2349ce7e93cScc 	if (msg_size < ETHERMIN) {
23525f2d433Sxy 		E1000G_DEBUG_STAT(tx_ring->stat_under_size);
236c7770590Smx 		tx_undersize_flag = B_TRUE;
23708057504Sxy 	}
23808057504Sxy 
23908057504Sxy 	/* Initialize variables */
24008057504Sxy 	desc_count = 1;	/* The initial value should be greater than 0 */
24108057504Sxy 	desc_total = 0;
2421b5c080fSchangqing li - Sun Microsystems - Beijing China 	new_mp = NULL;
24308057504Sxy 	QUEUE_INIT_LIST(&pending_list);
24408057504Sxy 
24508057504Sxy 	/* Process each mblk fragment and fill tx descriptors */
24643a17687SMiles Xu, Sun Microsystems 	/*
24743a17687SMiles Xu, Sun Microsystems 	 * The software should guarantee LSO packet header(MAC+IP+TCP)
24843a17687SMiles Xu, Sun Microsystems 	 * to be within one descriptor. Here we reallocate and refill the
24943a17687SMiles Xu, Sun Microsystems 	 * the header if it's physical memory non-contiguous.
25043a17687SMiles Xu, Sun Microsystems 	 */
25143a17687SMiles Xu, Sun Microsystems 	if (cur_context.lso_flag) {
25243a17687SMiles Xu, Sun Microsystems 		/* find the last fragment of the header */
25343a17687SMiles Xu, Sun Microsystems 		len = MBLKL(mp);
25443a17687SMiles Xu, Sun Microsystems 		ASSERT(len > 0);
2551b5c080fSchangqing li - Sun Microsystems - Beijing China 		next_mp = mp;
25643a17687SMiles Xu, Sun Microsystems 		pre_mp = NULL;
25743a17687SMiles Xu, Sun Microsystems 		while (len < cur_context.hdr_len) {
2581b5c080fSchangqing li - Sun Microsystems - Beijing China 			pre_mp = next_mp;
2591b5c080fSchangqing li - Sun Microsystems - Beijing China 			next_mp = next_mp->b_cont;
2601b5c080fSchangqing li - Sun Microsystems - Beijing China 			len += MBLKL(next_mp);
26143a17687SMiles Xu, Sun Microsystems 		}
26243a17687SMiles Xu, Sun Microsystems 		/*
26343a17687SMiles Xu, Sun Microsystems 		 * If the header and the payload are in different mblks,
26443a17687SMiles Xu, Sun Microsystems 		 * we simply force the header to be copied into pre-allocated
26543a17687SMiles Xu, Sun Microsystems 		 * page-aligned buffer.
26643a17687SMiles Xu, Sun Microsystems 		 */
26743a17687SMiles Xu, Sun Microsystems 		if (len == cur_context.hdr_len)
26843a17687SMiles Xu, Sun Microsystems 			goto adjust_threshold;
26943a17687SMiles Xu, Sun Microsystems 
2701b5c080fSchangqing li - Sun Microsystems - Beijing China 		hdr_frag_len = cur_context.hdr_len - (len - MBLKL(next_mp));
27143a17687SMiles Xu, Sun Microsystems 		/*
27296ea4e93Schangqing li - Sun Microsystems - Beijing China 		 * There are three cases we need to reallocate a mblk for the
27343a17687SMiles Xu, Sun Microsystems 		 * last header fragment:
27496ea4e93Schangqing li - Sun Microsystems - Beijing China 		 *
27543a17687SMiles Xu, Sun Microsystems 		 * 1. the header is in multiple mblks and the last fragment
27643a17687SMiles Xu, Sun Microsystems 		 * share the same mblk with the payload
27796ea4e93Schangqing li - Sun Microsystems - Beijing China 		 *
27843a17687SMiles Xu, Sun Microsystems 		 * 2. the header is in a single mblk shared with the payload
27943a17687SMiles Xu, Sun Microsystems 		 * and the header is physical memory non-contiguous
28096ea4e93Schangqing li - Sun Microsystems - Beijing China 		 *
28196ea4e93Schangqing li - Sun Microsystems - Beijing China 		 * 3. there is 4 KB boundary within the header and 64 bytes
28296ea4e93Schangqing li - Sun Microsystems - Beijing China 		 * following the end of the header bytes. The case may cause
28396ea4e93Schangqing li - Sun Microsystems - Beijing China 		 * TCP data corruption issue.
28496ea4e93Schangqing li - Sun Microsystems - Beijing China 		 *
28596ea4e93Schangqing li - Sun Microsystems - Beijing China 		 * The workaround for the case #2 and case #3 is:
28696ea4e93Schangqing li - Sun Microsystems - Beijing China 		 *   Assuming standard Ethernet/IP/TCP headers of 54 bytes,
28796ea4e93Schangqing li - Sun Microsystems - Beijing China 		 *   this means that the buffer(containing the headers) should
28896ea4e93Schangqing li - Sun Microsystems - Beijing China 		 *   not start -118 bytes before a 4 KB boundary. For example,
28996ea4e93Schangqing li - Sun Microsystems - Beijing China 		 *   128-byte alignment for this buffer could be used to fulfill
29096ea4e93Schangqing li - Sun Microsystems - Beijing China 		 *   this condition.
29143a17687SMiles Xu, Sun Microsystems 		 */
2921b5c080fSchangqing li - Sun Microsystems - Beijing China 		if ((next_mp != mp) ||
29396ea4e93Schangqing li - Sun Microsystems - Beijing China 		    (P2NPHASE((uintptr_t)next_mp->b_rptr,
29496ea4e93Schangqing li - Sun Microsystems - Beijing China 		    E1000_LSO_FIRST_DESC_ALIGNMENT_BOUNDARY_4K)
29596ea4e93Schangqing li - Sun Microsystems - Beijing China 		    < E1000_LSO_FIRST_DESC_ALIGNMENT)) {
29643a17687SMiles Xu, Sun Microsystems 			E1000G_DEBUG_STAT(tx_ring->stat_lso_header_fail);
29743a17687SMiles Xu, Sun Microsystems 			/*
29843a17687SMiles Xu, Sun Microsystems 			 * reallocate the mblk for the last header fragment,
29943a17687SMiles Xu, Sun Microsystems 			 * expect to bcopy into pre-allocated page-aligned
30043a17687SMiles Xu, Sun Microsystems 			 * buffer
30143a17687SMiles Xu, Sun Microsystems 			 */
302*f52680feSToomas Soome 			new_mp = allocb(hdr_frag_len, 0);
30343a17687SMiles Xu, Sun Microsystems 			if (!new_mp)
30443a17687SMiles Xu, Sun Microsystems 				return (B_FALSE);
3051b5c080fSchangqing li - Sun Microsystems - Beijing China 			bcopy(next_mp->b_rptr, new_mp->b_rptr, hdr_frag_len);
30643a17687SMiles Xu, Sun Microsystems 			/* link the new header fragment with the other parts */
30743a17687SMiles Xu, Sun Microsystems 			new_mp->b_wptr = new_mp->b_rptr + hdr_frag_len;
3081b5c080fSchangqing li - Sun Microsystems - Beijing China 			new_mp->b_cont = next_mp;
30943a17687SMiles Xu, Sun Microsystems 			if (pre_mp)
31043a17687SMiles Xu, Sun Microsystems 				pre_mp->b_cont = new_mp;
31154e0d7a5SMiles Xu, Sun Microsystems 			else
31243a17687SMiles Xu, Sun Microsystems 				mp = new_mp;
3131b5c080fSchangqing li - Sun Microsystems - Beijing China 			next_mp->b_rptr += hdr_frag_len;
3141b5c080fSchangqing li - Sun Microsystems - Beijing China 			frag_count++;
31543a17687SMiles Xu, Sun Microsystems 		}
31643a17687SMiles Xu, Sun Microsystems adjust_threshold:
31743a17687SMiles Xu, Sun Microsystems 		/*
31843a17687SMiles Xu, Sun Microsystems 		 * adjust the bcopy threshhold to guarantee
31943a17687SMiles Xu, Sun Microsystems 		 * the header to use bcopy way
32043a17687SMiles Xu, Sun Microsystems 		 */
32143a17687SMiles Xu, Sun Microsystems 		if (bcopy_thresh < cur_context.hdr_len)
32243a17687SMiles Xu, Sun Microsystems 			bcopy_thresh = cur_context.hdr_len;
32343a17687SMiles Xu, Sun Microsystems 	}
32443a17687SMiles Xu, Sun Microsystems 
32508057504Sxy 	packet = NULL;
32608057504Sxy 	nmp = mp;
32708057504Sxy 	while (nmp) {
32808057504Sxy 		tmp = nmp->b_cont;
32908057504Sxy 
33008057504Sxy 		len = MBLKL(nmp);
33108057504Sxy 		/* Check zero length mblks */
33208057504Sxy 		if (len == 0) {
33325f2d433Sxy 			E1000G_DEBUG_STAT(tx_ring->stat_empty_frags);
33408057504Sxy 			/*
33508057504Sxy 			 * If there're no packet buffers have been used,
33608057504Sxy 			 * or we just completed processing a buffer, then
33708057504Sxy 			 * skip the empty mblk fragment.
33808057504Sxy 			 * Otherwise, there's still a pending buffer that
33908057504Sxy 			 * needs to be processed (tx_copy).
34008057504Sxy 			 */
34108057504Sxy 			if (desc_count > 0) {
34208057504Sxy 				nmp = tmp;
34308057504Sxy 				continue;
34408057504Sxy 			}
34508057504Sxy 		}
34608057504Sxy 
34708057504Sxy 		/*
34808057504Sxy 		 * Get a new TxSwPacket to process mblk buffers.
34908057504Sxy 		 */
35008057504Sxy 		if (desc_count > 0) {
35108057504Sxy 			mutex_enter(&tx_ring->freelist_lock);
35225f2d433Sxy 			packet = (p_tx_sw_packet_t)
35308057504Sxy 			    QUEUE_POP_HEAD(&tx_ring->free_list);
35408057504Sxy 			mutex_exit(&tx_ring->freelist_lock);
35508057504Sxy 
35608057504Sxy 			if (packet == NULL) {
35725f2d433Sxy 				E1000G_DEBUGLOG_0(Adapter, E1000G_INFO_LEVEL,
35808057504Sxy 				    "No Tx SwPacket available\n");
35925f2d433Sxy 				E1000G_STAT(tx_ring->stat_no_swpkt);
36008057504Sxy 				goto tx_send_failed;
36108057504Sxy 			}
36208057504Sxy 			QUEUE_PUSH_TAIL(&pending_list, &packet->Link);
36308057504Sxy 		}
36408057504Sxy 
36508057504Sxy 		ASSERT(packet);
36608057504Sxy 		/*
36708057504Sxy 		 * If the size of the fragment is less than the tx_bcopy_thresh
36808057504Sxy 		 * we'll use bcopy; Otherwise, we'll use DMA binding.
36908057504Sxy 		 */
37043a17687SMiles Xu, Sun Microsystems 		if ((len <= bcopy_thresh) || tx_undersize_flag) {
37108057504Sxy 			desc_count =
372c7770590Smx 			    e1000g_tx_copy(tx_ring, packet, nmp,
373c7770590Smx 			    tx_undersize_flag);
37425f2d433Sxy 			E1000G_DEBUG_STAT(tx_ring->stat_copy);
37508057504Sxy 		} else {
37608057504Sxy 			desc_count =
37725f2d433Sxy 			    e1000g_tx_bind(tx_ring, packet, nmp);
37825f2d433Sxy 			E1000G_DEBUG_STAT(tx_ring->stat_bind);
37908057504Sxy 		}
38008057504Sxy 
38108057504Sxy 		if (desc_count > 0)
38208057504Sxy 			desc_total += desc_count;
38325f2d433Sxy 		else if (desc_count < 0)
38425f2d433Sxy 			goto tx_send_failed;
38508057504Sxy 
38608057504Sxy 		nmp = tmp;
38708057504Sxy 	}
38808057504Sxy 
38908057504Sxy 	/* Assign the message to the last sw packet */
39008057504Sxy 	ASSERT(packet);
39108057504Sxy 	ASSERT(packet->mp == NULL);
39208057504Sxy 	packet->mp = mp;
39308057504Sxy 
39408057504Sxy 	/* Try to recycle the tx descriptors again */
39596ea4e93Schangqing li - Sun Microsystems - Beijing China 	if (tx_ring->tbd_avail < (desc_total + 3)) {
39625f2d433Sxy 		E1000G_DEBUG_STAT(tx_ring->stat_recycle_retry);
39708057504Sxy 		(void) e1000g_recycle(tx_ring);
39808057504Sxy 	}
39908057504Sxy 
40008057504Sxy 	mutex_enter(&tx_ring->tx_lock);
40108057504Sxy 
40208057504Sxy 	/*
40308057504Sxy 	 * If the number of available tx descriptors is not enough for transmit
40408057504Sxy 	 * (one redundant descriptor and one hw checksum context descriptor are
40508057504Sxy 	 * included), then return failure.
40608057504Sxy 	 */
40796ea4e93Schangqing li - Sun Microsystems - Beijing China 	if (tx_ring->tbd_avail < (desc_total + 3)) {
40825f2d433Sxy 		E1000G_DEBUGLOG_0(Adapter, E1000G_INFO_LEVEL,
40908057504Sxy 		    "No Enough Tx descriptors\n");
41025f2d433Sxy 		E1000G_STAT(tx_ring->stat_no_desc);
41108057504Sxy 		mutex_exit(&tx_ring->tx_lock);
41208057504Sxy 		goto tx_send_failed;
41308057504Sxy 	}
41408057504Sxy 
415c7770590Smx 	desc_count = e1000g_fill_tx_ring(tx_ring, &pending_list, &cur_context);
41608057504Sxy 
41708057504Sxy 	mutex_exit(&tx_ring->tx_lock);
41808057504Sxy 
41908057504Sxy 	ASSERT(desc_count > 0);
42008057504Sxy 
42108057504Sxy 	/* Send successful */
42208057504Sxy 	return (B_TRUE);
42308057504Sxy 
42408057504Sxy tx_send_failed:
4251b5c080fSchangqing li - Sun Microsystems - Beijing China 	/* Restore mp to original */
4261b5c080fSchangqing li - Sun Microsystems - Beijing China 	if (new_mp) {
4271b5c080fSchangqing li - Sun Microsystems - Beijing China 		if (pre_mp) {
4281b5c080fSchangqing li - Sun Microsystems - Beijing China 			pre_mp->b_cont = next_mp;
4291b5c080fSchangqing li - Sun Microsystems - Beijing China 		}
4301b5c080fSchangqing li - Sun Microsystems - Beijing China 		new_mp->b_cont = NULL;
4311b5c080fSchangqing li - Sun Microsystems - Beijing China 		freemsg(new_mp);
4321b5c080fSchangqing li - Sun Microsystems - Beijing China 
4331b5c080fSchangqing li - Sun Microsystems - Beijing China 		next_mp->b_rptr -= hdr_frag_len;
4341b5c080fSchangqing li - Sun Microsystems - Beijing China 	}
4351b5c080fSchangqing li - Sun Microsystems - Beijing China 
43647b7744cSyy 	/*
43747b7744cSyy 	 * Enable Transmit interrupts, so that the interrupt routine can
43847b7744cSyy 	 * call mac_tx_update() when transmit descriptors become available.
43947b7744cSyy 	 */
440da14cebeSEric Cheng 	tx_ring->resched_timestamp = ddi_get_lbolt();
44147b7744cSyy 	tx_ring->resched_needed = B_TRUE;
44247b7744cSyy 	if (!Adapter->tx_intr_enable)
44347b7744cSyy 		e1000g_mask_tx_interrupt(Adapter);
44447b7744cSyy 
44508057504Sxy 	/* Free pending TxSwPackets */
44625f2d433Sxy 	packet = (p_tx_sw_packet_t)QUEUE_GET_HEAD(&pending_list);
44708057504Sxy 	while (packet) {
44808057504Sxy 		packet->mp = NULL;
44925f2d433Sxy 		e1000g_free_tx_swpkt(packet);
45025f2d433Sxy 		packet = (p_tx_sw_packet_t)
45108057504Sxy 		    QUEUE_GET_NEXT(&pending_list, &packet->Link);
45208057504Sxy 	}
45308057504Sxy 
45408057504Sxy 	/* Return pending TxSwPackets to the "Free" list */
45508057504Sxy 	mutex_enter(&tx_ring->freelist_lock);
45608057504Sxy 	QUEUE_APPEND(&tx_ring->free_list, &pending_list);
45708057504Sxy 	mutex_exit(&tx_ring->freelist_lock);
45808057504Sxy 
45925f2d433Sxy 	E1000G_STAT(tx_ring->stat_send_fail);
46008057504Sxy 
46147b7744cSyy 	/* Message will be scheduled for re-transmit */
46247b7744cSyy 	return (B_FALSE);
46308057504Sxy 
46408057504Sxy tx_no_resource:
46508057504Sxy 	/*
46608057504Sxy 	 * Enable Transmit interrupts, so that the interrupt routine can
46708057504Sxy 	 * call mac_tx_update() when transmit descriptors become available.
46808057504Sxy 	 */
469da14cebeSEric Cheng 	tx_ring->resched_timestamp = ddi_get_lbolt();
47025f2d433Sxy 	tx_ring->resched_needed = B_TRUE;
47108057504Sxy 	if (!Adapter->tx_intr_enable)
47225f2d433Sxy 		e1000g_mask_tx_interrupt(Adapter);
47308057504Sxy 
47408057504Sxy 	/* Message will be scheduled for re-transmit */
47508057504Sxy 	return (B_FALSE);
47608057504Sxy }
47708057504Sxy 
4787941757cSxy static boolean_t
e1000g_retrieve_context(mblk_t * mp,context_data_t * cur_context,size_t msg_size)4794d737963Sxiangtao you - Sun Microsystems - Beijing China e1000g_retrieve_context(mblk_t *mp, context_data_t *cur_context,
480c7770590Smx     size_t msg_size)
4817941757cSxy {
482c7770590Smx 	uintptr_t ip_start;
483c7770590Smx 	uintptr_t tcp_start;
484c7770590Smx 	mblk_t *nmp;
485da14cebeSEric Cheng 	uint32_t lsoflags;
486da14cebeSEric Cheng 	uint32_t mss;
4877941757cSxy 
488c7770590Smx 	bzero(cur_context, sizeof (context_data_t));
4897941757cSxy 
490da14cebeSEric Cheng 	/* first check lso information */
4910dc2366fSVenugopal Iyer 	mac_lso_get(mp, &mss, &lsoflags);
492da14cebeSEric Cheng 
493c7770590Smx 	/* retrieve checksum info */
4940dc2366fSVenugopal Iyer 	mac_hcksum_get(mp, &cur_context->cksum_start,
495c7770590Smx 	    &cur_context->cksum_stuff, NULL, NULL, &cur_context->cksum_flags);
4964d737963Sxiangtao you - Sun Microsystems - Beijing China 	/* retrieve ethernet header size */
497fe62dec3SChen-Liang Xu 	if (((struct ether_vlan_header *)(uintptr_t)mp->b_rptr)->ether_tpid ==
498c7770590Smx 	    htons(ETHERTYPE_VLAN))
499c7770590Smx 		cur_context->ether_header_size =
500c7770590Smx 		    sizeof (struct ether_vlan_header);
501c7770590Smx 	else
502c7770590Smx 		cur_context->ether_header_size =
503c7770590Smx 		    sizeof (struct ether_header);
504c7770590Smx 
505da14cebeSEric Cheng 	if (lsoflags & HW_LSO) {
506da14cebeSEric Cheng 		ASSERT(mss != 0);
507da14cebeSEric Cheng 
508da14cebeSEric Cheng 		/* free the invalid packet */
509da14cebeSEric Cheng 		if (mss == 0 ||
510da14cebeSEric Cheng 		    !((cur_context->cksum_flags & HCK_PARTIALCKSUM) &&
511da14cebeSEric Cheng 		    (cur_context->cksum_flags & HCK_IPV4_HDRCKSUM))) {
512da14cebeSEric Cheng 			return (B_FALSE);
513da14cebeSEric Cheng 		}
514da14cebeSEric Cheng 		cur_context->mss = (uint16_t)mss;
515da14cebeSEric Cheng 		cur_context->lso_flag = B_TRUE;
516da14cebeSEric Cheng 
517da14cebeSEric Cheng 		/*
518da14cebeSEric Cheng 		 * Some fields are cleared for the hardware to fill
519da14cebeSEric Cheng 		 * in. We don't assume Ethernet header, IP header and
520da14cebeSEric Cheng 		 * TCP header are always in the same mblk fragment,
521da14cebeSEric Cheng 		 * while we assume each header is always within one
522da14cebeSEric Cheng 		 * mblk fragment and Ethernet header is always in the
523da14cebeSEric Cheng 		 * first mblk fragment.
524da14cebeSEric Cheng 		 */
525da14cebeSEric Cheng 		nmp = mp;
526da14cebeSEric Cheng 		ip_start = (uintptr_t)(nmp->b_rptr)
527da14cebeSEric Cheng 		    + cur_context->ether_header_size;
528da14cebeSEric Cheng 		if (ip_start >= (uintptr_t)(nmp->b_wptr)) {
529da14cebeSEric Cheng 			ip_start = (uintptr_t)nmp->b_cont->b_rptr
530da14cebeSEric Cheng 			    + (ip_start - (uintptr_t)(nmp->b_wptr));
531da14cebeSEric Cheng 			nmp = nmp->b_cont;
532c7770590Smx 		}
533da14cebeSEric Cheng 		tcp_start = ip_start +
534da14cebeSEric Cheng 		    IPH_HDR_LENGTH((ipha_t *)ip_start);
535da14cebeSEric Cheng 		if (tcp_start >= (uintptr_t)(nmp->b_wptr)) {
536da14cebeSEric Cheng 			tcp_start = (uintptr_t)nmp->b_cont->b_rptr
537da14cebeSEric Cheng 			    + (tcp_start - (uintptr_t)(nmp->b_wptr));
538da14cebeSEric Cheng 			nmp = nmp->b_cont;
539da14cebeSEric Cheng 		}
540da14cebeSEric Cheng 		cur_context->hdr_len = cur_context->ether_header_size
541da14cebeSEric Cheng 		    + IPH_HDR_LENGTH((ipha_t *)ip_start)
542da14cebeSEric Cheng 		    + TCP_HDR_LENGTH((tcph_t *)tcp_start);
543da14cebeSEric Cheng 		((ipha_t *)ip_start)->ipha_length = 0;
544da14cebeSEric Cheng 		((ipha_t *)ip_start)->ipha_hdr_checksum = 0;
545da14cebeSEric Cheng 		/* calculate the TCP packet payload length */
546da14cebeSEric Cheng 		cur_context->pay_len = msg_size - cur_context->hdr_len;
547c7770590Smx 	}
548c7770590Smx 	return (B_TRUE);
549c7770590Smx }
5507941757cSxy 
551c7770590Smx static boolean_t
e1000g_check_context(e1000g_tx_ring_t * tx_ring,context_data_t * cur_context)552c7770590Smx e1000g_check_context(e1000g_tx_ring_t *tx_ring, context_data_t *cur_context)
553c7770590Smx {
554c7770590Smx 	boolean_t context_reload;
555c7770590Smx 	context_data_t *pre_context;
556c7770590Smx 	struct e1000g *Adapter;
557c7770590Smx 
558c7770590Smx 	context_reload = B_FALSE;
559c7770590Smx 	pre_context = &tx_ring->pre_context;
560c7770590Smx 	Adapter = tx_ring->adapter;
561c7770590Smx 
562c7770590Smx 	/*
563c7770590Smx 	 * The following code determine if the context descriptor is
564c7770590Smx 	 * needed to be reloaded. The sequence of the conditions is
565c7770590Smx 	 * made by their possibilities of changing.
566c7770590Smx 	 */
567c7770590Smx 	/*
568c7770590Smx 	 * workaround for 82546EB, context descriptor must be reloaded
569c7770590Smx 	 * per LSO/hw_cksum packet if LSO is enabled.
570c7770590Smx 	 */
571c7770590Smx 	if (Adapter->lso_premature_issue &&
572c7770590Smx 	    Adapter->lso_enable &&
573c7770590Smx 	    (cur_context->cksum_flags != 0)) {
574c7770590Smx 
575c7770590Smx 		context_reload = B_TRUE;
576c7770590Smx 	} else if (cur_context->lso_flag) {
57743a17687SMiles Xu, Sun Microsystems 		if ((cur_context->lso_flag != pre_context->lso_flag) ||
57843a17687SMiles Xu, Sun Microsystems 		    (cur_context->cksum_flags != pre_context->cksum_flags) ||
579c7770590Smx 		    (cur_context->pay_len != pre_context->pay_len) ||
580c7770590Smx 		    (cur_context->mss != pre_context->mss) ||
581c7770590Smx 		    (cur_context->hdr_len != pre_context->hdr_len) ||
582c7770590Smx 		    (cur_context->cksum_stuff != pre_context->cksum_stuff) ||
583c7770590Smx 		    (cur_context->cksum_start != pre_context->cksum_start) ||
584c7770590Smx 		    (cur_context->ether_header_size !=
585c7770590Smx 		    pre_context->ether_header_size)) {
586c7770590Smx 
587c7770590Smx 			context_reload = B_TRUE;
588c7770590Smx 		}
589c7770590Smx 	} else if (cur_context->cksum_flags != 0) {
59043a17687SMiles Xu, Sun Microsystems 		if ((cur_context->lso_flag != pre_context->lso_flag) ||
59143a17687SMiles Xu, Sun Microsystems 		    (cur_context->cksum_flags != pre_context->cksum_flags) ||
592c7770590Smx 		    (cur_context->cksum_stuff != pre_context->cksum_stuff) ||
593c7770590Smx 		    (cur_context->cksum_start != pre_context->cksum_start) ||
594c7770590Smx 		    (cur_context->ether_header_size !=
595c7770590Smx 		    pre_context->ether_header_size)) {
596c7770590Smx 
597c7770590Smx 			context_reload = B_TRUE;
5987941757cSxy 		}
5997941757cSxy 	}
6007941757cSxy 
601c7770590Smx 	return (context_reload);
6027941757cSxy }
6037941757cSxy 
60408057504Sxy static int
e1000g_fill_tx_ring(e1000g_tx_ring_t * tx_ring,LIST_DESCRIBER * pending_list,context_data_t * cur_context)60508057504Sxy e1000g_fill_tx_ring(e1000g_tx_ring_t *tx_ring, LIST_DESCRIBER *pending_list,
606c7770590Smx     context_data_t *cur_context)
60708057504Sxy {
60808057504Sxy 	struct e1000g *Adapter;
60925f2d433Sxy 	struct e1000_hw *hw;
61025f2d433Sxy 	p_tx_sw_packet_t first_packet;
61125f2d433Sxy 	p_tx_sw_packet_t packet;
612c7770590Smx 	p_tx_sw_packet_t previous_packet;
613c7770590Smx 	boolean_t context_reload;
61408057504Sxy 	struct e1000_tx_desc *first_data_desc;
61508057504Sxy 	struct e1000_tx_desc *next_desc;
61608057504Sxy 	struct e1000_tx_desc *descriptor;
6175c68564dSBryan Cantrill 	struct e1000_data_desc zeroed;
61808057504Sxy 	int desc_count;
619c7770590Smx 	boolean_t buff_overrun_flag;
62008057504Sxy 	int i;
62108057504Sxy 
62208057504Sxy 	Adapter = tx_ring->adapter;
62325f2d433Sxy 	hw = &Adapter->shared;
62408057504Sxy 
62508057504Sxy 	desc_count = 0;
6267941757cSxy 	first_packet = NULL;
62708057504Sxy 	first_data_desc = NULL;
62808057504Sxy 	descriptor = NULL;
629c7770590Smx 	first_packet = NULL;
630c7770590Smx 	packet = NULL;
631c7770590Smx 	buff_overrun_flag = B_FALSE;
6325c68564dSBryan Cantrill 	zeroed.upper.data = 0;
63308057504Sxy 
63408057504Sxy 	next_desc = tx_ring->tbd_next;
63508057504Sxy 
636c7770590Smx 	/* Context descriptor reload check */
637c7770590Smx 	context_reload = e1000g_check_context(tx_ring, cur_context);
6387941757cSxy 
639c7770590Smx 	if (context_reload) {
64025f2d433Sxy 		first_packet = (p_tx_sw_packet_t)QUEUE_GET_HEAD(pending_list);
64108057504Sxy 
6427941757cSxy 		descriptor = next_desc;
64308057504Sxy 
644c7770590Smx 		e1000g_fill_context_descriptor(cur_context,
6457941757cSxy 		    (struct e1000_context_desc *)descriptor);
64608057504Sxy 
64708057504Sxy 		/* Check the wrap-around case */
64808057504Sxy 		if (descriptor == tx_ring->tbd_last)
64908057504Sxy 			next_desc = tx_ring->tbd_first;
65008057504Sxy 		else
65108057504Sxy 			next_desc++;
65208057504Sxy 
65308057504Sxy 		desc_count++;
65408057504Sxy 	}
65508057504Sxy 
65608057504Sxy 	first_data_desc = next_desc;
65708057504Sxy 
6585c68564dSBryan Cantrill 	/*
6595c68564dSBryan Cantrill 	 * According to the documentation, the packet options field (POPTS) is
6605c68564dSBryan Cantrill 	 * "ignored except on the first data descriptor of a packet."  However,
6615c68564dSBryan Cantrill 	 * there is a bug in QEMU (638955) whereby the POPTS field within a
6625c68564dSBryan Cantrill 	 * given data descriptor is used to interpret that data descriptor --
6635c68564dSBryan Cantrill 	 * regardless of whether or not the descriptor is the first in a packet
6645c68564dSBryan Cantrill 	 * or not.  For a packet that spans multiple descriptors, the (virtual)
6655c68564dSBryan Cantrill 	 * HW checksum (either TCP/UDP or IP or both) will therefore _not_ be
6665c68564dSBryan Cantrill 	 * performed on descriptors after the first, resulting in incorrect
6675c68564dSBryan Cantrill 	 * checksums and mysteriously dropped/retransmitted packets.  Other
6685c68564dSBryan Cantrill 	 * drivers do not have this issue because they (harmlessly) set the
6695c68564dSBryan Cantrill 	 * POPTS field on every data descriptor to be the intended options for
6705c68564dSBryan Cantrill 	 * the entire packet.  To circumvent this QEMU bug, we engage in this
6715c68564dSBryan Cantrill 	 * same behavior iff the subsystem vendor and device IDs indicate that
6725c68564dSBryan Cantrill 	 * this is an emulated QEMU device (1af4,1100).
6735c68564dSBryan Cantrill 	 */
6745c68564dSBryan Cantrill 	if (hw->subsystem_vendor_id == 0x1af4 &&
6755c68564dSBryan Cantrill 	    hw->subsystem_device_id == 0x1100 &&
6765c68564dSBryan Cantrill 	    cur_context->cksum_flags) {
6775c68564dSBryan Cantrill 		if (cur_context->cksum_flags & HCK_IPV4_HDRCKSUM)
6785c68564dSBryan Cantrill 			zeroed.upper.fields.popts |= E1000_TXD_POPTS_IXSM;
6795c68564dSBryan Cantrill 
6805c68564dSBryan Cantrill 		if (cur_context->cksum_flags & HCK_PARTIALCKSUM)
6815c68564dSBryan Cantrill 			zeroed.upper.fields.popts |= E1000_TXD_POPTS_TXSM;
6825c68564dSBryan Cantrill 	}
6835c68564dSBryan Cantrill 
68425f2d433Sxy 	packet = (p_tx_sw_packet_t)QUEUE_GET_HEAD(pending_list);
68508057504Sxy 	while (packet) {
68608057504Sxy 		ASSERT(packet->num_desc);
68708057504Sxy 
68808057504Sxy 		for (i = 0; i < packet->num_desc; i++) {
68925f2d433Sxy 			ASSERT(tx_ring->tbd_avail > 0);
69008057504Sxy 
69108057504Sxy 			descriptor = next_desc;
69208057504Sxy 			descriptor->buffer_addr =
69325f2d433Sxy 			    packet->desc[i].address;
69408057504Sxy 			descriptor->lower.data =
69525f2d433Sxy 			    packet->desc[i].length;
69608057504Sxy 
69708057504Sxy 			/* Zero out status */
6985c68564dSBryan Cantrill 			descriptor->upper.data = zeroed.upper.data;
69908057504Sxy 
70008057504Sxy 			descriptor->lower.data |=
70108057504Sxy 			    E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
70208057504Sxy 			/* must set RS on every outgoing descriptor */
70308057504Sxy 			descriptor->lower.data |=
70408057504Sxy 			    E1000_TXD_CMD_RS;
70508057504Sxy 
706c7770590Smx 			if (cur_context->lso_flag)
707c7770590Smx 				descriptor->lower.data |= E1000_TXD_CMD_TSE;
708c7770590Smx 
70908057504Sxy 			/* Check the wrap-around case */
71008057504Sxy 			if (descriptor == tx_ring->tbd_last)
71108057504Sxy 				next_desc = tx_ring->tbd_first;
71208057504Sxy 			else
71308057504Sxy 				next_desc++;
71408057504Sxy 
71508057504Sxy 			desc_count++;
716c7770590Smx 
717c7770590Smx 			/*
718c7770590Smx 			 * workaround for 82546EB errata 33, hang in PCI-X
719c7770590Smx 			 * systems due to 2k Buffer Overrun during Transmit
720c7770590Smx 			 * Operation. The workaround applies to all the Intel
721c7770590Smx 			 * PCI-X chips.
722c7770590Smx 			 */
723c7770590Smx 			if (hw->bus.type == e1000_bus_type_pcix &&
724c7770590Smx 			    descriptor == first_data_desc &&
725c7770590Smx 			    ((descriptor->lower.data & E1000G_TBD_LENGTH_MASK)
726c7770590Smx 			    > E1000_TX_BUFFER_OEVRRUN_THRESHOLD)) {
727c7770590Smx 				/* modified the first descriptor */
728c7770590Smx 				descriptor->lower.data &=
729c7770590Smx 				    ~E1000G_TBD_LENGTH_MASK;
730c7770590Smx 				descriptor->lower.flags.length =
731c7770590Smx 				    E1000_TX_BUFFER_OEVRRUN_THRESHOLD;
732c7770590Smx 
733c7770590Smx 				/* insert a new descriptor */
734c7770590Smx 				ASSERT(tx_ring->tbd_avail > 0);
735c7770590Smx 				next_desc->buffer_addr =
736c7770590Smx 				    packet->desc[0].address +
737c7770590Smx 				    E1000_TX_BUFFER_OEVRRUN_THRESHOLD;
738c7770590Smx 				next_desc->lower.data =
739c7770590Smx 				    packet->desc[0].length -
740c7770590Smx 				    E1000_TX_BUFFER_OEVRRUN_THRESHOLD;
741c7770590Smx 
742c7770590Smx 				/* Zero out status */
7435c68564dSBryan Cantrill 				next_desc->upper.data = zeroed.upper.data;
744c7770590Smx 
745c7770590Smx 				next_desc->lower.data |=
746c7770590Smx 				    E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
747c7770590Smx 				/* must set RS on every outgoing descriptor */
748c7770590Smx 				next_desc->lower.data |=
749c7770590Smx 				    E1000_TXD_CMD_RS;
750c7770590Smx 
751c7770590Smx 				if (cur_context->lso_flag)
752c7770590Smx 					next_desc->lower.data |=
753c7770590Smx 					    E1000_TXD_CMD_TSE;
754c7770590Smx 
755c7770590Smx 				descriptor = next_desc;
756c7770590Smx 
757c7770590Smx 				/* Check the wrap-around case */
758c7770590Smx 				if (next_desc == tx_ring->tbd_last)
759c7770590Smx 					next_desc = tx_ring->tbd_first;
760c7770590Smx 				else
761c7770590Smx 					next_desc++;
762c7770590Smx 
763c7770590Smx 				desc_count++;
764c7770590Smx 				buff_overrun_flag = B_TRUE;
765c7770590Smx 			}
766c7770590Smx 		}
767c7770590Smx 
768c7770590Smx 		if (buff_overrun_flag) {
769c7770590Smx 			packet->num_desc++;
770c7770590Smx 			buff_overrun_flag = B_FALSE;
77108057504Sxy 		}
77208057504Sxy 
77308057504Sxy 		if (first_packet != NULL) {
77408057504Sxy 			/*
77508057504Sxy 			 * Count the checksum context descriptor for
77608057504Sxy 			 * the first SwPacket.
77708057504Sxy 			 */
77808057504Sxy 			first_packet->num_desc++;
77908057504Sxy 			first_packet = NULL;
78008057504Sxy 		}
78108057504Sxy 
782d3d50737SRafael Vanoni 		packet->tickstamp = ddi_get_lbolt64();
78354e0d7a5SMiles Xu, Sun Microsystems 
784c7770590Smx 		previous_packet = packet;
78525f2d433Sxy 		packet = (p_tx_sw_packet_t)
78608057504Sxy 		    QUEUE_GET_NEXT(pending_list, &packet->Link);
78708057504Sxy 	}
78808057504Sxy 
789c7770590Smx 	/*
790c7770590Smx 	 * workaround for 82546EB errata 21, LSO Premature Descriptor Write Back
791c7770590Smx 	 */
792c7770590Smx 	if (Adapter->lso_premature_issue && cur_context->lso_flag &&
793c7770590Smx 	    ((descriptor->lower.data & E1000G_TBD_LENGTH_MASK) > 8)) {
794c7770590Smx 		/* modified the previous descriptor */
795c7770590Smx 		descriptor->lower.data -= 4;
796c7770590Smx 
797c7770590Smx 		/* insert a new descriptor */
798c7770590Smx 		ASSERT(tx_ring->tbd_avail > 0);
799c7770590Smx 		/* the lower 20 bits of lower.data is the length field */
800c7770590Smx 		next_desc->buffer_addr =
801c7770590Smx 		    descriptor->buffer_addr +
802c7770590Smx 		    (descriptor->lower.data & E1000G_TBD_LENGTH_MASK);
803c7770590Smx 		next_desc->lower.data = 4;
804c7770590Smx 
805c7770590Smx 		/* Zero out status */
8065c68564dSBryan Cantrill 		next_desc->upper.data = zeroed.upper.data;
807c7770590Smx 		/* It must be part of a LSO packet */
808c7770590Smx 		next_desc->lower.data |=
809c7770590Smx 		    E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D |
810c7770590Smx 		    E1000_TXD_CMD_RS | E1000_TXD_CMD_TSE;
811c7770590Smx 
812c7770590Smx 		descriptor = next_desc;
813c7770590Smx 
814c7770590Smx 		/* Check the wrap-around case */
815c7770590Smx 		if (descriptor == tx_ring->tbd_last)
816c7770590Smx 			next_desc = tx_ring->tbd_first;
817c7770590Smx 		else
818c7770590Smx 			next_desc++;
819c7770590Smx 
820c7770590Smx 		desc_count++;
821c7770590Smx 		/* update the number of descriptors */
822c7770590Smx 		previous_packet->num_desc++;
823c7770590Smx 	}
824c7770590Smx 
82508057504Sxy 	ASSERT(descriptor);
82608057504Sxy 
827c7770590Smx 	if (cur_context->cksum_flags) {
828c7770590Smx 		if (cur_context->cksum_flags & HCK_IPV4_HDRCKSUM)
82908057504Sxy 			((struct e1000_data_desc *)first_data_desc)->
8305633182fSyy 			    upper.fields.popts |= E1000_TXD_POPTS_IXSM;
831c7770590Smx 		if (cur_context->cksum_flags & HCK_PARTIALCKSUM)
83208057504Sxy 			((struct e1000_data_desc *)first_data_desc)->
8335633182fSyy 			    upper.fields.popts |= E1000_TXD_POPTS_TXSM;
83408057504Sxy 	}
83508057504Sxy 
83608057504Sxy 	/*
83708057504Sxy 	 * Last Descriptor of Packet needs End Of Packet (EOP), Report
838c7770590Smx 	 * Status (RS) set.
83908057504Sxy 	 */
84025f2d433Sxy 	if (Adapter->tx_intr_delay) {
84108057504Sxy 		descriptor->lower.data |= E1000_TXD_CMD_IDE |
842c7770590Smx 		    E1000_TXD_CMD_EOP;
843c7770590Smx 	} else {
844c7770590Smx 		descriptor->lower.data |= E1000_TXD_CMD_EOP;
845c7770590Smx 	}
846c7770590Smx 
847c7770590Smx 	/* Set append Ethernet CRC (IFCS) bits */
848c7770590Smx 	if (cur_context->lso_flag) {
849c7770590Smx 		first_data_desc->lower.data |= E1000_TXD_CMD_IFCS;
85008057504Sxy 	} else {
851c7770590Smx 		descriptor->lower.data |= E1000_TXD_CMD_IFCS;
85208057504Sxy 	}
85308057504Sxy 
85408057504Sxy 	/*
85508057504Sxy 	 * Sync the Tx descriptors DMA buffer
85608057504Sxy 	 */
85725f2d433Sxy 	(void) ddi_dma_sync(tx_ring->tbd_dma_handle,
85825f2d433Sxy 	    0, 0, DDI_DMA_SYNC_FORDEV);
85908057504Sxy 
86008057504Sxy 	tx_ring->tbd_next = next_desc;
86108057504Sxy 
86208057504Sxy 	/*
86308057504Sxy 	 * Advance the Transmit Descriptor Tail (Tdt), this tells the
86408057504Sxy 	 * FX1000 that this frame is available to transmit.
86508057504Sxy 	 */
86625f2d433Sxy 	if (hw->mac.type == e1000_82547)
86708057504Sxy 		e1000g_82547_tx_move_tail(tx_ring);
86808057504Sxy 	else
869592a4d85Scc 		E1000_WRITE_REG(hw, E1000_TDT(0),
87008057504Sxy 		    (uint32_t)(next_desc - tx_ring->tbd_first));
87108057504Sxy 
8729b6541b3Sgl 	if (e1000g_check_acc_handle(Adapter->osdep.reg_handle) != DDI_FM_OK) {
8739b6541b3Sgl 		ddi_fm_service_impact(Adapter->dip, DDI_SERVICE_DEGRADED);
874d5c3073dSchenlu chen - Sun Microsystems - Beijing China 		Adapter->e1000g_state |= E1000G_ERROR;
8759b6541b3Sgl 	}
8769b6541b3Sgl 
87708057504Sxy 	/* Put the pending SwPackets to the "Used" list */
87808057504Sxy 	mutex_enter(&tx_ring->usedlist_lock);
87908057504Sxy 	QUEUE_APPEND(&tx_ring->used_list, pending_list);
88025f2d433Sxy 	tx_ring->tbd_avail -= desc_count;
88108057504Sxy 	mutex_exit(&tx_ring->usedlist_lock);
88208057504Sxy 
883c7770590Smx 	/* update LSO related data */
884c7770590Smx 	if (context_reload)
885c7770590Smx 		tx_ring->pre_context = *cur_context;
8867941757cSxy 
88708057504Sxy 	return (desc_count);
88808057504Sxy }
88908057504Sxy 
89008057504Sxy /*
89125f2d433Sxy  * e1000g_tx_setup - setup tx data structures
89225f2d433Sxy  *
89325f2d433Sxy  * This routine initializes all of the transmit related
89425f2d433Sxy  * structures. This includes the Transmit descriptors,
89525f2d433Sxy  * and the tx_sw_packet structures.
89608057504Sxy  */
89708057504Sxy void
e1000g_tx_setup(struct e1000g * Adapter)89825f2d433Sxy e1000g_tx_setup(struct e1000g *Adapter)
89908057504Sxy {
90008057504Sxy 	struct e1000_hw *hw;
90125f2d433Sxy 	p_tx_sw_packet_t packet;
9024d737963Sxiangtao you - Sun Microsystems - Beijing China 	uint32_t i;
90308057504Sxy 	uint32_t buf_high;
90408057504Sxy 	uint32_t buf_low;
90508057504Sxy 	uint32_t reg_tipg;
90608057504Sxy 	uint32_t reg_tctl;
90708057504Sxy 	int size;
90808057504Sxy 	e1000g_tx_ring_t *tx_ring;
90908057504Sxy 
91025f2d433Sxy 	hw = &Adapter->shared;
91108057504Sxy 	tx_ring = Adapter->tx_ring;
91208057504Sxy 
91308057504Sxy 	/* init the lists */
91408057504Sxy 	/*
91508057504Sxy 	 * Here we don't need to protect the lists using the
91625f2d433Sxy 	 * usedlist_lock and freelist_lock, for they have
91708057504Sxy 	 * been protected by the chip_lock.
91808057504Sxy 	 */
91908057504Sxy 	QUEUE_INIT_LIST(&tx_ring->used_list);
92008057504Sxy 	QUEUE_INIT_LIST(&tx_ring->free_list);
92108057504Sxy 
92208057504Sxy 	/* Go through and set up each SW_Packet */
92308057504Sxy 	packet = tx_ring->packet_area;
92425f2d433Sxy 	for (i = 0; i < Adapter->tx_freelist_num; i++, packet++) {
92525f2d433Sxy 		/* Initialize this tx_sw_apcket area */
92625f2d433Sxy 		e1000g_free_tx_swpkt(packet);
92725f2d433Sxy 		/* Add this tx_sw_packet to the free list */
92808057504Sxy 		QUEUE_PUSH_TAIL(&tx_ring->free_list,
92908057504Sxy 		    &packet->Link);
93008057504Sxy 	}
93108057504Sxy 
93208057504Sxy 	/* Setup TX descriptor pointers */
93308057504Sxy 	tx_ring->tbd_next = tx_ring->tbd_first;
93408057504Sxy 	tx_ring->tbd_oldest = tx_ring->tbd_first;
93508057504Sxy 
93608057504Sxy 	/*
93708057504Sxy 	 * Setup Hardware TX Registers
93808057504Sxy 	 */
93908057504Sxy 	/* Setup the Transmit Control Register (TCTL). */
940a2e9a830Scc 	reg_tctl = E1000_READ_REG(hw, E1000_TCTL);
941a2e9a830Scc 	reg_tctl |= E1000_TCTL_PSP | E1000_TCTL_EN |
94208057504Sxy 	    (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT) |
94325f2d433Sxy 	    (E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT) |
94425f2d433Sxy 	    E1000_TCTL_RTLC;
94508057504Sxy 
94608057504Sxy 	/* Enable the MULR bit */
94725f2d433Sxy 	if (hw->bus.type == e1000_bus_type_pci_express)
94808057504Sxy 		reg_tctl |= E1000_TCTL_MULR;
94908057504Sxy 
95025f2d433Sxy 	E1000_WRITE_REG(hw, E1000_TCTL, reg_tctl);
95108057504Sxy 
95208057504Sxy 	/* Setup HW Base and Length of Tx descriptor area */
95325f2d433Sxy 	size = (Adapter->tx_desc_num * sizeof (struct e1000_tx_desc));
954592a4d85Scc 	E1000_WRITE_REG(hw, E1000_TDLEN(0), size);
955592a4d85Scc 	size = E1000_READ_REG(hw, E1000_TDLEN(0));
95608057504Sxy 
95708057504Sxy 	buf_low = (uint32_t)tx_ring->tbd_dma_addr;
95808057504Sxy 	buf_high = (uint32_t)(tx_ring->tbd_dma_addr >> 32);
95908057504Sxy 
960ede5269eSchenlu chen - Sun Microsystems - Beijing China 	/*
961ede5269eSchenlu chen - Sun Microsystems - Beijing China 	 * Write the highest location first and work backward to the lowest.
962ede5269eSchenlu chen - Sun Microsystems - Beijing China 	 * This is necessary for some adapter types to
963ede5269eSchenlu chen - Sun Microsystems - Beijing China 	 * prevent write combining from occurring.
964ede5269eSchenlu chen - Sun Microsystems - Beijing China 	 */
965592a4d85Scc 	E1000_WRITE_REG(hw, E1000_TDBAH(0), buf_high);
966ede5269eSchenlu chen - Sun Microsystems - Beijing China 	E1000_WRITE_REG(hw, E1000_TDBAL(0), buf_low);
96708057504Sxy 
96808057504Sxy 	/* Setup our HW Tx Head & Tail descriptor pointers */
969592a4d85Scc 	E1000_WRITE_REG(hw, E1000_TDH(0), 0);
970592a4d85Scc 	E1000_WRITE_REG(hw, E1000_TDT(0), 0);
97108057504Sxy 
97208057504Sxy 	/* Set the default values for the Tx Inter Packet Gap timer */
97325f2d433Sxy 	if ((hw->mac.type == e1000_82542) &&
97425f2d433Sxy 	    ((hw->revision_id == E1000_REVISION_2) ||
97525f2d433Sxy 	    (hw->revision_id == E1000_REVISION_3))) {
97608057504Sxy 		reg_tipg = DEFAULT_82542_TIPG_IPGT;
97708057504Sxy 		reg_tipg |=
97808057504Sxy 		    DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
97908057504Sxy 		reg_tipg |=
98008057504Sxy 		    DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
981a2e9a830Scc 	} else if (hw->mac.type == e1000_80003es2lan) {
982a2e9a830Scc 		reg_tipg = DEFAULT_82543_TIPG_IPGR1;
98335ae85e6Scc 		reg_tipg |= DEFAULT_80003ES2LAN_TIPG_IPGR2 <<
984a2e9a830Scc 		    E1000_TIPG_IPGR2_SHIFT;
98525f2d433Sxy 	} else {
986592a4d85Scc 		if (hw->phy.media_type == e1000_media_type_fiber)
98708057504Sxy 			reg_tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
98808057504Sxy 		else
98908057504Sxy 			reg_tipg = DEFAULT_82543_TIPG_IPGT_COPPER;
99008057504Sxy 		reg_tipg |=
99108057504Sxy 		    DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
99208057504Sxy 		reg_tipg |=
99308057504Sxy 		    DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
99408057504Sxy 	}
99525f2d433Sxy 	E1000_WRITE_REG(hw, E1000_TIPG, reg_tipg);
99608057504Sxy 
99708057504Sxy 	/* Setup Transmit Interrupt Delay Value */
99847b7744cSyy 	E1000_WRITE_REG(hw, E1000_TIDV, Adapter->tx_intr_delay);
99947b7744cSyy 	E1000G_DEBUGLOG_1(Adapter, E1000G_INFO_LEVEL,
100047b7744cSyy 	    "E1000_TIDV: 0x%x\n", Adapter->tx_intr_delay);
100147b7744cSyy 
100247b7744cSyy 	if (hw->mac.type >= e1000_82540) {
100347b7744cSyy 		E1000_WRITE_REG(&Adapter->shared, E1000_TADV,
100447b7744cSyy 		    Adapter->tx_intr_abs_delay);
100547b7744cSyy 		E1000G_DEBUGLOG_1(Adapter, E1000G_INFO_LEVEL,
100647b7744cSyy 		    "E1000_TADV: 0x%x\n", Adapter->tx_intr_abs_delay);
100708057504Sxy 	}
100808057504Sxy 
100925f2d433Sxy 	tx_ring->tbd_avail = Adapter->tx_desc_num;
101025f2d433Sxy 
1011c7770590Smx 	/* Initialize stored context information */
1012c7770590Smx 	bzero(&(tx_ring->pre_context), sizeof (context_data_t));
101308057504Sxy }
101408057504Sxy 
101508057504Sxy /*
101625f2d433Sxy  * e1000g_recycle - recycle the tx descriptors and tx sw packets
101708057504Sxy  */
101808057504Sxy int
e1000g_recycle(e1000g_tx_ring_t * tx_ring)101908057504Sxy e1000g_recycle(e1000g_tx_ring_t *tx_ring)
102008057504Sxy {
102108057504Sxy 	struct e1000g *Adapter;
102208057504Sxy 	LIST_DESCRIBER pending_list;
102325f2d433Sxy 	p_tx_sw_packet_t packet;
102408057504Sxy 	mblk_t *mp;
102508057504Sxy 	mblk_t *nmp;
102608057504Sxy 	struct e1000_tx_desc *descriptor;
102708057504Sxy 	int desc_count;
102854e0d7a5SMiles Xu, Sun Microsystems 	int64_t delta;
102908057504Sxy 
103008057504Sxy 	/*
103108057504Sxy 	 * This function will examine each TxSwPacket in the 'used' queue
103208057504Sxy 	 * if the e1000g is done with it then the associated resources (Tx
103308057504Sxy 	 * Descriptors) will be "freed" and the TxSwPacket will be
103408057504Sxy 	 * returned to the 'free' queue.
103508057504Sxy 	 */
103608057504Sxy 	Adapter = tx_ring->adapter;
103754e0d7a5SMiles Xu, Sun Microsystems 	delta = 0;
103808057504Sxy 
103925f2d433Sxy 	packet = (p_tx_sw_packet_t)QUEUE_GET_HEAD(&tx_ring->used_list);
104008057504Sxy 	if (packet == NULL) {
104154e0d7a5SMiles Xu, Sun Microsystems 		Adapter->stall_flag = B_FALSE;
104208057504Sxy 		return (0);
104308057504Sxy 	}
104408057504Sxy 
104547b7744cSyy 	desc_count = 0;
104647b7744cSyy 	QUEUE_INIT_LIST(&pending_list);
104747b7744cSyy 
104825f2d433Sxy 	/* Sync the Tx descriptor DMA buffer */
104925f2d433Sxy 	(void) ddi_dma_sync(tx_ring->tbd_dma_handle,
105025f2d433Sxy 	    0, 0, DDI_DMA_SYNC_FORKERNEL);
10519b6541b3Sgl 	if (e1000g_check_dma_handle(
10529b6541b3Sgl 	    tx_ring->tbd_dma_handle) != DDI_FM_OK) {
10539b6541b3Sgl 		ddi_fm_service_impact(Adapter->dip, DDI_SERVICE_DEGRADED);
1054d5c3073dSchenlu chen - Sun Microsystems - Beijing China 		Adapter->e1000g_state |= E1000G_ERROR;
10559b6541b3Sgl 		return (0);
10569b6541b3Sgl 	}
105725f2d433Sxy 
105808057504Sxy 	/*
105908057504Sxy 	 * While there are still TxSwPackets in the used queue check them
106008057504Sxy 	 */
1061da14cebeSEric Cheng 	mutex_enter(&tx_ring->usedlist_lock);
1062fe62dec3SChen-Liang Xu 	while ((packet =
1063fe62dec3SChen-Liang Xu 	    (p_tx_sw_packet_t)QUEUE_GET_HEAD(&tx_ring->used_list)) != NULL) {
106408057504Sxy 
106508057504Sxy 		/*
106608057504Sxy 		 * Get hold of the next descriptor that the e1000g will
106708057504Sxy 		 * report status back to (this will be the last descriptor
106825f2d433Sxy 		 * of a given sw packet). We only want to free the
106925f2d433Sxy 		 * sw packet (and it resources) if the e1000g is done
107008057504Sxy 		 * with ALL of the descriptors.  If the e1000g is done
107108057504Sxy 		 * with the last one then it is done with all of them.
107208057504Sxy 		 */
107308057504Sxy 		ASSERT(packet->num_desc);
107425f2d433Sxy 		descriptor = tx_ring->tbd_oldest + (packet->num_desc - 1);
107508057504Sxy 
107608057504Sxy 		/* Check for wrap case */
107708057504Sxy 		if (descriptor > tx_ring->tbd_last)
107825f2d433Sxy 			descriptor -= Adapter->tx_desc_num;
107908057504Sxy 
108008057504Sxy 		/*
108108057504Sxy 		 * If the descriptor done bit is set free TxSwPacket and
108208057504Sxy 		 * associated resources
108308057504Sxy 		 */
108408057504Sxy 		if (descriptor->upper.fields.status & E1000_TXD_STAT_DD) {
108508057504Sxy 			QUEUE_POP_HEAD(&tx_ring->used_list);
108608057504Sxy 			QUEUE_PUSH_TAIL(&pending_list, &packet->Link);
108708057504Sxy 
108808057504Sxy 			if (descriptor == tx_ring->tbd_last)
108908057504Sxy 				tx_ring->tbd_oldest =
109008057504Sxy 				    tx_ring->tbd_first;
109108057504Sxy 			else
109208057504Sxy 				tx_ring->tbd_oldest =
109308057504Sxy 				    descriptor + 1;
109408057504Sxy 
109508057504Sxy 			desc_count += packet->num_desc;
109608057504Sxy 		} else {
109708057504Sxy 			/*
109825f2d433Sxy 			 * Found a sw packet that the e1000g is not done
109908057504Sxy 			 * with then there is no reason to check the rest
110008057504Sxy 			 * of the queue.
110108057504Sxy 			 */
1102d3d50737SRafael Vanoni 			delta = ddi_get_lbolt64() - packet->tickstamp;
110308057504Sxy 			break;
110408057504Sxy 		}
110508057504Sxy 	}
110608057504Sxy 
110725f2d433Sxy 	tx_ring->tbd_avail += desc_count;
110847b7744cSyy 	Adapter->tx_pkt_cnt += desc_count;
110925f2d433Sxy 
111008057504Sxy 	mutex_exit(&tx_ring->usedlist_lock);
111108057504Sxy 
111208057504Sxy 	if (desc_count == 0) {
111325f2d433Sxy 		E1000G_DEBUG_STAT(tx_ring->stat_recycle_none);
111454e0d7a5SMiles Xu, Sun Microsystems 		/*
11155f0b6ff9Sguoqing zhu - Sun Microsystems - Beijing China 		 * If the packet hasn't been sent out for seconds and
11165f0b6ff9Sguoqing zhu - Sun Microsystems - Beijing China 		 * the transmitter is not under paused flowctrl condition,
111754e0d7a5SMiles Xu, Sun Microsystems 		 * the transmitter is considered to be stalled.
111854e0d7a5SMiles Xu, Sun Microsystems 		 */
11195f0b6ff9Sguoqing zhu - Sun Microsystems - Beijing China 		if ((delta > Adapter->stall_threshold) &&
11205f0b6ff9Sguoqing zhu - Sun Microsystems - Beijing China 		    !(E1000_READ_REG(&Adapter->shared,
11215f0b6ff9Sguoqing zhu - Sun Microsystems - Beijing China 		    E1000_STATUS) & E1000_STATUS_TXOFF)) {
112254e0d7a5SMiles Xu, Sun Microsystems 			Adapter->stall_flag = B_TRUE;
112354e0d7a5SMiles Xu, Sun Microsystems 		}
112408057504Sxy 		return (0);
112508057504Sxy 	}
112608057504Sxy 
112754e0d7a5SMiles Xu, Sun Microsystems 	Adapter->stall_flag = B_FALSE;
112808057504Sxy 
112908057504Sxy 	mp = NULL;
113008057504Sxy 	nmp = NULL;
113125f2d433Sxy 	packet = (p_tx_sw_packet_t)QUEUE_GET_HEAD(&pending_list);
113208057504Sxy 	ASSERT(packet != NULL);
113308057504Sxy 	while (packet != NULL) {
113408057504Sxy 		if (packet->mp != NULL) {
113508057504Sxy 			ASSERT(packet->mp->b_next == NULL);
113608057504Sxy 			/* Assemble the message chain */
113708057504Sxy 			if (mp == NULL) {
113808057504Sxy 				mp = packet->mp;
113908057504Sxy 				nmp = packet->mp;
114008057504Sxy 			} else {
114108057504Sxy 				nmp->b_next = packet->mp;
114208057504Sxy 				nmp = packet->mp;
114308057504Sxy 			}
114408057504Sxy 			/* Disconnect the message from the sw packet */
114508057504Sxy 			packet->mp = NULL;
114608057504Sxy 		}
114708057504Sxy 
114808057504Sxy 		/* Free the TxSwPackets */
114925f2d433Sxy 		e1000g_free_tx_swpkt(packet);
115008057504Sxy 
115125f2d433Sxy 		packet = (p_tx_sw_packet_t)
115208057504Sxy 		    QUEUE_GET_NEXT(&pending_list, &packet->Link);
115308057504Sxy 	}
115408057504Sxy 
115508057504Sxy 	/* Return the TxSwPackets back to the FreeList */
115608057504Sxy 	mutex_enter(&tx_ring->freelist_lock);
115708057504Sxy 	QUEUE_APPEND(&tx_ring->free_list, &pending_list);
115808057504Sxy 	mutex_exit(&tx_ring->freelist_lock);
115908057504Sxy 
116047b7744cSyy 	if (mp != NULL)
116147b7744cSyy 		freemsgchain(mp);
116247b7744cSyy 
116308057504Sxy 	return (desc_count);
116408057504Sxy }
116508057504Sxy /*
116608057504Sxy  * 82544 Coexistence issue workaround:
116708057504Sxy  *    There are 2 issues.
116808057504Sxy  *    1. If a 32 bit split completion happens from P64H2 and another
116908057504Sxy  *	agent drives a 64 bit request/split completion after ONLY
117008057504Sxy  *	1 idle clock (BRCM/Emulex/Adaptec fiber channel cards) then
117108057504Sxy  *	82544 has a problem where in to clock all the data in, it
117208057504Sxy  *	looks at REQ64# signal and since it has changed so fast (i.e. 1
117308057504Sxy  *	idle clock turn around), it will fail to clock all the data in.
117408057504Sxy  *	Data coming from certain ending addresses has exposure to this issue.
117508057504Sxy  *
117608057504Sxy  * To detect this issue, following equation can be used...
117708057504Sxy  *	SIZE[3:0] + ADDR[2:0] = SUM[3:0].
117808057504Sxy  *	If SUM[3:0] is in between 1 to 4, we will have this issue.
117908057504Sxy  *
118008057504Sxy  * ROOT CAUSE:
118108057504Sxy  *	The erratum involves the 82544 PCIX elasticity FIFO implementations as
118208057504Sxy  *	64-bit FIFO's and flushing of the final partial-bytes corresponding
118308057504Sxy  *	to the end of a requested read burst. Under a specific burst condition
118408057504Sxy  *	of ending-data alignment and 32-byte split-completions, the final
118508057504Sxy  *	byte(s) of split-completion data require an extra clock cycle to flush
118608057504Sxy  *	into 64-bit FIFO orientation.  An incorrect logic dependency on the
118708057504Sxy  *	REQ64# signal occurring during during this clock cycle may cause the
118808057504Sxy  *	residual byte(s) to be lost, thereby rendering the internal DMA client
118908057504Sxy  *	forever awaiting the final byte(s) for an outbound data-fetch.  The
119008057504Sxy  *	erratum is confirmed to *only* occur if certain subsequent external
119108057504Sxy  *	64-bit PCIX bus transactions occur immediately (minimum possible bus
119208057504Sxy  *	turn- around) following the odd-aligned 32-bit split-completion
119308057504Sxy  *	containing the final byte(s).  Intel has confirmed that this has been
119408057504Sxy  *	seen only with chipset/bridges which have the capability to provide
119508057504Sxy  *	32-bit split-completion data, and in the presence of newer PCIX bus
119608057504Sxy  *	agents which fully-optimize the inter-transaction turn-around (zero
119708057504Sxy  *	additional initiator latency when pre-granted bus ownership).
119808057504Sxy  *
1199*f52680feSToomas Soome  *	This issue does not exist in PCI bus mode, when any agent is operating
120008057504Sxy  *	in 32 bit only mode or on chipsets that do not do 32 bit split
120108057504Sxy  *	completions for 64 bit read requests (Serverworks chipsets). P64H2 does
120208057504Sxy  *	32 bit split completions for any read request that has bit 2 set to 1
120308057504Sxy  *	for the requested address and read request size is more than 8 bytes.
120408057504Sxy  *
120508057504Sxy  *   2. Another issue is related to 82544 driving DACs under the similar
120608057504Sxy  *	scenario (32 bit split completion followed by 64 bit transaction with
120708057504Sxy  *	only 1 cycle turnaround). This issue is still being root caused. We
120808057504Sxy  *	think that both of these issues can be avoided if following workaround
120908057504Sxy  *	is implemented. It seems DAC issues is related to ending addresses being
121008057504Sxy  *	0x9, 0xA, 0xB, 0xC and hence ending up at odd boundaries in elasticity
121108057504Sxy  *	FIFO which does not get flushed due to REQ64# dependency. We will only
121208057504Sxy  *	know the full story after it has been simulated successfully by HW team.
121308057504Sxy  *
121408057504Sxy  * WORKAROUND:
121508057504Sxy  *	Make sure we do not have ending address as 1,2,3,4(Hang) or 9,a,b,c(DAC)
121608057504Sxy  */
121708057504Sxy static uint32_t
e1000g_fill_82544_desc(uint64_t address,size_t length,p_desc_array_t desc_array)121825f2d433Sxy e1000g_fill_82544_desc(uint64_t address,
121925f2d433Sxy     size_t length, p_desc_array_t desc_array)
122008057504Sxy {
122108057504Sxy 	/*
122208057504Sxy 	 * Since issue is sensitive to length and address.
122308057504Sxy 	 * Let us first check the address...
122408057504Sxy 	 */
122508057504Sxy 	uint32_t safe_terminator;
122608057504Sxy 
122725f2d433Sxy 	if (length <= 4) {
122825f2d433Sxy 		desc_array->descriptor[0].address = address;
1229fe62dec3SChen-Liang Xu 		desc_array->descriptor[0].length = (uint32_t)length;
123025f2d433Sxy 		desc_array->elements = 1;
123125f2d433Sxy 		return (desc_array->elements);
123208057504Sxy 	}
123308057504Sxy 	safe_terminator =
123425f2d433Sxy 	    (uint32_t)((((uint32_t)address & 0x7) +
123525f2d433Sxy 	    (length & 0xF)) & 0xF);
123608057504Sxy 	/*
123708057504Sxy 	 * if it does not fall between 0x1 to 0x4 and 0x9 to 0xC then
123808057504Sxy 	 * return
123908057504Sxy 	 */
124008057504Sxy 	if (safe_terminator == 0 ||
124125f2d433Sxy 	    (safe_terminator > 4 && safe_terminator < 9) ||
124208057504Sxy 	    (safe_terminator > 0xC && safe_terminator <= 0xF)) {
124325f2d433Sxy 		desc_array->descriptor[0].address = address;
1244fe62dec3SChen-Liang Xu 		desc_array->descriptor[0].length = (uint32_t)length;
124525f2d433Sxy 		desc_array->elements = 1;
124625f2d433Sxy 		return (desc_array->elements);
124708057504Sxy 	}
124808057504Sxy 
124925f2d433Sxy 	desc_array->descriptor[0].address = address;
125025f2d433Sxy 	desc_array->descriptor[0].length = length - 4;
125125f2d433Sxy 	desc_array->descriptor[1].address = address + (length - 4);
125225f2d433Sxy 	desc_array->descriptor[1].length = 4;
125325f2d433Sxy 	desc_array->elements = 2;
125425f2d433Sxy 	return (desc_array->elements);
125508057504Sxy }
125608057504Sxy 
125708057504Sxy static int
e1000g_tx_copy(e1000g_tx_ring_t * tx_ring,p_tx_sw_packet_t packet,mblk_t * mp,boolean_t tx_undersize_flag)125825f2d433Sxy e1000g_tx_copy(e1000g_tx_ring_t *tx_ring, p_tx_sw_packet_t packet,
1259c7770590Smx     mblk_t *mp, boolean_t tx_undersize_flag)
126008057504Sxy {
126108057504Sxy 	size_t len;
126208057504Sxy 	size_t len1;
126308057504Sxy 	dma_buffer_t *tx_buf;
126408057504Sxy 	mblk_t *nmp;
126508057504Sxy 	boolean_t finished;
126608057504Sxy 	int desc_count;
126708057504Sxy 
126808057504Sxy 	desc_count = 0;
126908057504Sxy 	tx_buf = packet->tx_buf;
127008057504Sxy 	len = MBLKL(mp);
127108057504Sxy 
127208057504Sxy 	ASSERT((tx_buf->len + len) <= tx_buf->size);
127308057504Sxy 
127408057504Sxy 	if (len > 0) {
127508057504Sxy 		bcopy(mp->b_rptr,
127608057504Sxy 		    tx_buf->address + tx_buf->len,
127708057504Sxy 		    len);
127808057504Sxy 		tx_buf->len += len;
127908057504Sxy 
128008057504Sxy 		packet->num_mblk_frag++;
128108057504Sxy 	}
128208057504Sxy 
128308057504Sxy 	nmp = mp->b_cont;
128408057504Sxy 	if (nmp == NULL) {
128508057504Sxy 		finished = B_TRUE;
128608057504Sxy 	} else {
128708057504Sxy 		len1 = MBLKL(nmp);
128808057504Sxy 		if ((tx_buf->len + len1) > tx_buf->size)
128908057504Sxy 			finished = B_TRUE;
1290c7770590Smx 		else if (tx_undersize_flag)
129108057504Sxy 			finished = B_FALSE;
129225f2d433Sxy 		else if (len1 > tx_ring->adapter->tx_bcopy_thresh)
129308057504Sxy 			finished = B_TRUE;
129408057504Sxy 		else
129508057504Sxy 			finished = B_FALSE;
129608057504Sxy 	}
129708057504Sxy 
129808057504Sxy 	if (finished) {
129925f2d433Sxy 		E1000G_DEBUG_STAT_COND(tx_ring->stat_multi_copy,
130025f2d433Sxy 		    (tx_buf->len > len));
130108057504Sxy 
130208057504Sxy 		/*
130308057504Sxy 		 * If the packet is smaller than 64 bytes, which is the
130408057504Sxy 		 * minimum ethernet packet size, pad the packet to make
130508057504Sxy 		 * it at least 60 bytes. The hardware will add 4 bytes
130608057504Sxy 		 * for CRC.
130708057504Sxy 		 */
1308c7770590Smx 		if (tx_undersize_flag) {
13099ce7e93cScc 			ASSERT(tx_buf->len < ETHERMIN);
131008057504Sxy 
131108057504Sxy 			bzero(tx_buf->address + tx_buf->len,
13129ce7e93cScc 			    ETHERMIN - tx_buf->len);
13139ce7e93cScc 			tx_buf->len = ETHERMIN;
131408057504Sxy 		}
131508057504Sxy 
131608057504Sxy #ifdef __sparc
131725f2d433Sxy 		if (packet->dma_type == USE_DVMA)
131808057504Sxy 			dvma_sync(tx_buf->dma_handle, 0, DDI_DMA_SYNC_FORDEV);
131925f2d433Sxy 		else
132008057504Sxy 			(void) ddi_dma_sync(tx_buf->dma_handle, 0,
132108057504Sxy 			    tx_buf->len, DDI_DMA_SYNC_FORDEV);
132225f2d433Sxy #else
132325f2d433Sxy 		(void) ddi_dma_sync(tx_buf->dma_handle, 0,
132425f2d433Sxy 		    tx_buf->len, DDI_DMA_SYNC_FORDEV);
132525f2d433Sxy #endif
132608057504Sxy 
132708057504Sxy 		packet->data_transfer_type = USE_BCOPY;
132808057504Sxy 
132925f2d433Sxy 		desc_count = e1000g_fill_tx_desc(tx_ring,
133008057504Sxy 		    packet,
133108057504Sxy 		    tx_buf->dma_address,
133208057504Sxy 		    tx_buf->len);
133308057504Sxy 
133408057504Sxy 		if (desc_count <= 0)
133508057504Sxy 			return (-1);
133608057504Sxy 	}
133708057504Sxy 
133808057504Sxy 	return (desc_count);
133908057504Sxy }
134008057504Sxy 
134108057504Sxy static int
e1000g_tx_bind(e1000g_tx_ring_t * tx_ring,p_tx_sw_packet_t packet,mblk_t * mp)134225f2d433Sxy e1000g_tx_bind(e1000g_tx_ring_t *tx_ring, p_tx_sw_packet_t packet, mblk_t *mp)
134308057504Sxy {
134408057504Sxy 	int j;
134508057504Sxy 	int mystat;
134608057504Sxy 	size_t len;
134708057504Sxy 	ddi_dma_cookie_t dma_cookie;
134808057504Sxy 	uint_t ncookies;
134908057504Sxy 	int desc_count;
135008057504Sxy 	uint32_t desc_total;
135108057504Sxy 
135208057504Sxy 	desc_total = 0;
135308057504Sxy 	len = MBLKL(mp);
135408057504Sxy 
135508057504Sxy 	/*
135608057504Sxy 	 * ddi_dma_addr_bind_handle() allocates  DMA  resources  for  a
135708057504Sxy 	 * memory  object such that a device can perform DMA to or from
135808057504Sxy 	 * the object.  DMA resources  are  allocated  considering  the
135908057504Sxy 	 * device's  DMA  attributes  as  expressed by ddi_dma_attr(9S)
136008057504Sxy 	 * (see ddi_dma_alloc_handle(9F)).
136108057504Sxy 	 *
136208057504Sxy 	 * ddi_dma_addr_bind_handle() fills in  the  first  DMA  cookie
136308057504Sxy 	 * pointed  to by cookiep with the appropriate address, length,
136408057504Sxy 	 * and bus type. *ccountp is set to the number of DMA  cookies
136508057504Sxy 	 * representing this DMA object. Subsequent DMA cookies must be
136608057504Sxy 	 * retrieved by calling ddi_dma_nextcookie(9F)  the  number  of
136708057504Sxy 	 * times specified by *countp - 1.
136808057504Sxy 	 */
136908057504Sxy 	switch (packet->dma_type) {
137008057504Sxy #ifdef __sparc
137108057504Sxy 	case USE_DVMA:
137208057504Sxy 		dvma_kaddr_load(packet->tx_dma_handle,
137308057504Sxy 		    (caddr_t)mp->b_rptr, len, 0, &dma_cookie);
137408057504Sxy 
137508057504Sxy 		dvma_sync(packet->tx_dma_handle, 0,
137608057504Sxy 		    DDI_DMA_SYNC_FORDEV);
137708057504Sxy 
137808057504Sxy 		ncookies = 1;
137908057504Sxy 		packet->data_transfer_type = USE_DVMA;
138008057504Sxy 		break;
138108057504Sxy #endif
138208057504Sxy 	case USE_DMA:
138308057504Sxy 		if ((mystat = ddi_dma_addr_bind_handle(
13845633182fSyy 		    packet->tx_dma_handle, NULL,
13855633182fSyy 		    (caddr_t)mp->b_rptr, len,
13865633182fSyy 		    DDI_DMA_WRITE | DDI_DMA_STREAMING,
13875633182fSyy 		    DDI_DMA_DONTWAIT, 0, &dma_cookie,
13885633182fSyy 		    &ncookies)) != DDI_DMA_MAPPED) {
138908057504Sxy 
139025f2d433Sxy 			e1000g_log(tx_ring->adapter, CE_WARN,
139108057504Sxy 			    "Couldn't bind mblk buffer to Tx DMA handle: "
139208057504Sxy 			    "return: %X, Pkt: %X\n",
139308057504Sxy 			    mystat, packet);
139408057504Sxy 			return (-1);
139508057504Sxy 		}
139608057504Sxy 
139708057504Sxy 		/*
139808057504Sxy 		 * An implicit ddi_dma_sync() is done when the
139908057504Sxy 		 * ddi_dma_addr_bind_handle() is called. So we
140008057504Sxy 		 * don't need to explicitly call ddi_dma_sync()
140108057504Sxy 		 * here any more.
140208057504Sxy 		 */
140308057504Sxy 		ASSERT(ncookies);
140425f2d433Sxy 		E1000G_DEBUG_STAT_COND(tx_ring->stat_multi_cookie,
140525f2d433Sxy 		    (ncookies > 1));
140608057504Sxy 
140708057504Sxy 		/*
140808057504Sxy 		 * The data_transfer_type value must be set after the handle
140925f2d433Sxy 		 * has been bound, for it will be used in e1000g_free_tx_swpkt()
141008057504Sxy 		 * to decide whether we need to unbind the handle.
141108057504Sxy 		 */
141208057504Sxy 		packet->data_transfer_type = USE_DMA;
141308057504Sxy 		break;
141408057504Sxy 	default:
141508057504Sxy 		ASSERT(B_FALSE);
141608057504Sxy 		break;
141708057504Sxy 	}
141808057504Sxy 
141908057504Sxy 	packet->num_mblk_frag++;
142008057504Sxy 
142108057504Sxy 	/*
142208057504Sxy 	 * Each address could span thru multpile cookie..
142308057504Sxy 	 * Each cookie will have one descriptor
142408057504Sxy 	 */
142508057504Sxy 	for (j = ncookies; j != 0; j--) {
142608057504Sxy 
142725f2d433Sxy 		desc_count = e1000g_fill_tx_desc(tx_ring,
142808057504Sxy 		    packet,
142908057504Sxy 		    dma_cookie.dmac_laddress,
143008057504Sxy 		    dma_cookie.dmac_size);
143108057504Sxy 
143208057504Sxy 		if (desc_count <= 0)
143308057504Sxy 			return (-1);
143408057504Sxy 
143508057504Sxy 		desc_total += desc_count;
143608057504Sxy 
143708057504Sxy 		/*
143808057504Sxy 		 * ddi_dma_nextcookie() retrieves subsequent DMA
143908057504Sxy 		 * cookies for a DMA object.
144008057504Sxy 		 * ddi_dma_nextcookie() fills in the
144108057504Sxy 		 * ddi_dma_cookie(9S) structure pointed to by
144208057504Sxy 		 * cookiep.  The ddi_dma_cookie(9S) structure
144308057504Sxy 		 * must be allocated prior to calling
144408057504Sxy 		 * ddi_dma_nextcookie(). The DMA cookie count
144508057504Sxy 		 * returned by ddi_dma_buf_bind_handle(9F),
144608057504Sxy 		 * ddi_dma_addr_bind_handle(9F), or
144708057504Sxy 		 * ddi_dma_getwin(9F) indicates the number of DMA
144808057504Sxy 		 * cookies a DMA object consists of.  If the
144908057504Sxy 		 * resulting cookie count, N, is larger than 1,
145008057504Sxy 		 * ddi_dma_nextcookie() must be called N-1 times
145108057504Sxy 		 * to retrieve all DMA cookies.
145208057504Sxy 		 */
145308057504Sxy 		if (j > 1) {
145408057504Sxy 			ddi_dma_nextcookie(packet->tx_dma_handle,
145508057504Sxy 			    &dma_cookie);
145608057504Sxy 		}
145708057504Sxy 	}
145808057504Sxy 
145908057504Sxy 	return (desc_total);
146008057504Sxy }
146108057504Sxy 
146208057504Sxy static void
e1000g_fill_context_descriptor(context_data_t * cur_context,struct e1000_context_desc * context_desc)1463c7770590Smx e1000g_fill_context_descriptor(context_data_t *cur_context,
1464c7770590Smx     struct e1000_context_desc *context_desc)
146508057504Sxy {
1466c7770590Smx 	if (cur_context->cksum_flags & HCK_IPV4_HDRCKSUM) {
1467c7770590Smx 		context_desc->lower_setup.ip_fields.ipcss =
1468c7770590Smx 		    cur_context->ether_header_size;
1469c7770590Smx 		context_desc->lower_setup.ip_fields.ipcso =
1470c7770590Smx 		    cur_context->ether_header_size +
147108057504Sxy 		    offsetof(struct ip, ip_sum);
1472c7770590Smx 		context_desc->lower_setup.ip_fields.ipcse =
1473c7770590Smx 		    cur_context->ether_header_size +
1474c7770590Smx 		    cur_context->cksum_start - 1;
147508057504Sxy 	} else
1476c7770590Smx 		context_desc->lower_setup.ip_config = 0;
147708057504Sxy 
1478c7770590Smx 	if (cur_context->cksum_flags & HCK_PARTIALCKSUM) {
147908057504Sxy 		/*
148008057504Sxy 		 * The packet with same protocol has the following
148108057504Sxy 		 * stuff and start offset:
148208057504Sxy 		 * |  Protocol  | Stuff  | Start  | Checksum
148308057504Sxy 		 * |		| Offset | Offset | Enable
148408057504Sxy 		 * | IPv4 + TCP |  0x24  |  0x14  |  Yes
148508057504Sxy 		 * | IPv4 + UDP |  0x1A  |  0x14  |  Yes
148608057504Sxy 		 * | IPv6 + TCP |  0x20  |  0x10  |  No
148708057504Sxy 		 * | IPv6 + UDP |  0x14  |  0x10  |  No
148808057504Sxy 		 */
1489c7770590Smx 		context_desc->upper_setup.tcp_fields.tucss =
1490c7770590Smx 		    cur_context->cksum_start + cur_context->ether_header_size;
1491c7770590Smx 		context_desc->upper_setup.tcp_fields.tucso =
1492c7770590Smx 		    cur_context->cksum_stuff + cur_context->ether_header_size;
1493c7770590Smx 		context_desc->upper_setup.tcp_fields.tucse = 0;
149408057504Sxy 	} else
1495c7770590Smx 		context_desc->upper_setup.tcp_config = 0;
149608057504Sxy 
1497c7770590Smx 	if (cur_context->lso_flag) {
1498c7770590Smx 		context_desc->tcp_seg_setup.fields.mss = cur_context->mss;
1499c7770590Smx 		context_desc->tcp_seg_setup.fields.hdr_len =
1500c7770590Smx 		    cur_context->hdr_len;
1501c7770590Smx 		/*
1502c7770590Smx 		 * workaround for 82546EB errata 23, status-writeback
1503c7770590Smx 		 * reporting (RS) should not be set on context or
1504c7770590Smx 		 * Null descriptors
1505c7770590Smx 		 */
1506c7770590Smx 		context_desc->cmd_and_length = E1000_TXD_CMD_DEXT
1507c7770590Smx 		    | E1000_TXD_CMD_TSE | E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP
1508c7770590Smx 		    | E1000_TXD_DTYP_C | cur_context->pay_len;
1509c7770590Smx 	} else {
1510c7770590Smx 		context_desc->cmd_and_length = E1000_TXD_CMD_DEXT
1511c7770590Smx 		    | E1000_TXD_DTYP_C;
1512c7770590Smx 		/*
1513c7770590Smx 		 * Zero out the options for TCP Segmentation Offload
1514c7770590Smx 		 */
1515c7770590Smx 		context_desc->tcp_seg_setup.data = 0;
1516c7770590Smx 	}
151708057504Sxy }
151808057504Sxy 
151908057504Sxy static int
e1000g_fill_tx_desc(e1000g_tx_ring_t * tx_ring,p_tx_sw_packet_t packet,uint64_t address,size_t size)152025f2d433Sxy e1000g_fill_tx_desc(e1000g_tx_ring_t *tx_ring,
152125f2d433Sxy     p_tx_sw_packet_t packet, uint64_t address, size_t size)
152208057504Sxy {
152325f2d433Sxy 	struct e1000_hw *hw = &tx_ring->adapter->shared;
152425f2d433Sxy 	p_sw_desc_t desc;
152508057504Sxy 
152625f2d433Sxy 	if (hw->mac.type == e1000_82544) {
152725f2d433Sxy 		if (hw->bus.type == e1000_bus_type_pcix)
152825f2d433Sxy 			return (e1000g_tx_workaround_PCIX_82544(packet,
152925f2d433Sxy 			    address, size));
153008057504Sxy 
153125f2d433Sxy 		if (size > JUMBO_FRAG_LENGTH)
153225f2d433Sxy 			return (e1000g_tx_workaround_jumbo_82544(packet,
153325f2d433Sxy 			    address, size));
153425f2d433Sxy 	}
153508057504Sxy 
153625f2d433Sxy 	ASSERT(packet->num_desc < MAX_TX_DESC_PER_PACKET);
153708057504Sxy 
153825f2d433Sxy 	desc = &packet->desc[packet->num_desc];
153925f2d433Sxy 	desc->address = address;
1540fe62dec3SChen-Liang Xu 	desc->length = (uint32_t)size;
154108057504Sxy 
154225f2d433Sxy 	packet->num_desc++;
154308057504Sxy 
154425f2d433Sxy 	return (1);
154508057504Sxy }
154608057504Sxy 
154708057504Sxy static int
e1000g_tx_workaround_PCIX_82544(p_tx_sw_packet_t packet,uint64_t address,size_t size)154825f2d433Sxy e1000g_tx_workaround_PCIX_82544(p_tx_sw_packet_t packet,
154925f2d433Sxy     uint64_t address, size_t size)
155008057504Sxy {
155125f2d433Sxy 	p_sw_desc_t desc;
155208057504Sxy 	int desc_count;
155308057504Sxy 	long size_left;
155408057504Sxy 	size_t len;
155508057504Sxy 	uint32_t counter;
155608057504Sxy 	uint32_t array_elements;
155725f2d433Sxy 	desc_array_t desc_array;
155808057504Sxy 
155908057504Sxy 	/*
156008057504Sxy 	 * Coexist Workaround for cordova: RP: 07/04/03
156108057504Sxy 	 *
156208057504Sxy 	 * RP: ERRATA: Workaround ISSUE:
156308057504Sxy 	 * 8kb_buffer_Lockup CONTROLLER: Cordova Breakup
156408057504Sxy 	 * Eachbuffer in to 8kb pieces until the
156508057504Sxy 	 * remainder is < 8kb
156608057504Sxy 	 */
156708057504Sxy 	size_left = size;
156808057504Sxy 	desc_count = 0;
156908057504Sxy 
157008057504Sxy 	while (size_left > 0) {
157108057504Sxy 		if (size_left > MAX_TX_BUF_SIZE)
157208057504Sxy 			len = MAX_TX_BUF_SIZE;
157308057504Sxy 		else
157408057504Sxy 			len = size_left;
157508057504Sxy 
157608057504Sxy 		array_elements = e1000g_fill_82544_desc(address,
157708057504Sxy 		    len, &desc_array);
157808057504Sxy 
157908057504Sxy 		for (counter = 0; counter < array_elements; counter++) {
158008057504Sxy 			ASSERT(packet->num_desc < MAX_TX_DESC_PER_PACKET);
158108057504Sxy 			/*
158208057504Sxy 			 * Put in the buffer address
158308057504Sxy 			 */
158408057504Sxy 			desc = &packet->desc[packet->num_desc];
158508057504Sxy 
158625f2d433Sxy 			desc->address =
158725f2d433Sxy 			    desc_array.descriptor[counter].address;
158825f2d433Sxy 			desc->length =
158925f2d433Sxy 			    desc_array.descriptor[counter].length;
159008057504Sxy 
159108057504Sxy 			packet->num_desc++;
159208057504Sxy 			desc_count++;
159308057504Sxy 		} /* for */
159408057504Sxy 
159508057504Sxy 		/*
159608057504Sxy 		 * Update the buffer address and length
159708057504Sxy 		 */
159808057504Sxy 		address += MAX_TX_BUF_SIZE;
159908057504Sxy 		size_left -= MAX_TX_BUF_SIZE;
160008057504Sxy 	} /* while */
160108057504Sxy 
160208057504Sxy 	return (desc_count);
160308057504Sxy }
160408057504Sxy 
160508057504Sxy static int
e1000g_tx_workaround_jumbo_82544(p_tx_sw_packet_t packet,uint64_t address,size_t size)160625f2d433Sxy e1000g_tx_workaround_jumbo_82544(p_tx_sw_packet_t packet,
160725f2d433Sxy     uint64_t address, size_t size)
160808057504Sxy {
160925f2d433Sxy 	p_sw_desc_t desc;
161008057504Sxy 	int desc_count;
161108057504Sxy 	long size_left;
161208057504Sxy 	uint32_t offset;
161308057504Sxy 
161408057504Sxy 	/*
161508057504Sxy 	 * Workaround for Jumbo Frames on Cordova
161608057504Sxy 	 * PSD 06/01/2001
161708057504Sxy 	 */
161808057504Sxy 	size_left = size;
161908057504Sxy 	desc_count = 0;
162008057504Sxy 	offset = 0;
162108057504Sxy 	while (size_left > 0) {
162208057504Sxy 		ASSERT(packet->num_desc < MAX_TX_DESC_PER_PACKET);
162308057504Sxy 
162408057504Sxy 		desc = &packet->desc[packet->num_desc];
162508057504Sxy 
162625f2d433Sxy 		desc->address = address + offset;
162708057504Sxy 
162808057504Sxy 		if (size_left > JUMBO_FRAG_LENGTH)
162925f2d433Sxy 			desc->length = JUMBO_FRAG_LENGTH;
163008057504Sxy 		else
1631fe62dec3SChen-Liang Xu 			desc->length = (uint32_t)size_left;
163208057504Sxy 
163308057504Sxy 		packet->num_desc++;
163408057504Sxy 		desc_count++;
163508057504Sxy 
163625f2d433Sxy 		offset += desc->length;
163708057504Sxy 		size_left -= JUMBO_FRAG_LENGTH;
163808057504Sxy 	}
163908057504Sxy 
164008057504Sxy 	return (desc_count);
164108057504Sxy }
164208057504Sxy 
164325f2d433Sxy #pragma inline(e1000g_82547_tx_move_tail_work)
164425f2d433Sxy 
164508057504Sxy static void
e1000g_82547_tx_move_tail_work(e1000g_tx_ring_t * tx_ring)164608057504Sxy e1000g_82547_tx_move_tail_work(e1000g_tx_ring_t *tx_ring)
164708057504Sxy {
164825f2d433Sxy 	struct e1000_hw *hw;
164908057504Sxy 	uint16_t hw_tdt;
165008057504Sxy 	uint16_t sw_tdt;
165108057504Sxy 	struct e1000_tx_desc *tx_desc;
165208057504Sxy 	uint16_t length = 0;
165308057504Sxy 	boolean_t eop = B_FALSE;
165408057504Sxy 	struct e1000g *Adapter;
165508057504Sxy 
165608057504Sxy 	Adapter = tx_ring->adapter;
165725f2d433Sxy 	hw = &Adapter->shared;
165808057504Sxy 
1659592a4d85Scc 	hw_tdt = E1000_READ_REG(hw, E1000_TDT(0));
166008057504Sxy 	sw_tdt = tx_ring->tbd_next - tx_ring->tbd_first;
166108057504Sxy 
166208057504Sxy 	while (hw_tdt != sw_tdt) {
166308057504Sxy 		tx_desc = &(tx_ring->tbd_first[hw_tdt]);
166408057504Sxy 		length += tx_desc->lower.flags.length;
166508057504Sxy 		eop = tx_desc->lower.data & E1000_TXD_CMD_EOP;
166625f2d433Sxy 		if (++hw_tdt == Adapter->tx_desc_num)
166708057504Sxy 			hw_tdt = 0;
166808057504Sxy 
166908057504Sxy 		if (eop) {
167008057504Sxy 			if ((Adapter->link_duplex == HALF_DUPLEX) &&
167125f2d433Sxy 			    (e1000_fifo_workaround_82547(hw, length)
167225f2d433Sxy 			    != E1000_SUCCESS)) {
167308057504Sxy 				if (tx_ring->timer_enable_82547) {
167408057504Sxy 					ASSERT(tx_ring->timer_id_82547 == 0);
167508057504Sxy 					tx_ring->timer_id_82547 =
167608057504Sxy 					    timeout(e1000g_82547_timeout,
16775633182fSyy 					    (void *)tx_ring,
16785633182fSyy 					    drv_usectohz(10000));
167908057504Sxy 				}
168008057504Sxy 				return;
168108057504Sxy 
168208057504Sxy 			} else {
1683592a4d85Scc 				E1000_WRITE_REG(hw, E1000_TDT(0), hw_tdt);
168425f2d433Sxy 				e1000_update_tx_fifo_head_82547(hw, length);
168508057504Sxy 				length = 0;
168608057504Sxy 			}
168708057504Sxy 		}
168808057504Sxy 	}
168908057504Sxy }
169008057504Sxy 
169108057504Sxy static void
e1000g_82547_timeout(void * arg)169208057504Sxy e1000g_82547_timeout(void *arg)
169308057504Sxy {
169408057504Sxy 	e1000g_tx_ring_t *tx_ring;
169508057504Sxy 
169608057504Sxy 	tx_ring = (e1000g_tx_ring_t *)arg;
169708057504Sxy 
169808057504Sxy 	mutex_enter(&tx_ring->tx_lock);
169908057504Sxy 
170008057504Sxy 	tx_ring->timer_id_82547 = 0;
170108057504Sxy 	e1000g_82547_tx_move_tail_work(tx_ring);
170208057504Sxy 
170308057504Sxy 	mutex_exit(&tx_ring->tx_lock);
170408057504Sxy }
170508057504Sxy 
170608057504Sxy static void
e1000g_82547_tx_move_tail(e1000g_tx_ring_t * tx_ring)170708057504Sxy e1000g_82547_tx_move_tail(e1000g_tx_ring_t *tx_ring)
170808057504Sxy {
170908057504Sxy 	timeout_id_t tid;
171008057504Sxy 
171108057504Sxy 	ASSERT(MUTEX_HELD(&tx_ring->tx_lock));
171208057504Sxy 
171308057504Sxy 	tid = tx_ring->timer_id_82547;
171408057504Sxy 	tx_ring->timer_id_82547 = 0;
171508057504Sxy 	if (tid != 0) {
171608057504Sxy 		tx_ring->timer_enable_82547 = B_FALSE;
171708057504Sxy 		mutex_exit(&tx_ring->tx_lock);
171808057504Sxy 
171908057504Sxy 		(void) untimeout(tid);
172008057504Sxy 
172108057504Sxy 		mutex_enter(&tx_ring->tx_lock);
172208057504Sxy 	}
172308057504Sxy 	tx_ring->timer_enable_82547 = B_TRUE;
172408057504Sxy 	e1000g_82547_tx_move_tail_work(tx_ring);
172508057504Sxy }
172649b78600SRobert Mustacchi 
172749b78600SRobert Mustacchi /*
172849b78600SRobert Mustacchi  * This is part of a workaround for the I219, see e1000g_flush_desc_rings() for
172949b78600SRobert Mustacchi  * more information.
173049b78600SRobert Mustacchi  *
173149b78600SRobert Mustacchi  * We need to clear any potential pending descriptors from the tx_ring.  As
173249b78600SRobert Mustacchi  * we're about to reset the device, we don't care about the data that we give it
173349b78600SRobert Mustacchi  * itself.
173449b78600SRobert Mustacchi  */
173549b78600SRobert Mustacchi void
e1000g_flush_tx_ring(struct e1000g * Adapter)173649b78600SRobert Mustacchi e1000g_flush_tx_ring(struct e1000g *Adapter)
173749b78600SRobert Mustacchi {
173849b78600SRobert Mustacchi 	struct e1000_hw *hw = &Adapter->shared;
173949b78600SRobert Mustacchi 	e1000g_tx_ring_t *tx_ring = &Adapter->tx_ring[0];
174049b78600SRobert Mustacchi 	uint32_t tctl, txd_lower = E1000_TXD_CMD_IFCS;
174149b78600SRobert Mustacchi 	uint16_t size = 512;
174249b78600SRobert Mustacchi 	struct e1000_tx_desc *desc;
174349b78600SRobert Mustacchi 
174449b78600SRobert Mustacchi 	tctl = E1000_READ_REG(hw, E1000_TCTL);
174549b78600SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_TCTL, tctl | E1000_TCTL_EN);
174649b78600SRobert Mustacchi 
174749b78600SRobert Mustacchi 	desc = tx_ring->tbd_next;
174849b78600SRobert Mustacchi 	if (tx_ring->tbd_next == tx_ring->tbd_last)
174949b78600SRobert Mustacchi 		tx_ring->tbd_next = tx_ring->tbd_first;
175049b78600SRobert Mustacchi 	else
175149b78600SRobert Mustacchi 		tx_ring->tbd_next++;
175249b78600SRobert Mustacchi 
175349b78600SRobert Mustacchi 	/* We just need to set any valid address, so we use the ring itself */
175449b78600SRobert Mustacchi 	desc->buffer_addr = tx_ring->tbd_dma_addr;
175549b78600SRobert Mustacchi 	desc->lower.data = LE_32(txd_lower | size);
175649b78600SRobert Mustacchi 	desc->upper.data = 0;
175749b78600SRobert Mustacchi 
175849b78600SRobert Mustacchi 	(void) ddi_dma_sync(tx_ring->tbd_dma_handle,
175949b78600SRobert Mustacchi 	    0, 0, DDI_DMA_SYNC_FORDEV);
176049b78600SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_TDT(0),
176149b78600SRobert Mustacchi 	    (uint32_t)(tx_ring->tbd_next - tx_ring->tbd_first));
176249b78600SRobert Mustacchi 	(void) E1000_READ_REG(hw, E1000_STATUS);
176349b78600SRobert Mustacchi 	usec_delay(250);
176449b78600SRobert Mustacchi }
1765