xref: /onnv-gate/usr/src/uts/common/io/ntxn/niu.c (revision 8687:5dca9cd6354a)
17956Sxiuyan.wang@Sun.COM /*
27956Sxiuyan.wang@Sun.COM  * CDDL HEADER START
37956Sxiuyan.wang@Sun.COM  *
47956Sxiuyan.wang@Sun.COM  * The contents of this file are subject to the terms of the
57956Sxiuyan.wang@Sun.COM  * Common Development and Distribution License (the "License").
67956Sxiuyan.wang@Sun.COM  * You may not use this file except in compliance with the License.
77956Sxiuyan.wang@Sun.COM  *
87956Sxiuyan.wang@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97956Sxiuyan.wang@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107956Sxiuyan.wang@Sun.COM  * See the License for the specific language governing permissions
117956Sxiuyan.wang@Sun.COM  * and limitations under the License.
127956Sxiuyan.wang@Sun.COM  *
137956Sxiuyan.wang@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147956Sxiuyan.wang@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157956Sxiuyan.wang@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167956Sxiuyan.wang@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177956Sxiuyan.wang@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187956Sxiuyan.wang@Sun.COM  *
197956Sxiuyan.wang@Sun.COM  * CDDL HEADER END
207956Sxiuyan.wang@Sun.COM  */
21*8687SJing.Xiong@Sun.COM 
227956Sxiuyan.wang@Sun.COM /*
237956Sxiuyan.wang@Sun.COM  * Copyright 2008 NetXen, Inc.  All rights reserved.
247956Sxiuyan.wang@Sun.COM  * Use is subject to license terms.
257956Sxiuyan.wang@Sun.COM  */
26*8687SJing.Xiong@Sun.COM 
277956Sxiuyan.wang@Sun.COM #include <sys/types.h>
287956Sxiuyan.wang@Sun.COM #include <sys/conf.h>
297956Sxiuyan.wang@Sun.COM #include <sys/debug.h>
307956Sxiuyan.wang@Sun.COM #include <sys/stropts.h>
317956Sxiuyan.wang@Sun.COM #include <sys/stream.h>
327956Sxiuyan.wang@Sun.COM #include <sys/strlog.h>
337956Sxiuyan.wang@Sun.COM #include <sys/kmem.h>
347956Sxiuyan.wang@Sun.COM #include <sys/stat.h>
357956Sxiuyan.wang@Sun.COM #include <sys/kstat.h>
367956Sxiuyan.wang@Sun.COM #include <sys/vtrace.h>
377956Sxiuyan.wang@Sun.COM #include <sys/dlpi.h>
387956Sxiuyan.wang@Sun.COM #include <sys/strsun.h>
397956Sxiuyan.wang@Sun.COM #include <sys/ethernet.h>
407956Sxiuyan.wang@Sun.COM #include <sys/modctl.h>
417956Sxiuyan.wang@Sun.COM #include <sys/errno.h>
427956Sxiuyan.wang@Sun.COM #include <sys/dditypes.h>
437956Sxiuyan.wang@Sun.COM #include <sys/ddi.h>
447956Sxiuyan.wang@Sun.COM #include <sys/sunddi.h>
457956Sxiuyan.wang@Sun.COM #include <sys/sysmacros.h>
467956Sxiuyan.wang@Sun.COM 
477956Sxiuyan.wang@Sun.COM #include <sys/pci.h>
487956Sxiuyan.wang@Sun.COM 
497956Sxiuyan.wang@Sun.COM #include "unm_inc.h"
507956Sxiuyan.wang@Sun.COM #include "unm_nic.h"
517956Sxiuyan.wang@Sun.COM 
527956Sxiuyan.wang@Sun.COM static long phy_lock_timeout = 100000000;
537956Sxiuyan.wang@Sun.COM 
phy_lock(struct unm_adapter_s * adapter)547956Sxiuyan.wang@Sun.COM static int phy_lock(struct unm_adapter_s *adapter)
557956Sxiuyan.wang@Sun.COM {
567956Sxiuyan.wang@Sun.COM 	u32	done = 0;
577956Sxiuyan.wang@Sun.COM 	int	timeout = 0;
587956Sxiuyan.wang@Sun.COM 
597956Sxiuyan.wang@Sun.COM 	while (!done) {
607956Sxiuyan.wang@Sun.COM 		/* acquire semaphore3 from PCI HW block */
617956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_pci_read_immediate(adapter,
627956Sxiuyan.wang@Sun.COM 		    UNM_PCIE_REG(PCIE_SEM3_LOCK), &done);
637956Sxiuyan.wang@Sun.COM 		if (done == 1)
647956Sxiuyan.wang@Sun.COM 			break;
657956Sxiuyan.wang@Sun.COM 		if (timeout >= phy_lock_timeout)
667956Sxiuyan.wang@Sun.COM 			return (-1);
677956Sxiuyan.wang@Sun.COM 		timeout++;
687956Sxiuyan.wang@Sun.COM 	}
697956Sxiuyan.wang@Sun.COM 
707956Sxiuyan.wang@Sun.COM 	adapter->unm_crb_writelit_adapter(adapter, UNM_PHY_LOCK_ID,
717956Sxiuyan.wang@Sun.COM 	    PHY_LOCK_DRIVER);
727956Sxiuyan.wang@Sun.COM 	return (0);
737956Sxiuyan.wang@Sun.COM }
747956Sxiuyan.wang@Sun.COM 
757956Sxiuyan.wang@Sun.COM static void
phy_unlock(struct unm_adapter_s * adapter)767956Sxiuyan.wang@Sun.COM phy_unlock(struct unm_adapter_s *adapter)
777956Sxiuyan.wang@Sun.COM {
787956Sxiuyan.wang@Sun.COM 	u32	val;
797956Sxiuyan.wang@Sun.COM 
807956Sxiuyan.wang@Sun.COM 	/* release semaphore3 */
817956Sxiuyan.wang@Sun.COM 	adapter->unm_nic_pci_read_immediate(adapter,
827956Sxiuyan.wang@Sun.COM 	    UNM_PCIE_REG(PCIE_SEM3_UNLOCK), &val);
837956Sxiuyan.wang@Sun.COM }
847956Sxiuyan.wang@Sun.COM 
857956Sxiuyan.wang@Sun.COM /*
867956Sxiuyan.wang@Sun.COM  * unm_niu_gbe_phy_read - read a register from the GbE PHY via
877956Sxiuyan.wang@Sun.COM  * mii management interface.
887956Sxiuyan.wang@Sun.COM  *
897956Sxiuyan.wang@Sun.COM  * Note: The MII management interface goes through port 0.
907956Sxiuyan.wang@Sun.COM  *	   Individual phys are addressed as follows:
917956Sxiuyan.wang@Sun.COM  *	   [15:8]  phy id
927956Sxiuyan.wang@Sun.COM  *	   [7:0]   register number
937956Sxiuyan.wang@Sun.COM  *
947956Sxiuyan.wang@Sun.COM  * Returns:  0 success
957956Sxiuyan.wang@Sun.COM  *	  -1 error
967956Sxiuyan.wang@Sun.COM  *
977956Sxiuyan.wang@Sun.COM  */
987956Sxiuyan.wang@Sun.COM long
unm_niu_gbe_phy_read(struct unm_adapter_s * adapter,long reg,unm_crbword_t * readval)997956Sxiuyan.wang@Sun.COM unm_niu_gbe_phy_read(struct unm_adapter_s *adapter, long reg,
1007956Sxiuyan.wang@Sun.COM     unm_crbword_t *readval)
1017956Sxiuyan.wang@Sun.COM {
1027956Sxiuyan.wang@Sun.COM 	long phy = adapter->physical_port;
1037956Sxiuyan.wang@Sun.COM 	unm_niu_gb_mii_mgmt_address_t address;
1047956Sxiuyan.wang@Sun.COM 	unm_niu_gb_mii_mgmt_command_t command;
1057956Sxiuyan.wang@Sun.COM 	unm_niu_gb_mii_mgmt_indicators_t status;
1067956Sxiuyan.wang@Sun.COM 
1077956Sxiuyan.wang@Sun.COM 	long timeout = 0;
1087956Sxiuyan.wang@Sun.COM 	long result = 0;
1097956Sxiuyan.wang@Sun.COM 	long restore = 0;
1107956Sxiuyan.wang@Sun.COM 	unm_niu_gb_mac_config_0_t mac_cfg0;
1117956Sxiuyan.wang@Sun.COM 
1127956Sxiuyan.wang@Sun.COM 	if (phy_lock(adapter) != 0)
1137956Sxiuyan.wang@Sun.COM 		return (-1);
1147956Sxiuyan.wang@Sun.COM 
1157956Sxiuyan.wang@Sun.COM 	/*
1167956Sxiuyan.wang@Sun.COM 	 * MII mgmt all goes through port 0 MAC interface, so it cannot be
1177956Sxiuyan.wang@Sun.COM 	 * in reset
1187956Sxiuyan.wang@Sun.COM 	 */
1197956Sxiuyan.wang@Sun.COM 	adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_GB_MAC_CONFIG_0(0),
1207956Sxiuyan.wang@Sun.COM 	    &mac_cfg0, 4);
1217956Sxiuyan.wang@Sun.COM 	if (mac_cfg0.soft_reset) {
1227956Sxiuyan.wang@Sun.COM 		unm_niu_gb_mac_config_0_t temp;
1237956Sxiuyan.wang@Sun.COM 		*(unm_crbword_t *)&temp = 0;
1247956Sxiuyan.wang@Sun.COM 		temp.tx_reset_pb = 1;
1257956Sxiuyan.wang@Sun.COM 		temp.rx_reset_pb = 1;
1267956Sxiuyan.wang@Sun.COM 		temp.tx_reset_mac = 1;
1277956Sxiuyan.wang@Sun.COM 		temp.rx_reset_mac = 1;
1287956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_write_wx(adapter,
1297956Sxiuyan.wang@Sun.COM 		    UNM_NIU_GB_MAC_CONFIG_0(0), &temp, 4);
1307956Sxiuyan.wang@Sun.COM 		restore = 1;
1317956Sxiuyan.wang@Sun.COM 	}
1327956Sxiuyan.wang@Sun.COM 
1337956Sxiuyan.wang@Sun.COM 	*(unm_crbword_t *)&address = 0;
1347956Sxiuyan.wang@Sun.COM 	address.reg_addr = (unm_crbword_t)reg;
1357956Sxiuyan.wang@Sun.COM 	address.phy_addr = (unm_crbword_t)phy;
1367956Sxiuyan.wang@Sun.COM 	adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_MII_MGMT_ADDR(0),
1377956Sxiuyan.wang@Sun.COM 	    &address, 4);
1387956Sxiuyan.wang@Sun.COM 
1397956Sxiuyan.wang@Sun.COM 	*(unm_crbword_t *)&command = 0;	/* turn off any prior activity */
1407956Sxiuyan.wang@Sun.COM 	adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_MII_MGMT_COMMAND(0),
1417956Sxiuyan.wang@Sun.COM 	    &command, 4);
1427956Sxiuyan.wang@Sun.COM 
1437956Sxiuyan.wang@Sun.COM 	/* send read command */
1447956Sxiuyan.wang@Sun.COM 	command.read_cycle = 1;
1457956Sxiuyan.wang@Sun.COM 	adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_MII_MGMT_COMMAND(0),
1467956Sxiuyan.wang@Sun.COM 	    &command, 4);
1477956Sxiuyan.wang@Sun.COM 
1487956Sxiuyan.wang@Sun.COM 	*(unm_crbword_t *)&status = 0;
1497956Sxiuyan.wang@Sun.COM 	do {
1507956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_read_wx(adapter,
1517956Sxiuyan.wang@Sun.COM 		    UNM_NIU_GB_MII_MGMT_INDICATE(0), &status, 4);
1527956Sxiuyan.wang@Sun.COM 		timeout++;
1537956Sxiuyan.wang@Sun.COM 	} while ((status.busy || status.notvalid) &&
1547956Sxiuyan.wang@Sun.COM 	    (timeout++ < UNM_NIU_PHY_WAITMAX));
1557956Sxiuyan.wang@Sun.COM 
1567956Sxiuyan.wang@Sun.COM 	if (timeout < UNM_NIU_PHY_WAITMAX) {
1577956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_read_wx(adapter,
1587956Sxiuyan.wang@Sun.COM 		    UNM_NIU_GB_MII_MGMT_STATUS(0), readval, 4);
1597956Sxiuyan.wang@Sun.COM 		result = 0;
1607956Sxiuyan.wang@Sun.COM 	} else
1617956Sxiuyan.wang@Sun.COM 		result = -1;
1627956Sxiuyan.wang@Sun.COM 
1637956Sxiuyan.wang@Sun.COM 	if (restore)
1647956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_write_wx(adapter,
1657956Sxiuyan.wang@Sun.COM 		    UNM_NIU_GB_MAC_CONFIG_0(0), &mac_cfg0, 4);
1667956Sxiuyan.wang@Sun.COM 
1677956Sxiuyan.wang@Sun.COM 	phy_unlock(adapter);
1687956Sxiuyan.wang@Sun.COM 
1697956Sxiuyan.wang@Sun.COM 	return (result);
1707956Sxiuyan.wang@Sun.COM }
1717956Sxiuyan.wang@Sun.COM 
1727956Sxiuyan.wang@Sun.COM /*
1737956Sxiuyan.wang@Sun.COM  * Return the current station MAC address.
1747956Sxiuyan.wang@Sun.COM  * Note that the passed-in value must already be in network byte order.
1757956Sxiuyan.wang@Sun.COM  */
1767956Sxiuyan.wang@Sun.COM int
unm_niu_macaddr_get(struct unm_adapter_s * adapter,unsigned char * addr)1777956Sxiuyan.wang@Sun.COM unm_niu_macaddr_get(struct unm_adapter_s *adapter, unsigned char *addr)
1787956Sxiuyan.wang@Sun.COM {
1797956Sxiuyan.wang@Sun.COM 	__uint64_t result;
1807956Sxiuyan.wang@Sun.COM 	int phy = adapter->physical_port;
1817956Sxiuyan.wang@Sun.COM 
1827956Sxiuyan.wang@Sun.COM 	if (addr == NULL)
1837956Sxiuyan.wang@Sun.COM 		return (-1);
1847956Sxiuyan.wang@Sun.COM 	if ((phy < 0) || (phy > 3))
1857956Sxiuyan.wang@Sun.COM 		return (-1);
1867956Sxiuyan.wang@Sun.COM 
1877956Sxiuyan.wang@Sun.COM 	UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
1887956Sxiuyan.wang@Sun.COM 	if (adapter->curr_window != 0) {
1897956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_pci_change_crbwindow(adapter, 0);
1907956Sxiuyan.wang@Sun.COM 	}
1917956Sxiuyan.wang@Sun.COM 
1927956Sxiuyan.wang@Sun.COM 	result = UNM_NIC_PCI_READ_32((void *)pci_base_offset(adapter,
1937956Sxiuyan.wang@Sun.COM 	    UNM_NIU_GB_STATION_ADDR_1(phy))) >> 16;
1947956Sxiuyan.wang@Sun.COM 	result |= ((uint64_t)UNM_NIC_PCI_READ_32((void *)pci_base_offset(
1957956Sxiuyan.wang@Sun.COM 	    adapter, UNM_NIU_GB_STATION_ADDR_0(phy)))) << 16;
1967956Sxiuyan.wang@Sun.COM 
1977956Sxiuyan.wang@Sun.COM 	(void) memcpy(addr, &result, sizeof (unm_ethernet_macaddr_t));
1987956Sxiuyan.wang@Sun.COM 
1997956Sxiuyan.wang@Sun.COM 	adapter->unm_nic_pci_change_crbwindow(adapter, 1);
2007956Sxiuyan.wang@Sun.COM 
2017956Sxiuyan.wang@Sun.COM 	UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
2027956Sxiuyan.wang@Sun.COM 
2037956Sxiuyan.wang@Sun.COM 	return (0);
2047956Sxiuyan.wang@Sun.COM }
2057956Sxiuyan.wang@Sun.COM 
2067956Sxiuyan.wang@Sun.COM /*
2077956Sxiuyan.wang@Sun.COM  * Set the station MAC address.
2087956Sxiuyan.wang@Sun.COM  * Note that the passed-in value must already be in network byte order.
2097956Sxiuyan.wang@Sun.COM  */
2107956Sxiuyan.wang@Sun.COM int
unm_niu_macaddr_set(struct unm_adapter_s * adapter,unm_ethernet_macaddr_t addr)2117956Sxiuyan.wang@Sun.COM unm_niu_macaddr_set(struct unm_adapter_s *adapter, unm_ethernet_macaddr_t addr)
2127956Sxiuyan.wang@Sun.COM {
2137956Sxiuyan.wang@Sun.COM 	unm_crbword_t temp = 0;
2147956Sxiuyan.wang@Sun.COM 	int phy = adapter->physical_port;
2157956Sxiuyan.wang@Sun.COM 
2167956Sxiuyan.wang@Sun.COM 	if ((phy < 0) || (phy > 3))
2177956Sxiuyan.wang@Sun.COM 		return (-1);
2187956Sxiuyan.wang@Sun.COM 
2197956Sxiuyan.wang@Sun.COM 	(void) memcpy(&temp, addr, 2);
2207956Sxiuyan.wang@Sun.COM 	temp <<= 16;
2217956Sxiuyan.wang@Sun.COM 	adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_STATION_ADDR_1(phy),
2227956Sxiuyan.wang@Sun.COM 	    &temp, 4);
2237956Sxiuyan.wang@Sun.COM 	temp = 0;
2247956Sxiuyan.wang@Sun.COM 	(void) memcpy(&temp, ((__uint8_t *)addr)+2, sizeof (unm_crbword_t));
2257956Sxiuyan.wang@Sun.COM 	adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_STATION_ADDR_0(phy),
2267956Sxiuyan.wang@Sun.COM 	    &temp, 4);
2277956Sxiuyan.wang@Sun.COM 	return (0);
2287956Sxiuyan.wang@Sun.COM }
2297956Sxiuyan.wang@Sun.COM 
2307956Sxiuyan.wang@Sun.COM /* Enable a GbE interface */
2317956Sxiuyan.wang@Sun.COM /* ARGSUSED */
unm_niu_enable_gbe_port(struct unm_adapter_s * adapter,unm_niu_gbe_ifmode_t mode_dont_care)2327956Sxiuyan.wang@Sun.COM native_t unm_niu_enable_gbe_port(struct unm_adapter_s *adapter,
2337956Sxiuyan.wang@Sun.COM 		unm_niu_gbe_ifmode_t mode_dont_care)
2347956Sxiuyan.wang@Sun.COM {
2357956Sxiuyan.wang@Sun.COM 	unm_niu_gb_mac_config_0_t mac_cfg0;
2367956Sxiuyan.wang@Sun.COM 	unm_niu_gb_mac_config_1_t mac_cfg1;
2377956Sxiuyan.wang@Sun.COM 	unm_niu_gb_mii_mgmt_config_t mii_cfg;
2387956Sxiuyan.wang@Sun.COM 	native_t port = adapter->physical_port;
2397956Sxiuyan.wang@Sun.COM 	int zero = 0;
2407956Sxiuyan.wang@Sun.COM 	int one = 1;
2417956Sxiuyan.wang@Sun.COM 	u32 port_mode = 0;
2427956Sxiuyan.wang@Sun.COM 
2437956Sxiuyan.wang@Sun.COM 	mode_dont_care = 0;
2447956Sxiuyan.wang@Sun.COM 
2457956Sxiuyan.wang@Sun.COM 	if ((port < 0) || (port > UNM_NIU_MAX_GBE_PORTS)) {
2467956Sxiuyan.wang@Sun.COM 		return (-1);
2477956Sxiuyan.wang@Sun.COM 	}
2487956Sxiuyan.wang@Sun.COM 
2497956Sxiuyan.wang@Sun.COM 	if (adapter->link_speed != MBPS_10 &&
2507956Sxiuyan.wang@Sun.COM 	    adapter->link_speed != MBPS_100 &&
2517956Sxiuyan.wang@Sun.COM 	    adapter->link_speed != MBPS_1000) {
2527956Sxiuyan.wang@Sun.COM 
2537956Sxiuyan.wang@Sun.COM 		if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
2547956Sxiuyan.wang@Sun.COM /*
2557956Sxiuyan.wang@Sun.COM  * Do NOT fail this call because the cable is unplugged.
2567956Sxiuyan.wang@Sun.COM  * Updated when the link comes up...
2577956Sxiuyan.wang@Sun.COM  */
2587956Sxiuyan.wang@Sun.COM 		adapter->link_speed = MBPS_1000;
2597956Sxiuyan.wang@Sun.COM 		} else {
2607956Sxiuyan.wang@Sun.COM 			return (-1);
2617956Sxiuyan.wang@Sun.COM 		}
2627956Sxiuyan.wang@Sun.COM 	}
2637956Sxiuyan.wang@Sun.COM 
2647956Sxiuyan.wang@Sun.COM 	port_mode = adapter->unm_nic_pci_read_normalize(adapter,
2657956Sxiuyan.wang@Sun.COM 	    UNM_PORT_MODE_ADDR);
2667956Sxiuyan.wang@Sun.COM 	if (port_mode == UNM_PORT_MODE_802_3_AP) {
2677956Sxiuyan.wang@Sun.COM 		*(unm_crbword_t *)&mac_cfg0 = 0x0000003f;
2687956Sxiuyan.wang@Sun.COM 		*(unm_crbword_t *)&mac_cfg1 = 0x0000f2df;
2697956Sxiuyan.wang@Sun.COM 		unm_crb_write_adapter(UNM_NIU_AP_MAC_CONFIG_0(port), &mac_cfg0,
2707956Sxiuyan.wang@Sun.COM 		    adapter);
2717956Sxiuyan.wang@Sun.COM 		unm_crb_write_adapter(UNM_NIU_AP_MAC_CONFIG_1(port), &mac_cfg1,
2727956Sxiuyan.wang@Sun.COM 		    adapter);
2737956Sxiuyan.wang@Sun.COM 	} else {
2747956Sxiuyan.wang@Sun.COM 		*(unm_crbword_t *)&mac_cfg0 = 0;
2757956Sxiuyan.wang@Sun.COM 		mac_cfg0.soft_reset = 1;
2767956Sxiuyan.wang@Sun.COM 		unm_crb_write_adapter(UNM_NIU_GB_MAC_CONFIG_0(port), &mac_cfg0,
2777956Sxiuyan.wang@Sun.COM 		    adapter);
2787956Sxiuyan.wang@Sun.COM 
2797956Sxiuyan.wang@Sun.COM 		*(unm_crbword_t *)&mac_cfg0 = 0;
2807956Sxiuyan.wang@Sun.COM 		mac_cfg0.tx_enable = 1;
2817956Sxiuyan.wang@Sun.COM 		mac_cfg0.rx_enable = 1;
2827956Sxiuyan.wang@Sun.COM 		mac_cfg0.rx_flowctl = 0;
2837956Sxiuyan.wang@Sun.COM 		mac_cfg0.tx_reset_pb = 1;
2847956Sxiuyan.wang@Sun.COM 		mac_cfg0.rx_reset_pb = 1;
2857956Sxiuyan.wang@Sun.COM 		mac_cfg0.tx_reset_mac = 1;
2867956Sxiuyan.wang@Sun.COM 		mac_cfg0.rx_reset_mac = 1;
2877956Sxiuyan.wang@Sun.COM 
2887956Sxiuyan.wang@Sun.COM 		unm_crb_write_adapter(UNM_NIU_GB_MAC_CONFIG_0(port), &mac_cfg0,
2897956Sxiuyan.wang@Sun.COM 		    adapter);
2907956Sxiuyan.wang@Sun.COM 
2917956Sxiuyan.wang@Sun.COM 		*(unm_crbword_t *)&mac_cfg1 = 0;
2927956Sxiuyan.wang@Sun.COM 		mac_cfg1.preamblelen = 0xf;
2937956Sxiuyan.wang@Sun.COM 		mac_cfg1.duplex = 1;
2947956Sxiuyan.wang@Sun.COM 		mac_cfg1.crc_enable = 1;
2957956Sxiuyan.wang@Sun.COM 		mac_cfg1.padshort = 1;
2967956Sxiuyan.wang@Sun.COM 		mac_cfg1.checklength = 1;
2977956Sxiuyan.wang@Sun.COM 		mac_cfg1.hugeframes = 1;
2987956Sxiuyan.wang@Sun.COM 
2997956Sxiuyan.wang@Sun.COM 		switch (adapter->link_speed) {
3007956Sxiuyan.wang@Sun.COM 			case MBPS_10:
3017956Sxiuyan.wang@Sun.COM 			case MBPS_100: /* Fall Through */
3027956Sxiuyan.wang@Sun.COM 				mac_cfg1.intfmode = 1;
3037956Sxiuyan.wang@Sun.COM 				unm_crb_write_adapter(UNM_NIU_GB_MAC_CONFIG_1
3047956Sxiuyan.wang@Sun.COM 				    (port), &mac_cfg1, adapter);
3057956Sxiuyan.wang@Sun.COM 
3067956Sxiuyan.wang@Sun.COM 				/* set mii mode */
3077956Sxiuyan.wang@Sun.COM 				unm_crb_write_adapter(
3087956Sxiuyan.wang@Sun.COM 				    UNM_NIU_GB0_GMII_MODE+(port<<3),
3097956Sxiuyan.wang@Sun.COM 				    &zero, adapter);
3107956Sxiuyan.wang@Sun.COM 				unm_crb_write_adapter(
3117956Sxiuyan.wang@Sun.COM 				    UNM_NIU_GB0_MII_MODE+(port<< 3),
3127956Sxiuyan.wang@Sun.COM 				    &one, adapter);
3137956Sxiuyan.wang@Sun.COM 				break;
3147956Sxiuyan.wang@Sun.COM 
3157956Sxiuyan.wang@Sun.COM 			case MBPS_1000:
3167956Sxiuyan.wang@Sun.COM 				mac_cfg1.intfmode = 2;
3177956Sxiuyan.wang@Sun.COM 				unm_crb_write_adapter(
3187956Sxiuyan.wang@Sun.COM 				    UNM_NIU_GB_MAC_CONFIG_1(port),
3197956Sxiuyan.wang@Sun.COM 				    &mac_cfg1, adapter);
3207956Sxiuyan.wang@Sun.COM 
3217956Sxiuyan.wang@Sun.COM 				/* set gmii mode */
3227956Sxiuyan.wang@Sun.COM 				unm_crb_write_adapter(
3237956Sxiuyan.wang@Sun.COM 				    UNM_NIU_GB0_MII_MODE+(port << 3),
3247956Sxiuyan.wang@Sun.COM 				    &zero, adapter);
3257956Sxiuyan.wang@Sun.COM 				unm_crb_write_adapter(
3267956Sxiuyan.wang@Sun.COM 				    UNM_NIU_GB0_GMII_MODE+(port << 3),
3277956Sxiuyan.wang@Sun.COM 				    &one, adapter);
3287956Sxiuyan.wang@Sun.COM 				break;
3297956Sxiuyan.wang@Sun.COM 
3307956Sxiuyan.wang@Sun.COM 			default:
3317956Sxiuyan.wang@Sun.COM 				/* Will not happen */
3327956Sxiuyan.wang@Sun.COM 				break;
3337956Sxiuyan.wang@Sun.COM 		}
3347956Sxiuyan.wang@Sun.COM 
3357956Sxiuyan.wang@Sun.COM 		*(unm_crbword_t *)&mii_cfg = 0;
3367956Sxiuyan.wang@Sun.COM 		mii_cfg.clockselect = 7;
3377956Sxiuyan.wang@Sun.COM 		unm_crb_write_adapter(UNM_NIU_GB_MII_MGMT_CONFIG(port),
3387956Sxiuyan.wang@Sun.COM 		    &mii_cfg, adapter);
3397956Sxiuyan.wang@Sun.COM 
3407956Sxiuyan.wang@Sun.COM 		*(unm_crbword_t *)&mac_cfg0 = 0;
3417956Sxiuyan.wang@Sun.COM 		mac_cfg0.tx_enable = 1;
3427956Sxiuyan.wang@Sun.COM 		mac_cfg0.rx_enable = 1;
3437956Sxiuyan.wang@Sun.COM 		mac_cfg0.tx_flowctl = 0;
3447956Sxiuyan.wang@Sun.COM 		mac_cfg0.rx_flowctl = 0;
3457956Sxiuyan.wang@Sun.COM 		unm_crb_write_adapter(UNM_NIU_GB_MAC_CONFIG_0(port),
3467956Sxiuyan.wang@Sun.COM 		    &mac_cfg0, adapter);
3477956Sxiuyan.wang@Sun.COM 	}
3487956Sxiuyan.wang@Sun.COM 
3497956Sxiuyan.wang@Sun.COM 	return (0);
3507956Sxiuyan.wang@Sun.COM }
3517956Sxiuyan.wang@Sun.COM 
3527956Sxiuyan.wang@Sun.COM /* Disable a GbE interface */
3537956Sxiuyan.wang@Sun.COM native_t
unm_niu_disable_gbe_port(struct unm_adapter_s * adapter)3547956Sxiuyan.wang@Sun.COM unm_niu_disable_gbe_port(struct unm_adapter_s *adapter)
3557956Sxiuyan.wang@Sun.COM {
3567956Sxiuyan.wang@Sun.COM 	native_t			port = adapter->physical_port;
3577956Sxiuyan.wang@Sun.COM 	unm_niu_gb_mac_config_0_t	mac_cfg0;
3587956Sxiuyan.wang@Sun.COM 
3597956Sxiuyan.wang@Sun.COM 	if ((port < 0) || (port > UNM_NIU_MAX_GBE_PORTS))
3607956Sxiuyan.wang@Sun.COM 		return (-1);
3617956Sxiuyan.wang@Sun.COM 
3627956Sxiuyan.wang@Sun.COM 	*(unm_crbword_t *)&mac_cfg0 = 0;
3637956Sxiuyan.wang@Sun.COM 	mac_cfg0.soft_reset = 1;
3647956Sxiuyan.wang@Sun.COM 
3657956Sxiuyan.wang@Sun.COM 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
3667956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_write_wx(adapter,
3677956Sxiuyan.wang@Sun.COM 		    UNM_NIU_GB_MAC_CONFIG_0(port), &mac_cfg0, 0);
3687956Sxiuyan.wang@Sun.COM 	else
3697956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_write_wx(adapter,
3707956Sxiuyan.wang@Sun.COM 		    UNM_NIU_GB_MAC_CONFIG_0(port), &mac_cfg0, 4);
3717956Sxiuyan.wang@Sun.COM 	return (0);
3727956Sxiuyan.wang@Sun.COM }
3737956Sxiuyan.wang@Sun.COM 
3747956Sxiuyan.wang@Sun.COM /* Disable an XG interface */
3757956Sxiuyan.wang@Sun.COM native_t
unm_niu_disable_xg_port(struct unm_adapter_s * adapter)3767956Sxiuyan.wang@Sun.COM unm_niu_disable_xg_port(struct unm_adapter_s *adapter)
3777956Sxiuyan.wang@Sun.COM {
3787956Sxiuyan.wang@Sun.COM 	native_t			port = adapter->physical_port;
3797956Sxiuyan.wang@Sun.COM 	unm_niu_xg_mac_config_0_t	mac_cfg;
3807956Sxiuyan.wang@Sun.COM 
3817956Sxiuyan.wang@Sun.COM 	*(unm_crbword_t *)&mac_cfg = 0;
3827956Sxiuyan.wang@Sun.COM 	mac_cfg.soft_reset = 1;
3837956Sxiuyan.wang@Sun.COM 
3847956Sxiuyan.wang@Sun.COM 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
3857956Sxiuyan.wang@Sun.COM 		if (port != 0)
3867956Sxiuyan.wang@Sun.COM 			return (-1);
3877956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_XGE_CONFIG_0,
3887956Sxiuyan.wang@Sun.COM 		    &mac_cfg, 4);
3897956Sxiuyan.wang@Sun.COM 	} else {
3907956Sxiuyan.wang@Sun.COM 		if ((port < 0) || (port >= UNM_NIU_MAX_XG_PORTS))
3917956Sxiuyan.wang@Sun.COM 			return (-1);
3927956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_XGE_CONFIG_0 +
3937956Sxiuyan.wang@Sun.COM 		    (port * 0x10000), &mac_cfg, 4);
3947956Sxiuyan.wang@Sun.COM 	}
3957956Sxiuyan.wang@Sun.COM 	return (0);
3967956Sxiuyan.wang@Sun.COM }
3977956Sxiuyan.wang@Sun.COM 
3987956Sxiuyan.wang@Sun.COM 
3997956Sxiuyan.wang@Sun.COM /* Set promiscuous mode for a GbE interface */
4007956Sxiuyan.wang@Sun.COM native_t
unm_niu_set_promiscuous_mode(struct unm_adapter_s * adapter,unm_niu_prom_mode_t mode)4017956Sxiuyan.wang@Sun.COM unm_niu_set_promiscuous_mode(struct unm_adapter_s *adapter,
4027956Sxiuyan.wang@Sun.COM     unm_niu_prom_mode_t mode)
4037956Sxiuyan.wang@Sun.COM {
4047956Sxiuyan.wang@Sun.COM 	native_t port = adapter->physical_port;
4057956Sxiuyan.wang@Sun.COM 	unm_niu_gb_drop_crc_t reg;
4067956Sxiuyan.wang@Sun.COM 	unm_niu_gb_mac_config_0_t mac_cfg;
4077956Sxiuyan.wang@Sun.COM 	unm_crbword_t data;
4087956Sxiuyan.wang@Sun.COM 	int cnt = 0, ret = 0;
4097956Sxiuyan.wang@Sun.COM 	ulong_t val;
4107956Sxiuyan.wang@Sun.COM 
4117956Sxiuyan.wang@Sun.COM 	if ((port < 0) || (port > UNM_NIU_MAX_GBE_PORTS))
4127956Sxiuyan.wang@Sun.COM 		return (-1);
4137956Sxiuyan.wang@Sun.COM 
4147956Sxiuyan.wang@Sun.COM 	/* Turn off mac */
4157956Sxiuyan.wang@Sun.COM 	adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_GB_MAC_CONFIG_0(port),
4167956Sxiuyan.wang@Sun.COM 	    &mac_cfg, 4);
4177956Sxiuyan.wang@Sun.COM 	mac_cfg.rx_enable = 0;
4187956Sxiuyan.wang@Sun.COM 	adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_MAC_CONFIG_0(port),
4197956Sxiuyan.wang@Sun.COM 	    &mac_cfg, 4);
4207956Sxiuyan.wang@Sun.COM 
4217956Sxiuyan.wang@Sun.COM 	/* wait until mac is drained by sre */
4227956Sxiuyan.wang@Sun.COM 	/* Port 0 rx fifo bit 5 */
4237956Sxiuyan.wang@Sun.COM 	val = (0x20 << port);
4247956Sxiuyan.wang@Sun.COM 	adapter->unm_crb_writelit_adapter(adapter, UNM_NIU_FRAME_COUNT_SELECT,
4257956Sxiuyan.wang@Sun.COM 	    val);
4267956Sxiuyan.wang@Sun.COM 
4277956Sxiuyan.wang@Sun.COM 	do {
4287956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_FRAME_COUNT,
4297956Sxiuyan.wang@Sun.COM 		    &val, 4);
4307956Sxiuyan.wang@Sun.COM 		cnt++;
4317956Sxiuyan.wang@Sun.COM 		if (cnt > 2000) {
4327956Sxiuyan.wang@Sun.COM 			ret = -1;
4337956Sxiuyan.wang@Sun.COM 			break;
4347956Sxiuyan.wang@Sun.COM 		}
4357956Sxiuyan.wang@Sun.COM 		drv_usecwait(10);
4367956Sxiuyan.wang@Sun.COM 	} while (val);
4377956Sxiuyan.wang@Sun.COM 
4387956Sxiuyan.wang@Sun.COM 	/* now set promiscuous mode */
4397956Sxiuyan.wang@Sun.COM 	if (ret != -1) {
4407956Sxiuyan.wang@Sun.COM 		if (mode == UNM_NIU_PROMISCOUS_MODE)
4417956Sxiuyan.wang@Sun.COM 			data = 0;
4427956Sxiuyan.wang@Sun.COM 		else
4437956Sxiuyan.wang@Sun.COM 			data = 1;
4447956Sxiuyan.wang@Sun.COM 
4457956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_GB_DROP_WRONGADDR,
4467956Sxiuyan.wang@Sun.COM 		    &reg, 4);
4477956Sxiuyan.wang@Sun.COM 		switch (port) {
4487956Sxiuyan.wang@Sun.COM 		case 0:
4497956Sxiuyan.wang@Sun.COM 			reg.drop_gb0 = data;
4507956Sxiuyan.wang@Sun.COM 			break;
4517956Sxiuyan.wang@Sun.COM 		case 1:
4527956Sxiuyan.wang@Sun.COM 			reg.drop_gb1 = data;
4537956Sxiuyan.wang@Sun.COM 			break;
4547956Sxiuyan.wang@Sun.COM 		case 2:
4557956Sxiuyan.wang@Sun.COM 			reg.drop_gb2 = data;
4567956Sxiuyan.wang@Sun.COM 			break;
4577956Sxiuyan.wang@Sun.COM 		case 3:
4587956Sxiuyan.wang@Sun.COM 			reg.drop_gb3 = data;
4597956Sxiuyan.wang@Sun.COM 			break;
4607956Sxiuyan.wang@Sun.COM 		default:
4617956Sxiuyan.wang@Sun.COM 			ret  = -1;
4627956Sxiuyan.wang@Sun.COM 			break;
4637956Sxiuyan.wang@Sun.COM 		}
4647956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_DROP_WRONGADDR,
4657956Sxiuyan.wang@Sun.COM 		    &reg, 4);
4667956Sxiuyan.wang@Sun.COM 	}
4677956Sxiuyan.wang@Sun.COM 
4687956Sxiuyan.wang@Sun.COM 	/* turn the mac on back */
4697956Sxiuyan.wang@Sun.COM 	mac_cfg.rx_enable = 1;
4707956Sxiuyan.wang@Sun.COM 	adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_MAC_CONFIG_0(port),
4717956Sxiuyan.wang@Sun.COM 	    &mac_cfg, 4);
4727956Sxiuyan.wang@Sun.COM 
4737956Sxiuyan.wang@Sun.COM 	return (ret);
4747956Sxiuyan.wang@Sun.COM }
4757956Sxiuyan.wang@Sun.COM 
4767956Sxiuyan.wang@Sun.COM /*
4777956Sxiuyan.wang@Sun.COM  * Set the MAC address for an XG port
4787956Sxiuyan.wang@Sun.COM  * Note that the passed-in value must already be in network byte order.
4797956Sxiuyan.wang@Sun.COM  */
4807956Sxiuyan.wang@Sun.COM int
unm_niu_xg_macaddr_set(struct unm_adapter_s * adapter,unm_ethernet_macaddr_t addr)4817956Sxiuyan.wang@Sun.COM unm_niu_xg_macaddr_set(struct unm_adapter_s *adapter,
4827956Sxiuyan.wang@Sun.COM 		unm_ethernet_macaddr_t addr)
4837956Sxiuyan.wang@Sun.COM {
4847956Sxiuyan.wang@Sun.COM 	int		phy = adapter->physical_port;
4857956Sxiuyan.wang@Sun.COM 	unm_crbword_t	temp = 0;
4867956Sxiuyan.wang@Sun.COM 	u32		port_mode = 0;
4877956Sxiuyan.wang@Sun.COM 
4887956Sxiuyan.wang@Sun.COM 	if ((phy < 0) || (phy > 3))
4897956Sxiuyan.wang@Sun.COM 		return (-1);
4907956Sxiuyan.wang@Sun.COM 
4917956Sxiuyan.wang@Sun.COM 	switch (phy) {
4927956Sxiuyan.wang@Sun.COM 	case 0:
4937956Sxiuyan.wang@Sun.COM 		(void) memcpy(&temp, addr, 2);
4947956Sxiuyan.wang@Sun.COM 		temp <<= 16;
4957956Sxiuyan.wang@Sun.COM 		port_mode = adapter->unm_nic_pci_read_normalize(adapter,
4967956Sxiuyan.wang@Sun.COM 		    UNM_PORT_MODE_ADDR);
4977956Sxiuyan.wang@Sun.COM 		if (port_mode == UNM_PORT_MODE_802_3_AP) {
4987956Sxiuyan.wang@Sun.COM 			adapter->unm_nic_hw_write_wx(adapter,
4997956Sxiuyan.wang@Sun.COM 			    UNM_NIU_AP_STATION_ADDR_1(phy), &temp, 4);
5007956Sxiuyan.wang@Sun.COM 			temp = 0;
5017956Sxiuyan.wang@Sun.COM 			(void) memcpy(&temp, ((__uint8_t *)addr) + 2,
5027956Sxiuyan.wang@Sun.COM 			    sizeof (unm_crbword_t));
5037956Sxiuyan.wang@Sun.COM 			adapter->unm_nic_hw_write_wx(adapter,
5047956Sxiuyan.wang@Sun.COM 			    UNM_NIU_AP_STATION_ADDR_0(phy), &temp, 4);
5057956Sxiuyan.wang@Sun.COM 		} else {
5067956Sxiuyan.wang@Sun.COM 			adapter->unm_nic_hw_write_wx(adapter,
5077956Sxiuyan.wang@Sun.COM 			    UNM_NIU_XGE_STATION_ADDR_0_1, &temp, 4);
5087956Sxiuyan.wang@Sun.COM 			temp = 0;
5097956Sxiuyan.wang@Sun.COM 			(void) memcpy(&temp, ((__uint8_t *)addr) + 2,
5107956Sxiuyan.wang@Sun.COM 			    sizeof (unm_crbword_t));
5117956Sxiuyan.wang@Sun.COM 			adapter->unm_nic_hw_write_wx(adapter,
5127956Sxiuyan.wang@Sun.COM 			    UNM_NIU_XGE_STATION_ADDR_0_HI, &temp, 4);
5137956Sxiuyan.wang@Sun.COM 		}
5147956Sxiuyan.wang@Sun.COM 		break;
5157956Sxiuyan.wang@Sun.COM 
5167956Sxiuyan.wang@Sun.COM 	case 1:
5177956Sxiuyan.wang@Sun.COM 		(void) memcpy(&temp, addr, 2);
5187956Sxiuyan.wang@Sun.COM 		temp <<= 16;
5197956Sxiuyan.wang@Sun.COM 		port_mode = adapter->unm_nic_pci_read_normalize(adapter,
5207956Sxiuyan.wang@Sun.COM 		    UNM_PORT_MODE_ADDR);
5217956Sxiuyan.wang@Sun.COM 		if (port_mode == UNM_PORT_MODE_802_3_AP) {
5227956Sxiuyan.wang@Sun.COM 			adapter->unm_nic_hw_write_wx(adapter,
5237956Sxiuyan.wang@Sun.COM 			    UNM_NIU_AP_STATION_ADDR_1(phy), &temp, 4);
5247956Sxiuyan.wang@Sun.COM 			temp = 0;
5257956Sxiuyan.wang@Sun.COM 			(void) memcpy(&temp, ((__uint8_t *)addr) + 2,
5267956Sxiuyan.wang@Sun.COM 			    sizeof (unm_crbword_t));
5277956Sxiuyan.wang@Sun.COM 			adapter->unm_nic_hw_write_wx(adapter,
5287956Sxiuyan.wang@Sun.COM 			    UNM_NIU_AP_STATION_ADDR_0(phy), &temp, 4);
5297956Sxiuyan.wang@Sun.COM 		} else {
5307956Sxiuyan.wang@Sun.COM 			adapter->unm_nic_hw_write_wx(adapter,
5317956Sxiuyan.wang@Sun.COM 			    UNM_NIU_XGE_STATION_ADDR_0_1, &temp, 4);
5327956Sxiuyan.wang@Sun.COM 			temp = 0;
5337956Sxiuyan.wang@Sun.COM 			(void) memcpy(&temp, ((__uint8_t *)addr) + 2,
5347956Sxiuyan.wang@Sun.COM 			    sizeof (unm_crbword_t));
5357956Sxiuyan.wang@Sun.COM 			adapter->unm_nic_hw_write_wx(adapter,
5367956Sxiuyan.wang@Sun.COM 			    UNM_NIU_XGE_STATION_ADDR_0_HI, &temp, 4);
5377956Sxiuyan.wang@Sun.COM 		}
5387956Sxiuyan.wang@Sun.COM 		break;
5397956Sxiuyan.wang@Sun.COM 
5407956Sxiuyan.wang@Sun.COM 	default:
5417956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "Unknown port %d\n", phy);
5427956Sxiuyan.wang@Sun.COM 		return (DDI_FAILURE);
5437956Sxiuyan.wang@Sun.COM 	}
5447956Sxiuyan.wang@Sun.COM 
5457956Sxiuyan.wang@Sun.COM 	return (0);
5467956Sxiuyan.wang@Sun.COM }
5477956Sxiuyan.wang@Sun.COM 
5487956Sxiuyan.wang@Sun.COM native_t
unm_niu_xg_set_promiscuous_mode(struct unm_adapter_s * adapter,unm_niu_prom_mode_t mode)5497956Sxiuyan.wang@Sun.COM unm_niu_xg_set_promiscuous_mode(struct unm_adapter_s *adapter,
5507956Sxiuyan.wang@Sun.COM     unm_niu_prom_mode_t mode)
5517956Sxiuyan.wang@Sun.COM {
5527956Sxiuyan.wang@Sun.COM 	long  reg;
5537956Sxiuyan.wang@Sun.COM 	unm_niu_xg_mac_config_0_t mac_cfg;
5547956Sxiuyan.wang@Sun.COM 	native_t port = adapter->physical_port;
5557956Sxiuyan.wang@Sun.COM 	int cnt = 0;
5567956Sxiuyan.wang@Sun.COM 	int result = 0;
5577956Sxiuyan.wang@Sun.COM 	u32 port_mode = 0;
5587956Sxiuyan.wang@Sun.COM 
5597956Sxiuyan.wang@Sun.COM 	if ((port < 0) || (port > UNM_NIU_MAX_XG_PORTS))
5607956Sxiuyan.wang@Sun.COM 		return (-1);
5617956Sxiuyan.wang@Sun.COM 
5627956Sxiuyan.wang@Sun.COM 	port_mode = adapter->unm_nic_pci_read_normalize(adapter,
5637956Sxiuyan.wang@Sun.COM 	    UNM_PORT_MODE_ADDR);
5647956Sxiuyan.wang@Sun.COM 
5657956Sxiuyan.wang@Sun.COM 	if (port_mode == UNM_PORT_MODE_802_3_AP) {
5667956Sxiuyan.wang@Sun.COM 		reg = 0;
5677956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_write_wx(adapter,
5687956Sxiuyan.wang@Sun.COM 		    UNM_NIU_GB_DROP_WRONGADDR, (void*)&reg, 4);
5697956Sxiuyan.wang@Sun.COM 	} else {
5707956Sxiuyan.wang@Sun.COM 		/* Turn off mac */
5717956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_XGE_CONFIG_0 +
5727956Sxiuyan.wang@Sun.COM 		    (0x10000 * port), &mac_cfg, 4);
5737956Sxiuyan.wang@Sun.COM 		mac_cfg.rx_enable = 0;
5747956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_XGE_CONFIG_0 +
5757956Sxiuyan.wang@Sun.COM 		    (0x10000 * port), &mac_cfg, 4);
5767956Sxiuyan.wang@Sun.COM 
5777956Sxiuyan.wang@Sun.COM 		/* wait until mac is drained by sre */
5787956Sxiuyan.wang@Sun.COM 		if ((adapter->ahw.boardcfg.board_type !=
5797956Sxiuyan.wang@Sun.COM 		    UNM_BRDTYPE_P2_SB31_10G_IMEZ) &&
5807956Sxiuyan.wang@Sun.COM 		    (adapter->ahw.boardcfg.board_type !=
5817956Sxiuyan.wang@Sun.COM 		    UNM_BRDTYPE_P2_SB31_10G_HMEZ)) {
5827956Sxiuyan.wang@Sun.COM 			/* single port case bit 9 */
5837956Sxiuyan.wang@Sun.COM 			reg = 0x0200;
5847956Sxiuyan.wang@Sun.COM 			adapter->unm_crb_writelit_adapter(adapter,
5857956Sxiuyan.wang@Sun.COM 			    UNM_NIU_FRAME_COUNT_SELECT, reg);
5867956Sxiuyan.wang@Sun.COM 		} else {
5877956Sxiuyan.wang@Sun.COM 			/* Port 0 rx fifo bit 5 */
5887956Sxiuyan.wang@Sun.COM 			reg = (0x20 << port);
5897956Sxiuyan.wang@Sun.COM 			adapter->unm_crb_writelit_adapter(adapter,
5907956Sxiuyan.wang@Sun.COM 			    UNM_NIU_FRAME_COUNT_SELECT, reg);
5917956Sxiuyan.wang@Sun.COM 		}
5927956Sxiuyan.wang@Sun.COM 		do {
5937956Sxiuyan.wang@Sun.COM 			adapter->unm_nic_hw_read_wx(adapter,
5947956Sxiuyan.wang@Sun.COM 			    UNM_NIU_FRAME_COUNT, &reg, 4);
5957956Sxiuyan.wang@Sun.COM 			cnt++;
5967956Sxiuyan.wang@Sun.COM 			if (cnt > 2000) {
5977956Sxiuyan.wang@Sun.COM 				result = -1;
5987956Sxiuyan.wang@Sun.COM 				break;
5997956Sxiuyan.wang@Sun.COM 			}
6007956Sxiuyan.wang@Sun.COM 			drv_usecwait(10);
6017956Sxiuyan.wang@Sun.COM 		} while (reg);
6027956Sxiuyan.wang@Sun.COM 
6037956Sxiuyan.wang@Sun.COM 		/* now set promiscuous mode */
6047956Sxiuyan.wang@Sun.COM 		if (result != -1) {
6057956Sxiuyan.wang@Sun.COM 			adapter->unm_nic_hw_read_wx(adapter,
6067956Sxiuyan.wang@Sun.COM 			    UNM_NIU_XGE_CONFIG_1 + (0x10000 * port), &reg, 4);
6077956Sxiuyan.wang@Sun.COM 			if (mode == UNM_NIU_PROMISCOUS_MODE) {
6087956Sxiuyan.wang@Sun.COM 				reg = (reg | 0x2000UL);
6097956Sxiuyan.wang@Sun.COM 			} else { /* FIXME  use the correct mode value here */
6107956Sxiuyan.wang@Sun.COM 				reg = (reg & ~0x2000UL);
6117956Sxiuyan.wang@Sun.COM 			}
6127956Sxiuyan.wang@Sun.COM 			adapter->unm_crb_writelit_adapter(adapter,
6137956Sxiuyan.wang@Sun.COM 			    UNM_NIU_XGE_CONFIG_1 + (0x10000 * port), reg);
6147956Sxiuyan.wang@Sun.COM 		}
6157956Sxiuyan.wang@Sun.COM 
6167956Sxiuyan.wang@Sun.COM 		/* turn the mac back on */
6177956Sxiuyan.wang@Sun.COM 		mac_cfg.rx_enable = 1;
6187956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_XGE_CONFIG_0 +
6197956Sxiuyan.wang@Sun.COM 		    (0x10000 * port), &mac_cfg, 4);
6207956Sxiuyan.wang@Sun.COM 	}
6217956Sxiuyan.wang@Sun.COM 
6227956Sxiuyan.wang@Sun.COM 	return (result);
6237956Sxiuyan.wang@Sun.COM }
6247956Sxiuyan.wang@Sun.COM 
6257956Sxiuyan.wang@Sun.COM int
unm_niu_xg_set_tx_flow_ctl(struct unm_adapter_s * adapter,int enable)6267956Sxiuyan.wang@Sun.COM unm_niu_xg_set_tx_flow_ctl(struct unm_adapter_s *adapter, int enable)
6277956Sxiuyan.wang@Sun.COM {
6287956Sxiuyan.wang@Sun.COM 	int port = adapter->physical_port;
6297956Sxiuyan.wang@Sun.COM 	unm_niu_xg_pause_ctl_t reg;
6307956Sxiuyan.wang@Sun.COM 
6317956Sxiuyan.wang@Sun.COM 	if ((port < 0) || (port > UNM_NIU_MAX_XG_PORTS))
6327956Sxiuyan.wang@Sun.COM 		return (-1);
6337956Sxiuyan.wang@Sun.COM 
6347956Sxiuyan.wang@Sun.COM 	adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_XG_PAUSE_CTL, &reg, 4);
6357956Sxiuyan.wang@Sun.COM 	if (port == 0)
6367956Sxiuyan.wang@Sun.COM 		reg.xg0_mask = !enable;
6377956Sxiuyan.wang@Sun.COM 	else
6387956Sxiuyan.wang@Sun.COM 		reg.xg1_mask = !enable;
6397956Sxiuyan.wang@Sun.COM 
6407956Sxiuyan.wang@Sun.COM 	adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_XG_PAUSE_CTL, &reg, 4);
6417956Sxiuyan.wang@Sun.COM 
6427956Sxiuyan.wang@Sun.COM 	return (0);
6437956Sxiuyan.wang@Sun.COM }
6447956Sxiuyan.wang@Sun.COM 
6457956Sxiuyan.wang@Sun.COM int
unm_niu_gbe_set_tx_flow_ctl(struct unm_adapter_s * adapter,int enable)6467956Sxiuyan.wang@Sun.COM unm_niu_gbe_set_tx_flow_ctl(struct unm_adapter_s *adapter, int enable)
6477956Sxiuyan.wang@Sun.COM {
6487956Sxiuyan.wang@Sun.COM 	int port = adapter->physical_port;
6497956Sxiuyan.wang@Sun.COM 	unm_niu_gb_pause_ctl_t reg;
6507956Sxiuyan.wang@Sun.COM 
6517956Sxiuyan.wang@Sun.COM 	if ((port < 0) || (port > UNM_NIU_MAX_GBE_PORTS))
6527956Sxiuyan.wang@Sun.COM 		return (-1);
6537956Sxiuyan.wang@Sun.COM 
6547956Sxiuyan.wang@Sun.COM 	adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_GB_PAUSE_CTL, &reg, 4);
6557956Sxiuyan.wang@Sun.COM 	switch (port) {
6567956Sxiuyan.wang@Sun.COM 	case (0):
6577956Sxiuyan.wang@Sun.COM 		reg.gb0_mask = !enable;
6587956Sxiuyan.wang@Sun.COM 		break;
6597956Sxiuyan.wang@Sun.COM 	case (1):
6607956Sxiuyan.wang@Sun.COM 		reg.gb1_mask = !enable;
6617956Sxiuyan.wang@Sun.COM 		break;
6627956Sxiuyan.wang@Sun.COM 	case (2):
6637956Sxiuyan.wang@Sun.COM 		reg.gb2_mask = !enable;
6647956Sxiuyan.wang@Sun.COM 		break;
6657956Sxiuyan.wang@Sun.COM 	case (3):
6667956Sxiuyan.wang@Sun.COM 	default:
6677956Sxiuyan.wang@Sun.COM 		reg.gb3_mask = !enable;
6687956Sxiuyan.wang@Sun.COM 		break;
6697956Sxiuyan.wang@Sun.COM 	}
6707956Sxiuyan.wang@Sun.COM 	adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_PAUSE_CTL, &reg, 4);
6717956Sxiuyan.wang@Sun.COM 
6727956Sxiuyan.wang@Sun.COM 	return (0);
6737956Sxiuyan.wang@Sun.COM }
6747956Sxiuyan.wang@Sun.COM 
6757956Sxiuyan.wang@Sun.COM int
unm_niu_gbe_set_rx_flow_ctl(struct unm_adapter_s * adapter,int enable)6767956Sxiuyan.wang@Sun.COM unm_niu_gbe_set_rx_flow_ctl(struct unm_adapter_s *adapter, int enable)
6777956Sxiuyan.wang@Sun.COM {
6787956Sxiuyan.wang@Sun.COM 	int port = adapter->physical_port;
6797956Sxiuyan.wang@Sun.COM 	unm_niu_gb_mac_config_0_t reg;
6807956Sxiuyan.wang@Sun.COM 
6817956Sxiuyan.wang@Sun.COM 	if ((port < 0) || (port > UNM_NIU_MAX_GBE_PORTS))
6827956Sxiuyan.wang@Sun.COM 		return (-1);
6837956Sxiuyan.wang@Sun.COM 
6847956Sxiuyan.wang@Sun.COM 	adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_GB_MAC_CONFIG_0(port),
6857956Sxiuyan.wang@Sun.COM 	    &reg, 4);
6867956Sxiuyan.wang@Sun.COM 	reg.rx_flowctl = enable;
6877956Sxiuyan.wang@Sun.COM 	adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_MAC_CONFIG_0(port),
6887956Sxiuyan.wang@Sun.COM 	    &reg, 4);
6897956Sxiuyan.wang@Sun.COM 
6907956Sxiuyan.wang@Sun.COM 	return (0);
6917956Sxiuyan.wang@Sun.COM }
692