16f3e57acSmx205022 /* 247693af9Smx205022 * CDDL HEADER START 347693af9Smx205022 * 447693af9Smx205022 * The contents of this file are subject to the terms of the 547693af9Smx205022 * Common Development and Distribution License (the "License"). 647693af9Smx205022 * You may not use this file except in compliance with the License. 747693af9Smx205022 * 847693af9Smx205022 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 947693af9Smx205022 * or http://www.opensolaris.org/os/licensing. 1047693af9Smx205022 * See the License for the specific language governing permissions 1147693af9Smx205022 * and limitations under the License. 1247693af9Smx205022 * 1347693af9Smx205022 * When distributing Covered Code, include this CDDL HEADER in each 1447693af9Smx205022 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1547693af9Smx205022 * If applicable, add the following below this CDDL HEADER, with the 1647693af9Smx205022 * fields enclosed by brackets "[]" replaced with your own identifying 1747693af9Smx205022 * information: Portions Copyright [yyyy] [name of copyright owner] 1847693af9Smx205022 * 1947693af9Smx205022 * CDDL HEADER END 206f3e57acSmx205022 */ 216f3e57acSmx205022 226f3e57acSmx205022 /* 23*0dc2366fSVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 2447693af9Smx205022 * Use is subject to license terms. 256f3e57acSmx205022 */ 266f3e57acSmx205022 276f3e57acSmx205022 #include "nge.h" 286f3e57acSmx205022 296f3e57acSmx205022 #undef NGE_DBG 306f3e57acSmx205022 #define NGE_DBG NGE_DBG_RECV 316f3e57acSmx205022 326f3e57acSmx205022 #define RXD_END 0x20000000 336f3e57acSmx205022 #define RXD_ERR 0x40000000 346f3e57acSmx205022 #define RXD_OWN 0x80000000 356f3e57acSmx205022 #define RXD_CSUM_MSK 0x1C000000 366f3e57acSmx205022 #define RXD_BCNT_MSK 0x00003FFF 376f3e57acSmx205022 386f3e57acSmx205022 #define RXD_CK8G_NO_HSUM 0x0 396f3e57acSmx205022 #define RXD_CK8G_TCP_SUM_ERR 0x04000000 406f3e57acSmx205022 #define RXD_CK8G_UDP_SUM_ERR 0x08000000 416f3e57acSmx205022 #define RXD_CK8G_IP_HSUM_ERR 0x0C000000 426f3e57acSmx205022 #define RXD_CK8G_IP_HSUM 0x10000000 436f3e57acSmx205022 #define RXD_CK8G_TCP_SUM 0x14000000 446f3e57acSmx205022 #define RXD_CK8G_UDP_SUM 0x18000000 456f3e57acSmx205022 #define RXD_CK8G_RESV 0x1C000000 466f3e57acSmx205022 476f3e57acSmx205022 extern ddi_device_acc_attr_t nge_data_accattr; 486f3e57acSmx205022 496f3e57acSmx205022 /* 5075675fb7Svb160487 * Callback code invoked from STREAMs when the recv data buffer is free for 5175675fb7Svb160487 * recycling. 5275675fb7Svb160487 * 5375675fb7Svb160487 * The following table describes function behaviour: 5475675fb7Svb160487 * 5575675fb7Svb160487 * | mac stopped | mac running 5675675fb7Svb160487 * --------------------------------------------------- 5775675fb7Svb160487 * buffer delivered | free buffer | recycle buffer 5875675fb7Svb160487 * buffer not delivered | do nothing | recycle buffer (*) 5975675fb7Svb160487 * 6075675fb7Svb160487 * Note (*): 6175675fb7Svb160487 * Recycle buffer only if mac state did not change during execution of 6275675fb7Svb160487 * function. Otherwise if mac state changed, set buffer delivered & re-enter 6375675fb7Svb160487 * function by calling freemsg(). 646f3e57acSmx205022 */ 656f3e57acSmx205022 666f3e57acSmx205022 void 676f3e57acSmx205022 nge_recv_recycle(caddr_t arg) 686f3e57acSmx205022 { 696f3e57acSmx205022 boolean_t val; 706f3e57acSmx205022 boolean_t valid; 716f3e57acSmx205022 nge_t *ngep; 726f3e57acSmx205022 dma_area_t *bufp; 736f3e57acSmx205022 buff_ring_t *brp; 746f3e57acSmx205022 nge_sw_statistics_t *sw_stp; 756f3e57acSmx205022 766f3e57acSmx205022 bufp = (dma_area_t *)arg; 776f3e57acSmx205022 ngep = (nge_t *)bufp->private; 786f3e57acSmx205022 brp = ngep->buff; 796f3e57acSmx205022 sw_stp = &ngep->statistics.sw_statistics; 806f3e57acSmx205022 816f3e57acSmx205022 /* 826f3e57acSmx205022 * Free the buffer directly if the buffer was allocated 836f3e57acSmx205022 * previously or mac was stopped. 846f3e57acSmx205022 */ 856f3e57acSmx205022 if (bufp->signature != brp->buf_sign) { 866f3e57acSmx205022 if (bufp->rx_delivered == B_TRUE) { 876f3e57acSmx205022 nge_free_dma_mem(bufp); 886f3e57acSmx205022 kmem_free(bufp, sizeof (dma_area_t)); 896f3e57acSmx205022 val = nge_atomic_decrease(&brp->rx_hold, 1); 906f3e57acSmx205022 ASSERT(val == B_TRUE); 916f3e57acSmx205022 } 926f3e57acSmx205022 return; 936f3e57acSmx205022 } 946f3e57acSmx205022 956f3e57acSmx205022 /* 966f3e57acSmx205022 * recycle the data buffer again and fill them in free ring 976f3e57acSmx205022 */ 986f3e57acSmx205022 bufp->rx_recycle.free_func = nge_recv_recycle; 996f3e57acSmx205022 bufp->rx_recycle.free_arg = (caddr_t)bufp; 1006f3e57acSmx205022 1016f3e57acSmx205022 bufp->mp = desballoc(DMA_VPTR(*bufp), 1026f3e57acSmx205022 ngep->buf_size + NGE_HEADROOM, 0, &bufp->rx_recycle); 1036f3e57acSmx205022 1046f3e57acSmx205022 if (bufp->mp == NULL) { 1056f3e57acSmx205022 sw_stp->mp_alloc_err++; 1066f3e57acSmx205022 sw_stp->recy_free++; 1076f3e57acSmx205022 nge_free_dma_mem(bufp); 1086f3e57acSmx205022 kmem_free(bufp, sizeof (dma_area_t)); 1096f3e57acSmx205022 val = nge_atomic_decrease(&brp->rx_hold, 1); 1106f3e57acSmx205022 ASSERT(val == B_TRUE); 1116f3e57acSmx205022 } else { 1126f3e57acSmx205022 1136f3e57acSmx205022 mutex_enter(brp->recycle_lock); 1146f3e57acSmx205022 if (bufp->signature != brp->buf_sign) 1156f3e57acSmx205022 valid = B_TRUE; 1166f3e57acSmx205022 else 1176f3e57acSmx205022 valid = B_FALSE; 1186f3e57acSmx205022 bufp->rx_delivered = valid; 1196f3e57acSmx205022 if (bufp->rx_delivered == B_FALSE) { 1206f3e57acSmx205022 bufp->next = brp->recycle_list; 1216f3e57acSmx205022 brp->recycle_list = bufp; 1226f3e57acSmx205022 } 1236f3e57acSmx205022 mutex_exit(brp->recycle_lock); 1246f3e57acSmx205022 if (valid == B_TRUE) 1256f3e57acSmx205022 /* call nge_rx_recycle again to free it */ 1266f3e57acSmx205022 freemsg(bufp->mp); 1276f3e57acSmx205022 else { 1286f3e57acSmx205022 val = nge_atomic_decrease(&brp->rx_hold, 1); 1296f3e57acSmx205022 ASSERT(val == B_TRUE); 1306f3e57acSmx205022 } 1316f3e57acSmx205022 } 1326f3e57acSmx205022 } 1336f3e57acSmx205022 1346f3e57acSmx205022 /* 1356f3e57acSmx205022 * Checking the rx's BDs (one or more) to receive 1366f3e57acSmx205022 * one complete packet. 1376f3e57acSmx205022 * start_index: the start indexer of BDs for one packet. 1386f3e57acSmx205022 * end_index: the end indexer of BDs for one packet. 1396f3e57acSmx205022 */ 1406f3e57acSmx205022 static mblk_t *nge_recv_packet(nge_t *ngep, uint32_t start_index, size_t len); 1416f3e57acSmx205022 #pragma inline(nge_recv_packet) 1426f3e57acSmx205022 1436f3e57acSmx205022 static mblk_t * 1446f3e57acSmx205022 nge_recv_packet(nge_t *ngep, uint32_t start_index, size_t len) 1456f3e57acSmx205022 { 1466f3e57acSmx205022 uint8_t *rptr; 1476f3e57acSmx205022 uint32_t minsize; 1486f3e57acSmx205022 uint32_t maxsize; 1496f3e57acSmx205022 mblk_t *mp; 1506f3e57acSmx205022 buff_ring_t *brp; 1516f3e57acSmx205022 sw_rx_sbd_t *srbdp; 1526f3e57acSmx205022 dma_area_t *bufp; 1536f3e57acSmx205022 nge_sw_statistics_t *sw_stp; 1546f3e57acSmx205022 void *hw_bd_p; 1556f3e57acSmx205022 1566f3e57acSmx205022 brp = ngep->buff; 1576f3e57acSmx205022 minsize = ETHERMIN; 1586f3e57acSmx205022 maxsize = ngep->max_sdu; 1596f3e57acSmx205022 sw_stp = &ngep->statistics.sw_statistics; 1606f3e57acSmx205022 mp = NULL; 1616f3e57acSmx205022 1626f3e57acSmx205022 srbdp = &brp->sw_rbds[start_index]; 1636f3e57acSmx205022 DMA_SYNC(*srbdp->bufp, DDI_DMA_SYNC_FORKERNEL); 1646f3e57acSmx205022 hw_bd_p = DMA_VPTR(srbdp->desc); 1656f3e57acSmx205022 1666f3e57acSmx205022 /* 1676f3e57acSmx205022 * First check the free_list, if it is NULL, 1686f3e57acSmx205022 * make the recycle_list be free_list. 1696f3e57acSmx205022 */ 1706f3e57acSmx205022 if (brp->free_list == NULL) { 1716f3e57acSmx205022 mutex_enter(brp->recycle_lock); 1726f3e57acSmx205022 brp->free_list = brp->recycle_list; 1736f3e57acSmx205022 brp->recycle_list = NULL; 1746f3e57acSmx205022 mutex_exit(brp->recycle_lock); 1756f3e57acSmx205022 } 1766f3e57acSmx205022 bufp = brp->free_list; 1776f3e57acSmx205022 /* If it's not a qualified packet, delete it */ 1786f3e57acSmx205022 if (len > maxsize || len < minsize) { 1796f3e57acSmx205022 ngep->desc_attr.rxd_fill(hw_bd_p, &srbdp->bufp->cookie, 1806f3e57acSmx205022 srbdp->bufp->alength); 1816f3e57acSmx205022 srbdp->flags = CONTROLER_OWN; 1826f3e57acSmx205022 return (NULL); 1836f3e57acSmx205022 } 1846f3e57acSmx205022 1856f3e57acSmx205022 /* 1866f3e57acSmx205022 * If receive packet size is smaller than RX bcopy threshold, 1876f3e57acSmx205022 * or there is no available buffer in free_list or recycle list, 1886f3e57acSmx205022 * we use bcopy directly. 1896f3e57acSmx205022 */ 1906f3e57acSmx205022 if (len <= ngep->param_rxbcopy_threshold || bufp == NULL) 1916f3e57acSmx205022 brp->rx_bcopy = B_TRUE; 1926f3e57acSmx205022 else 1936f3e57acSmx205022 brp->rx_bcopy = B_FALSE; 1946f3e57acSmx205022 1956f3e57acSmx205022 if (brp->rx_bcopy) { 1966f3e57acSmx205022 mp = allocb(len + NGE_HEADROOM, 0); 1976f3e57acSmx205022 if (mp == NULL) { 1986f3e57acSmx205022 sw_stp->mp_alloc_err++; 1996f3e57acSmx205022 ngep->desc_attr.rxd_fill(hw_bd_p, &srbdp->bufp->cookie, 2006f3e57acSmx205022 srbdp->bufp->alength); 2016f3e57acSmx205022 srbdp->flags = CONTROLER_OWN; 2026f3e57acSmx205022 return (NULL); 2036f3e57acSmx205022 } 2046f3e57acSmx205022 rptr = DMA_VPTR(*srbdp->bufp); 2056f3e57acSmx205022 mp->b_rptr = mp->b_rptr + NGE_HEADROOM; 2066f3e57acSmx205022 bcopy(rptr + NGE_HEADROOM, mp->b_rptr, len); 2076f3e57acSmx205022 mp->b_wptr = mp->b_rptr + len; 2086f3e57acSmx205022 } else { 2096f3e57acSmx205022 mp = srbdp->bufp->mp; 2106f3e57acSmx205022 /* 2116f3e57acSmx205022 * Make sure the packet *contents* 4-byte aligned 2126f3e57acSmx205022 */ 2136f3e57acSmx205022 mp->b_rptr += NGE_HEADROOM; 2146f3e57acSmx205022 mp->b_wptr = mp->b_rptr + len; 2156f3e57acSmx205022 mp->b_next = mp->b_cont = NULL; 2166f3e57acSmx205022 srbdp->bufp->rx_delivered = B_TRUE; 2176f3e57acSmx205022 srbdp->bufp = NULL; 2186f3e57acSmx205022 nge_atomic_increase(&brp->rx_hold, 1); 2196f3e57acSmx205022 2206f3e57acSmx205022 /* Fill the buffer from free_list */ 2216f3e57acSmx205022 srbdp->bufp = bufp; 2226f3e57acSmx205022 brp->free_list = bufp->next; 2236f3e57acSmx205022 bufp->next = NULL; 2246f3e57acSmx205022 } 2256f3e57acSmx205022 2266f3e57acSmx205022 /* replenish the buffer for hardware descriptor */ 2276f3e57acSmx205022 ngep->desc_attr.rxd_fill(hw_bd_p, &srbdp->bufp->cookie, 2286f3e57acSmx205022 srbdp->bufp->alength); 2296f3e57acSmx205022 srbdp->flags = CONTROLER_OWN; 2306f3e57acSmx205022 sw_stp->rbytes += len; 2316f3e57acSmx205022 sw_stp->recv_count++; 2326f3e57acSmx205022 2336f3e57acSmx205022 return (mp); 2346f3e57acSmx205022 } 2356f3e57acSmx205022 2366f3e57acSmx205022 2376f3e57acSmx205022 #define RX_HW_ERR 0x01 2386f3e57acSmx205022 #define RX_SUM_NO 0x02 2396f3e57acSmx205022 #define RX_SUM_ERR 0x04 2406f3e57acSmx205022 2416f3e57acSmx205022 /* 2426f3e57acSmx205022 * Statistic the rx's error 2436f3e57acSmx205022 * and generate a log msg for these. 2446f3e57acSmx205022 * Note: 2456f3e57acSmx205022 * RXE, Parity Error, Symbo error, CRC error 2466f3e57acSmx205022 * have been recored by nvidia's hardware 2476f3e57acSmx205022 * statistics part (nge_statistics). So it is uncessary to record them by 2486f3e57acSmx205022 * driver in this place. 2496f3e57acSmx205022 */ 2506f3e57acSmx205022 static uint32_t 2516f3e57acSmx205022 nge_rxsta_handle(nge_t *ngep, uint32_t stflag, uint32_t *pflags); 2526f3e57acSmx205022 #pragma inline(nge_rxsta_handle) 2536f3e57acSmx205022 2546f3e57acSmx205022 static uint32_t 2556f3e57acSmx205022 nge_rxsta_handle(nge_t *ngep, uint32_t stflag, uint32_t *pflags) 2566f3e57acSmx205022 { 2576f3e57acSmx205022 uint32_t errors; 2586f3e57acSmx205022 uint32_t err_flag; 2596f3e57acSmx205022 nge_sw_statistics_t *sw_stp; 2606f3e57acSmx205022 2616f3e57acSmx205022 err_flag = 0; 2626f3e57acSmx205022 sw_stp = &ngep->statistics.sw_statistics; 2636f3e57acSmx205022 2646f3e57acSmx205022 if ((RXD_END & stflag) == 0) 2656f3e57acSmx205022 return (RX_HW_ERR); 2666f3e57acSmx205022 2676f3e57acSmx205022 errors = stflag & RXD_CSUM_MSK; 2686f3e57acSmx205022 switch (errors) { 2696f3e57acSmx205022 default: 2706f3e57acSmx205022 break; 2716f3e57acSmx205022 2726f3e57acSmx205022 case RXD_CK8G_TCP_SUM: 2736f3e57acSmx205022 case RXD_CK8G_UDP_SUM: 274*0dc2366fSVenugopal Iyer *pflags |= HCK_IPV4_HDRCKSUM_OK; 2756f3e57acSmx205022 *pflags |= HCK_FULLCKSUM_OK; 2766f3e57acSmx205022 break; 2776f3e57acSmx205022 2786f3e57acSmx205022 case RXD_CK8G_TCP_SUM_ERR: 2796f3e57acSmx205022 case RXD_CK8G_UDP_SUM_ERR: 2806f3e57acSmx205022 sw_stp->tcp_hwsum_err++; 281*0dc2366fSVenugopal Iyer *pflags |= HCK_IPV4_HDRCKSUM_OK; 2826f3e57acSmx205022 break; 2836f3e57acSmx205022 2846f3e57acSmx205022 case RXD_CK8G_IP_HSUM: 285*0dc2366fSVenugopal Iyer *pflags |= HCK_IPV4_HDRCKSUM_OK; 2866f3e57acSmx205022 break; 2876f3e57acSmx205022 2886f3e57acSmx205022 case RXD_CK8G_NO_HSUM: 2896f3e57acSmx205022 err_flag |= RX_SUM_NO; 2906f3e57acSmx205022 break; 2916f3e57acSmx205022 2926f3e57acSmx205022 case RXD_CK8G_IP_HSUM_ERR: 2936f3e57acSmx205022 sw_stp->ip_hwsum_err++; 2946f3e57acSmx205022 err_flag |= RX_SUM_ERR; 2956f3e57acSmx205022 break; 2966f3e57acSmx205022 } 2976f3e57acSmx205022 2986f3e57acSmx205022 if ((stflag & RXD_ERR) != 0) { 2996f3e57acSmx205022 3006f3e57acSmx205022 err_flag |= RX_HW_ERR; 3016f3e57acSmx205022 NGE_DEBUG(("Receive desc error, status: 0x%x", stflag)); 3026f3e57acSmx205022 } 3036f3e57acSmx205022 3046f3e57acSmx205022 return (err_flag); 3056f3e57acSmx205022 } 3066f3e57acSmx205022 3076f3e57acSmx205022 static mblk_t * 3086f3e57acSmx205022 nge_recv_ring(nge_t *ngep) 3096f3e57acSmx205022 { 3106f3e57acSmx205022 uint32_t stflag; 3116f3e57acSmx205022 uint32_t flag_err; 3126f3e57acSmx205022 uint32_t sum_flags; 3136f3e57acSmx205022 size_t len; 3146f3e57acSmx205022 uint64_t end_index; 3156f3e57acSmx205022 uint64_t sync_start; 3166f3e57acSmx205022 mblk_t *mp; 3176f3e57acSmx205022 mblk_t **tail; 3186f3e57acSmx205022 mblk_t *head; 3196f3e57acSmx205022 recv_ring_t *rrp; 3206f3e57acSmx205022 buff_ring_t *brp; 3216f3e57acSmx205022 sw_rx_sbd_t *srbdp; 3226f3e57acSmx205022 void * hw_bd_p; 3236f3e57acSmx205022 nge_mode_cntl mode_cntl; 3246f3e57acSmx205022 3256f3e57acSmx205022 mp = NULL; 3266f3e57acSmx205022 head = NULL; 3276f3e57acSmx205022 tail = &head; 3286f3e57acSmx205022 rrp = ngep->recv; 3296f3e57acSmx205022 brp = ngep->buff; 3306f3e57acSmx205022 3316f3e57acSmx205022 end_index = sync_start = rrp->prod_index; 3326f3e57acSmx205022 /* Sync the descriptor for kernel */ 3336f3e57acSmx205022 if (sync_start + ngep->param_recv_max_packet <= ngep->rx_desc) { 3346f3e57acSmx205022 (void) ddi_dma_sync(rrp->desc.dma_hdl, 3356f3e57acSmx205022 sync_start * ngep->desc_attr.rxd_size, 3366f3e57acSmx205022 ngep->param_recv_max_packet * ngep->desc_attr.rxd_size, 3376f3e57acSmx205022 DDI_DMA_SYNC_FORKERNEL); 3386f3e57acSmx205022 } else { 3396f3e57acSmx205022 (void) ddi_dma_sync(rrp->desc.dma_hdl, 3406f3e57acSmx205022 sync_start * ngep->desc_attr.rxd_size, 3416f3e57acSmx205022 0, 3426f3e57acSmx205022 DDI_DMA_SYNC_FORKERNEL); 3436f3e57acSmx205022 (void) ddi_dma_sync(rrp->desc.dma_hdl, 3446f3e57acSmx205022 0, 3456f3e57acSmx205022 (ngep->param_recv_max_packet + sync_start - ngep->rx_desc) * 3466f3e57acSmx205022 ngep->desc_attr.rxd_size, 3476f3e57acSmx205022 DDI_DMA_SYNC_FORKERNEL); 3486f3e57acSmx205022 } 3496f3e57acSmx205022 3506f3e57acSmx205022 /* 3516f3e57acSmx205022 * Looking through the rx's ring to find the good packets 3526f3e57acSmx205022 * and try to receive more and more packets in rx's ring 3536f3e57acSmx205022 */ 3546f3e57acSmx205022 for (;;) { 3556f3e57acSmx205022 sum_flags = 0; 3566f3e57acSmx205022 flag_err = 0; 3576f3e57acSmx205022 end_index = rrp->prod_index; 3586f3e57acSmx205022 srbdp = &brp->sw_rbds[end_index]; 3596f3e57acSmx205022 hw_bd_p = DMA_VPTR(srbdp->desc); 3606f3e57acSmx205022 stflag = ngep->desc_attr.rxd_check(hw_bd_p, &len); 3616f3e57acSmx205022 /* 3626f3e57acSmx205022 * If there is no packet in receving ring 3636f3e57acSmx205022 * break the loop 3646f3e57acSmx205022 */ 3656f3e57acSmx205022 if ((stflag & RXD_OWN) != 0 || HOST_OWN == srbdp->flags) 3666f3e57acSmx205022 break; 3676f3e57acSmx205022 3686f3e57acSmx205022 ngep->recv_count++; 3696f3e57acSmx205022 flag_err = nge_rxsta_handle(ngep, stflag, &sum_flags); 3706f3e57acSmx205022 if ((flag_err & RX_HW_ERR) == 0) { 3716f3e57acSmx205022 srbdp->flags = NGE_END_PACKET; 3726f3e57acSmx205022 mp = nge_recv_packet(ngep, end_index, len); 3736f3e57acSmx205022 } else { 3746f3e57acSmx205022 /* Hardware error, re-use the buffer */ 3756f3e57acSmx205022 ngep->desc_attr.rxd_fill(hw_bd_p, &srbdp->bufp->cookie, 3766f3e57acSmx205022 srbdp->bufp->alength); 3776f3e57acSmx205022 srbdp->flags = CONTROLER_OWN; 3786f3e57acSmx205022 } 3796f3e57acSmx205022 if (mp != NULL) { 3806f3e57acSmx205022 if (!(flag_err & (RX_SUM_NO | RX_SUM_ERR))) { 381*0dc2366fSVenugopal Iyer mac_hcksum_set(mp, 0, 0, 0, 0, sum_flags); 3826f3e57acSmx205022 } 3836f3e57acSmx205022 *tail = mp; 3846f3e57acSmx205022 tail = &mp->b_next; 3856f3e57acSmx205022 mp = NULL; 3866f3e57acSmx205022 } 3876f3e57acSmx205022 rrp->prod_index = NEXT(end_index, rrp->desc.nslots); 3886ad24245SWinson Wang - Sun Microsystems - Beijing China if (ngep->recv_count >= ngep->param_recv_max_packet) 3896f3e57acSmx205022 break; 3906f3e57acSmx205022 } 3916f3e57acSmx205022 3926f3e57acSmx205022 /* Sync the descriptors for device */ 39302d51d0dSjj146644 if (sync_start + ngep->recv_count <= ngep->rx_desc) { 3946f3e57acSmx205022 (void) ddi_dma_sync(rrp->desc.dma_hdl, 3956f3e57acSmx205022 sync_start * ngep->desc_attr.rxd_size, 39602d51d0dSjj146644 ngep->recv_count * ngep->desc_attr.rxd_size, 3976f3e57acSmx205022 DDI_DMA_SYNC_FORDEV); 3986f3e57acSmx205022 } else { 3996f3e57acSmx205022 (void) ddi_dma_sync(rrp->desc.dma_hdl, 4006f3e57acSmx205022 sync_start * ngep->desc_attr.rxd_size, 4016f3e57acSmx205022 0, 4026f3e57acSmx205022 DDI_DMA_SYNC_FORDEV); 4036f3e57acSmx205022 (void) ddi_dma_sync(rrp->desc.dma_hdl, 4046f3e57acSmx205022 0, 40502d51d0dSjj146644 (ngep->recv_count + sync_start - ngep->rx_desc) * 4066f3e57acSmx205022 ngep->desc_attr.rxd_size, 4076f3e57acSmx205022 DDI_DMA_SYNC_FORDEV); 4086f3e57acSmx205022 } 4096f3e57acSmx205022 mode_cntl.mode_val = nge_reg_get32(ngep, NGE_MODE_CNTL); 4106f3e57acSmx205022 mode_cntl.mode_bits.rxdm = NGE_SET; 4116f3e57acSmx205022 mode_cntl.mode_bits.tx_rcom_en = NGE_SET; 4126f3e57acSmx205022 nge_reg_put32(ngep, NGE_MODE_CNTL, mode_cntl.mode_val); 4136f3e57acSmx205022 4146f3e57acSmx205022 return (head); 4156f3e57acSmx205022 } 4166f3e57acSmx205022 4176f3e57acSmx205022 void 4186f3e57acSmx205022 nge_receive(nge_t *ngep) 4196f3e57acSmx205022 { 4206f3e57acSmx205022 mblk_t *mp; 4216f3e57acSmx205022 recv_ring_t *rrp; 4226f3e57acSmx205022 rrp = ngep->recv; 4236f3e57acSmx205022 4246f3e57acSmx205022 mp = nge_recv_ring(ngep); 4256f3e57acSmx205022 mutex_exit(ngep->genlock); 4266f3e57acSmx205022 if (mp != NULL) 4276f3e57acSmx205022 mac_rx(ngep->mh, rrp->handle, mp); 4286f3e57acSmx205022 mutex_enter(ngep->genlock); 4296f3e57acSmx205022 } 4306f3e57acSmx205022 4316f3e57acSmx205022 void 4326f3e57acSmx205022 nge_hot_rxd_fill(void *hwd, const ddi_dma_cookie_t *cookie, size_t len) 4336f3e57acSmx205022 { 4346f3e57acSmx205022 uint64_t dmac_addr; 4356f3e57acSmx205022 hot_rx_bd * hw_bd_p; 4366f3e57acSmx205022 4376f3e57acSmx205022 hw_bd_p = (hot_rx_bd *)hwd; 4386f3e57acSmx205022 dmac_addr = cookie->dmac_laddress + NGE_HEADROOM; 4396f3e57acSmx205022 4406f3e57acSmx205022 hw_bd_p->cntl_status.cntl_val = 0; 4416f3e57acSmx205022 4426f3e57acSmx205022 hw_bd_p->host_buf_addr_hi = dmac_addr >> 32; 443a55f7119SMiles Xu, Sun Microsystems hw_bd_p->host_buf_addr_lo = (uint32_t)dmac_addr; 4446f3e57acSmx205022 hw_bd_p->cntl_status.control_bits.bcnt = len - 1; 4456f3e57acSmx205022 4466f3e57acSmx205022 membar_producer(); 4476f3e57acSmx205022 hw_bd_p->cntl_status.control_bits.own = NGE_SET; 4486f3e57acSmx205022 } 4496f3e57acSmx205022 4506f3e57acSmx205022 void 4516f3e57acSmx205022 nge_sum_rxd_fill(void *hwd, const ddi_dma_cookie_t *cookie, size_t len) 4526f3e57acSmx205022 { 4536f3e57acSmx205022 sum_rx_bd * hw_bd_p; 4546f3e57acSmx205022 4556f3e57acSmx205022 hw_bd_p = hwd; 4566f3e57acSmx205022 4576f3e57acSmx205022 hw_bd_p->cntl_status.cntl_val = 0; 4586f3e57acSmx205022 459a55f7119SMiles Xu, Sun Microsystems hw_bd_p->host_buf_addr = 460a55f7119SMiles Xu, Sun Microsystems (uint32_t)(cookie->dmac_address + NGE_HEADROOM); 4616f3e57acSmx205022 hw_bd_p->cntl_status.control_bits.bcnt = len - 1; 4626f3e57acSmx205022 4636f3e57acSmx205022 membar_producer(); 4646f3e57acSmx205022 hw_bd_p->cntl_status.control_bits.own = NGE_SET; 4656f3e57acSmx205022 } 4666f3e57acSmx205022 4676f3e57acSmx205022 uint32_t 4686f3e57acSmx205022 nge_hot_rxd_check(const void *hwd, size_t *len) 4696f3e57acSmx205022 { 4706f3e57acSmx205022 uint32_t err_flag; 4716f3e57acSmx205022 const hot_rx_bd * hrbdp; 4726f3e57acSmx205022 4736f3e57acSmx205022 hrbdp = hwd; 4749fa05d92SWinson Wang - Sun Microsystems - Beijing China err_flag = hrbdp->cntl_status.cntl_val; 4759fa05d92SWinson Wang - Sun Microsystems - Beijing China *len = err_flag & RXD_BCNT_MSK; 4766f3e57acSmx205022 return (err_flag); 4776f3e57acSmx205022 } 4786f3e57acSmx205022 4796f3e57acSmx205022 uint32_t 4806f3e57acSmx205022 nge_sum_rxd_check(const void *hwd, size_t *len) 4816f3e57acSmx205022 { 4826f3e57acSmx205022 uint32_t err_flag; 4836f3e57acSmx205022 const sum_rx_bd * hrbdp; 4846f3e57acSmx205022 4856f3e57acSmx205022 hrbdp = hwd; 4866f3e57acSmx205022 4879fa05d92SWinson Wang - Sun Microsystems - Beijing China err_flag = hrbdp->cntl_status.cntl_val; 4889fa05d92SWinson Wang - Sun Microsystems - Beijing China *len = err_flag & RXD_BCNT_MSK; 4896f3e57acSmx205022 return (err_flag); 4906f3e57acSmx205022 } 491