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