19a5557fdSlucy wang - Sun Microsystems - Beijing China /*
29a5557fdSlucy wang - Sun Microsystems - Beijing China  * CDDL HEADER START
39a5557fdSlucy wang - Sun Microsystems - Beijing China  *
49a5557fdSlucy wang - Sun Microsystems - Beijing China  * The contents of this file are subject to the terms of the
59a5557fdSlucy wang - Sun Microsystems - Beijing China  * Common Development and Distribution License (the "License").
69a5557fdSlucy wang - Sun Microsystems - Beijing China  * You may not use this file except in compliance with the License.
79a5557fdSlucy wang - Sun Microsystems - Beijing China  *
89a5557fdSlucy wang - Sun Microsystems - Beijing China  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99a5557fdSlucy wang - Sun Microsystems - Beijing China  * or http://www.opensolaris.org/os/licensing.
109a5557fdSlucy wang - Sun Microsystems - Beijing China  * See the License for the specific language governing permissions
119a5557fdSlucy wang - Sun Microsystems - Beijing China  * and limitations under the License.
129a5557fdSlucy wang - Sun Microsystems - Beijing China  *
139a5557fdSlucy wang - Sun Microsystems - Beijing China  * When distributing Covered Code, include this CDDL HEADER in each
149a5557fdSlucy wang - Sun Microsystems - Beijing China  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159a5557fdSlucy wang - Sun Microsystems - Beijing China  * If applicable, add the following below this CDDL HEADER, with the
169a5557fdSlucy wang - Sun Microsystems - Beijing China  * fields enclosed by brackets "[]" replaced with your own identifying
179a5557fdSlucy wang - Sun Microsystems - Beijing China  * information: Portions Copyright [yyyy] [name of copyright owner]
189a5557fdSlucy wang - Sun Microsystems - Beijing China  *
199a5557fdSlucy wang - Sun Microsystems - Beijing China  * CDDL HEADER END
209a5557fdSlucy wang - Sun Microsystems - Beijing China  */
219a5557fdSlucy wang - Sun Microsystems - Beijing China /*
229a5557fdSlucy wang - Sun Microsystems - Beijing China  * Copyright 2008 NetXen, Inc.  All rights reserved.
239a5557fdSlucy wang - Sun Microsystems - Beijing China  * Use is subject to license terms.
249a5557fdSlucy wang - Sun Microsystems - Beijing China  */
259a5557fdSlucy wang - Sun Microsystems - Beijing China /*
260dc2366fSVenugopal Iyer  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
279a5557fdSlucy wang - Sun Microsystems - Beijing China  * Use is subject to license terms.
289a5557fdSlucy wang - Sun Microsystems - Beijing China  */
299a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/types.h>
309a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/conf.h>
319a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/debug.h>
329a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/stropts.h>
339a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/stream.h>
349a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/strlog.h>
359a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/kmem.h>
369a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/stat.h>
379a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/kstat.h>
389a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/vtrace.h>
399a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/dlpi.h>
409a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/strsun.h>
419a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/ethernet.h>
429a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/modctl.h>
439a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/errno.h>
449a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/dditypes.h>
459a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/ddi.h>
469a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/sunddi.h>
479a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/sysmacros.h>
489a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/pci.h>
499a5557fdSlucy wang - Sun Microsystems - Beijing China 
509a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/gld.h>
519a5557fdSlucy wang - Sun Microsystems - Beijing China #include <netinet/in.h>
529a5557fdSlucy wang - Sun Microsystems - Beijing China #include <inet/ip.h>
539a5557fdSlucy wang - Sun Microsystems - Beijing China #include <inet/tcp.h>
549a5557fdSlucy wang - Sun Microsystems - Beijing China 
559a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/rwlock.h>
569a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/mutex.h>
579a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/pattr.h>
589a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/strsubr.h>
599a5557fdSlucy wang - Sun Microsystems - Beijing China #include <sys/ddi_impldefs.h>
609a5557fdSlucy wang - Sun Microsystems - Beijing China #include<sys/task.h>
619a5557fdSlucy wang - Sun Microsystems - Beijing China 
629a5557fdSlucy wang - Sun Microsystems - Beijing China #include "unm_nic_hw.h"
639a5557fdSlucy wang - Sun Microsystems - Beijing China #include "unm_nic.h"
649a5557fdSlucy wang - Sun Microsystems - Beijing China 
659a5557fdSlucy wang - Sun Microsystems - Beijing China #include "nic_phan_reg.h"
669a5557fdSlucy wang - Sun Microsystems - Beijing China #include "unm_nic_ioctl.h"
679a5557fdSlucy wang - Sun Microsystems - Beijing China #include "nic_cmn.h"
689a5557fdSlucy wang - Sun Microsystems - Beijing China #include "unm_version.h"
699a5557fdSlucy wang - Sun Microsystems - Beijing China #include "unm_brdcfg.h"
709a5557fdSlucy wang - Sun Microsystems - Beijing China 
719a5557fdSlucy wang - Sun Microsystems - Beijing China #if defined(lint)
729a5557fdSlucy wang - Sun Microsystems - Beijing China #undef MBLKL
739a5557fdSlucy wang - Sun Microsystems - Beijing China #define	MBLKL(_mp_)	((uintptr_t)(_mp_)->b_wptr - (uintptr_t)(_mp_)->b_rptr)
749a5557fdSlucy wang - Sun Microsystems - Beijing China #endif /* lint */
759a5557fdSlucy wang - Sun Microsystems - Beijing China 
769a5557fdSlucy wang - Sun Microsystems - Beijing China #undef UNM_LOOPBACK
779a5557fdSlucy wang - Sun Microsystems - Beijing China #undef SINGLE_DMA_BUF
789a5557fdSlucy wang - Sun Microsystems - Beijing China 
799a5557fdSlucy wang - Sun Microsystems - Beijing China #define	UNM_ADAPTER_UP_MAGIC	777
809a5557fdSlucy wang - Sun Microsystems - Beijing China #define	VLAN_TAGSZ		0x4
819a5557fdSlucy wang - Sun Microsystems - Beijing China 
829a5557fdSlucy wang - Sun Microsystems - Beijing China #define	index2rxbuf(_rdp_, _idx_)	((_rdp_)->rx_buf_pool + (_idx_))
839a5557fdSlucy wang - Sun Microsystems - Beijing China #define	rxbuf2index(_rdp_, _bufp_)	((_bufp_) - (_rdp_)->rx_buf_pool)
849a5557fdSlucy wang - Sun Microsystems - Beijing China 
859a5557fdSlucy wang - Sun Microsystems - Beijing China /*
869a5557fdSlucy wang - Sun Microsystems - Beijing China  * Receive ISR processes NX_RX_MAXBUFS incoming packets at most, then posts
879a5557fdSlucy wang - Sun Microsystems - Beijing China  * as many buffers as packets processed. This loop repeats as required to
889a5557fdSlucy wang - Sun Microsystems - Beijing China  * process all incoming packets delivered in a single interrupt. Higher
899a5557fdSlucy wang - Sun Microsystems - Beijing China  * value of NX_RX_MAXBUFS improves performance by posting rx buffers less
909a5557fdSlucy wang - Sun Microsystems - Beijing China  * frequently, but at the cost of not posting quickly enough when card is
919a5557fdSlucy wang - Sun Microsystems - Beijing China  * running out of rx buffers.
929a5557fdSlucy wang - Sun Microsystems - Beijing China  */
939a5557fdSlucy wang - Sun Microsystems - Beijing China #define	NX_RX_THRESHOLD		32
949a5557fdSlucy wang - Sun Microsystems - Beijing China #define	NX_RX_MAXBUFS		128
959a5557fdSlucy wang - Sun Microsystems - Beijing China #define	NX_MAX_TXCOMPS		256
969a5557fdSlucy wang - Sun Microsystems - Beijing China 
97dda0720aSjing xiong ERI-SUN extern int create_rxtx_rings(unm_adapter *adapter);
98dda0720aSjing xiong ERI-SUN extern void destroy_rxtx_rings(unm_adapter *adapter);
999a5557fdSlucy wang - Sun Microsystems - Beijing China 
1009a5557fdSlucy wang - Sun Microsystems - Beijing China static void unm_post_rx_buffers_nodb(struct unm_adapter_s *adapter,
1019a5557fdSlucy wang - Sun Microsystems - Beijing China     uint32_t ringid);
1029a5557fdSlucy wang - Sun Microsystems - Beijing China static mblk_t *unm_process_rcv(unm_adapter *adapter, statusDesc_t *desc);
1039a5557fdSlucy wang - Sun Microsystems - Beijing China static int unm_process_rcv_ring(unm_adapter *, int);
1049a5557fdSlucy wang - Sun Microsystems - Beijing China static int unm_process_cmd_ring(struct unm_adapter_s *adapter);
1059a5557fdSlucy wang - Sun Microsystems - Beijing China 
1069a5557fdSlucy wang - Sun Microsystems - Beijing China static int unm_nic_do_ioctl(unm_adapter *adapter, queue_t *q, mblk_t *mp);
1079a5557fdSlucy wang - Sun Microsystems - Beijing China static void unm_nic_ioctl(struct unm_adapter_s *adapter, int cmd, queue_t *q,
1089a5557fdSlucy wang - Sun Microsystems - Beijing China     mblk_t *mp);
1099a5557fdSlucy wang - Sun Microsystems - Beijing China 
1109a5557fdSlucy wang - Sun Microsystems - Beijing China /* GLDv3 interface functions */
1119a5557fdSlucy wang - Sun Microsystems - Beijing China static int ntxn_m_start(void *);
1129a5557fdSlucy wang - Sun Microsystems - Beijing China static void ntxn_m_stop(void *);
1139a5557fdSlucy wang - Sun Microsystems - Beijing China static int ntxn_m_multicst(void *, boolean_t, const uint8_t *);
1149a5557fdSlucy wang - Sun Microsystems - Beijing China static int ntxn_m_promisc(void *, boolean_t);
1159a5557fdSlucy wang - Sun Microsystems - Beijing China static int ntxn_m_stat(void *arg, uint_t stat, uint64_t *val);
1169a5557fdSlucy wang - Sun Microsystems - Beijing China static mblk_t *ntxn_m_tx(void *, mblk_t *);
1179a5557fdSlucy wang - Sun Microsystems - Beijing China static void ntxn_m_ioctl(void *arg, queue_t *wq, mblk_t *mp);
1189a5557fdSlucy wang - Sun Microsystems - Beijing China static boolean_t ntxn_m_getcapab(void *arg, mac_capab_t cap, void *cap_data);
1199a5557fdSlucy wang - Sun Microsystems - Beijing China 
1209a5557fdSlucy wang - Sun Microsystems - Beijing China /*
1219a5557fdSlucy wang - Sun Microsystems - Beijing China  * Allocates DMA handle, virtual memory and binds them
1229a5557fdSlucy wang - Sun Microsystems - Beijing China  * returns size of actual memory binded and the physical address.
1239a5557fdSlucy wang - Sun Microsystems - Beijing China  */
1249a5557fdSlucy wang - Sun Microsystems - Beijing China int
unm_pci_alloc_consistent(unm_adapter * adapter,int size,caddr_t * address,ddi_dma_cookie_t * cookie,ddi_dma_handle_t * dma_handle,ddi_acc_handle_t * handlep)1259a5557fdSlucy wang - Sun Microsystems - Beijing China unm_pci_alloc_consistent(unm_adapter *adapter,
126*b9e319bfSToomas Soome     int size, caddr_t *address, ddi_dma_cookie_t *cookie,
127*b9e319bfSToomas Soome     ddi_dma_handle_t *dma_handle, ddi_acc_handle_t *handlep)
1289a5557fdSlucy wang - Sun Microsystems - Beijing China {
1299a5557fdSlucy wang - Sun Microsystems - Beijing China 	int			err;
1309a5557fdSlucy wang - Sun Microsystems - Beijing China 	uint32_t		ncookies;
1319a5557fdSlucy wang - Sun Microsystems - Beijing China 	size_t			ring_len;
1329a5557fdSlucy wang - Sun Microsystems - Beijing China 	uint_t			dma_flags = DDI_DMA_RDWR | DDI_DMA_CONSISTENT;
1339a5557fdSlucy wang - Sun Microsystems - Beijing China 
1349a5557fdSlucy wang - Sun Microsystems - Beijing China 	*dma_handle = NULL;
1359a5557fdSlucy wang - Sun Microsystems - Beijing China 
1369a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (size <= 0)
1379a5557fdSlucy wang - Sun Microsystems - Beijing China 		return (DDI_ENOMEM);
1389a5557fdSlucy wang - Sun Microsystems - Beijing China 
1399a5557fdSlucy wang - Sun Microsystems - Beijing China 	err = ddi_dma_alloc_handle(adapter->dip,
1409a5557fdSlucy wang - Sun Microsystems - Beijing China 	    &adapter->gc_dma_attr_desc,
1419a5557fdSlucy wang - Sun Microsystems - Beijing China 	    DDI_DMA_DONTWAIT, NULL, dma_handle);
1429a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
1439a5557fdSlucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "!%s: %s: ddi_dma_alloc_handle FAILED:"
1449a5557fdSlucy wang - Sun Microsystems - Beijing China 		    " %d", unm_nic_driver_name, __func__, err);
1459a5557fdSlucy wang - Sun Microsystems - Beijing China 		return (DDI_ENOMEM);
1469a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
1479a5557fdSlucy wang - Sun Microsystems - Beijing China 
1489a5557fdSlucy wang - Sun Microsystems - Beijing China 	err = ddi_dma_mem_alloc(*dma_handle,
1499a5557fdSlucy wang - Sun Microsystems - Beijing China 	    size, &adapter->gc_attr_desc,
1509a5557fdSlucy wang - Sun Microsystems - Beijing China 	    dma_flags & (DDI_DMA_STREAMING | DDI_DMA_CONSISTENT),
1519a5557fdSlucy wang - Sun Microsystems - Beijing China 	    DDI_DMA_DONTWAIT, NULL, address, &ring_len,
1529a5557fdSlucy wang - Sun Microsystems - Beijing China 	    handlep);
1539a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
1549a5557fdSlucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "!%s: %s: ddi_dma_mem_alloc failed:"
1559a5557fdSlucy wang - Sun Microsystems - Beijing China 		    "ret %d, request size: %d",
1569a5557fdSlucy wang - Sun Microsystems - Beijing China 		    unm_nic_driver_name, __func__, err, size);
1579a5557fdSlucy wang - Sun Microsystems - Beijing China 		ddi_dma_free_handle(dma_handle);
1589a5557fdSlucy wang - Sun Microsystems - Beijing China 		return (DDI_ENOMEM);
1599a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
1609a5557fdSlucy wang - Sun Microsystems - Beijing China 
1619a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (ring_len < size) {
1629a5557fdSlucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: %s: could not allocate required "
1639a5557fdSlucy wang - Sun Microsystems - Beijing China 		    "memory :%d\n", unm_nic_driver_name,
1649a5557fdSlucy wang - Sun Microsystems - Beijing China 		    __func__, err);
1659a5557fdSlucy wang - Sun Microsystems - Beijing China 		ddi_dma_mem_free(handlep);
1669a5557fdSlucy wang - Sun Microsystems - Beijing China 		ddi_dma_free_handle(dma_handle);
1679a5557fdSlucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
1689a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
1699a5557fdSlucy wang - Sun Microsystems - Beijing China 
1709a5557fdSlucy wang - Sun Microsystems - Beijing China 	(void) memset(*address, 0, size);
1719a5557fdSlucy wang - Sun Microsystems - Beijing China 
1729a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (((err = ddi_dma_addr_bind_handle(*dma_handle,
1739a5557fdSlucy wang - Sun Microsystems - Beijing China 	    NULL, *address, ring_len,
1749a5557fdSlucy wang - Sun Microsystems - Beijing China 	    dma_flags,
1759a5557fdSlucy wang - Sun Microsystems - Beijing China 	    DDI_DMA_DONTWAIT, NULL,
1769a5557fdSlucy wang - Sun Microsystems - Beijing China 	    cookie, &ncookies)) != DDI_DMA_MAPPED) ||
1779a5557fdSlucy wang - Sun Microsystems - Beijing China 	    (ncookies != 1)) {
1789a5557fdSlucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN,
1799a5557fdSlucy wang - Sun Microsystems - Beijing China 		    "!%s: %s: ddi_dma_addr_bind_handle FAILED: %d",
1809a5557fdSlucy wang - Sun Microsystems - Beijing China 		    unm_nic_driver_name, __func__, err);
1819a5557fdSlucy wang - Sun Microsystems - Beijing China 		ddi_dma_mem_free(handlep);
1829a5557fdSlucy wang - Sun Microsystems - Beijing China 		ddi_dma_free_handle(dma_handle);
1839a5557fdSlucy wang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
1849a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
1859a5557fdSlucy wang - Sun Microsystems - Beijing China 
1869a5557fdSlucy wang - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
1879a5557fdSlucy wang - Sun Microsystems - Beijing China }
1889a5557fdSlucy wang - Sun Microsystems - Beijing China 
1899a5557fdSlucy wang - Sun Microsystems - Beijing China /*
1909a5557fdSlucy wang - Sun Microsystems - Beijing China  * Unbinds the memory, frees the DMA handle and at the end, frees the memory
1919a5557fdSlucy wang - Sun Microsystems - Beijing China  */
1929a5557fdSlucy wang - Sun Microsystems - Beijing China void
unm_pci_free_consistent(ddi_dma_handle_t * dma_handle,ddi_acc_handle_t * acc_handle)1939a5557fdSlucy wang - Sun Microsystems - Beijing China unm_pci_free_consistent(ddi_dma_handle_t *dma_handle,
1949a5557fdSlucy wang - Sun Microsystems - Beijing China     ddi_acc_handle_t *acc_handle)
1959a5557fdSlucy wang - Sun Microsystems - Beijing China {
1969a5557fdSlucy wang - Sun Microsystems - Beijing China 	int err;
1979a5557fdSlucy wang - Sun Microsystems - Beijing China 
1989a5557fdSlucy wang - Sun Microsystems - Beijing China 	err = ddi_dma_unbind_handle(*dma_handle);
1999a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
2009a5557fdSlucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s: Error unbinding memory\n", __func__);
2019a5557fdSlucy wang - Sun Microsystems - Beijing China 		return;
2029a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
2039a5557fdSlucy wang - Sun Microsystems - Beijing China 
2049a5557fdSlucy wang - Sun Microsystems - Beijing China 	ddi_dma_mem_free(acc_handle);
2059a5557fdSlucy wang - Sun Microsystems - Beijing China 	ddi_dma_free_handle(dma_handle);
2069a5557fdSlucy wang - Sun Microsystems - Beijing China }
2079a5557fdSlucy wang - Sun Microsystems - Beijing China 
2089a5557fdSlucy wang - Sun Microsystems - Beijing China static uint32_t msi_tgt_status[] = {
2099a5557fdSlucy wang - Sun Microsystems - Beijing China     ISR_INT_TARGET_STATUS, ISR_INT_TARGET_STATUS_F1,
2109a5557fdSlucy wang - Sun Microsystems - Beijing China     ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3,
2119a5557fdSlucy wang - Sun Microsystems - Beijing China     ISR_INT_TARGET_STATUS_F4, ISR_INT_TARGET_STATUS_F5,
2129a5557fdSlucy wang - Sun Microsystems - Beijing China     ISR_INT_TARGET_STATUS_F6, ISR_INT_TARGET_STATUS_F7
2139a5557fdSlucy wang - Sun Microsystems - Beijing China };
2149a5557fdSlucy wang - Sun Microsystems - Beijing China 
2159a5557fdSlucy wang - Sun Microsystems - Beijing China static void
unm_nic_disable_int(unm_adapter * adapter)2169a5557fdSlucy wang - Sun Microsystems - Beijing China unm_nic_disable_int(unm_adapter *adapter)
2179a5557fdSlucy wang - Sun Microsystems - Beijing China {
2189a5557fdSlucy wang - Sun Microsystems - Beijing China 	__uint32_t	temp = 0;
2199a5557fdSlucy wang - Sun Microsystems - Beijing China 
2209a5557fdSlucy wang - Sun Microsystems - Beijing China 	adapter->unm_nic_hw_write_wx(adapter, adapter->interrupt_crb,
2219a5557fdSlucy wang - Sun Microsystems - Beijing China 	    &temp, 4);
2229a5557fdSlucy wang - Sun Microsystems - Beijing China }
2239a5557fdSlucy wang - Sun Microsystems - Beijing China 
224dda0720aSjing xiong ERI-SUN static inline int
unm_nic_clear_int(unm_adapter * adapter)2259a5557fdSlucy wang - Sun Microsystems - Beijing China unm_nic_clear_int(unm_adapter *adapter)
2269a5557fdSlucy wang - Sun Microsystems - Beijing China {
2279a5557fdSlucy wang - Sun Microsystems - Beijing China 	uint32_t	mask, temp, our_int, status;
2289a5557fdSlucy wang - Sun Microsystems - Beijing China 
2299a5557fdSlucy wang - Sun Microsystems - Beijing China 	UNM_READ_LOCK(&adapter->adapter_lock);
2309a5557fdSlucy wang - Sun Microsystems - Beijing China 
2319a5557fdSlucy wang - Sun Microsystems - Beijing China 	/* check whether it's our interrupt */
2329a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (!UNM_IS_MSI_FAMILY(adapter)) {
2339a5557fdSlucy wang - Sun Microsystems - Beijing China 
2349a5557fdSlucy wang - Sun Microsystems - Beijing China 		/* Legacy Interrupt case */
2359a5557fdSlucy wang - Sun Microsystems - Beijing China 		adapter->unm_nic_pci_read_immediate(adapter, ISR_INT_VECTOR,
2369a5557fdSlucy wang - Sun Microsystems - Beijing China 		    &status);
2379a5557fdSlucy wang - Sun Microsystems - Beijing China 
2389a5557fdSlucy wang - Sun Microsystems - Beijing China 		if (!(status & adapter->legacy_intr.int_vec_bit)) {
2399a5557fdSlucy wang - Sun Microsystems - Beijing China 			UNM_READ_UNLOCK(&adapter->adapter_lock);
2409a5557fdSlucy wang - Sun Microsystems - Beijing China 			return (-1);
2419a5557fdSlucy wang - Sun Microsystems - Beijing China 		}
2429a5557fdSlucy wang - Sun Microsystems - Beijing China 
2439a5557fdSlucy wang - Sun Microsystems - Beijing China 		if (adapter->ahw.revision_id >= NX_P3_B1) {
2449a5557fdSlucy wang - Sun Microsystems - Beijing China 			adapter->unm_nic_pci_read_immediate(adapter,
2459a5557fdSlucy wang - Sun Microsystems - Beijing China 			    ISR_INT_STATE_REG, &temp);
2469a5557fdSlucy wang - Sun Microsystems - Beijing China 			if (!ISR_IS_LEGACY_INTR_TRIGGERED(temp)) {
2479a5557fdSlucy wang - Sun Microsystems - Beijing China 				UNM_READ_UNLOCK(&adapter->adapter_lock);
2489a5557fdSlucy wang - Sun Microsystems - Beijing China 				return (-1);
2499a5557fdSlucy wang - Sun Microsystems - Beijing China 			}
2509a5557fdSlucy wang - Sun Microsystems - Beijing China 		} else if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
2519a5557fdSlucy wang - Sun Microsystems - Beijing China 			our_int = adapter->unm_nic_pci_read_normalize(adapter,
2529a5557fdSlucy wang - Sun Microsystems - Beijing China 			    CRB_INT_VECTOR);
2539a5557fdSlucy wang - Sun Microsystems - Beijing China 
2549a5557fdSlucy wang - Sun Microsystems - Beijing China 			/* FIXME: Assumes pci_func is same as ctx */
2559a5557fdSlucy wang - Sun Microsystems - Beijing China 			if ((our_int & (0x80 << adapter->portnum)) == 0) {
2569a5557fdSlucy wang - Sun Microsystems - Beijing China 				if (our_int != 0) {
2579a5557fdSlucy wang - Sun Microsystems - Beijing China 					/* not our interrupt */
2589a5557fdSlucy wang - Sun Microsystems - Beijing China 					UNM_READ_UNLOCK(&adapter->adapter_lock);
2599a5557fdSlucy wang - Sun Microsystems - Beijing China 					return (-1);
2609a5557fdSlucy wang - Sun Microsystems - Beijing China 				}
2619a5557fdSlucy wang - Sun Microsystems - Beijing China 			}
2629a5557fdSlucy wang - Sun Microsystems - Beijing China 			temp = our_int & ~((u32)(0x80 << adapter->portnum));
2639a5557fdSlucy wang - Sun Microsystems - Beijing China 			adapter->unm_nic_pci_write_normalize(adapter,
2649a5557fdSlucy wang - Sun Microsystems - Beijing China 			    CRB_INT_VECTOR, temp);
2659a5557fdSlucy wang - Sun Microsystems - Beijing China 		}
2669a5557fdSlucy wang - Sun Microsystems - Beijing China 
2679a5557fdSlucy wang - Sun Microsystems - Beijing China 		if (adapter->fw_major < 4)
2689a5557fdSlucy wang - Sun Microsystems - Beijing China 			unm_nic_disable_int(adapter);
2699a5557fdSlucy wang - Sun Microsystems - Beijing China 
2709a5557fdSlucy wang - Sun Microsystems - Beijing China 		/* claim interrupt */
2719a5557fdSlucy wang - Sun Microsystems - Beijing China 		temp = 0xffffffff;
2729a5557fdSlucy wang - Sun Microsystems - Beijing China 		adapter->unm_nic_pci_write_immediate(adapter,
2739a5557fdSlucy wang - Sun Microsystems - Beijing China 		    adapter->legacy_intr.tgt_status_reg, &temp);
2749a5557fdSlucy wang - Sun Microsystems - Beijing China 
2759a5557fdSlucy wang - Sun Microsystems - Beijing China 		adapter->unm_nic_pci_read_immediate(adapter, ISR_INT_VECTOR,
2769a5557fdSlucy wang - Sun Microsystems - Beijing China 		    &mask);
2779a5557fdSlucy wang - Sun Microsystems - Beijing China 
2789a5557fdSlucy wang - Sun Microsystems - Beijing China 		/*
2799a5557fdSlucy wang - Sun Microsystems - Beijing China 		 * Read again to make sure the legacy interrupt message got
2809a5557fdSlucy wang - Sun Microsystems - Beijing China 		 * flushed out
2819a5557fdSlucy wang - Sun Microsystems - Beijing China 		 */
2829a5557fdSlucy wang - Sun Microsystems - Beijing China 		adapter->unm_nic_pci_read_immediate(adapter, ISR_INT_VECTOR,
2839a5557fdSlucy wang - Sun Microsystems - Beijing China 		    &mask);
2849a5557fdSlucy wang - Sun Microsystems - Beijing China 	} else if (adapter->flags & UNM_NIC_MSI_ENABLED) {
2859a5557fdSlucy wang - Sun Microsystems - Beijing China 		/* clear interrupt */
2869a5557fdSlucy wang - Sun Microsystems - Beijing China 		temp = 0xffffffff;
2879a5557fdSlucy wang - Sun Microsystems - Beijing China 		adapter->unm_nic_pci_write_immediate(adapter,
2889a5557fdSlucy wang - Sun Microsystems - Beijing China 		    msi_tgt_status[adapter->ahw.pci_func], &temp);
2899a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
2909a5557fdSlucy wang - Sun Microsystems - Beijing China 
2919a5557fdSlucy wang - Sun Microsystems - Beijing China 	UNM_READ_UNLOCK(&adapter->adapter_lock);
2929a5557fdSlucy wang - Sun Microsystems - Beijing China 
2939a5557fdSlucy wang - Sun Microsystems - Beijing China 	return (0);
2949a5557fdSlucy wang - Sun Microsystems - Beijing China }
2959a5557fdSlucy wang - Sun Microsystems - Beijing China 
2969a5557fdSlucy wang - Sun Microsystems - Beijing China static void
unm_nic_enable_int(unm_adapter * adapter)2979a5557fdSlucy wang - Sun Microsystems - Beijing China unm_nic_enable_int(unm_adapter *adapter)
2989a5557fdSlucy wang - Sun Microsystems - Beijing China {
2999a5557fdSlucy wang - Sun Microsystems - Beijing China 	u32	temp = 1;
3009a5557fdSlucy wang - Sun Microsystems - Beijing China 
3019a5557fdSlucy wang - Sun Microsystems - Beijing China 	adapter->unm_nic_hw_write_wx(adapter, adapter->interrupt_crb,
3029a5557fdSlucy wang - Sun Microsystems - Beijing China 	    &temp, 4);
3039a5557fdSlucy wang - Sun Microsystems - Beijing China 
3049a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (!UNM_IS_MSI_FAMILY(adapter)) {
3059a5557fdSlucy wang - Sun Microsystems - Beijing China 		u32	mask = 0xfbff;
3069a5557fdSlucy wang - Sun Microsystems - Beijing China 
3079a5557fdSlucy wang - Sun Microsystems - Beijing China 		adapter->unm_nic_pci_write_immediate(adapter,
3089a5557fdSlucy wang - Sun Microsystems - Beijing China 		    adapter->legacy_intr.tgt_mask_reg, &mask);
3099a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
3109a5557fdSlucy wang - Sun Microsystems - Beijing China }
3119a5557fdSlucy wang - Sun Microsystems - Beijing China 
3129a5557fdSlucy wang - Sun Microsystems - Beijing China static void
unm_free_hw_resources(unm_adapter * adapter)3139a5557fdSlucy wang - Sun Microsystems - Beijing China unm_free_hw_resources(unm_adapter *adapter)
3149a5557fdSlucy wang - Sun Microsystems - Beijing China {
3159a5557fdSlucy wang - Sun Microsystems - Beijing China 	unm_recv_context_t *recv_ctx;
3169a5557fdSlucy wang - Sun Microsystems - Beijing China 	unm_rcv_desc_ctx_t *rcv_desc;
3179a5557fdSlucy wang - Sun Microsystems - Beijing China 	int ctx, ring;
3189a5557fdSlucy wang - Sun Microsystems - Beijing China 
3199a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (adapter->context_alloced == 1) {
3209a5557fdSlucy wang - Sun Microsystems - Beijing China 		netxen_destroy_rxtx(adapter);
3219a5557fdSlucy wang - Sun Microsystems - Beijing China 		adapter->context_alloced = 0;
3229a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
3239a5557fdSlucy wang - Sun Microsystems - Beijing China 
3249a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (adapter->ctxDesc != NULL) {
3259a5557fdSlucy wang - Sun Microsystems - Beijing China 		unm_pci_free_consistent(&adapter->ctxDesc_dma_handle,
3269a5557fdSlucy wang - Sun Microsystems - Beijing China 		    &adapter->ctxDesc_acc_handle);
3279a5557fdSlucy wang - Sun Microsystems - Beijing China 		adapter->ctxDesc = NULL;
3289a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
3299a5557fdSlucy wang - Sun Microsystems - Beijing China 
3309a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (adapter->ahw.cmdDescHead != NULL) {
3319a5557fdSlucy wang - Sun Microsystems - Beijing China 		unm_pci_free_consistent(&adapter->ahw.cmd_desc_dma_handle,
3329a5557fdSlucy wang - Sun Microsystems - Beijing China 		    &adapter->ahw.cmd_desc_acc_handle);
3338f61ab7aSToomas Soome 		adapter->ahw.cmdDesc_physAddr = 0;
3349a5557fdSlucy wang - Sun Microsystems - Beijing China 		adapter->ahw.cmdDescHead = NULL;
3359a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
3369a5557fdSlucy wang - Sun Microsystems - Beijing China 
3379a5557fdSlucy wang - Sun Microsystems - Beijing China 	for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
3389a5557fdSlucy wang - Sun Microsystems - Beijing China 		recv_ctx = &adapter->recv_ctx[ctx];
3399a5557fdSlucy wang - Sun Microsystems - Beijing China 		for (ring = 0; ring < adapter->max_rds_rings; ring++) {
3409a5557fdSlucy wang - Sun Microsystems - Beijing China 			rcv_desc = &recv_ctx->rcv_desc[ring];
3419a5557fdSlucy wang - Sun Microsystems - Beijing China 
3429a5557fdSlucy wang - Sun Microsystems - Beijing China 			if (rcv_desc->desc_head != NULL) {
3439a5557fdSlucy wang - Sun Microsystems - Beijing China 				unm_pci_free_consistent(
3449a5557fdSlucy wang - Sun Microsystems - Beijing China 				    &rcv_desc->rx_desc_dma_handle,
3459a5557fdSlucy wang - Sun Microsystems - Beijing China 				    &rcv_desc->rx_desc_acc_handle);
3469a5557fdSlucy wang - Sun Microsystems - Beijing China 				rcv_desc->desc_head = NULL;
3478f61ab7aSToomas Soome 				rcv_desc->phys_addr = 0;
3489a5557fdSlucy wang - Sun Microsystems - Beijing China 			}
3499a5557fdSlucy wang - Sun Microsystems - Beijing China 		}
3509a5557fdSlucy wang - Sun Microsystems - Beijing China 
3519a5557fdSlucy wang - Sun Microsystems - Beijing China 		if (recv_ctx->rcvStatusDescHead != NULL) {
3529a5557fdSlucy wang - Sun Microsystems - Beijing China 			unm_pci_free_consistent(
3539a5557fdSlucy wang - Sun Microsystems - Beijing China 			    &recv_ctx->status_desc_dma_handle,
3549a5557fdSlucy wang - Sun Microsystems - Beijing China 			    &recv_ctx->status_desc_acc_handle);
3558f61ab7aSToomas Soome 			recv_ctx->rcvStatusDesc_physAddr = 0;
3569a5557fdSlucy wang - Sun Microsystems - Beijing China 			recv_ctx->rcvStatusDescHead = NULL;
3579a5557fdSlucy wang - Sun Microsystems - Beijing China 		}
3589a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
3599a5557fdSlucy wang - Sun Microsystems - Beijing China }
3609a5557fdSlucy wang - Sun Microsystems - Beijing China 
3619a5557fdSlucy wang - Sun Microsystems - Beijing China static void
cleanup_adapter(struct unm_adapter_s * adapter)3629a5557fdSlucy wang - Sun Microsystems - Beijing China cleanup_adapter(struct unm_adapter_s *adapter)
3639a5557fdSlucy wang - Sun Microsystems - Beijing China {
3649a5557fdSlucy wang - Sun Microsystems - Beijing China 	ddi_regs_map_free(&(adapter->regs_handle));
3659a5557fdSlucy wang - Sun Microsystems - Beijing China 	ddi_regs_map_free(&(adapter->db_handle));
3669a5557fdSlucy wang - Sun Microsystems - Beijing China 	kmem_free(adapter, sizeof (unm_adapter));
3679a5557fdSlucy wang - Sun Microsystems - Beijing China }
3689a5557fdSlucy wang - Sun Microsystems - Beijing China 
3699a5557fdSlucy wang - Sun Microsystems - Beijing China void
unm_nic_remove(unm_adapter * adapter)3709a5557fdSlucy wang - Sun Microsystems - Beijing China unm_nic_remove(unm_adapter *adapter)
3719a5557fdSlucy wang - Sun Microsystems - Beijing China {
3729a5557fdSlucy wang - Sun Microsystems - Beijing China 	mac_link_update(adapter->mach, LINK_STATE_DOWN);
3739a5557fdSlucy wang - Sun Microsystems - Beijing China 	unm_nic_stop_port(adapter);
3749a5557fdSlucy wang - Sun Microsystems - Beijing China 
3759a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (adapter->interrupt_crb) {
3769a5557fdSlucy wang - Sun Microsystems - Beijing China 		UNM_READ_LOCK(&adapter->adapter_lock);
3779a5557fdSlucy wang - Sun Microsystems - Beijing China 		unm_nic_disable_int(adapter);
3789a5557fdSlucy wang - Sun Microsystems - Beijing China 		UNM_READ_UNLOCK(&adapter->adapter_lock);
3799a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
3809a5557fdSlucy wang - Sun Microsystems - Beijing China 	(void) untimeout(adapter->watchdog_timer);
3819a5557fdSlucy wang - Sun Microsystems - Beijing China 
3829a5557fdSlucy wang - Sun Microsystems - Beijing China 	unm_free_hw_resources(adapter);
3839a5557fdSlucy wang - Sun Microsystems - Beijing China 
384dda0720aSjing xiong ERI-SUN 	if (adapter->is_up == UNM_ADAPTER_UP_MAGIC)
385dda0720aSjing xiong ERI-SUN 		destroy_rxtx_rings(adapter);
3869a5557fdSlucy wang - Sun Microsystems - Beijing China 
3879a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (adapter->portnum == 0)
3889a5557fdSlucy wang - Sun Microsystems - Beijing China 		unm_free_dummy_dma(adapter);
3899a5557fdSlucy wang - Sun Microsystems - Beijing China 
3909a5557fdSlucy wang - Sun Microsystems - Beijing China 	unm_destroy_intr(adapter);
3919a5557fdSlucy wang - Sun Microsystems - Beijing China 
3929a5557fdSlucy wang - Sun Microsystems - Beijing China 	ddi_set_driver_private(adapter->dip, NULL);
3939a5557fdSlucy wang - Sun Microsystems - Beijing China 	cleanup_adapter(adapter);
3949a5557fdSlucy wang - Sun Microsystems - Beijing China }
3959a5557fdSlucy wang - Sun Microsystems - Beijing China 
3969a5557fdSlucy wang - Sun Microsystems - Beijing China static int
init_firmware(unm_adapter * adapter)3979a5557fdSlucy wang - Sun Microsystems - Beijing China init_firmware(unm_adapter *adapter)
3989a5557fdSlucy wang - Sun Microsystems - Beijing China {
3999a5557fdSlucy wang - Sun Microsystems - Beijing China 	uint32_t state = 0, loops = 0, tempout;
4009a5557fdSlucy wang - Sun Microsystems - Beijing China 
4019a5557fdSlucy wang - Sun Microsystems - Beijing China 	/* Window 1 call */
4029a5557fdSlucy wang - Sun Microsystems - Beijing China 	UNM_READ_LOCK(&adapter->adapter_lock);
4039a5557fdSlucy wang - Sun Microsystems - Beijing China 	state = adapter->unm_nic_pci_read_normalize(adapter, CRB_CMDPEG_STATE);
4049a5557fdSlucy wang - Sun Microsystems - Beijing China 	UNM_READ_UNLOCK(&adapter->adapter_lock);
4059a5557fdSlucy wang - Sun Microsystems - Beijing China 
4069a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (state == PHAN_INITIALIZE_ACK)
4079a5557fdSlucy wang - Sun Microsystems - Beijing China 		return (0);
4089a5557fdSlucy wang - Sun Microsystems - Beijing China 
4099a5557fdSlucy wang - Sun Microsystems - Beijing China 	while (state != PHAN_INITIALIZE_COMPLETE && loops < 200000) {
4109a5557fdSlucy wang - Sun Microsystems - Beijing China 		drv_usecwait(100);
4119a5557fdSlucy wang - Sun Microsystems - Beijing China 		/* Window 1 call */
4129a5557fdSlucy wang - Sun Microsystems - Beijing China 		UNM_READ_LOCK(&adapter->adapter_lock);
4139a5557fdSlucy wang - Sun Microsystems - Beijing China 		state = adapter->unm_nic_pci_read_normalize(adapter,
4149a5557fdSlucy wang - Sun Microsystems - Beijing China 		    CRB_CMDPEG_STATE);
4159a5557fdSlucy wang - Sun Microsystems - Beijing China 		UNM_READ_UNLOCK(&adapter->adapter_lock);
4169a5557fdSlucy wang - Sun Microsystems - Beijing China 		loops++;
4179a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
4189a5557fdSlucy wang - Sun Microsystems - Beijing China 
4199a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (loops >= 200000) {
4209a5557fdSlucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "%s%d: CmdPeg init incomplete:%x\n",
4219a5557fdSlucy wang - Sun Microsystems - Beijing China 		    adapter->name, adapter->instance, state);
4229a5557fdSlucy wang - Sun Microsystems - Beijing China 		return (-EIO);
4239a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
4249a5557fdSlucy wang - Sun Microsystems - Beijing China 
4259a5557fdSlucy wang - Sun Microsystems - Beijing China 	/* Window 1 call */
4269a5557fdSlucy wang - Sun Microsystems - Beijing China 	UNM_READ_LOCK(&adapter->adapter_lock);
4279a5557fdSlucy wang - Sun Microsystems - Beijing China 	tempout = INTR_SCHEME_PERPORT;
4289a5557fdSlucy wang - Sun Microsystems - Beijing China 	adapter->unm_nic_hw_write_wx(adapter, CRB_NIC_CAPABILITIES_HOST,
4299a5557fdSlucy wang - Sun Microsystems - Beijing China 	    &tempout, 4);
4309a5557fdSlucy wang - Sun Microsystems - Beijing China 	tempout = MSI_MODE_MULTIFUNC;
4319a5557fdSlucy wang - Sun Microsystems - Beijing China 	adapter->unm_nic_hw_write_wx(adapter, CRB_NIC_MSI_MODE_HOST,
4329a5557fdSlucy wang - Sun Microsystems - Beijing China 	    &tempout, 4);
4339a5557fdSlucy wang - Sun Microsystems - Beijing China 	tempout = MPORT_MULTI_FUNCTION_MODE;
4349a5557fdSlucy wang - Sun Microsystems - Beijing China 	adapter->unm_nic_hw_write_wx(adapter, CRB_MPORT_MODE, &tempout, 4);
4359a5557fdSlucy wang - Sun Microsystems - Beijing China 	tempout = PHAN_INITIALIZE_ACK;
4369a5557fdSlucy wang - Sun Microsystems - Beijing China 	adapter->unm_nic_hw_write_wx(adapter, CRB_CMDPEG_STATE, &tempout, 4);
4379a5557fdSlucy wang - Sun Microsystems - Beijing China 	UNM_READ_UNLOCK(&adapter->adapter_lock);
4389a5557fdSlucy wang - Sun Microsystems - Beijing China 
4399a5557fdSlucy wang - Sun Microsystems - Beijing China 	return (0);
4409a5557fdSlucy wang - Sun Microsystems - Beijing China }
4419a5557fdSlucy wang - Sun Microsystems - Beijing China 
4429a5557fdSlucy wang - Sun Microsystems - Beijing China /*
4439a5557fdSlucy wang - Sun Microsystems - Beijing China  * Utility to synchronize with receive peg.
4449a5557fdSlucy wang - Sun Microsystems - Beijing China  *  Returns   0 on sucess
4459a5557fdSlucy wang - Sun Microsystems - Beijing China  *         -EIO on error
4469a5557fdSlucy wang - Sun Microsystems - Beijing China  */
4479a5557fdSlucy wang - Sun Microsystems - Beijing China int
receive_peg_ready(struct unm_adapter_s * adapter)4489a5557fdSlucy wang - Sun Microsystems - Beijing China receive_peg_ready(struct unm_adapter_s *adapter)
4499a5557fdSlucy wang - Sun Microsystems - Beijing China {
4509a5557fdSlucy wang - Sun Microsystems - Beijing China 	uint32_t state = 0;
4519a5557fdSlucy wang - Sun Microsystems - Beijing China 	int loops = 0, err = 0;
4529a5557fdSlucy wang - Sun Microsystems - Beijing China 
4539a5557fdSlucy wang - Sun Microsystems - Beijing China 	/* Window 1 call */
4549a5557fdSlucy wang - Sun Microsystems - Beijing China 	UNM_READ_LOCK(&adapter->adapter_lock);
4559a5557fdSlucy wang - Sun Microsystems - Beijing China 	state = adapter->unm_nic_pci_read_normalize(adapter, CRB_RCVPEG_STATE);
4569a5557fdSlucy wang - Sun Microsystems - Beijing China 	UNM_READ_UNLOCK(&adapter->adapter_lock);
4579a5557fdSlucy wang - Sun Microsystems - Beijing China 
4589a5557fdSlucy wang - Sun Microsystems - Beijing China 	while ((state != PHAN_PEG_RCV_INITIALIZED) && (loops < 20000)) {
4599a5557fdSlucy wang - Sun Microsystems - Beijing China 		drv_usecwait(100);
4609a5557fdSlucy wang - Sun Microsystems - Beijing China 		/* Window 1 call */
4619a5557fdSlucy wang - Sun Microsystems - Beijing China 
4629a5557fdSlucy wang - Sun Microsystems - Beijing China 		UNM_READ_LOCK(&adapter->adapter_lock);
4639a5557fdSlucy wang - Sun Microsystems - Beijing China 		state = adapter->unm_nic_pci_read_normalize(adapter,
4649a5557fdSlucy wang - Sun Microsystems - Beijing China 		    CRB_RCVPEG_STATE);
4659a5557fdSlucy wang - Sun Microsystems - Beijing China 		UNM_READ_UNLOCK(&adapter->adapter_lock);
4669a5557fdSlucy wang - Sun Microsystems - Beijing China 
4679a5557fdSlucy wang - Sun Microsystems - Beijing China 		loops++;
4689a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
4699a5557fdSlucy wang - Sun Microsystems - Beijing China 
4709a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (loops >= 20000) {
4719a5557fdSlucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "Receive Peg initialization incomplete 0x%x\n",
4729a5557fdSlucy wang - Sun Microsystems - Beijing China 		    state);
4739a5557fdSlucy wang - Sun Microsystems - Beijing China 		err = -EIO;
4749a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
4759a5557fdSlucy wang - Sun Microsystems - Beijing China 
4769a5557fdSlucy wang - Sun Microsystems - Beijing China 	return (err);
4779a5557fdSlucy wang - Sun Microsystems - Beijing China }
4789a5557fdSlucy wang - Sun Microsystems - Beijing China 
4799a5557fdSlucy wang - Sun Microsystems - Beijing China /*
4809a5557fdSlucy wang - Sun Microsystems - Beijing China  * check if the firmware has been downloaded and ready to run  and
4819a5557fdSlucy wang - Sun Microsystems - Beijing China  * setup the address for the descriptors in the adapter
4829a5557fdSlucy wang - Sun Microsystems - Beijing China  */
4839a5557fdSlucy wang - Sun Microsystems - Beijing China static int
unm_nic_hw_resources(unm_adapter * adapter)4849a5557fdSlucy wang - Sun Microsystems - Beijing China unm_nic_hw_resources(unm_adapter *adapter)
4859a5557fdSlucy wang - Sun Microsystems - Beijing China {
4869a5557fdSlucy wang - Sun Microsystems - Beijing China 	hardware_context	*hw = &adapter->ahw;
4879a5557fdSlucy wang - Sun Microsystems - Beijing China 	void			*addr;
4889a5557fdSlucy wang - Sun Microsystems - Beijing China 	int			err;
4899a5557fdSlucy wang - Sun Microsystems - Beijing China 	int			ctx, ring;
4909a5557fdSlucy wang - Sun Microsystems - Beijing China 	unm_recv_context_t	*recv_ctx;
4919a5557fdSlucy wang - Sun Microsystems - Beijing China 	unm_rcv_desc_ctx_t	*rcv_desc;
4929a5557fdSlucy wang - Sun Microsystems - Beijing China 	ddi_dma_cookie_t	cookie;
4939a5557fdSlucy wang - Sun Microsystems - Beijing China 	int			size;
4949a5557fdSlucy wang - Sun Microsystems - Beijing China 
4959a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (err = receive_peg_ready(adapter))
4969a5557fdSlucy wang - Sun Microsystems - Beijing China 		return (err);
4979a5557fdSlucy wang - Sun Microsystems - Beijing China 
4989a5557fdSlucy wang - Sun Microsystems - Beijing China 	size = (sizeof (RingContext) + sizeof (uint32_t));
4999a5557fdSlucy wang - Sun Microsystems - Beijing China 
5009a5557fdSlucy wang - Sun Microsystems - Beijing China 	err = unm_pci_alloc_consistent(adapter,
5019a5557fdSlucy wang - Sun Microsystems - Beijing China 	    size, (caddr_t *)&addr, &cookie,
5029a5557fdSlucy wang - Sun Microsystems - Beijing China 	    &adapter->ctxDesc_dma_handle,
5039a5557fdSlucy wang - Sun Microsystems - Beijing China 	    &adapter->ctxDesc_acc_handle);
5049a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
5059a5557fdSlucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "Failed to allocate HW context\n");
5069a5557fdSlucy wang - Sun Microsystems - Beijing China 		return (err);
5079a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
5089a5557fdSlucy wang - Sun Microsystems - Beijing China 
5099a5557fdSlucy wang - Sun Microsystems - Beijing China 	adapter->ctxDesc_physAddr = cookie.dmac_laddress;
5109a5557fdSlucy wang - Sun Microsystems - Beijing China 
5119a5557fdSlucy wang - Sun Microsystems - Beijing China 	(void) memset(addr, 0, sizeof (RingContext));
5129a5557fdSlucy wang - Sun Microsystems - Beijing China 
5139a5557fdSlucy wang - Sun Microsystems - Beijing China 	adapter->ctxDesc = (RingContext *) addr;
5149a5557fdSlucy wang - Sun Microsystems - Beijing China 	adapter->ctxDesc->CtxId = adapter->portnum;
5159a5557fdSlucy wang - Sun Microsystems - Beijing China 	adapter->ctxDesc->CMD_CONSUMER_OFFSET =
5169a5557fdSlucy wang - Sun Microsystems - Beijing China 	    adapter->ctxDesc_physAddr + sizeof (RingContext);
5179a5557fdSlucy wang - Sun Microsystems - Beijing China 	adapter->cmdConsumer =
5189a5557fdSlucy wang - Sun Microsystems - Beijing China 	    (uint32_t *)(uintptr_t)(((char *)addr) + sizeof (RingContext));
5199a5557fdSlucy wang - Sun Microsystems - Beijing China 
5209a5557fdSlucy wang - Sun Microsystems - Beijing China 	ASSERT(!((unsigned long)adapter->ctxDesc_physAddr & 0x3f));
5219a5557fdSlucy wang - Sun Microsystems - Beijing China 
5229a5557fdSlucy wang - Sun Microsystems - Beijing China 	/*
5239a5557fdSlucy wang - Sun Microsystems - Beijing China 	 * Allocate command descriptor ring.
5249a5557fdSlucy wang - Sun Microsystems - Beijing China 	 */
5259a5557fdSlucy wang - Sun Microsystems - Beijing China 	size = (sizeof (cmdDescType0_t) * adapter->MaxTxDescCount);
5269a5557fdSlucy wang - Sun Microsystems - Beijing China 	err = unm_pci_alloc_consistent(adapter,
5279a5557fdSlucy wang - Sun Microsystems - Beijing China 	    size, (caddr_t *)&addr, &cookie,
5289a5557fdSlucy wang - Sun Microsystems - Beijing China 	    &hw->cmd_desc_dma_handle,
5299a5557fdSlucy wang - Sun Microsystems - Beijing China 	    &hw->cmd_desc_acc_handle);
5309a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
5319a5557fdSlucy wang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "Failed to allocate cmd desc ring\n");
5329a5557fdSlucy wang - Sun Microsystems - Beijing China 		return (err);
5339a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
5349a5557fdSlucy wang - Sun Microsystems - Beijing China 
5359a5557fdSlucy wang - Sun Microsystems - Beijing China 	hw->cmdDesc_physAddr = cookie.dmac_laddress;
5369a5557fdSlucy wang - Sun Microsystems - Beijing China 	hw->cmdDescHead = (cmdDescType0_t *)addr;
5379a5557fdSlucy wang - Sun Microsystems - Beijing China 
5389a5557fdSlucy wang - Sun Microsystems - Beijing China 	for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
5399a5557fdSlucy wang - Sun Microsystems - Beijing China 		recv_ctx = &adapter->recv_ctx[ctx];
5409a5557fdSlucy wang - Sun Microsystems - Beijing China 
5419a5557fdSlucy wang - Sun Microsystems - Beijing China 		size = (sizeof (statusDesc_t)* adapter->MaxRxDescCount);
5429a5557fdSlucy wang - Sun Microsystems - Beijing China 		err = unm_pci_alloc_consistent(adapter,
5439a5557fdSlucy wang - Sun Microsystems - Beijing China 		    size, (caddr_t *)&addr,
5449a5557fdSlucy wang - Sun Microsystems - Beijing China 		    &recv_ctx->status_desc_dma_cookie,
5459a5557fdSlucy wang - Sun Microsystems - Beijing China 		    &recv_ctx->status_desc_dma_handle,
5469a5557fdSlucy wang - Sun Microsystems - Beijing China 		    &recv_ctx->status_desc_acc_handle);
5479a5557fdSlucy wang - Sun Microsystems - Beijing China 		if (err != DDI_SUCCESS) {
5489a5557fdSlucy wang - Sun Microsystems - Beijing China 			cmn_err(CE_WARN, "Failed to allocate sts desc ring\n");
5499a5557fdSlucy wang - Sun Microsystems - Beijing China 			goto free_cmd_desc;
5509a5557fdSlucy wang - Sun Microsystems - Beijing China 		}
5519a5557fdSlucy wang - Sun Microsystems - Beijing China 
5529a5557fdSlucy wang - Sun Microsystems - Beijing China 		(void) memset(addr, 0, size);
5539a5557fdSlucy wang - Sun Microsystems - Beijing China 		recv_ctx->rcvStatusDesc_physAddr =
5549a5557fdSlucy wang - Sun Microsystems - Beijing China 		    recv_ctx->status_desc_dma_cookie.dmac_laddress;
5559a5557fdSlucy wang - Sun Microsystems - Beijing China 		recv_ctx->rcvStatusDescHead = (statusDesc_t *)addr;
5569a5557fdSlucy wang - Sun Microsystems - Beijing China 
5579a5557fdSlucy wang - Sun Microsystems - Beijing China 		/* rds rings */
5589a5557fdSlucy wang - Sun Microsystems - Beijing China 		for (ring = 0; ring < adapter->max_rds_rings; ring++) {
5599a5557fdSlucy wang - Sun Microsystems - Beijing China 			rcv_desc = &recv_ctx->rcv_desc[ring];
5609a5557fdSlucy wang - Sun Microsystems - Beijing China 
5619a5557fdSlucy wang - Sun Microsystems - Beijing China 			size = (sizeof (rcvDesc_t) * adapter->MaxRxDescCount);
5629a5557fdSlucy wang - Sun Microsystems - Beijing China 			err = unm_pci_alloc_consistent(adapter,
5639a5557fdSlucy wang - Sun Microsystems - Beijing China 			    size, (caddr_t *)&addr,
5649a5557fdSlucy wang - Sun Microsystems - Beijing China 			    &rcv_desc->rx_desc_dma_cookie,
5659a5557fdSlucy wang - Sun Microsystems - Beijing China 			    &rcv_desc->rx_desc_dma_handle,
5669a5557fdSlucy wang - Sun Microsystems - Beijing China 			    &rcv_desc->rx_desc_acc_handle);
5679a5557fdSlucy wang - Sun Microsystems - Beijing China 			if (err != DDI_SUCCESS) {
5689a5557fdSlucy wang - Sun Microsystems - Beijing China 				cmn_err(CE_WARN, "Failed to allocate "
5699a5557fdSlucy wang - Sun Microsystems - Beijing China 				    "rx desc ring %d\n", ring);
5709a5557fdSlucy wang - Sun Microsystems - Beijing China 				goto free_status_desc;
5719a5557fdSlucy wang - Sun Microsystems - Beijing China 			}
5729a5557fdSlucy wang - Sun Microsystems - Beijing China 
5739a5557fdSlucy wang - Sun Microsystems - Beijing China 			rcv_desc->phys_addr =
5749a5557fdSlucy wang - Sun Microsystems - Beijing China 			    rcv_desc->rx_desc_dma_cookie.dmac_laddress;
5759a5557fdSlucy wang - Sun Microsystems - Beijing China 			rcv_desc->desc_head = (rcvDesc_t *)addr;
5769a5557fdSlucy wang - Sun Microsystems - Beijing China 		}
5779a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
5789a5557fdSlucy wang - Sun Microsystems - Beijing China 
5799a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (err = netxen_create_rxtx(adapter))
5809a5557fdSlucy wang - Sun Microsystems - Beijing China 		goto free_statusrx_desc;
5819a5557fdSlucy wang - Sun Microsystems - Beijing China 	adapter->context_alloced = 1;
5829a5557fdSlucy wang - Sun Microsystems - Beijing China 
5839a5557fdSlucy wang - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
5849a5557fdSlucy wang - Sun Microsystems - Beijing China 
5859a5557fdSlucy wang - Sun Microsystems - Beijing China free_statusrx_desc:
5869a5557fdSlucy wang - Sun Microsystems - Beijing China free_status_desc:
5879a5557fdSlucy wang - Sun Microsystems - Beijing China free_cmd_desc:
5889a5557fdSlucy wang - Sun Microsystems - Beijing China 	unm_free_hw_resources(adapter);
5899a5557fdSlucy wang - Sun Microsystems - Beijing China 
5909a5557fdSlucy wang - Sun Microsystems - Beijing China 	return (err);
5919a5557fdSlucy wang - Sun Microsystems - Beijing China }
5929a5557fdSlucy wang - Sun Microsystems - Beijing China 
unm_desc_dma_sync(ddi_dma_handle_t handle,uint_t start,uint_t count,uint_t range,uint_t unit_size,uint_t direction)5939a5557fdSlucy wang - Sun Microsystems - Beijing China void unm_desc_dma_sync(ddi_dma_handle_t handle, uint_t start, uint_t count,
5949a5557fdSlucy wang - Sun Microsystems - Beijing China     uint_t range, uint_t unit_size, uint_t direction)
5959a5557fdSlucy wang - Sun Microsystems - Beijing China {
5969a5557fdSlucy wang - Sun Microsystems - Beijing China 	if ((start + count) < range) {
5979a5557fdSlucy wang - Sun Microsystems - Beijing China 		(void) ddi_dma_sync(handle, start * unit_size,
5989a5557fdSlucy wang - Sun Microsystems - Beijing China 		    count * unit_size, direction);
5999a5557fdSlucy wang - Sun Microsystems - Beijing China 	} else {
6009a5557fdSlucy wang - Sun Microsystems - Beijing China 		(void) ddi_dma_sync(handle, start * unit_size, 0, direction);
6019a5557fdSlucy wang - Sun Microsystems - Beijing China 		(void) ddi_dma_sync(handle, 0,
6029a5557fdSlucy wang - Sun Microsystems - Beijing China 		    (start + count - range) * unit_size, DDI_DMA_SYNC_FORCPU);
6039a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
6049a5557fdSlucy wang - Sun Microsystems - Beijing China }
6059a5557fdSlucy wang - Sun Microsystems - Beijing China 
6069a5557fdSlucy wang - Sun Microsystems - Beijing China static uint32_t crb_cmd_producer[4] = { CRB_CMD_PRODUCER_OFFSET,
6079a5557fdSlucy wang - Sun Microsystems - Beijing China     CRB_CMD_PRODUCER_OFFSET_1, CRB_CMD_PRODUCER_OFFSET_2,
6089a5557fdSlucy wang - Sun Microsystems - Beijing China     CRB_CMD_PRODUCER_OFFSET_3 };
6099a5557fdSlucy wang - Sun Microsystems - Beijing China 
6109a5557fdSlucy wang - Sun Microsystems - Beijing China static uint32_t crb_cmd_consumer[4] = { CRB_CMD_CONSUMER_OFFSET,
6119a5557fdSlucy wang - Sun Microsystems - Beijing China     CRB_CMD_CONSUMER_OFFSET_1, CRB_CMD_CONSUMER_OFFSET_2,
6129a5557fdSlucy wang - Sun Microsystems - Beijing China     CRB_CMD_CONSUMER_OFFSET_3 };
6139a5557fdSlucy wang - Sun Microsystems - Beijing China 
6149a5557fdSlucy wang - Sun Microsystems - Beijing China void
unm_nic_update_cmd_producer(struct unm_adapter_s * adapter,uint32_t crb_producer)6159a5557fdSlucy wang - Sun Microsystems - Beijing China unm_nic_update_cmd_producer(struct unm_adapter_s *adapter,
6169a5557fdSlucy wang - Sun Microsystems - Beijing China     uint32_t crb_producer)
6179a5557fdSlucy wang - Sun Microsystems - Beijing China {
6189a5557fdSlucy wang - Sun Microsystems - Beijing China 	int data = crb_producer;
6199a5557fdSlucy wang - Sun Microsystems - Beijing China 
6209a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (adapter->crb_addr_cmd_producer) {
6219a5557fdSlucy wang - Sun Microsystems - Beijing China 		UNM_READ_LOCK(&adapter->adapter_lock);
6229a5557fdSlucy wang - Sun Microsystems - Beijing China 		adapter->unm_nic_hw_write_wx(adapter,
6239a5557fdSlucy wang - Sun Microsystems - Beijing China 		    adapter->crb_addr_cmd_producer, &data, 4);
6249a5557fdSlucy wang - Sun Microsystems - Beijing China 		UNM_READ_UNLOCK(&adapter->adapter_lock);
6259a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
6269a5557fdSlucy wang - Sun Microsystems - Beijing China }
6279a5557fdSlucy wang - Sun Microsystems - Beijing China 
6289a5557fdSlucy wang - Sun Microsystems - Beijing China static void
unm_nic_update_cmd_consumer(struct unm_adapter_s * adapter,uint32_t crb_producer)6299a5557fdSlucy wang - Sun Microsystems - Beijing China unm_nic_update_cmd_consumer(struct unm_adapter_s *adapter,
6309a5557fdSlucy wang - Sun Microsystems - Beijing China     uint32_t crb_producer)
6319a5557fdSlucy wang - Sun Microsystems - Beijing China {
6329a5557fdSlucy wang - Sun Microsystems - Beijing China 	int data = crb_producer;
6339a5557fdSlucy wang - Sun Microsystems - Beijing China 
6349a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (adapter->crb_addr_cmd_consumer)
6359a5557fdSlucy wang - Sun Microsystems - Beijing China 		adapter->unm_nic_hw_write_wx(adapter,
6369a5557fdSlucy wang - Sun Microsystems - Beijing China 		    adapter->crb_addr_cmd_consumer, &data, 4);
6379a5557fdSlucy wang - Sun Microsystems - Beijing China }
6389a5557fdSlucy wang - Sun Microsystems - Beijing China 
6399a5557fdSlucy wang - Sun Microsystems - Beijing China /*
6409a5557fdSlucy wang - Sun Microsystems - Beijing China  * Looks for type of packet and sets opcode accordingly
6419a5557fdSlucy wang - Sun Microsystems - Beijing China  * so that checksum offload can be used.
6429a5557fdSlucy wang - Sun Microsystems - Beijing China  */
6439a5557fdSlucy wang - Sun Microsystems - Beijing China static void
unm_tx_csum(cmdDescType0_t * desc,mblk_t * mp,pktinfo_t * pktinfo)6449a5557fdSlucy wang - Sun Microsystems - Beijing China unm_tx_csum(cmdDescType0_t *desc, mblk_t *mp, pktinfo_t *pktinfo)
6459a5557fdSlucy wang - Sun Microsystems - Beijing China {
6469a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (pktinfo->mac_hlen == sizeof (struct ether_vlan_header))
6479a5557fdSlucy wang - Sun Microsystems - Beijing China 		desc->u1.s1.flags = FLAGS_VLAN_TAGGED;
6489a5557fdSlucy wang - Sun Microsystems - Beijing China 
6499a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (pktinfo->etype == htons(ETHERTYPE_IP)) {
6509a5557fdSlucy wang - Sun Microsystems - Beijing China 		uint32_t	start, flags;
6519a5557fdSlucy wang - Sun Microsystems - Beijing China 
6520dc2366fSVenugopal Iyer 		mac_hcksum_get(mp, &start, NULL, NULL, NULL, &flags);
6539a5557fdSlucy wang - Sun Microsystems - Beijing China 		if ((flags & (HCK_FULLCKSUM | HCK_IPV4_HDRCKSUM)) == 0)
6549a5557fdSlucy wang - Sun Microsystems - Beijing China 			return;
6559a5557fdSlucy wang - Sun Microsystems - Beijing China 
6569a5557fdSlucy wang - Sun Microsystems - Beijing China 		/*
6579a5557fdSlucy wang - Sun Microsystems - Beijing China 		 * For TCP/UDP, ask hardware to do both IP header and
6589a5557fdSlucy wang - Sun Microsystems - Beijing China 		 * full checksum, even if stack has already done one or
6599a5557fdSlucy wang - Sun Microsystems - Beijing China 		 * the other. Hardware will always get it correct even
6609a5557fdSlucy wang - Sun Microsystems - Beijing China 		 * if stack has already done it.
6619a5557fdSlucy wang - Sun Microsystems - Beijing China 		 */
6629a5557fdSlucy wang - Sun Microsystems - Beijing China 		switch (pktinfo->l4_proto) {
6639a5557fdSlucy wang - Sun Microsystems - Beijing China 			case IPPROTO_TCP:
6649a5557fdSlucy wang - Sun Microsystems - Beijing China 				desc->u1.s1.opcode = TX_TCP_PKT;
6659a5557fdSlucy wang - Sun Microsystems - Beijing China 				break;
6669a5557fdSlucy wang - Sun Microsystems - Beijing China 			case IPPROTO_UDP:
6679a5557fdSlucy wang - Sun Microsystems - Beijing China 				desc->u1.s1.opcode = TX_UDP_PKT;
6689a5557fdSlucy wang - Sun Microsystems - Beijing China 				break;
6699a5557fdSlucy wang - Sun Microsystems - Beijing China 			default:
6709a5557fdSlucy wang - Sun Microsystems - Beijing China 				/* Must be here with HCK_IPV4_HDRCKSUM */
6719a5557fdSlucy wang - Sun Microsystems - Beijing China 				desc->u1.s1.opcode = TX_IP_PKT;
6729a5557fdSlucy wang - Sun Microsystems - Beijing China 				return;
6739a5557fdSlucy wang - Sun Microsystems - Beijing China 		}
6749a5557fdSlucy wang - Sun Microsystems - Beijing China 
6759a5557fdSlucy wang - Sun Microsystems - Beijing China 		desc->u1.s1.ipHdrOffset = pktinfo->mac_hlen;
6769a5557fdSlucy wang - Sun Microsystems - Beijing China 		desc->u1.s1.tcpHdrOffset = pktinfo->mac_hlen + pktinfo->ip_hlen;
6779a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
6789a5557fdSlucy wang - Sun Microsystems - Beijing China }
6799a5557fdSlucy wang - Sun Microsystems - Beijing China 
6809a5557fdSlucy wang - Sun Microsystems - Beijing China /*
6819a5557fdSlucy wang - Sun Microsystems - Beijing China  * For IP/UDP/TCP checksum offload, this checks for MAC+IP header in one
6829a5557fdSlucy wang - Sun Microsystems - Beijing China  * contiguous block ending at 8 byte aligned address as required by hardware.
6839a5557fdSlucy wang - Sun Microsystems - Beijing China  * Caller assumes pktinfo->total_len will be updated by this function and
6849a5557fdSlucy wang - Sun Microsystems - Beijing China  * if pktinfo->etype is set to 0, it will need to linearize the mblk and
6859a5557fdSlucy wang - Sun Microsystems - Beijing China  * invoke unm_update_pkt_info() to determine ethertype, IP header len and
6869a5557fdSlucy wang - Sun Microsystems - Beijing China  * protocol.
6879a5557fdSlucy wang - Sun Microsystems - Beijing China  */
6889a5557fdSlucy wang - Sun Microsystems - Beijing China static boolean_t
unm_get_pkt_info(mblk_t * mp,pktinfo_t * pktinfo)6899a5557fdSlucy wang - Sun Microsystems - Beijing China unm_get_pkt_info(mblk_t *mp, pktinfo_t *pktinfo)
6909a5557fdSlucy wang - Sun Microsystems - Beijing China {
6919a5557fdSlucy wang - Sun Microsystems - Beijing China 	mblk_t		*bp;
6929a5557fdSlucy wang - Sun Microsystems - Beijing China 	ushort_t	type;
6939a5557fdSlucy wang - Sun Microsystems - Beijing China 
6949a5557fdSlucy wang - Sun Microsystems - Beijing China 	(void) memset(pktinfo, 0, sizeof (pktinfo_t));
6959a5557fdSlucy wang - Sun Microsystems - Beijing China 
6969a5557fdSlucy wang - Sun Microsystems - Beijing China 	for (bp = mp; bp != NULL; bp = bp->b_cont) {
6979a5557fdSlucy wang - Sun Microsystems - Beijing China 		if (MBLKL(bp) == 0)
6989a5557fdSlucy wang - Sun Microsystems - Beijing China 			continue;
6999a5557fdSlucy wang - Sun Microsystems - Beijing China 		pktinfo->mblk_no++;
7009a5557fdSlucy wang - Sun Microsystems - Beijing China 		pktinfo->total_len += MBLKL(bp);
7019a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
7029a5557fdSlucy wang - Sun Microsystems - Beijing China 
7039a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (MBLKL(mp) < (sizeof (struct ether_header) + sizeof (ipha_t)))
7049a5557fdSlucy wang - Sun Microsystems - Beijing China 		return (B_FALSE);
7059a5557fdSlucy wang - Sun Microsystems - Beijing China 
7069a5557fdSlucy wang - Sun Microsystems - Beijing China 	/*
7079a5557fdSlucy wang - Sun Microsystems - Beijing China 	 * We just need non 1 byte aligned address, since ether_type is
7089a5557fdSlucy wang - Sun Microsystems - Beijing China 	 * ushort.
7099a5557fdSlucy wang - Sun Microsystems - Beijing China 	 */
7109a5557fdSlucy wang - Sun Microsystems - Beijing China 	if ((uintptr_t)mp->b_rptr & 1)
7119a5557fdSlucy wang - Sun Microsystems - Beijing China 		return (B_FALSE);
7129a5557fdSlucy wang - Sun Microsystems - Beijing China 
7139a5557fdSlucy wang - Sun Microsystems - Beijing China 	type = ((struct ether_header *)(uintptr_t)mp->b_rptr)->ether_type;
7149a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (type == htons(ETHERTYPE_VLAN)) {
7159a5557fdSlucy wang - Sun Microsystems - Beijing China 		if (MBLKL(mp) < (sizeof (struct ether_vlan_header) +
7169a5557fdSlucy wang - Sun Microsystems - Beijing China 		    sizeof (ipha_t)))
7179a5557fdSlucy wang - Sun Microsystems - Beijing China 			return (B_FALSE);
7189a5557fdSlucy wang - Sun Microsystems - Beijing China 		type = ((struct ether_vlan_header *) \
7199a5557fdSlucy wang - Sun Microsystems - Beijing China 		    (uintptr_t)mp->b_rptr)->ether_type;
7209a5557fdSlucy wang - Sun Microsystems - Beijing China 		pktinfo->mac_hlen = sizeof (struct ether_vlan_header);
7219a5557fdSlucy wang - Sun Microsystems - Beijing China 	} else {
7229a5557fdSlucy wang - Sun Microsystems - Beijing China 		pktinfo->mac_hlen = sizeof (struct ether_header);
7239a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
7249a5557fdSlucy wang - Sun Microsystems - Beijing China 	pktinfo->etype = type;
7259a5557fdSlucy wang - Sun Microsystems - Beijing China 
7269a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (pktinfo->etype == htons(ETHERTYPE_IP)) {
7279a5557fdSlucy wang - Sun Microsystems - Beijing China 		uchar_t *ip_off = mp->b_rptr + pktinfo->mac_hlen;
7289a5557fdSlucy wang - Sun Microsystems - Beijing China 
7299a5557fdSlucy wang - Sun Microsystems - Beijing China 		pktinfo->ip_hlen = IPH_HDR_LENGTH((uintptr_t)ip_off);
7309a5557fdSlucy wang - Sun Microsystems - Beijing China 		pktinfo->l4_proto =
7319a5557fdSlucy wang - Sun Microsystems - Beijing China 		    ((ipha_t *)(uintptr_t)ip_off)->ipha_protocol;
7329a5557fdSlucy wang - Sun Microsystems - Beijing China 
7339a5557fdSlucy wang - Sun Microsystems - Beijing China 		/* IP header not aligned to quadward boundary? */
7349a5557fdSlucy wang - Sun Microsystems - Beijing China 		if ((unsigned long)(ip_off + pktinfo->ip_hlen) % 8 != 0)
7359a5557fdSlucy wang - Sun Microsystems - Beijing China 			return (B_FALSE);
7369a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
7379a5557fdSlucy wang - Sun Microsystems - Beijing China 
7389a5557fdSlucy wang - Sun Microsystems - Beijing China 	return (B_TRUE);
7399a5557fdSlucy wang - Sun Microsystems - Beijing China }
7409a5557fdSlucy wang - Sun Microsystems - Beijing China 
7419a5557fdSlucy wang - Sun Microsystems - Beijing China static void
unm_update_pkt_info(char * ptr,pktinfo_t * pktinfo)7429a5557fdSlucy wang - Sun Microsystems - Beijing China unm_update_pkt_info(char *ptr, pktinfo_t *pktinfo)
7439a5557fdSlucy wang - Sun Microsystems - Beijing China {
7449a5557fdSlucy wang - Sun Microsystems - Beijing China 	ushort_t	type;
7459a5557fdSlucy wang - Sun Microsystems - Beijing China 
7469a5557fdSlucy wang - Sun Microsystems - Beijing China 	type = ((struct ether_header *)(uintptr_t)ptr)->ether_type;
7479a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (type == htons(ETHERTYPE_VLAN)) {
7489a5557fdSlucy wang - Sun Microsystems - Beijing China 		type = ((struct ether_vlan_header *)(uintptr_t)ptr)->ether_type;
7499a5557fdSlucy wang - Sun Microsystems - Beijing China 		pktinfo->mac_hlen = sizeof (struct ether_vlan_header);
7509a5557fdSlucy wang - Sun Microsystems - Beijing China 	} else {
7519a5557fdSlucy wang - Sun Microsystems - Beijing China 		pktinfo->mac_hlen = sizeof (struct ether_header);
7529a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
7539a5557fdSlucy wang - Sun Microsystems - Beijing China 	pktinfo->etype = type;
7549a5557fdSlucy wang - Sun Microsystems - Beijing China 
7559a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (pktinfo->etype == htons(ETHERTYPE_IP)) {
7569a5557fdSlucy wang - Sun Microsystems - Beijing China 		char *ipp = ptr + pktinfo->mac_hlen;
7579a5557fdSlucy wang - Sun Microsystems - Beijing China 
7589a5557fdSlucy wang - Sun Microsystems - Beijing China 		pktinfo->ip_hlen = IPH_HDR_LENGTH((uintptr_t)ipp);
7599a5557fdSlucy wang - Sun Microsystems - Beijing China 		pktinfo->l4_proto = ((ipha_t *)(uintptr_t)ipp)->ipha_protocol;
7609a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
7619a5557fdSlucy wang - Sun Microsystems - Beijing China }
7629a5557fdSlucy wang - Sun Microsystems - Beijing China 
7639a5557fdSlucy wang - Sun Microsystems - Beijing China static boolean_t
unm_send_copy(struct unm_adapter_s * adapter,mblk_t * mp,pktinfo_t * pktinfo)7649a5557fdSlucy wang - Sun Microsystems - Beijing China unm_send_copy(struct unm_adapter_s *adapter, mblk_t *mp, pktinfo_t *pktinfo)
7659a5557fdSlucy wang - Sun Microsystems - Beijing China {
7669a5557fdSlucy wang - Sun Microsystems - Beijing China 	hardware_context *hw;
7679a5557fdSlucy wang - Sun Microsystems - Beijing China 	u32				producer = 0;
7689a5557fdSlucy wang - Sun Microsystems - Beijing China 	cmdDescType0_t			*hwdesc;
7699a5557fdSlucy wang - Sun Microsystems - Beijing China 	struct unm_cmd_buffer		*pbuf = NULL;
7709a5557fdSlucy wang - Sun Microsystems - Beijing China 	u32				mblen;
7719a5557fdSlucy wang - Sun Microsystems - Beijing China 	int				no_of_desc = 1;
7729a5557fdSlucy wang - Sun Microsystems - Beijing China 	int				MaxTxDescCount;
7739a5557fdSlucy wang - Sun Microsystems - Beijing China 	mblk_t				*bp;
7749a5557fdSlucy wang - Sun Microsystems - Beijing China 	char				*txb;
7759a5557fdSlucy wang - Sun Microsystems - Beijing China 
7769a5557fdSlucy wang - Sun Microsystems - Beijing China 	hw = &adapter->ahw;
7779a5557fdSlucy wang - Sun Microsystems - Beijing China 	MaxTxDescCount = adapter->MaxTxDescCount;
7789a5557fdSlucy wang - Sun Microsystems - Beijing China 
7799a5557fdSlucy wang - Sun Microsystems - Beijing China 	UNM_SPIN_LOCK(&adapter->tx_lock);
7809a5557fdSlucy wang - Sun Microsystems - Beijing China 	membar_enter();
7819a5557fdSlucy wang - Sun Microsystems - Beijing China 
7829a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (find_diff_among(adapter->cmdProducer, adapter->lastCmdConsumer,
7839a5557fdSlucy wang - Sun Microsystems - Beijing China 	    MaxTxDescCount) <= 2) {
7849a5557fdSlucy wang - Sun Microsystems - Beijing China 		adapter->stats.outofcmddesc++;
7859a5557fdSlucy wang - Sun Microsystems - Beijing China 		adapter->resched_needed = 1;
7869a5557fdSlucy wang - Sun Microsystems - Beijing China 		membar_exit();
7879a5557fdSlucy wang - Sun Microsystems - Beijing China 		UNM_SPIN_UNLOCK(&adapter->tx_lock);
7889a5557fdSlucy wang - Sun Microsystems - Beijing China 		return (B_FALSE);
7899a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
7909a5557fdSlucy wang - Sun Microsystems - Beijing China 	adapter->freecmds -= no_of_desc;
7919a5557fdSlucy wang - Sun Microsystems - Beijing China 
7929a5557fdSlucy wang - Sun Microsystems - Beijing China 	producer = adapter->cmdProducer;
7939a5557fdSlucy wang - Sun Microsystems - Beijing China 
7949a5557fdSlucy wang - Sun Microsystems - Beijing China 	adapter->cmdProducer = get_index_range(adapter->cmdProducer,
7959a5557fdSlucy wang - Sun Microsystems - Beijing China 	    MaxTxDescCount, no_of_desc);
7969a5557fdSlucy wang - Sun Microsystems - Beijing China 
7979a5557fdSlucy wang - Sun Microsystems - Beijing China 	hwdesc = &hw->cmdDescHead[producer];
7989a5557fdSlucy wang - Sun Microsystems - Beijing China 	(void) memset(hwdesc, 0, sizeof (cmdDescType0_t));
7999a5557fdSlucy wang - Sun Microsystems - Beijing China 	pbuf = &adapter->cmd_buf_arr[producer];
8009a5557fdSlucy wang - Sun Microsystems - Beijing China 
8019a5557fdSlucy wang - Sun Microsystems - Beijing China 	pbuf->msg = NULL;
8029a5557fdSlucy wang - Sun Microsystems - Beijing China 	pbuf->head = NULL;
8039a5557fdSlucy wang - Sun Microsystems - Beijing China 	pbuf->tail = NULL;
8049a5557fdSlucy wang - Sun Microsystems - Beijing China 
8059a5557fdSlucy wang - Sun Microsystems - Beijing China 	txb = pbuf->dma_area.vaddr;
8069a5557fdSlucy wang - Sun Microsystems - Beijing China 
8079a5557fdSlucy wang - Sun Microsystems - Beijing China 	for (bp = mp; bp != NULL; bp = bp->b_cont) {
8089a5557fdSlucy wang - Sun Microsystems - Beijing China 		if ((mblen = MBLKL(bp)) == 0)
8099a5557fdSlucy wang - Sun Microsystems - Beijing China 			continue;
8109a5557fdSlucy wang - Sun Microsystems - Beijing China 		bcopy(bp->b_rptr, txb, mblen);
8119a5557fdSlucy wang - Sun Microsystems - Beijing China 		txb += mblen;
8129a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
8139a5557fdSlucy wang - Sun Microsystems - Beijing China 
8149a5557fdSlucy wang - Sun Microsystems - Beijing China 	/*
8159a5557fdSlucy wang - Sun Microsystems - Beijing China 	 * Determine metadata if not previously done due to fragmented mblk.
8169a5557fdSlucy wang - Sun Microsystems - Beijing China 	 */
8179a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (pktinfo->etype == 0)
8189a5557fdSlucy wang - Sun Microsystems - Beijing China 		unm_update_pkt_info(pbuf->dma_area.vaddr, pktinfo);
8199a5557fdSlucy wang - Sun Microsystems - Beijing China 
8209a5557fdSlucy wang - Sun Microsystems - Beijing China 	(void) ddi_dma_sync(pbuf->dma_area.dma_hdl,
8219a5557fdSlucy wang - Sun Microsystems - Beijing China 	    0, pktinfo->total_len, DDI_DMA_SYNC_FORDEV);
8229a5557fdSlucy wang - Sun Microsystems - Beijing China 
8239a5557fdSlucy wang - Sun Microsystems - Beijing China 	/* hwdesc->u1.s1.tcpHdrOffset = 0; */
8249a5557fdSlucy wang - Sun Microsystems - Beijing China 	/* hwdesc->mss = 0; */
8259a5557fdSlucy wang - Sun Microsystems - Beijing China 	hwdesc->u1.s1.opcode = TX_ETHER_PKT;
8269a5557fdSlucy wang - Sun Microsystems - Beijing China 	hwdesc->u3.s1.port = adapter->portnum;
8279a5557fdSlucy wang - Sun Microsystems - Beijing China 	hwdesc->u3.s1.ctx_id = adapter->portnum;
8289a5557fdSlucy wang - Sun Microsystems - Beijing China 
8299a5557fdSlucy wang - Sun Microsystems - Beijing China 	hwdesc->u6.s1.buffer1Length = pktinfo->total_len;
8309a5557fdSlucy wang - Sun Microsystems - Beijing China 	hwdesc->u5.AddrBuffer1 = pbuf->dma_area.dma_addr;
8319a5557fdSlucy wang - Sun Microsystems - Beijing China 	hwdesc->u1.s1.numOfBuffers = 1;
8329a5557fdSlucy wang - Sun Microsystems - Beijing China 	hwdesc->u1.s1.totalLength = pktinfo->total_len;
8339a5557fdSlucy wang - Sun Microsystems - Beijing China 
8349a5557fdSlucy wang - Sun Microsystems - Beijing China 	unm_tx_csum(hwdesc, mp, pktinfo);
8359a5557fdSlucy wang - Sun Microsystems - Beijing China 
8369a5557fdSlucy wang - Sun Microsystems - Beijing China 	unm_desc_dma_sync(hw->cmd_desc_dma_handle,
8379a5557fdSlucy wang - Sun Microsystems - Beijing China 	    producer,
8389a5557fdSlucy wang - Sun Microsystems - Beijing China 	    no_of_desc,
8399a5557fdSlucy wang - Sun Microsystems - Beijing China 	    MaxTxDescCount,
8409a5557fdSlucy wang - Sun Microsystems - Beijing China 	    sizeof (cmdDescType0_t),
8419a5557fdSlucy wang - Sun Microsystems - Beijing China 	    DDI_DMA_SYNC_FORDEV);
8429a5557fdSlucy wang - Sun Microsystems - Beijing China 
8439a5557fdSlucy wang - Sun Microsystems - Beijing China 	hw->cmdProducer = adapter->cmdProducer;
8449a5557fdSlucy wang - Sun Microsystems - Beijing China 	unm_nic_update_cmd_producer(adapter, adapter->cmdProducer);
8459a5557fdSlucy wang - Sun Microsystems - Beijing China 
8469a5557fdSlucy wang - Sun Microsystems - Beijing China 	adapter->stats.txbytes += pktinfo->total_len;
8479a5557fdSlucy wang - Sun Microsystems - Beijing China 	adapter->stats.xmitfinished++;
8489a5557fdSlucy wang - Sun Microsystems - Beijing China 	adapter->stats.txcopyed++;
8499a5557fdSlucy wang - Sun Microsystems - Beijing China 	UNM_SPIN_UNLOCK(&adapter->tx_lock);
8509a5557fdSlucy wang - Sun Microsystems - Beijing China 
8519a5557fdSlucy wang - Sun Microsystems - Beijing China 	freemsg(mp);
8529a5557fdSlucy wang - Sun Microsystems - Beijing China 	return (B_TRUE);
8539a5557fdSlucy wang - Sun Microsystems - Beijing China }
8549a5557fdSlucy wang - Sun Microsystems - Beijing China 
8559a5557fdSlucy wang - Sun Microsystems - Beijing China /* Should be called with adapter->tx_lock held. */
8569a5557fdSlucy wang - Sun Microsystems - Beijing China static void
unm_return_dma_handle(unm_adapter * adapter,unm_dmah_node_t * head,unm_dmah_node_t * tail,uint32_t num)8579a5557fdSlucy wang - Sun Microsystems - Beijing China unm_return_dma_handle(unm_adapter *adapter, unm_dmah_node_t *head,
8589a5557fdSlucy wang - Sun Microsystems - Beijing China     unm_dmah_node_t *tail, uint32_t num)
8599a5557fdSlucy wang - Sun Microsystems - Beijing China {
8609a5557fdSlucy wang - Sun Microsystems - Beijing China 	ASSERT(tail != NULL);
8619a5557fdSlucy wang - Sun Microsystems - Beijing China 	tail->next = adapter->dmahdl_pool;
8629a5557fdSlucy wang - Sun Microsystems - Beijing China 	adapter->dmahdl_pool = head;
8639a5557fdSlucy wang - Sun Microsystems - Beijing China 	adapter->freehdls += num;
8649a5557fdSlucy wang - Sun Microsystems - Beijing China }
8659a5557fdSlucy wang - Sun Microsystems - Beijing China 
8669a5557fdSlucy wang - Sun Microsystems - Beijing China static unm_dmah_node_t *
unm_reserve_dma_handle(unm_adapter * adapter)8679a5557fdSlucy wang - Sun Microsystems - Beijing China unm_reserve_dma_handle(unm_adapter* adapter)
8689a5557fdSlucy wang - Sun Microsystems - Beijing China {
8699a5557fdSlucy wang - Sun Microsystems - Beijing China 	unm_dmah_node_t *dmah = NULL;
8709a5557fdSlucy wang - Sun Microsystems - Beijing China 
8719a5557fdSlucy wang - Sun Microsystems - Beijing China 	dmah = adapter->dmahdl_pool;
8729a5557fdSlucy wang - Sun Microsystems - Beijing China 	if (dmah != NULL) {
8739a5557fdSlucy wang - Sun Microsystems - Beijing China 		adapter->dmahdl_pool = dmah->next;
8749a5557fdSlucy wang - Sun Microsystems - Beijing China 		dmah->next = NULL;
8759a5557fdSlucy wang - Sun Microsystems - Beijing China 		adapter->freehdls--;
8769a5557fdSlucy wang - Sun Microsystems - Beijing China 		membar_exit();
8779a5557fdSlucy wang - Sun Microsystems - Beijing China 	}
8789a5557fdSlucy wang - Sun Microsystems - Beijing China 
8799a5557fdSlucy wang - Sun Microsystems - Beijing China 	return (dmah);
8809a5557fdSlucy wang - Sun Microsystems - Beijing China }
8819a5557fdSlucy wang - Sun Microsystems - Beijing China 
882