xref: /onnv-gate/usr/src/uts/common/io/nge/nge_rx.c (revision 11878:ac93462db6d7)
15578Smx205022 /*
25578Smx205022  * CDDL HEADER START
35578Smx205022  *
45578Smx205022  * The contents of this file are subject to the terms of the
55578Smx205022  * Common Development and Distribution License (the "License").
65578Smx205022  * You may not use this file except in compliance with the License.
75578Smx205022  *
85578Smx205022  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95578Smx205022  * or http://www.opensolaris.org/os/licensing.
105578Smx205022  * See the License for the specific language governing permissions
115578Smx205022  * and limitations under the License.
125578Smx205022  *
135578Smx205022  * When distributing Covered Code, include this CDDL HEADER in each
145578Smx205022  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155578Smx205022  * If applicable, add the following below this CDDL HEADER, with the
165578Smx205022  * fields enclosed by brackets "[]" replaced with your own identifying
175578Smx205022  * information: Portions Copyright [yyyy] [name of copyright owner]
185578Smx205022  *
195578Smx205022  * CDDL HEADER END
205578Smx205022  */
215578Smx205022 
225574Smx205022 /*
23*11878SVenu.Iyer@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
245574Smx205022  * Use is subject to license terms.
255574Smx205022  */
265574Smx205022 
275574Smx205022 #include "nge.h"
285574Smx205022 
295574Smx205022 #undef	NGE_DBG
305574Smx205022 #define	NGE_DBG		NGE_DBG_RECV
315574Smx205022 
325574Smx205022 #define	RXD_END		0x20000000
335574Smx205022 #define	RXD_ERR		0x40000000
345574Smx205022 #define	RXD_OWN		0x80000000
355574Smx205022 #define	RXD_CSUM_MSK	0x1C000000
365574Smx205022 #define	RXD_BCNT_MSK	0x00003FFF
375574Smx205022 
385574Smx205022 #define	RXD_CK8G_NO_HSUM	0x0
395574Smx205022 #define	RXD_CK8G_TCP_SUM_ERR	0x04000000
405574Smx205022 #define	RXD_CK8G_UDP_SUM_ERR	0x08000000
415574Smx205022 #define	RXD_CK8G_IP_HSUM_ERR	0x0C000000
425574Smx205022 #define	RXD_CK8G_IP_HSUM	0x10000000
435574Smx205022 #define	RXD_CK8G_TCP_SUM	0x14000000
445574Smx205022 #define	RXD_CK8G_UDP_SUM	0x18000000
455574Smx205022 #define	RXD_CK8G_RESV		0x1C000000
465574Smx205022 
475574Smx205022 extern ddi_device_acc_attr_t nge_data_accattr;
485574Smx205022 
495574Smx205022 /*
505988Svb160487  * Callback code invoked from STREAMs when the recv data buffer is free for
515988Svb160487  * recycling.
525988Svb160487  *
535988Svb160487  * The following table describes function behaviour:
545988Svb160487  *
555988Svb160487  *                      | mac stopped | mac running
565988Svb160487  * ---------------------------------------------------
575988Svb160487  * buffer delivered     | free buffer | recycle buffer
585988Svb160487  * buffer not delivered | do nothing  | recycle buffer (*)
595988Svb160487  *
605988Svb160487  * Note (*):
615988Svb160487  *   Recycle buffer only if mac state did not change during execution of
625988Svb160487  *   function. Otherwise if mac state changed, set buffer delivered & re-enter
635988Svb160487  *   function by calling freemsg().
645574Smx205022  */
655574Smx205022 
665574Smx205022 void
nge_recv_recycle(caddr_t arg)675574Smx205022 nge_recv_recycle(caddr_t arg)
685574Smx205022 {
695574Smx205022 	boolean_t val;
705574Smx205022 	boolean_t valid;
715574Smx205022 	nge_t *ngep;
725574Smx205022 	dma_area_t *bufp;
735574Smx205022 	buff_ring_t *brp;
745574Smx205022 	nge_sw_statistics_t *sw_stp;
755574Smx205022 
765574Smx205022 	bufp = (dma_area_t *)arg;
775574Smx205022 	ngep = (nge_t *)bufp->private;
785574Smx205022 	brp = ngep->buff;
795574Smx205022 	sw_stp = &ngep->statistics.sw_statistics;
805574Smx205022 
815574Smx205022 	/*
825574Smx205022 	 * Free the buffer directly if the buffer was allocated
835574Smx205022 	 * previously or mac was stopped.
845574Smx205022 	 */
855574Smx205022 	if (bufp->signature != brp->buf_sign) {
865574Smx205022 		if (bufp->rx_delivered == B_TRUE) {
875574Smx205022 			nge_free_dma_mem(bufp);
885574Smx205022 			kmem_free(bufp, sizeof (dma_area_t));
895574Smx205022 			val = nge_atomic_decrease(&brp->rx_hold, 1);
905574Smx205022 			ASSERT(val == B_TRUE);
915574Smx205022 		}
925574Smx205022 		return;
935574Smx205022 	}
945574Smx205022 
955574Smx205022 	/*
965574Smx205022 	 * recycle the data buffer again and fill them in free ring
975574Smx205022 	 */
985574Smx205022 	bufp->rx_recycle.free_func = nge_recv_recycle;
995574Smx205022 	bufp->rx_recycle.free_arg = (caddr_t)bufp;
1005574Smx205022 
1015574Smx205022 	bufp->mp = desballoc(DMA_VPTR(*bufp),
1025574Smx205022 	    ngep->buf_size + NGE_HEADROOM, 0, &bufp->rx_recycle);
1035574Smx205022 
1045574Smx205022 	if (bufp->mp == NULL) {
1055574Smx205022 		sw_stp->mp_alloc_err++;
1065574Smx205022 		sw_stp->recy_free++;
1075574Smx205022 		nge_free_dma_mem(bufp);
1085574Smx205022 		kmem_free(bufp, sizeof (dma_area_t));
1095574Smx205022 		val = nge_atomic_decrease(&brp->rx_hold, 1);
1105574Smx205022 		ASSERT(val == B_TRUE);
1115574Smx205022 	} else {
1125574Smx205022 
1135574Smx205022 		mutex_enter(brp->recycle_lock);
1145574Smx205022 		if (bufp->signature != brp->buf_sign)
1155574Smx205022 			valid = B_TRUE;
1165574Smx205022 		else
1175574Smx205022 			valid = B_FALSE;
1185574Smx205022 		bufp->rx_delivered = valid;
1195574Smx205022 		if (bufp->rx_delivered == B_FALSE)  {
1205574Smx205022 			bufp->next = brp->recycle_list;
1215574Smx205022 			brp->recycle_list = bufp;
1225574Smx205022 		}
1235574Smx205022 		mutex_exit(brp->recycle_lock);
1245574Smx205022 		if (valid == B_TRUE)
1255574Smx205022 			/* call nge_rx_recycle again to free it */
1265574Smx205022 			freemsg(bufp->mp);
1275574Smx205022 		else {
1285574Smx205022 			val = nge_atomic_decrease(&brp->rx_hold, 1);
1295574Smx205022 			ASSERT(val == B_TRUE);
1305574Smx205022 		}
1315574Smx205022 	}
1325574Smx205022 }
1335574Smx205022 
1345574Smx205022 /*
1355574Smx205022  * Checking the rx's BDs (one or more) to receive
1365574Smx205022  * one complete packet.
1375574Smx205022  * start_index: the start indexer of BDs for one packet.
1385574Smx205022  * end_index: the end indexer of BDs for one packet.
1395574Smx205022  */
1405574Smx205022 static mblk_t *nge_recv_packet(nge_t *ngep, uint32_t start_index, size_t len);
1415574Smx205022 #pragma	inline(nge_recv_packet)
1425574Smx205022 
1435574Smx205022 static mblk_t *
nge_recv_packet(nge_t * ngep,uint32_t start_index,size_t len)1445574Smx205022 nge_recv_packet(nge_t *ngep, uint32_t start_index, size_t len)
1455574Smx205022 {
1465574Smx205022 	uint8_t *rptr;
1475574Smx205022 	uint32_t minsize;
1485574Smx205022 	uint32_t maxsize;
1495574Smx205022 	mblk_t *mp;
1505574Smx205022 	buff_ring_t *brp;
1515574Smx205022 	sw_rx_sbd_t *srbdp;
1525574Smx205022 	dma_area_t *bufp;
1535574Smx205022 	nge_sw_statistics_t *sw_stp;
1545574Smx205022 	void *hw_bd_p;
1555574Smx205022 
1565574Smx205022 	brp = ngep->buff;
1575574Smx205022 	minsize = ETHERMIN;
1585574Smx205022 	maxsize = ngep->max_sdu;
1595574Smx205022 	sw_stp = &ngep->statistics.sw_statistics;
1605574Smx205022 	mp = NULL;
1615574Smx205022 
1625574Smx205022 	srbdp = &brp->sw_rbds[start_index];
1635574Smx205022 	DMA_SYNC(*srbdp->bufp, DDI_DMA_SYNC_FORKERNEL);
1645574Smx205022 	hw_bd_p = DMA_VPTR(srbdp->desc);
1655574Smx205022 
1665574Smx205022 	/*
1675574Smx205022 	 * First check the free_list, if it is NULL,
1685574Smx205022 	 * make the recycle_list be free_list.
1695574Smx205022 	 */
1705574Smx205022 	if (brp->free_list == NULL) {
1715574Smx205022 		mutex_enter(brp->recycle_lock);
1725574Smx205022 		brp->free_list = brp->recycle_list;
1735574Smx205022 		brp->recycle_list = NULL;
1745574Smx205022 		mutex_exit(brp->recycle_lock);
1755574Smx205022 	}
1765574Smx205022 	bufp = brp->free_list;
1775574Smx205022 	/* If it's not a qualified packet, delete it */
1785574Smx205022 	if (len > maxsize || len < minsize) {
1795574Smx205022 		ngep->desc_attr.rxd_fill(hw_bd_p, &srbdp->bufp->cookie,
1805574Smx205022 		    srbdp->bufp->alength);
1815574Smx205022 		srbdp->flags = CONTROLER_OWN;
1825574Smx205022 		return (NULL);
1835574Smx205022 	}
1845574Smx205022 
1855574Smx205022 	/*
1865574Smx205022 	 * If receive packet size is smaller than RX bcopy threshold,
1875574Smx205022 	 * or there is no available buffer in free_list or recycle list,
1885574Smx205022 	 * we use bcopy directly.
1895574Smx205022 	 */
1905574Smx205022 	if (len <= ngep->param_rxbcopy_threshold || bufp == NULL)
1915574Smx205022 		brp->rx_bcopy = B_TRUE;
1925574Smx205022 	else
1935574Smx205022 		brp->rx_bcopy = B_FALSE;
1945574Smx205022 
1955574Smx205022 	if (brp->rx_bcopy) {
1965574Smx205022 		mp = allocb(len + NGE_HEADROOM, 0);
1975574Smx205022 		if (mp == NULL) {
1985574Smx205022 			sw_stp->mp_alloc_err++;
1995574Smx205022 			ngep->desc_attr.rxd_fill(hw_bd_p, &srbdp->bufp->cookie,
2005574Smx205022 			    srbdp->bufp->alength);
2015574Smx205022 			srbdp->flags = CONTROLER_OWN;
2025574Smx205022 			return (NULL);
2035574Smx205022 		}
2045574Smx205022 		rptr = DMA_VPTR(*srbdp->bufp);
2055574Smx205022 		mp->b_rptr = mp->b_rptr + NGE_HEADROOM;
2065574Smx205022 		bcopy(rptr + NGE_HEADROOM, mp->b_rptr, len);
2075574Smx205022 		mp->b_wptr = mp->b_rptr + len;
2085574Smx205022 	} else {
2095574Smx205022 		mp = srbdp->bufp->mp;
2105574Smx205022 		/*
2115574Smx205022 		 * Make sure the packet *contents* 4-byte aligned
2125574Smx205022 		 */
2135574Smx205022 		mp->b_rptr += NGE_HEADROOM;
2145574Smx205022 		mp->b_wptr = mp->b_rptr + len;
2155574Smx205022 		mp->b_next = mp->b_cont = NULL;
2165574Smx205022 		srbdp->bufp->rx_delivered = B_TRUE;
2175574Smx205022 		srbdp->bufp = NULL;
2185574Smx205022 		nge_atomic_increase(&brp->rx_hold, 1);
2195574Smx205022 
2205574Smx205022 		/* Fill the buffer from free_list */
2215574Smx205022 		srbdp->bufp = bufp;
2225574Smx205022 		brp->free_list = bufp->next;
2235574Smx205022 		bufp->next = NULL;
2245574Smx205022 	}
2255574Smx205022 
2265574Smx205022 	/* replenish the buffer for hardware descriptor */
2275574Smx205022 	ngep->desc_attr.rxd_fill(hw_bd_p, &srbdp->bufp->cookie,
2285574Smx205022 	    srbdp->bufp->alength);
2295574Smx205022 	srbdp->flags = CONTROLER_OWN;
2305574Smx205022 	sw_stp->rbytes += len;
2315574Smx205022 	sw_stp->recv_count++;
2325574Smx205022 
2335574Smx205022 	return (mp);
2345574Smx205022 }
2355574Smx205022 
2365574Smx205022 
2375574Smx205022 #define	RX_HW_ERR	0x01
2385574Smx205022 #define	RX_SUM_NO	0x02
2395574Smx205022 #define	RX_SUM_ERR	0x04
2405574Smx205022 
2415574Smx205022 /*
2425574Smx205022  * Statistic the rx's error
2435574Smx205022  * and generate a log msg for these.
2445574Smx205022  * Note:
2455574Smx205022  * RXE, Parity Error, Symbo error, CRC error
2465574Smx205022  * have been recored by nvidia's  hardware
2475574Smx205022  * statistics part (nge_statistics). So it is uncessary to record them by
2485574Smx205022  * driver in this place.
2495574Smx205022  */
2505574Smx205022 static uint32_t
2515574Smx205022 nge_rxsta_handle(nge_t *ngep, uint32_t stflag, uint32_t *pflags);
2525574Smx205022 #pragma	inline(nge_rxsta_handle)
2535574Smx205022 
2545574Smx205022 static uint32_t
nge_rxsta_handle(nge_t * ngep,uint32_t stflag,uint32_t * pflags)2555574Smx205022 nge_rxsta_handle(nge_t *ngep,  uint32_t stflag, uint32_t *pflags)
2565574Smx205022 {
2575574Smx205022 	uint32_t errors;
2585574Smx205022 	uint32_t err_flag;
2595574Smx205022 	nge_sw_statistics_t *sw_stp;
2605574Smx205022 
2615574Smx205022 	err_flag = 0;
2625574Smx205022 	sw_stp = &ngep->statistics.sw_statistics;
2635574Smx205022 
2645574Smx205022 	if ((RXD_END & stflag) == 0)
2655574Smx205022 		return (RX_HW_ERR);
2665574Smx205022 
2675574Smx205022 	errors = stflag & RXD_CSUM_MSK;
2685574Smx205022 	switch (errors) {
2695574Smx205022 	default:
2705574Smx205022 	break;
2715574Smx205022 
2725574Smx205022 	case RXD_CK8G_TCP_SUM:
2735574Smx205022 	case RXD_CK8G_UDP_SUM:
274*11878SVenu.Iyer@Sun.COM 		*pflags |= HCK_IPV4_HDRCKSUM_OK;
2755574Smx205022 		*pflags |= HCK_FULLCKSUM_OK;
2765574Smx205022 		break;
2775574Smx205022 
2785574Smx205022 	case RXD_CK8G_TCP_SUM_ERR:
2795574Smx205022 	case RXD_CK8G_UDP_SUM_ERR:
2805574Smx205022 		sw_stp->tcp_hwsum_err++;
281*11878SVenu.Iyer@Sun.COM 		*pflags |= HCK_IPV4_HDRCKSUM_OK;
2825574Smx205022 		break;
2835574Smx205022 
2845574Smx205022 	case RXD_CK8G_IP_HSUM:
285*11878SVenu.Iyer@Sun.COM 		*pflags |= HCK_IPV4_HDRCKSUM_OK;
2865574Smx205022 		break;
2875574Smx205022 
2885574Smx205022 	case RXD_CK8G_NO_HSUM:
2895574Smx205022 		err_flag |= RX_SUM_NO;
2905574Smx205022 		break;
2915574Smx205022 
2925574Smx205022 	case RXD_CK8G_IP_HSUM_ERR:
2935574Smx205022 		sw_stp->ip_hwsum_err++;
2945574Smx205022 		err_flag |=  RX_SUM_ERR;
2955574Smx205022 		break;
2965574Smx205022 	}
2975574Smx205022 
2985574Smx205022 	if ((stflag & RXD_ERR) != 0)	{
2995574Smx205022 
3005574Smx205022 		err_flag |= RX_HW_ERR;
3015574Smx205022 		NGE_DEBUG(("Receive desc error, status: 0x%x", stflag));
3025574Smx205022 	}
3035574Smx205022 
3045574Smx205022 	return (err_flag);
3055574Smx205022 }
3065574Smx205022 
3075574Smx205022 static mblk_t *
nge_recv_ring(nge_t * ngep)3085574Smx205022 nge_recv_ring(nge_t *ngep)
3095574Smx205022 {
3105574Smx205022 	uint32_t stflag;
3115574Smx205022 	uint32_t flag_err;
3125574Smx205022 	uint32_t sum_flags;
3135574Smx205022 	size_t len;
3145574Smx205022 	uint64_t end_index;
3155574Smx205022 	uint64_t sync_start;
3165574Smx205022 	mblk_t *mp;
3175574Smx205022 	mblk_t **tail;
3185574Smx205022 	mblk_t *head;
3195574Smx205022 	recv_ring_t *rrp;
3205574Smx205022 	buff_ring_t *brp;
3215574Smx205022 	sw_rx_sbd_t *srbdp;
3225574Smx205022 	void * hw_bd_p;
3235574Smx205022 	nge_mode_cntl mode_cntl;
3245574Smx205022 
3255574Smx205022 	mp = NULL;
3265574Smx205022 	head = NULL;
3275574Smx205022 	tail = &head;
3285574Smx205022 	rrp = ngep->recv;
3295574Smx205022 	brp = ngep->buff;
3305574Smx205022 
3315574Smx205022 	end_index = sync_start = rrp->prod_index;
3325574Smx205022 	/* Sync the descriptor for kernel */
3335574Smx205022 	if (sync_start + ngep->param_recv_max_packet <= ngep->rx_desc) {
3345574Smx205022 		(void) ddi_dma_sync(rrp->desc.dma_hdl,
3355574Smx205022 		    sync_start * ngep->desc_attr.rxd_size,
3365574Smx205022 		    ngep->param_recv_max_packet * ngep->desc_attr.rxd_size,
3375574Smx205022 		    DDI_DMA_SYNC_FORKERNEL);
3385574Smx205022 	} else {
3395574Smx205022 		(void) ddi_dma_sync(rrp->desc.dma_hdl,
3405574Smx205022 		    sync_start * ngep->desc_attr.rxd_size,
3415574Smx205022 		    0,
3425574Smx205022 		    DDI_DMA_SYNC_FORKERNEL);
3435574Smx205022 		(void) ddi_dma_sync(rrp->desc.dma_hdl,
3445574Smx205022 		    0,
3455574Smx205022 		    (ngep->param_recv_max_packet + sync_start - ngep->rx_desc) *
3465574Smx205022 		    ngep->desc_attr.rxd_size,
3475574Smx205022 		    DDI_DMA_SYNC_FORKERNEL);
3485574Smx205022 	}
3495574Smx205022 
3505574Smx205022 	/*
3515574Smx205022 	 * Looking through the rx's ring to find the good packets
3525574Smx205022 	 * and try to receive more and more packets in rx's ring
3535574Smx205022 	 */
3545574Smx205022 	for (;;) {
3555574Smx205022 		sum_flags = 0;
3565574Smx205022 		flag_err = 0;
3575574Smx205022 		end_index = rrp->prod_index;
3585574Smx205022 		srbdp = &brp->sw_rbds[end_index];
3595574Smx205022 		hw_bd_p = DMA_VPTR(srbdp->desc);
3605574Smx205022 		stflag = ngep->desc_attr.rxd_check(hw_bd_p, &len);
3615574Smx205022 		/*
3625574Smx205022 		 * If there is no packet in receving ring
3635574Smx205022 		 * break the loop
3645574Smx205022 		 */
3655574Smx205022 		if ((stflag & RXD_OWN) != 0 || HOST_OWN == srbdp->flags)
3665574Smx205022 			break;
3675574Smx205022 
3685574Smx205022 		ngep->recv_count++;
3695574Smx205022 		flag_err = nge_rxsta_handle(ngep, stflag, &sum_flags);
3705574Smx205022 		if ((flag_err & RX_HW_ERR) == 0) {
3715574Smx205022 			srbdp->flags = NGE_END_PACKET;
3725574Smx205022 			mp = nge_recv_packet(ngep, end_index, len);
3735574Smx205022 		} else {
3745574Smx205022 			/* Hardware error, re-use the buffer */
3755574Smx205022 			ngep->desc_attr.rxd_fill(hw_bd_p, &srbdp->bufp->cookie,
3765574Smx205022 			    srbdp->bufp->alength);
3775574Smx205022 			srbdp->flags = CONTROLER_OWN;
3785574Smx205022 		}
3795574Smx205022 		if (mp != NULL) {
3805574Smx205022 			if (!(flag_err & (RX_SUM_NO | RX_SUM_ERR))) {
381*11878SVenu.Iyer@Sun.COM 				mac_hcksum_set(mp, 0, 0, 0, 0, sum_flags);
3825574Smx205022 			}
3835574Smx205022 			*tail = mp;
3845574Smx205022 			tail = &mp->b_next;
3855574Smx205022 			mp = NULL;
3865574Smx205022 		}
3875574Smx205022 		rrp->prod_index = NEXT(end_index, rrp->desc.nslots);
3888848SZhen.W@Sun.COM 		if (ngep->recv_count >= ngep->param_recv_max_packet)
3895574Smx205022 			break;
3905574Smx205022 	}
3915574Smx205022 
3925574Smx205022 	/* Sync the descriptors for device */
3935659Sjj146644 	if (sync_start + ngep->recv_count <= ngep->rx_desc) {
3945574Smx205022 		(void) ddi_dma_sync(rrp->desc.dma_hdl,
3955574Smx205022 		    sync_start * ngep->desc_attr.rxd_size,
3965659Sjj146644 		    ngep->recv_count * ngep->desc_attr.rxd_size,
3975574Smx205022 		    DDI_DMA_SYNC_FORDEV);
3985574Smx205022 	} else {
3995574Smx205022 		(void) ddi_dma_sync(rrp->desc.dma_hdl,
4005574Smx205022 		    sync_start * ngep->desc_attr.rxd_size,
4015574Smx205022 		    0,
4025574Smx205022 		    DDI_DMA_SYNC_FORDEV);
4035574Smx205022 		(void) ddi_dma_sync(rrp->desc.dma_hdl,
4045574Smx205022 		    0,
4055659Sjj146644 		    (ngep->recv_count + sync_start - ngep->rx_desc) *
4065574Smx205022 		    ngep->desc_attr.rxd_size,
4075574Smx205022 		    DDI_DMA_SYNC_FORDEV);
4085574Smx205022 	}
4095574Smx205022 	mode_cntl.mode_val = nge_reg_get32(ngep, NGE_MODE_CNTL);
4105574Smx205022 	mode_cntl.mode_bits.rxdm = NGE_SET;
4115574Smx205022 	mode_cntl.mode_bits.tx_rcom_en = NGE_SET;
4125574Smx205022 	nge_reg_put32(ngep, NGE_MODE_CNTL, mode_cntl.mode_val);
4135574Smx205022 
4145574Smx205022 	return (head);
4155574Smx205022 }
4165574Smx205022 
4175574Smx205022 void
nge_receive(nge_t * ngep)4185574Smx205022 nge_receive(nge_t *ngep)
4195574Smx205022 {
4205574Smx205022 	mblk_t *mp;
4215574Smx205022 	recv_ring_t *rrp;
4225574Smx205022 	rrp = ngep->recv;
4235574Smx205022 
4245574Smx205022 	mp = nge_recv_ring(ngep);
4255574Smx205022 	mutex_exit(ngep->genlock);
4265574Smx205022 	if (mp != NULL)
4275574Smx205022 		mac_rx(ngep->mh, rrp->handle, mp);
4285574Smx205022 	mutex_enter(ngep->genlock);
4295574Smx205022 }
4305574Smx205022 
4315574Smx205022 void
nge_hot_rxd_fill(void * hwd,const ddi_dma_cookie_t * cookie,size_t len)4325574Smx205022 nge_hot_rxd_fill(void *hwd, const ddi_dma_cookie_t *cookie, size_t len)
4335574Smx205022 {
4345574Smx205022 	uint64_t dmac_addr;
4355574Smx205022 	hot_rx_bd * hw_bd_p;
4365574Smx205022 
4375574Smx205022 	hw_bd_p = (hot_rx_bd *)hwd;
4385574Smx205022 	dmac_addr = cookie->dmac_laddress + NGE_HEADROOM;
4395574Smx205022 
4405574Smx205022 	hw_bd_p->cntl_status.cntl_val = 0;
4415574Smx205022 
4425574Smx205022 	hw_bd_p->host_buf_addr_hi = dmac_addr >> 32;
4437781SMin.Xu@Sun.COM 	hw_bd_p->host_buf_addr_lo = (uint32_t)dmac_addr;
4445574Smx205022 	hw_bd_p->cntl_status.control_bits.bcnt = len - 1;
4455574Smx205022 
4465574Smx205022 	membar_producer();
4475574Smx205022 	hw_bd_p->cntl_status.control_bits.own = NGE_SET;
4485574Smx205022 }
4495574Smx205022 
4505574Smx205022 void
nge_sum_rxd_fill(void * hwd,const ddi_dma_cookie_t * cookie,size_t len)4515574Smx205022 nge_sum_rxd_fill(void *hwd, const ddi_dma_cookie_t *cookie, size_t len)
4525574Smx205022 {
4535574Smx205022 	sum_rx_bd * hw_bd_p;
4545574Smx205022 
4555574Smx205022 	hw_bd_p = hwd;
4565574Smx205022 
4575574Smx205022 	hw_bd_p->cntl_status.cntl_val = 0;
4585574Smx205022 
4597781SMin.Xu@Sun.COM 	hw_bd_p->host_buf_addr =
4607781SMin.Xu@Sun.COM 	    (uint32_t)(cookie->dmac_address + NGE_HEADROOM);
4615574Smx205022 	hw_bd_p->cntl_status.control_bits.bcnt = len - 1;
4625574Smx205022 
4635574Smx205022 	membar_producer();
4645574Smx205022 	hw_bd_p->cntl_status.control_bits.own = NGE_SET;
4655574Smx205022 }
4665574Smx205022 
4675574Smx205022 uint32_t
nge_hot_rxd_check(const void * hwd,size_t * len)4685574Smx205022 nge_hot_rxd_check(const void *hwd, size_t *len)
4695574Smx205022 {
4705574Smx205022 	uint32_t err_flag;
4715574Smx205022 	const hot_rx_bd * hrbdp;
4725574Smx205022 
4735574Smx205022 	hrbdp = hwd;
4749906SZhen.W@Sun.COM 	err_flag = hrbdp->cntl_status.cntl_val;
4759906SZhen.W@Sun.COM 	*len = err_flag & RXD_BCNT_MSK;
4765574Smx205022 	return (err_flag);
4775574Smx205022 }
4785574Smx205022 
4795574Smx205022 uint32_t
nge_sum_rxd_check(const void * hwd,size_t * len)4805574Smx205022 nge_sum_rxd_check(const void *hwd, size_t *len)
4815574Smx205022 {
4825574Smx205022 	uint32_t err_flag;
4835574Smx205022 	const sum_rx_bd * hrbdp;
4845574Smx205022 
4855574Smx205022 	hrbdp = hwd;
4865574Smx205022 
4879906SZhen.W@Sun.COM 	err_flag = hrbdp->cntl_status.cntl_val;
4889906SZhen.W@Sun.COM 	*len = err_flag & RXD_BCNT_MSK;
4895574Smx205022 	return (err_flag);
4905574Smx205022 }
491