xref: /onnv-gate/usr/src/uts/common/io/nge/nge_chip.c (revision 10615:4bb212e117c7)
15578Smx205022 /*
25578Smx205022  * CDDL HEADER START
35578Smx205022  *
45578Smx205022  * The contents of this file are subject to the terms of the
55578Smx205022  * Common Development and Distribution License (the "License").
65578Smx205022  * You may not use this file except in compliance with the License.
75578Smx205022  *
85578Smx205022  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95578Smx205022  * or http://www.opensolaris.org/os/licensing.
105578Smx205022  * See the License for the specific language governing permissions
115578Smx205022  * and limitations under the License.
125578Smx205022  *
135578Smx205022  * When distributing Covered Code, include this CDDL HEADER in each
145578Smx205022  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155578Smx205022  * If applicable, add the following below this CDDL HEADER, with the
165578Smx205022  * fields enclosed by brackets "[]" replaced with your own identifying
175578Smx205022  * information: Portions Copyright [yyyy] [name of copyright owner]
185578Smx205022  *
195578Smx205022  * CDDL HEADER END
205578Smx205022  */
215578Smx205022 
225574Smx205022 /*
239604SZhen.W@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
245574Smx205022  * Use is subject to license terms.
255574Smx205022  */
265574Smx205022 
275574Smx205022 #include "nge.h"
28*10615SZhen.W@Sun.COM static uint32_t	nge_watchdog_count	= 1 << 5;
29*10615SZhen.W@Sun.COM static uint32_t	nge_watchdog_check	= 1 << 3;
305574Smx205022 extern boolean_t nge_enable_msi;
315574Smx205022 static void nge_sync_mac_modes(nge_t *);
325574Smx205022 
335574Smx205022 #undef NGE_DBG
345574Smx205022 #define	NGE_DBG		NGE_DBG_CHIP
355574Smx205022 
365574Smx205022 /*
375574Smx205022  * Operating register get/set access routines
385574Smx205022  */
395574Smx205022 uint8_t nge_reg_get8(nge_t *ngep, nge_regno_t regno);
405574Smx205022 #pragma	inline(nge_reg_get8)
415574Smx205022 
425574Smx205022 uint8_t
nge_reg_get8(nge_t * ngep,nge_regno_t regno)435574Smx205022 nge_reg_get8(nge_t *ngep, nge_regno_t regno)
445574Smx205022 {
455574Smx205022 	NGE_TRACE(("nge_reg_get8($%p, 0x%lx)", (void *)ngep, regno));
465574Smx205022 
475574Smx205022 	return (ddi_get8(ngep->io_handle, PIO_ADDR(ngep, regno)));
485574Smx205022 }
495574Smx205022 
505574Smx205022 void nge_reg_put8(nge_t *ngep, nge_regno_t regno, uint8_t data);
515574Smx205022 #pragma	inline(nge_reg_put8)
525574Smx205022 
535574Smx205022 void
nge_reg_put8(nge_t * ngep,nge_regno_t regno,uint8_t data)545574Smx205022 nge_reg_put8(nge_t *ngep, nge_regno_t regno, uint8_t data)
555574Smx205022 {
565574Smx205022 	NGE_TRACE(("nge_reg_put8($%p, 0x%lx, 0x%x)",
575574Smx205022 	    (void *)ngep, regno, data));
585574Smx205022 	ddi_put8(ngep->io_handle, PIO_ADDR(ngep, regno), data);
595574Smx205022 
605574Smx205022 }
615574Smx205022 
625574Smx205022 uint16_t nge_reg_get16(nge_t *ngep, nge_regno_t regno);
635574Smx205022 #pragma	inline(nge_reg_get16)
645574Smx205022 
655574Smx205022 uint16_t
nge_reg_get16(nge_t * ngep,nge_regno_t regno)665574Smx205022 nge_reg_get16(nge_t *ngep, nge_regno_t regno)
675574Smx205022 {
685574Smx205022 	NGE_TRACE(("nge_reg_get16($%p, 0x%lx)", (void *)ngep, regno));
695574Smx205022 	return (ddi_get16(ngep->io_handle, PIO_ADDR(ngep, regno)));
705574Smx205022 }
715574Smx205022 
725574Smx205022 void nge_reg_put16(nge_t *ngep, nge_regno_t regno, uint16_t data);
735574Smx205022 #pragma	inline(nge_reg_put16)
745574Smx205022 
755574Smx205022 void
nge_reg_put16(nge_t * ngep,nge_regno_t regno,uint16_t data)765574Smx205022 nge_reg_put16(nge_t *ngep, nge_regno_t regno, uint16_t data)
775574Smx205022 {
785574Smx205022 	NGE_TRACE(("nge_reg_put16($%p, 0x%lx, 0x%x)",
795574Smx205022 	    (void *)ngep, regno, data));
805574Smx205022 	ddi_put16(ngep->io_handle, PIO_ADDR(ngep, regno), data);
815574Smx205022 
825574Smx205022 }
835574Smx205022 
845574Smx205022 uint32_t nge_reg_get32(nge_t *ngep, nge_regno_t regno);
855574Smx205022 #pragma	inline(nge_reg_get32)
865574Smx205022 
875574Smx205022 uint32_t
nge_reg_get32(nge_t * ngep,nge_regno_t regno)885574Smx205022 nge_reg_get32(nge_t *ngep, nge_regno_t regno)
895574Smx205022 {
905574Smx205022 	NGE_TRACE(("nge_reg_get32($%p, 0x%lx)", (void *)ngep, regno));
915574Smx205022 	return (ddi_get32(ngep->io_handle, PIO_ADDR(ngep, regno)));
925574Smx205022 }
935574Smx205022 
945574Smx205022 void nge_reg_put32(nge_t *ngep, nge_regno_t regno, uint32_t data);
955574Smx205022 #pragma	inline(nge_reg_put32)
965574Smx205022 
975574Smx205022 void
nge_reg_put32(nge_t * ngep,nge_regno_t regno,uint32_t data)985574Smx205022 nge_reg_put32(nge_t *ngep, nge_regno_t regno, uint32_t data)
995574Smx205022 {
1005574Smx205022 	NGE_TRACE(("nge_reg_put32($%p, 0x%lx, 0x%x)",
1015574Smx205022 	    (void *)ngep, regno, data));
1025574Smx205022 	ddi_put32(ngep->io_handle, PIO_ADDR(ngep, regno), data);
1035574Smx205022 
1045574Smx205022 }
1055574Smx205022 
1065574Smx205022 
1075574Smx205022 static int nge_chip_peek_cfg(nge_t *ngep, nge_peekpoke_t *ppd);
1085574Smx205022 #pragma	no_inline(nge_chip_peek_cfg)
1095574Smx205022 
1105574Smx205022 static int
nge_chip_peek_cfg(nge_t * ngep,nge_peekpoke_t * ppd)1115574Smx205022 nge_chip_peek_cfg(nge_t *ngep, nge_peekpoke_t *ppd)
1125574Smx205022 {
1135574Smx205022 	int err;
1145574Smx205022 	uint64_t regval;
1155574Smx205022 	uint64_t regno;
1165574Smx205022 
1175574Smx205022 	NGE_TRACE(("nge_chip_peek_cfg($%p, $%p)",
1185574Smx205022 	    (void *)ngep, (void *)ppd));
1195574Smx205022 
1205574Smx205022 	err = DDI_SUCCESS;
1215574Smx205022 	regno = ppd->pp_acc_offset;
1225574Smx205022 
1235574Smx205022 	switch (ppd->pp_acc_size) {
1245574Smx205022 	case 1:
1255574Smx205022 		regval = pci_config_get8(ngep->cfg_handle, regno);
1265574Smx205022 		break;
1275574Smx205022 
1285574Smx205022 	case 2:
1295574Smx205022 		regval = pci_config_get16(ngep->cfg_handle, regno);
1305574Smx205022 		break;
1315574Smx205022 
1325574Smx205022 	case 4:
1335574Smx205022 		regval = pci_config_get32(ngep->cfg_handle, regno);
1345574Smx205022 		break;
1355574Smx205022 
1365574Smx205022 	case 8:
1375574Smx205022 		regval = pci_config_get64(ngep->cfg_handle, regno);
1385574Smx205022 		break;
1395574Smx205022 	}
1405574Smx205022 	ppd->pp_acc_data = regval;
1415574Smx205022 	return (err);
1425574Smx205022 }
1435574Smx205022 
1445574Smx205022 static int nge_chip_poke_cfg(nge_t *ngep, nge_peekpoke_t *ppd);
1455574Smx205022 
1465574Smx205022 static int
nge_chip_poke_cfg(nge_t * ngep,nge_peekpoke_t * ppd)1475574Smx205022 nge_chip_poke_cfg(nge_t *ngep, nge_peekpoke_t *ppd)
1485574Smx205022 {
1495574Smx205022 	int err;
1505574Smx205022 	uint64_t regval;
1515574Smx205022 	uint64_t regno;
1525574Smx205022 
1535574Smx205022 	NGE_TRACE(("nge_chip_poke_cfg($%p, $%p)",
1545574Smx205022 	    (void *)ngep, (void *)ppd));
1555574Smx205022 
1565574Smx205022 	err = DDI_SUCCESS;
1575574Smx205022 	regno = ppd->pp_acc_offset;
1585574Smx205022 	regval = ppd->pp_acc_data;
1595574Smx205022 
1605574Smx205022 	switch (ppd->pp_acc_size) {
1615574Smx205022 	case 1:
1625574Smx205022 		pci_config_put8(ngep->cfg_handle, regno, regval);
1635574Smx205022 		break;
1645574Smx205022 
1655574Smx205022 	case 2:
1665574Smx205022 		pci_config_put16(ngep->cfg_handle, regno, regval);
1675574Smx205022 		break;
1685574Smx205022 
1695574Smx205022 	case 4:
1705574Smx205022 		pci_config_put32(ngep->cfg_handle, regno, regval);
1715574Smx205022 		break;
1725574Smx205022 
1735574Smx205022 	case 8:
1745574Smx205022 		pci_config_put64(ngep->cfg_handle, regno, regval);
1755574Smx205022 		break;
1765574Smx205022 	}
1775574Smx205022 
1785574Smx205022 	return (err);
1795574Smx205022 
1805574Smx205022 }
1815574Smx205022 
1825574Smx205022 static int nge_chip_peek_reg(nge_t *ngep, nge_peekpoke_t *ppd);
1835574Smx205022 
1845574Smx205022 static int
nge_chip_peek_reg(nge_t * ngep,nge_peekpoke_t * ppd)1855574Smx205022 nge_chip_peek_reg(nge_t *ngep, nge_peekpoke_t *ppd)
1865574Smx205022 {
1875574Smx205022 	int err;
1885574Smx205022 	uint64_t regval;
1895574Smx205022 	void *regaddr;
1905574Smx205022 
1915574Smx205022 	NGE_TRACE(("nge_chip_peek_reg($%p, $%p)",
1925574Smx205022 	    (void *)ngep, (void *)ppd));
1935574Smx205022 
1945574Smx205022 	err = DDI_SUCCESS;
1955574Smx205022 	regaddr = PIO_ADDR(ngep, ppd->pp_acc_offset);
1965574Smx205022 
1975574Smx205022 	switch (ppd->pp_acc_size) {
1985574Smx205022 	case 1:
1995574Smx205022 		regval = ddi_get8(ngep->io_handle, regaddr);
2005574Smx205022 	break;
2015574Smx205022 
2025574Smx205022 	case 2:
2035574Smx205022 		regval = ddi_get16(ngep->io_handle, regaddr);
2045574Smx205022 	break;
2055574Smx205022 
2065574Smx205022 	case 4:
2075574Smx205022 		regval = ddi_get32(ngep->io_handle, regaddr);
2085574Smx205022 	break;
2095574Smx205022 
2105574Smx205022 	case 8:
2115574Smx205022 		regval = ddi_get64(ngep->io_handle, regaddr);
2125574Smx205022 	break;
2135574Smx205022 
2145574Smx205022 	default:
2155574Smx205022 		regval = 0x0ull;
2165574Smx205022 	break;
2175574Smx205022 	}
2185574Smx205022 	ppd->pp_acc_data = regval;
2195574Smx205022 	return (err);
2205574Smx205022 }
2215574Smx205022 
2225574Smx205022 static int nge_chip_poke_reg(nge_t *ngep, nge_peekpoke_t *ppd);
2235574Smx205022 
2245574Smx205022 static int
nge_chip_poke_reg(nge_t * ngep,nge_peekpoke_t * ppd)2255574Smx205022 nge_chip_poke_reg(nge_t *ngep, nge_peekpoke_t *ppd)
2265574Smx205022 {
2275574Smx205022 	int err;
2285574Smx205022 	uint64_t regval;
2295574Smx205022 	void *regaddr;
2305574Smx205022 
2315574Smx205022 	NGE_TRACE(("nge_chip_poke_reg($%p, $%p)",
2325574Smx205022 	    (void *)ngep, (void *)ppd));
2335574Smx205022 
2345574Smx205022 	err = DDI_SUCCESS;
2355574Smx205022 	regaddr = PIO_ADDR(ngep, ppd->pp_acc_offset);
2365574Smx205022 	regval = ppd->pp_acc_data;
2375574Smx205022 
2385574Smx205022 	switch (ppd->pp_acc_size) {
2395574Smx205022 	case 1:
2405574Smx205022 		ddi_put8(ngep->io_handle, regaddr, regval);
2415574Smx205022 		break;
2425574Smx205022 
2435574Smx205022 	case 2:
2445574Smx205022 		ddi_put16(ngep->io_handle, regaddr, regval);
2455574Smx205022 		break;
2465574Smx205022 
2475574Smx205022 	case 4:
2485574Smx205022 		ddi_put32(ngep->io_handle, regaddr, regval);
2495574Smx205022 		break;
2505574Smx205022 
2515574Smx205022 	case 8:
2525574Smx205022 		ddi_put64(ngep->io_handle, regaddr, regval);
2535574Smx205022 		break;
2545574Smx205022 	}
2555574Smx205022 	return (err);
2565574Smx205022 }
2575574Smx205022 
2585574Smx205022 static int nge_chip_peek_mii(nge_t *ngep, nge_peekpoke_t *ppd);
2595574Smx205022 #pragma	no_inline(nge_chip_peek_mii)
2605574Smx205022 
2615574Smx205022 static int
nge_chip_peek_mii(nge_t * ngep,nge_peekpoke_t * ppd)2625574Smx205022 nge_chip_peek_mii(nge_t *ngep, nge_peekpoke_t *ppd)
2635574Smx205022 {
2645574Smx205022 	int err;
2655574Smx205022 
2665574Smx205022 	err = DDI_SUCCESS;
2675574Smx205022 	ppd->pp_acc_data = nge_mii_get16(ngep, ppd->pp_acc_offset/2);
2685574Smx205022 	return (err);
2695574Smx205022 }
2705574Smx205022 
2715574Smx205022 static int nge_chip_poke_mii(nge_t *ngep, nge_peekpoke_t *ppd);
2725574Smx205022 #pragma	no_inline(nge_chip_poke_mii)
2735574Smx205022 
2745574Smx205022 static int
nge_chip_poke_mii(nge_t * ngep,nge_peekpoke_t * ppd)2755574Smx205022 nge_chip_poke_mii(nge_t *ngep, nge_peekpoke_t *ppd)
2765574Smx205022 {
2775574Smx205022 	int err;
2785574Smx205022 	err = DDI_SUCCESS;
2795574Smx205022 	nge_mii_put16(ngep, ppd->pp_acc_offset/2, ppd->pp_acc_data);
2805574Smx205022 	return (err);
2815574Smx205022 }
2825574Smx205022 
2835574Smx205022 /*
2845574Smx205022  * Basic SEEPROM get/set access routine
2855574Smx205022  *
2865574Smx205022  * This uses the chip's SEEPROM auto-access method, controlled by the
2875574Smx205022  * Serial EEPROM Address/Data Registers at 0x504h, so the CPU
2885574Smx205022  * doesn't have to fiddle with the individual bits.
2895574Smx205022  *
2905574Smx205022  * The caller should hold <genlock> and *also* have already acquired
2915574Smx205022  * the right to access the SEEPROM.
2925574Smx205022  *
2935574Smx205022  * Return value:
2945574Smx205022  *	0 on success,
2955574Smx205022  *	ENODATA on access timeout (maybe retryable: device may just be busy)
2965574Smx205022  *	EPROTO on other h/w or s/w errors.
2975574Smx205022  *
2985574Smx205022  * <*dp> is an input to a SEEPROM_ACCESS_WRITE operation, or an output
2995574Smx205022  * from a (successful) SEEPROM_ACCESS_READ.
3005574Smx205022  */
3015574Smx205022 
3025574Smx205022 static int
nge_seeprom_access(nge_t * ngep,uint32_t cmd,nge_regno_t addr,uint16_t * dp)3035574Smx205022 nge_seeprom_access(nge_t *ngep, uint32_t cmd, nge_regno_t addr, uint16_t *dp)
3045574Smx205022 {
3055574Smx205022 	uint32_t tries;
3065574Smx205022 	nge_ep_cmd cmd_reg;
3075574Smx205022 	nge_ep_data data_reg;
3085574Smx205022 
3095574Smx205022 	NGE_TRACE(("nge_seeprom_access($%p, %d, %x, $%p)",
3105574Smx205022 	    (void *)ngep, cmd, addr, (void *)dp));
3115574Smx205022 
3125574Smx205022 	ASSERT(mutex_owned(ngep->genlock));
3135574Smx205022 
3145574Smx205022 	/*
3155574Smx205022 	 * Check there's no command in progress.
3165574Smx205022 	 *
3175574Smx205022 	 * Note: this *shouldn't* ever find that there is a command
3185574Smx205022 	 * in progress, because we already hold the <genlock> mutex.
3195574Smx205022 	 * Also, to ensure we don't have a conflict with the chip's
3205574Smx205022 	 * internal firmware or a process accessing the same (shared)
3215574Smx205022 	 * So this is just a final consistency check: we shouldn't
3225574Smx205022 	 * see EITHER the START bit (command started but not complete)
3235574Smx205022 	 * OR the COMPLETE bit (command completed but not cleared).
3245574Smx205022 	 */
3255574Smx205022 	cmd_reg.cmd_val = nge_reg_get32(ngep, NGE_EP_CMD);
3265574Smx205022 	for (tries = 0; tries < 30; tries++) {
3275574Smx205022 		if (cmd_reg.cmd_bits.sts == SEEPROM_READY)
3285574Smx205022 			break;
3295574Smx205022 		drv_usecwait(10);
3305574Smx205022 		cmd_reg.cmd_val = nge_reg_get32(ngep, NGE_EP_CMD);
3315574Smx205022 	}
3325574Smx205022 
3335574Smx205022 	/*
3345574Smx205022 	 * This should not happen. If so, we have to restart eeprom
3355574Smx205022 	 *  state machine
3365574Smx205022 	 */
3375574Smx205022 	if (tries == 30) {
3385574Smx205022 		cmd_reg.cmd_bits.sts = SEEPROM_READY;
3395574Smx205022 		nge_reg_put32(ngep, NGE_EP_CMD, cmd_reg.cmd_val);
3405574Smx205022 		drv_usecwait(10);
3415574Smx205022 		/*
3425574Smx205022 		 * Polling the status bit to make assure the eeprom is ready
3435574Smx205022 		 */
3445574Smx205022 		cmd_reg.cmd_val = nge_reg_get32(ngep, NGE_EP_CMD);
3455574Smx205022 		for (tries = 0; tries < 30; tries++) {
3465574Smx205022 			if (cmd_reg.cmd_bits.sts == SEEPROM_READY)
3475574Smx205022 				break;
3485574Smx205022 			drv_usecwait(10);
3495574Smx205022 			cmd_reg.cmd_val = nge_reg_get32(ngep, NGE_EP_CMD);
3505574Smx205022 		}
3515574Smx205022 	}
3525574Smx205022 
3535574Smx205022 	/*
3545574Smx205022 	 * Assemble the command ...
3555574Smx205022 	 */
3567781SMin.Xu@Sun.COM 	cmd_reg.cmd_bits.addr = (uint32_t)addr;
3575574Smx205022 	cmd_reg.cmd_bits.cmd = cmd;
3585574Smx205022 	cmd_reg.cmd_bits.sts = 0;
3595574Smx205022 
3605574Smx205022 	nge_reg_put32(ngep, NGE_EP_CMD, cmd_reg.cmd_val);
3615574Smx205022 
3625574Smx205022 	/*
3635574Smx205022 	 * Polling whether the access is successful.
3645574Smx205022 	 *
3655574Smx205022 	 */
3665574Smx205022 	cmd_reg.cmd_val = nge_reg_get32(ngep, NGE_EP_CMD);
3675574Smx205022 	for (tries = 0; tries < 30; tries++) {
3685574Smx205022 		if (cmd_reg.cmd_bits.sts == SEEPROM_READY)
3695574Smx205022 			break;
3705574Smx205022 		drv_usecwait(10);
3715574Smx205022 		cmd_reg.cmd_val = nge_reg_get32(ngep, NGE_EP_CMD);
3725574Smx205022 	}
3735574Smx205022 
3745574Smx205022 	if (tries == 30) {
3755574Smx205022 		nge_report(ngep, NGE_HW_ROM);
3765574Smx205022 		return (DDI_FAILURE);
3775574Smx205022 	}
3785574Smx205022 	switch (cmd) {
3795574Smx205022 	default:
3805574Smx205022 	case SEEPROM_CMD_WRITE_ENABLE:
3815574Smx205022 	case SEEPROM_CMD_ERASE:
3825574Smx205022 	case SEEPROM_CMD_ERALSE_ALL:
3835574Smx205022 	case SEEPROM_CMD_WRITE_DIS:
3845574Smx205022 	break;
3855574Smx205022 
3865574Smx205022 	case SEEPROM_CMD_READ:
3875574Smx205022 		data_reg.data_val = nge_reg_get32(ngep, NGE_EP_DATA);
3885574Smx205022 		*dp = data_reg.data_bits.data;
3895574Smx205022 	break;
3905574Smx205022 
3915574Smx205022 	case SEEPROM_CMD_WRITE:
3925574Smx205022 		data_reg.data_val = nge_reg_get32(ngep, NGE_EP_DATA);
3935574Smx205022 		data_reg.data_bits.data = *dp;
3945574Smx205022 		nge_reg_put32(ngep, NGE_EP_DATA, data_reg.data_val);
3955574Smx205022 	break;
3965574Smx205022 	}
3975574Smx205022 
3985574Smx205022 	return (DDI_SUCCESS);
3995574Smx205022 }
4005574Smx205022 
4015574Smx205022 
4025574Smx205022 static int
nge_chip_peek_seeprom(nge_t * ngep,nge_peekpoke_t * ppd)4035574Smx205022 nge_chip_peek_seeprom(nge_t *ngep, nge_peekpoke_t *ppd)
4045574Smx205022 {
4055574Smx205022 	uint16_t data;
4065574Smx205022 	int err;
4075574Smx205022 
4085574Smx205022 	err = nge_seeprom_access(ngep, SEEPROM_CMD_READ,
4095574Smx205022 	    ppd->pp_acc_offset, &data);
4105574Smx205022 	ppd->pp_acc_data =  data;
4115574Smx205022 	return (err);
4125574Smx205022 }
4135574Smx205022 
4145574Smx205022 static int
nge_chip_poke_seeprom(nge_t * ngep,nge_peekpoke_t * ppd)4155574Smx205022 nge_chip_poke_seeprom(nge_t *ngep, nge_peekpoke_t *ppd)
4165574Smx205022 {
4175574Smx205022 	uint16_t data;
4185574Smx205022 	int err;
4195574Smx205022 
4205574Smx205022 	data = ppd->pp_acc_data;
4215574Smx205022 	err = nge_seeprom_access(ngep, SEEPROM_CMD_WRITE,
4225574Smx205022 	    ppd->pp_acc_offset, &data);
4235574Smx205022 	return (err);
4245574Smx205022 }
4255574Smx205022 
4265574Smx205022 void
nge_init_dev_spec_param(nge_t * ngep)4275574Smx205022 nge_init_dev_spec_param(nge_t *ngep)
4285574Smx205022 {
4295574Smx205022 	nge_dev_spec_param_t	*dev_param_p;
4305574Smx205022 	chip_info_t	*infop;
4315574Smx205022 
4325574Smx205022 	dev_param_p = &ngep->dev_spec_param;
4335574Smx205022 	infop = (chip_info_t *)&ngep->chipinfo;
4345574Smx205022 
4355574Smx205022 	switch (infop->device) {
4365574Smx205022 	case DEVICE_ID_NF3_E6:
4375574Smx205022 	case DEVICE_ID_NF3_DF:
4385574Smx205022 	case DEVICE_ID_MCP04_37:
4395574Smx205022 	case DEVICE_ID_MCP04_38:
4405574Smx205022 		dev_param_p->msi = B_FALSE;
4415574Smx205022 		dev_param_p->msi_x = B_FALSE;
4425574Smx205022 		dev_param_p->vlan = B_FALSE;
4435848Sjj146644 		dev_param_p->advanced_pm = B_FALSE;
4448218SMin.Xu@Sun.COM 		dev_param_p->mac_addr_order = B_FALSE;
4455574Smx205022 		dev_param_p->tx_pause_frame = B_FALSE;
4465574Smx205022 		dev_param_p->rx_pause_frame = B_FALSE;
4475574Smx205022 		dev_param_p->jumbo = B_FALSE;
4485574Smx205022 		dev_param_p->tx_rx_64byte = B_FALSE;
4495574Smx205022 		dev_param_p->rx_hw_checksum = B_FALSE;
4505574Smx205022 		dev_param_p->tx_hw_checksum = 0;
4515574Smx205022 		dev_param_p->desc_type = DESC_OFFLOAD;
4525574Smx205022 		dev_param_p->rx_desc_num = NGE_RECV_SLOTS_DESC_1024;
4535574Smx205022 		dev_param_p->tx_desc_num = NGE_SEND_SLOTS_DESC_1024;
4545574Smx205022 		dev_param_p->nge_split = NGE_SPLIT_32;
4555574Smx205022 		break;
4565574Smx205022 
4575574Smx205022 	case DEVICE_ID_CK804_56:
4585574Smx205022 	case DEVICE_ID_CK804_57:
4595574Smx205022 		dev_param_p->msi = B_TRUE;
4605574Smx205022 		dev_param_p->msi_x = B_TRUE;
4615574Smx205022 		dev_param_p->vlan = B_FALSE;
4625848Sjj146644 		dev_param_p->advanced_pm = B_FALSE;
4638218SMin.Xu@Sun.COM 		dev_param_p->mac_addr_order = B_FALSE;
4645574Smx205022 		dev_param_p->tx_pause_frame = B_FALSE;
4655574Smx205022 		dev_param_p->rx_pause_frame = B_TRUE;
4665574Smx205022 		dev_param_p->jumbo = B_TRUE;
4675574Smx205022 		dev_param_p->tx_rx_64byte = B_FALSE;
4685574Smx205022 		dev_param_p->rx_hw_checksum = B_TRUE;
4695574Smx205022 		dev_param_p->tx_hw_checksum = HCKSUM_IPHDRCKSUM;
4705574Smx205022 		dev_param_p->desc_type = DESC_HOT;
4715574Smx205022 		dev_param_p->rx_desc_num = NGE_RECV_SLOTS_DESC_3072;
4725574Smx205022 		dev_param_p->tx_desc_num = NGE_SEND_SLOTS_DESC_3072;
4735574Smx205022 		dev_param_p->nge_split = NGE_SPLIT_96;
4745574Smx205022 		break;
4755574Smx205022 
4765574Smx205022 	case DEVICE_ID_MCP51_268:
4775574Smx205022 	case DEVICE_ID_MCP51_269:
4785574Smx205022 		dev_param_p->msi = B_FALSE;
4795574Smx205022 		dev_param_p->msi_x = B_FALSE;
4805574Smx205022 		dev_param_p->vlan = B_FALSE;
4815848Sjj146644 		dev_param_p->advanced_pm = B_TRUE;
4828218SMin.Xu@Sun.COM 		dev_param_p->mac_addr_order = B_FALSE;
4835574Smx205022 		dev_param_p->tx_pause_frame = B_FALSE;
4845574Smx205022 		dev_param_p->rx_pause_frame = B_FALSE;
4855574Smx205022 		dev_param_p->jumbo = B_FALSE;
4865574Smx205022 		dev_param_p->tx_rx_64byte = B_TRUE;
4875574Smx205022 		dev_param_p->rx_hw_checksum = B_FALSE;
4885574Smx205022 		dev_param_p->tx_hw_checksum = 0;
4895574Smx205022 		dev_param_p->desc_type = DESC_OFFLOAD;
4905574Smx205022 		dev_param_p->rx_desc_num = NGE_RECV_SLOTS_DESC_1024;
4915574Smx205022 		dev_param_p->tx_desc_num = NGE_SEND_SLOTS_DESC_1024;
4925574Smx205022 		dev_param_p->nge_split = NGE_SPLIT_32;
4935574Smx205022 		break;
4945574Smx205022 
4955574Smx205022 	case DEVICE_ID_MCP55_372:
4965574Smx205022 	case DEVICE_ID_MCP55_373:
4975574Smx205022 		dev_param_p->msi = B_TRUE;
4985574Smx205022 		dev_param_p->msi_x = B_TRUE;
4995574Smx205022 		dev_param_p->vlan = B_TRUE;
5005848Sjj146644 		dev_param_p->advanced_pm = B_TRUE;
5018218SMin.Xu@Sun.COM 		dev_param_p->mac_addr_order = B_FALSE;
5025574Smx205022 		dev_param_p->tx_pause_frame = B_TRUE;
5035574Smx205022 		dev_param_p->rx_pause_frame = B_TRUE;
5045574Smx205022 		dev_param_p->jumbo = B_TRUE;
5055574Smx205022 		dev_param_p->tx_rx_64byte = B_TRUE;
5065574Smx205022 		dev_param_p->rx_hw_checksum = B_TRUE;
5075574Smx205022 		dev_param_p->tx_hw_checksum = HCKSUM_IPHDRCKSUM;
5085574Smx205022 		dev_param_p->desc_type = DESC_HOT;
5095574Smx205022 		dev_param_p->rx_desc_num = NGE_RECV_SLOTS_DESC_3072;
5105574Smx205022 		dev_param_p->tx_desc_num = NGE_SEND_SLOTS_DESC_3072;
5115574Smx205022 		dev_param_p->nge_split = NGE_SPLIT_96;
5125574Smx205022 		break;
5135574Smx205022 
5148218SMin.Xu@Sun.COM 	case DEVICE_ID_MCP61_3EE:
5158218SMin.Xu@Sun.COM 	case DEVICE_ID_MCP61_3EF:
5168218SMin.Xu@Sun.COM 		dev_param_p->msi = B_FALSE;
5178218SMin.Xu@Sun.COM 		dev_param_p->msi_x = B_FALSE;
5188218SMin.Xu@Sun.COM 		dev_param_p->vlan = B_FALSE;
5198218SMin.Xu@Sun.COM 		dev_param_p->advanced_pm = B_TRUE;
5208218SMin.Xu@Sun.COM 		dev_param_p->mac_addr_order = B_TRUE;
5218218SMin.Xu@Sun.COM 		dev_param_p->tx_pause_frame = B_FALSE;
5228218SMin.Xu@Sun.COM 		dev_param_p->rx_pause_frame = B_FALSE;
5238218SMin.Xu@Sun.COM 		dev_param_p->jumbo = B_FALSE;
5248218SMin.Xu@Sun.COM 		dev_param_p->tx_rx_64byte = B_TRUE;
5258218SMin.Xu@Sun.COM 		dev_param_p->rx_hw_checksum = B_FALSE;
5268218SMin.Xu@Sun.COM 		dev_param_p->tx_hw_checksum = 0;
5278218SMin.Xu@Sun.COM 		dev_param_p->desc_type = DESC_OFFLOAD;
5288218SMin.Xu@Sun.COM 		dev_param_p->rx_desc_num = NGE_RECV_SLOTS_DESC_1024;
5298218SMin.Xu@Sun.COM 		dev_param_p->tx_desc_num = NGE_SEND_SLOTS_DESC_1024;
5308218SMin.Xu@Sun.COM 		dev_param_p->nge_split = NGE_SPLIT_32;
5318218SMin.Xu@Sun.COM 		break;
5328218SMin.Xu@Sun.COM 
5339708SZhen.W@Sun.COM 	case DEVICE_ID_MCP77_760:
5349906SZhen.W@Sun.COM 	case DEVICE_ID_MCP79_AB0:
5359708SZhen.W@Sun.COM 		dev_param_p->msi = B_FALSE;
5369708SZhen.W@Sun.COM 		dev_param_p->msi_x = B_FALSE;
5379708SZhen.W@Sun.COM 		dev_param_p->vlan = B_FALSE;
5389708SZhen.W@Sun.COM 		dev_param_p->advanced_pm = B_TRUE;
5399708SZhen.W@Sun.COM 		dev_param_p->mac_addr_order = B_TRUE;
5409708SZhen.W@Sun.COM 		dev_param_p->tx_pause_frame = B_FALSE;
5419708SZhen.W@Sun.COM 		dev_param_p->rx_pause_frame = B_FALSE;
5429708SZhen.W@Sun.COM 		dev_param_p->jumbo = B_FALSE;
5439708SZhen.W@Sun.COM 		dev_param_p->tx_rx_64byte = B_TRUE;
5449708SZhen.W@Sun.COM 		dev_param_p->rx_hw_checksum = B_FALSE;
5459708SZhen.W@Sun.COM 		dev_param_p->tx_hw_checksum = 0;
5469708SZhen.W@Sun.COM 		dev_param_p->desc_type = DESC_HOT;
5479708SZhen.W@Sun.COM 		dev_param_p->rx_desc_num = NGE_RECV_SLOTS_DESC_1024;
5489708SZhen.W@Sun.COM 		dev_param_p->tx_desc_num = NGE_SEND_SLOTS_DESC_1024;
5499708SZhen.W@Sun.COM 		dev_param_p->nge_split = NGE_SPLIT_32;
5509708SZhen.W@Sun.COM 		break;
5519708SZhen.W@Sun.COM 
5525574Smx205022 	default:
5535574Smx205022 		dev_param_p->msi = B_FALSE;
5545574Smx205022 		dev_param_p->msi_x = B_FALSE;
5555574Smx205022 		dev_param_p->vlan = B_FALSE;
5565848Sjj146644 		dev_param_p->advanced_pm = B_FALSE;
5578218SMin.Xu@Sun.COM 		dev_param_p->mac_addr_order = B_FALSE;
5585574Smx205022 		dev_param_p->tx_pause_frame = B_FALSE;
5595574Smx205022 		dev_param_p->rx_pause_frame = B_FALSE;
5605574Smx205022 		dev_param_p->jumbo = B_FALSE;
5615574Smx205022 		dev_param_p->tx_rx_64byte = B_FALSE;
5625574Smx205022 		dev_param_p->rx_hw_checksum = B_FALSE;
5635574Smx205022 		dev_param_p->tx_hw_checksum = 0;
5645574Smx205022 		dev_param_p->desc_type = DESC_OFFLOAD;
5655574Smx205022 		dev_param_p->rx_desc_num = NGE_RECV_SLOTS_DESC_1024;
5665574Smx205022 		dev_param_p->tx_desc_num = NGE_SEND_SLOTS_DESC_1024;
5675574Smx205022 		dev_param_p->nge_split = NGE_SPLIT_32;
5685574Smx205022 		return;
5695574Smx205022 	}
5705574Smx205022 }
5715574Smx205022 /*
5725574Smx205022  * Perform first-stage chip (re-)initialisation, using only config-space
5735574Smx205022  * accesses:
5745574Smx205022  *
5755574Smx205022  * + Read the vendor/device/revision/subsystem/cache-line-size registers,
5765574Smx205022  *   returning the data in the structure pointed to by <infop>.
5775574Smx205022  */
5785574Smx205022 void nge_chip_cfg_init(nge_t *ngep, chip_info_t *infop, boolean_t reset);
5795574Smx205022 #pragma	no_inline(nge_chip_cfg_init)
5805574Smx205022 
5815574Smx205022 void
nge_chip_cfg_init(nge_t * ngep,chip_info_t * infop,boolean_t reset)5825574Smx205022 nge_chip_cfg_init(nge_t *ngep, chip_info_t *infop, boolean_t reset)
5835574Smx205022 {
5845574Smx205022 	uint16_t command;
5855574Smx205022 	ddi_acc_handle_t handle;
5865574Smx205022 	nge_interbus_conf interbus_conf;
5875574Smx205022 	nge_msi_mask_conf msi_mask_conf;
5885574Smx205022 	nge_msi_map_cap_conf cap_conf;
5895574Smx205022 
5905574Smx205022 	NGE_TRACE(("nge_chip_cfg_init($%p, $%p, %d)",
5915574Smx205022 	    (void *)ngep, (void *)infop, reset));
5925574Smx205022 
5935574Smx205022 	/*
5945574Smx205022 	 * save PCI cache line size and subsystem vendor ID
5955574Smx205022 	 *
5965574Smx205022 	 * Read all the config-space registers that characterise the
5975574Smx205022 	 * chip, specifically vendor/device/revision/subsystem vendor
5985574Smx205022 	 * and subsystem device id.  We expect (but don't check) that
5995574Smx205022 	 */
6005574Smx205022 	handle = ngep->cfg_handle;
6015574Smx205022 	/* reading the vendor information once */
6025574Smx205022 	if (reset == B_FALSE) {
6035574Smx205022 		infop->command = pci_config_get16(handle,
6045574Smx205022 		    PCI_CONF_COMM);
6055574Smx205022 		infop->vendor = pci_config_get16(handle,
6065574Smx205022 		    PCI_CONF_VENID);
6075574Smx205022 		infop->device = pci_config_get16(handle,
6085574Smx205022 		    PCI_CONF_DEVID);
6095574Smx205022 		infop->subven = pci_config_get16(handle,
6105574Smx205022 		    PCI_CONF_SUBVENID);
6115574Smx205022 		infop->subdev = pci_config_get16(handle,
6125574Smx205022 		    PCI_CONF_SUBSYSID);
6135574Smx205022 		infop->class_code = pci_config_get8(handle,
6145574Smx205022 		    PCI_CONF_BASCLASS);
6155574Smx205022 		infop->revision = pci_config_get8(handle,
6165574Smx205022 		    PCI_CONF_REVID);
6175574Smx205022 		infop->clsize = pci_config_get8(handle,
6185574Smx205022 		    PCI_CONF_CACHE_LINESZ);
6195574Smx205022 		infop->latency = pci_config_get8(handle,
6205574Smx205022 		    PCI_CONF_LATENCY_TIMER);
6215574Smx205022 	}
6225574Smx205022 	if (nge_enable_msi) {
6235574Smx205022 		/* Disable the hidden for MSI support */
6245574Smx205022 		interbus_conf.conf_val = pci_config_get32(handle,
6255574Smx205022 		    PCI_CONF_HT_INTERNAL);
6265574Smx205022 		if ((infop->device == DEVICE_ID_MCP55_373) ||
6275574Smx205022 		    (infop->device == DEVICE_ID_MCP55_372))
6285574Smx205022 			interbus_conf.conf_bits.msix_off = NGE_SET;
6295574Smx205022 		interbus_conf.conf_bits.msi_off = NGE_CLEAR;
6305574Smx205022 		pci_config_put32(handle, PCI_CONF_HT_INTERNAL,
6315574Smx205022 		    interbus_conf.conf_val);
6325574Smx205022 
6335574Smx205022 		if ((infop->device == DEVICE_ID_MCP55_373) ||
6345574Smx205022 		    (infop->device == DEVICE_ID_MCP55_372)) {
6355574Smx205022 
6365574Smx205022 			/* Disable the vector off for mcp55 */
6375574Smx205022 			msi_mask_conf.msi_mask_conf_val =
6385574Smx205022 			    pci_config_get32(handle, PCI_CONF_HT_MSI_MASK);
6395574Smx205022 			msi_mask_conf.msi_mask_bits.vec0_off = NGE_CLEAR;
6405574Smx205022 			msi_mask_conf.msi_mask_bits.vec1_off = NGE_CLEAR;
6415574Smx205022 			msi_mask_conf.msi_mask_bits.vec2_off = NGE_CLEAR;
6425574Smx205022 			msi_mask_conf.msi_mask_bits.vec3_off = NGE_CLEAR;
6435574Smx205022 			msi_mask_conf.msi_mask_bits.vec4_off = NGE_CLEAR;
6445574Smx205022 			msi_mask_conf.msi_mask_bits.vec5_off = NGE_CLEAR;
6455574Smx205022 			msi_mask_conf.msi_mask_bits.vec6_off = NGE_CLEAR;
6465574Smx205022 			msi_mask_conf.msi_mask_bits.vec7_off = NGE_CLEAR;
6475574Smx205022 			pci_config_put32(handle, PCI_CONF_HT_MSI_MASK,
6485574Smx205022 			    msi_mask_conf.msi_mask_conf_val);
6495574Smx205022 
6505574Smx205022 			/* Enable the MSI mapping */
6515574Smx205022 			cap_conf.msi_map_cap_conf_val =
6525574Smx205022 			    pci_config_get32(handle, PCI_CONF_HT_MSI_MAP_CAP);
6535574Smx205022 			cap_conf.map_cap_conf_bits.map_en = NGE_SET;
6545574Smx205022 			pci_config_put32(handle, PCI_CONF_HT_MSI_MAP_CAP,
6555574Smx205022 			    cap_conf.msi_map_cap_conf_val);
6565574Smx205022 		}
6575574Smx205022 	} else {
6585574Smx205022 		interbus_conf.conf_val = pci_config_get32(handle,
6595574Smx205022 		    PCI_CONF_HT_INTERNAL);
6605574Smx205022 		interbus_conf.conf_bits.msi_off = NGE_SET;
6615574Smx205022 		pci_config_put32(handle, PCI_CONF_HT_INTERNAL,
6625574Smx205022 		    interbus_conf.conf_val);
6635574Smx205022 	}
6645574Smx205022 	command = infop->command | PCI_COMM_MAE;
6655574Smx205022 	command &= ~PCI_COMM_MEMWR_INVAL;
6665574Smx205022 	command |= PCI_COMM_ME;
6675574Smx205022 	pci_config_put16(handle, PCI_CONF_COMM, command);
6685574Smx205022 	pci_config_put16(handle, PCI_CONF_STAT, ~0);
6695574Smx205022 
6705574Smx205022 }
6715574Smx205022 
6725574Smx205022 int
nge_chip_stop(nge_t * ngep,boolean_t fault)6735574Smx205022 nge_chip_stop(nge_t *ngep, boolean_t fault)
6745574Smx205022 {
6755574Smx205022 	int err;
6765574Smx205022 	uint32_t reg_val;
6775574Smx205022 	uint32_t	tries;
6785574Smx205022 	nge_mintr_src mintr_src;
6795574Smx205022 	nge_mii_cs mii_cs;
6805574Smx205022 	nge_rx_poll rx_poll;
6815574Smx205022 	nge_tx_poll tx_poll;
6825574Smx205022 	nge_rx_en rx_en;
6835574Smx205022 	nge_tx_en tx_en;
6845574Smx205022 	nge_tx_sta tx_sta;
6855574Smx205022 	nge_rx_sta rx_sta;
6865574Smx205022 	nge_mode_cntl mode;
6875574Smx205022 	nge_pmu_cntl2 pmu_cntl2;
6885574Smx205022 
6895574Smx205022 	NGE_TRACE(("nge_chip_stop($%p, %d)", (void *)ngep, fault));
6905574Smx205022 
6915574Smx205022 	err = DDI_SUCCESS;
6925848Sjj146644 
6935848Sjj146644 	/* Clear any pending PHY interrupt */
6945574Smx205022 	mintr_src.src_val = nge_reg_get8(ngep, NGE_MINTR_SRC);
6955574Smx205022 	nge_reg_put8(ngep, NGE_MINTR_SRC, mintr_src.src_val);
6965574Smx205022 
6975574Smx205022 	/* Mask all interrupts */
6985574Smx205022 	reg_val = nge_reg_get32(ngep, NGE_INTR_MASK);
6995574Smx205022 	reg_val &= ~NGE_INTR_ALL_EN;
7005574Smx205022 	nge_reg_put32(ngep, NGE_INTR_MASK, reg_val);
7015574Smx205022 
7025574Smx205022 	/* Disable auto-polling of phy */
7035574Smx205022 	mii_cs.cs_val = nge_reg_get32(ngep, NGE_MII_CS);
7045574Smx205022 	mii_cs.cs_bits.ap_en = NGE_CLEAR;
7055574Smx205022 	nge_reg_put32(ngep, NGE_MII_CS, mii_cs.cs_val);
7065574Smx205022 
7075574Smx205022 	/* Reset buffer management & DMA */
7085574Smx205022 	mode.mode_val = nge_reg_get32(ngep, NGE_MODE_CNTL);
7095574Smx205022 	mode.mode_bits.dma_dis = NGE_SET;
7105574Smx205022 	mode.mode_bits.desc_type = ngep->desc_mode;
7115574Smx205022 	nge_reg_put32(ngep, NGE_MODE_CNTL, mode.mode_val);
7125574Smx205022 
7137155Smx205022 	for (tries = 0; tries < 10000; tries++) {
7145574Smx205022 		drv_usecwait(10);
7155574Smx205022 		mode.mode_val = nge_reg_get32(ngep, NGE_MODE_CNTL);
7165574Smx205022 		if (mode.mode_bits.dma_status == NGE_SET)
7175574Smx205022 			break;
7185574Smx205022 	}
7197155Smx205022 	if (tries == 10000) {
7209708SZhen.W@Sun.COM 		ngep->nge_chip_state = NGE_CHIP_ERROR;
7215574Smx205022 		return (DDI_FAILURE);
7225574Smx205022 	}
7235574Smx205022 
7249604SZhen.W@Sun.COM 	/* Disable rx's machine */
7259604SZhen.W@Sun.COM 	rx_en.val = nge_reg_get8(ngep, NGE_RX_EN);
7269604SZhen.W@Sun.COM 	rx_en.bits.rx_en = NGE_CLEAR;
7279604SZhen.W@Sun.COM 	nge_reg_put8(ngep, NGE_RX_EN, rx_en.val);
7285574Smx205022 
7299604SZhen.W@Sun.COM 	/* Disable tx's machine */
7309604SZhen.W@Sun.COM 	tx_en.val = nge_reg_get8(ngep, NGE_TX_EN);
7319604SZhen.W@Sun.COM 	tx_en.bits.tx_en = NGE_CLEAR;
7329604SZhen.W@Sun.COM 	nge_reg_put8(ngep, NGE_TX_EN, tx_en.val);
7335574Smx205022 
7345574Smx205022 	/*
7355574Smx205022 	 * Clean the status of tx's state machine
7365574Smx205022 	 * and Make assure the tx's channel is idle
7375574Smx205022 	 */
7385574Smx205022 	tx_sta.sta_val = nge_reg_get32(ngep, NGE_TX_STA);
7395574Smx205022 	for (tries = 0; tries < 1000; tries++) {
7405574Smx205022 		if (tx_sta.sta_bits.tx_chan_sta == NGE_CLEAR)
7415574Smx205022 			break;
7425574Smx205022 		drv_usecwait(10);
7435574Smx205022 		tx_sta.sta_val = nge_reg_get32(ngep, NGE_TX_STA);
7445574Smx205022 	}
7455574Smx205022 	if (tries == 1000) {
7469708SZhen.W@Sun.COM 		ngep->nge_chip_state = NGE_CHIP_ERROR;
7475574Smx205022 		return (DDI_FAILURE);
7485574Smx205022 	}
7495574Smx205022 	nge_reg_put32(ngep, NGE_TX_STA,  tx_sta.sta_val);
7505574Smx205022 
7515574Smx205022 	/*
7525574Smx205022 	 * Clean the status of rx's state machine
7535574Smx205022 	 * and Make assure the tx's channel is idle
7545574Smx205022 	 */
7555574Smx205022 	rx_sta.sta_val = nge_reg_get32(ngep, NGE_RX_STA);
7565574Smx205022 	for (tries = 0; tries < 1000; tries++) {
7575574Smx205022 		if (rx_sta.sta_bits.rx_chan_sta == NGE_CLEAR)
7585574Smx205022 			break;
7595574Smx205022 		drv_usecwait(10);
7605574Smx205022 		rx_sta.sta_val = nge_reg_get32(ngep, NGE_RX_STA);
7615574Smx205022 	}
7625574Smx205022 	if (tries == 1000) {
7639708SZhen.W@Sun.COM 		ngep->nge_chip_state = NGE_CHIP_ERROR;
7645574Smx205022 		return (DDI_FAILURE);
7655574Smx205022 	}
7665574Smx205022 	nge_reg_put32(ngep, NGE_RX_STA, rx_sta.sta_val);
7675574Smx205022 
7685848Sjj146644 	/* Disable auto-poll of rx's state machine */
7695848Sjj146644 	rx_poll.poll_val = nge_reg_get32(ngep, NGE_RX_POLL);
7705848Sjj146644 	rx_poll.poll_bits.rpen = NGE_CLEAR;
7715848Sjj146644 	rx_poll.poll_bits.rpi = NGE_CLEAR;
7725848Sjj146644 	nge_reg_put32(ngep, NGE_RX_POLL, rx_poll.poll_val);
7735848Sjj146644 
7745848Sjj146644 	/* Disable auto-polling of tx's  state machine */
7755848Sjj146644 	tx_poll.poll_val = nge_reg_get32(ngep, NGE_TX_POLL);
7765848Sjj146644 	tx_poll.poll_bits.tpen = NGE_CLEAR;
7775848Sjj146644 	tx_poll.poll_bits.tpi = NGE_CLEAR;
7785848Sjj146644 	nge_reg_put32(ngep, NGE_TX_POLL, tx_poll.poll_val);
7795848Sjj146644 
7805848Sjj146644 	/* Restore buffer management */
7815848Sjj146644 	mode.mode_val = nge_reg_get32(ngep, NGE_MODE_CNTL);
7825848Sjj146644 	mode.mode_bits.bm_reset = NGE_SET;
7835848Sjj146644 	mode.mode_bits.tx_rcom_en = NGE_SET;
7845848Sjj146644 	nge_reg_put32(ngep, NGE_MODE_CNTL, mode.mode_val);
7855848Sjj146644 
7865848Sjj146644 	if (ngep->dev_spec_param.advanced_pm) {
7875574Smx205022 
7885574Smx205022 		nge_reg_put32(ngep, NGE_PMU_CIDLE_LIMIT, 0);
7895574Smx205022 		nge_reg_put32(ngep, NGE_PMU_DIDLE_LIMIT, 0);
7905574Smx205022 
7915574Smx205022 		pmu_cntl2.cntl2_val = nge_reg_get32(ngep, NGE_PMU_CNTL2);
7925574Smx205022 		pmu_cntl2.cntl2_bits.cidle_timer = NGE_CLEAR;
7935574Smx205022 		pmu_cntl2.cntl2_bits.didle_timer = NGE_CLEAR;
7945574Smx205022 		nge_reg_put32(ngep, NGE_PMU_CNTL2, pmu_cntl2.cntl2_val);
7955574Smx205022 	}
7965574Smx205022 	if (fault)
7975574Smx205022 		ngep->nge_chip_state = NGE_CHIP_FAULT;
7985574Smx205022 	else
7995574Smx205022 		ngep->nge_chip_state = NGE_CHIP_STOPPED;
8005574Smx205022 
8015574Smx205022 	return (err);
8025574Smx205022 }
8035574Smx205022 
8045574Smx205022 static void
nge_rx_setup(nge_t * ngep)8055574Smx205022 nge_rx_setup(nge_t *ngep)
8065574Smx205022 {
8075574Smx205022 	uint64_t desc_addr;
8085574Smx205022 	nge_rxtx_dlen dlen;
8095574Smx205022 	nge_rx_poll rx_poll;
8105574Smx205022 
8115574Smx205022 	/*
8125574Smx205022 	 * Filling the address and length of rx's descriptors
8135574Smx205022 	 */
8145574Smx205022 	desc_addr = ngep->recv->desc.cookie.dmac_laddress;
8155574Smx205022 	nge_reg_put32(ngep, NGE_RX_DADR, desc_addr);
8165574Smx205022 	nge_reg_put32(ngep, NGE_RX_DADR_HI, desc_addr >> 32);
8175574Smx205022 	dlen.dlen_val = nge_reg_get32(ngep, NGE_RXTX_DLEN);
8185574Smx205022 	dlen.dlen_bits.rdlen = ngep->recv->desc.nslots - 1;
8195574Smx205022 	nge_reg_put32(ngep, NGE_RXTX_DLEN, dlen.dlen_val);
8205574Smx205022 
8215574Smx205022 	rx_poll.poll_val = nge_reg_get32(ngep, NGE_RX_POLL);
8225574Smx205022 	rx_poll.poll_bits.rpi = RX_POLL_INTV_1G;
8235574Smx205022 	rx_poll.poll_bits.rpen = NGE_SET;
8245574Smx205022 	nge_reg_put32(ngep, NGE_RX_POLL, rx_poll.poll_val);
8255574Smx205022 }
8265574Smx205022 
8275574Smx205022 static void
nge_tx_setup(nge_t * ngep)8285574Smx205022 nge_tx_setup(nge_t *ngep)
8295574Smx205022 {
8305574Smx205022 	uint64_t desc_addr;
8315574Smx205022 	nge_rxtx_dlen dlen;
8325574Smx205022 
8335574Smx205022 	/*
8345574Smx205022 	 * Filling the address and length of tx's descriptors
8355574Smx205022 	 */
8365574Smx205022 	desc_addr = ngep->send->desc.cookie.dmac_laddress;
8375574Smx205022 	nge_reg_put32(ngep, NGE_TX_DADR, desc_addr);
8385574Smx205022 	nge_reg_put32(ngep, NGE_TX_DADR_HI, desc_addr >> 32);
8395574Smx205022 	dlen.dlen_val = nge_reg_get32(ngep, NGE_RXTX_DLEN);
8405574Smx205022 	dlen.dlen_bits.tdlen = ngep->send->desc.nslots - 1;
8415574Smx205022 	nge_reg_put32(ngep, NGE_RXTX_DLEN, dlen.dlen_val);
8425574Smx205022 }
8435574Smx205022 
8445574Smx205022 static int
nge_buff_setup(nge_t * ngep)8455574Smx205022 nge_buff_setup(nge_t *ngep)
8465574Smx205022 {
8475574Smx205022 	nge_mode_cntl mode_cntl;
8485574Smx205022 	nge_dev_spec_param_t	*dev_param_p;
8495574Smx205022 
8505574Smx205022 	dev_param_p = &ngep->dev_spec_param;
8515574Smx205022 
8525574Smx205022 	/*
8535574Smx205022 	 * Configure Rx&Tx's buffer
8545574Smx205022 	 */
8555574Smx205022 	nge_rx_setup(ngep);
8565574Smx205022 	nge_tx_setup(ngep);
8575574Smx205022 
8585574Smx205022 	/*
8595574Smx205022 	 * Configure buffer attribute
8605574Smx205022 	 */
8615574Smx205022 	mode_cntl.mode_val = nge_reg_get32(ngep, NGE_MODE_CNTL);
8625574Smx205022 
8635574Smx205022 	/*
8645574Smx205022 	 * Enable Dma access request
8655574Smx205022 	 */
8665574Smx205022 	mode_cntl.mode_bits.dma_dis = NGE_CLEAR;
8675574Smx205022 
8685574Smx205022 	/*
8695574Smx205022 	 * Enbale Buffer management
8705574Smx205022 	 */
8715574Smx205022 	mode_cntl.mode_bits.bm_reset = NGE_CLEAR;
8725574Smx205022 
8735574Smx205022 	/*
8745574Smx205022 	 * Support Standoffload Descriptor
8755574Smx205022 	 */
8765574Smx205022 	mode_cntl.mode_bits.desc_type = ngep->desc_mode;
8775574Smx205022 
8785574Smx205022 	/*
8795574Smx205022 	 * Support receive hardware checksum
8805574Smx205022 	 */
8815574Smx205022 	if (dev_param_p->rx_hw_checksum) {
8825574Smx205022 		mode_cntl.mode_bits.rx_sum_en = NGE_SET;
8835574Smx205022 	} else
8845574Smx205022 		mode_cntl.mode_bits.rx_sum_en = NGE_CLEAR;
8855574Smx205022 
8865574Smx205022 	/*
8875574Smx205022 	 * Disable Tx PRD coarse update
8885574Smx205022 	 */
8895574Smx205022 	mode_cntl.mode_bits.tx_prd_cu_en = NGE_CLEAR;
8905574Smx205022 
8915574Smx205022 	/*
8925574Smx205022 	 * Disable 64-byte access
8935574Smx205022 	 */
8945574Smx205022 	mode_cntl.mode_bits.w64_dis = NGE_SET;
8955574Smx205022 
8965574Smx205022 	/*
8975574Smx205022 	 * Skip Rx Error Frame is not supported and if
8985574Smx205022 	 * enable it, jumbo frame does not work any more.
8995574Smx205022 	 */
9005574Smx205022 	mode_cntl.mode_bits.rx_filter_en = NGE_CLEAR;
9015574Smx205022 
9025574Smx205022 	/*
9035574Smx205022 	 * Can not support hot mode now
9045574Smx205022 	 */
9055574Smx205022 	mode_cntl.mode_bits.resv15 = NGE_CLEAR;
9065574Smx205022 
9075574Smx205022 	if (dev_param_p->vlan) {
9085574Smx205022 		/* Disable the vlan strip for devices which support vlan */
9095574Smx205022 		mode_cntl.mode_bits.vlan_strip = NGE_CLEAR;
9105574Smx205022 
9115574Smx205022 		/* Disable the vlan insert for devices which supprot vlan */
9125574Smx205022 		mode_cntl.mode_bits.vlan_ins = NGE_CLEAR;
9135574Smx205022 	}
9145574Smx205022 
9155574Smx205022 	if (dev_param_p->tx_rx_64byte) {
9165574Smx205022 
9175574Smx205022 		/* Set the maximum TX PRD fetch size to 64 bytes */
9185574Smx205022 		mode_cntl.mode_bits.tx_fetch_prd = NGE_SET;
9195574Smx205022 
9205574Smx205022 		/* Set the maximum RX PRD fetch size to 64 bytes */
9215574Smx205022 		mode_cntl.mode_bits.rx_fetch_prd = NGE_SET;
9225574Smx205022 	}
9235574Smx205022 	/*
9245574Smx205022 	 * Upload Rx data as it arrives, rather than waiting for full frame
9255574Smx205022 	 */
9265574Smx205022 	mode_cntl.mode_bits.resv16 = NGE_CLEAR;
9275574Smx205022 
9285574Smx205022 	/*
9295574Smx205022 	 * Normal HOT table accesses
9305574Smx205022 	 */
9315574Smx205022 	mode_cntl.mode_bits.resv17 = NGE_CLEAR;
9325574Smx205022 
9335574Smx205022 	/*
9345574Smx205022 	 * Normal HOT buffer requesting
9355574Smx205022 	 */
9365574Smx205022 	mode_cntl.mode_bits.resv18 = NGE_CLEAR;
9375574Smx205022 	nge_reg_put32(ngep, NGE_MODE_CNTL, mode_cntl.mode_val);
9385574Smx205022 
9395574Smx205022 	/*
9405574Smx205022 	 * Signal controller to check for new Rx descriptors
9415574Smx205022 	 */
9425574Smx205022 	mode_cntl.mode_val = nge_reg_get32(ngep, NGE_MODE_CNTL);
9435574Smx205022 	mode_cntl.mode_bits.rxdm = NGE_SET;
9445574Smx205022 	mode_cntl.mode_bits.tx_rcom_en = NGE_SET;
9455574Smx205022 	nge_reg_put32(ngep, NGE_MODE_CNTL, mode_cntl.mode_val);
9465574Smx205022 
9475574Smx205022 
9485574Smx205022 	return (DDI_SUCCESS);
9495574Smx205022 }
9505574Smx205022 
9515574Smx205022 /*
9525574Smx205022  * When chipset resets, the chipset can not restore  the orignial
9535574Smx205022  * mac address to the mac address registers.
9545574Smx205022  *
9555574Smx205022  * When the driver is dettached, the function will write the orignial
9565574Smx205022  * mac address to the mac address registers.
9575574Smx205022  */
9585574Smx205022 
9595574Smx205022 void
nge_restore_mac_addr(nge_t * ngep)9605574Smx205022 nge_restore_mac_addr(nge_t *ngep)
9615574Smx205022 {
9625574Smx205022 	uint32_t mac_addr;
9635574Smx205022 
9645574Smx205022 	mac_addr = (uint32_t)ngep->chipinfo.hw_mac_addr;
9655574Smx205022 	nge_reg_put32(ngep, NGE_UNI_ADDR0, mac_addr);
9665574Smx205022 	mac_addr = (uint32_t)(ngep->chipinfo.hw_mac_addr >> 32);
9675574Smx205022 	nge_reg_put32(ngep, NGE_UNI_ADDR1, mac_addr);
9685574Smx205022 }
9695574Smx205022 
9705574Smx205022 int
nge_chip_reset(nge_t * ngep)9715574Smx205022 nge_chip_reset(nge_t *ngep)
9725574Smx205022 {
9735574Smx205022 	int err;
9745574Smx205022 	uint8_t i;
9755574Smx205022 	uint32_t regno;
9768218SMin.Xu@Sun.COM 	uint64_t mac = 0;
9775574Smx205022 	nge_uni_addr1 uaddr1;
9785574Smx205022 	nge_cp_cntl ee_cntl;
9795574Smx205022 	nge_soft_misc soft_misc;
9805574Smx205022 	nge_pmu_cntl0 pmu_cntl0;
9815574Smx205022 	nge_pmu_cntl2 pmu_cntl2;
9825574Smx205022 	nge_pm_cntl2 pm_cntl2;
9835574Smx205022 	const nge_ksindex_t *ksip;
9845574Smx205022 
9855574Smx205022 	NGE_TRACE(("nge_chip_reset($%p)", (void *)ngep));
9865574Smx205022 
9875574Smx205022 	/*
9885574Smx205022 	 * Clear the statistics by reading the statistics register
9895574Smx205022 	 */
9905574Smx205022 	for (ksip = nge_statistics; ksip->name != NULL; ++ksip) {
9915574Smx205022 		regno = KS_BASE + ksip->index * sizeof (uint32_t);
9925574Smx205022 		(void) nge_reg_get32(ngep, regno);
9935574Smx205022 	}
9945574Smx205022 
9955574Smx205022 	/*
9965574Smx205022 	 * Setup seeprom control
9975574Smx205022 	 */
9985574Smx205022 	ee_cntl.cntl_val = nge_reg_get32(ngep, NGE_EP_CNTL);
9995574Smx205022 	ee_cntl.cntl_bits.clkdiv = EEPROM_CLKDIV;
10005574Smx205022 	ee_cntl.cntl_bits.rom_size = EEPROM_32K;
10015574Smx205022 	ee_cntl.cntl_bits.word_wid = ACCESS_16BIT;
10025574Smx205022 	ee_cntl.cntl_bits.wait_slots = EEPROM_WAITCLK;
10035574Smx205022 	nge_reg_put32(ngep, NGE_EP_CNTL, ee_cntl.cntl_val);
10045574Smx205022 
10055574Smx205022 	/*
10065574Smx205022 	 * Reading the unicast mac address table
10075574Smx205022 	 */
10085574Smx205022 	if (ngep->nge_chip_state == NGE_CHIP_INITIAL) {
10095574Smx205022 		uaddr1.addr_val = nge_reg_get32(ngep, NGE_UNI_ADDR1);
10105574Smx205022 		mac = uaddr1.addr_bits.addr;
10115574Smx205022 		mac <<= 32;
10125574Smx205022 		mac |= nge_reg_get32(ngep, NGE_UNI_ADDR0);
10139708SZhen.W@Sun.COM 			ngep->chipinfo.hw_mac_addr = mac;
10149708SZhen.W@Sun.COM 			if (ngep->dev_spec_param.mac_addr_order) {
10159708SZhen.W@Sun.COM 				for (i = 0; i < ETHERADDRL; i++) {
10169708SZhen.W@Sun.COM 					ngep->chipinfo.vendor_addr.addr[i] =
10179708SZhen.W@Sun.COM 					    (uchar_t)mac;
10189708SZhen.W@Sun.COM 					ngep->cur_uni_addr.addr[i] =
10199708SZhen.W@Sun.COM 					    (uchar_t)mac;
10208218SMin.Xu@Sun.COM 					mac >>= 8;
10218218SMin.Xu@Sun.COM 				}
10229708SZhen.W@Sun.COM 			} else {
10239708SZhen.W@Sun.COM 				for (i = ETHERADDRL; i-- != 0; ) {
10249708SZhen.W@Sun.COM 					ngep->chipinfo.vendor_addr.addr[i] =
10259708SZhen.W@Sun.COM 					    (uchar_t)mac;
10269708SZhen.W@Sun.COM 					ngep->cur_uni_addr.addr[i] =
10279708SZhen.W@Sun.COM 					    (uchar_t)mac;
10289708SZhen.W@Sun.COM 					mac >>= 8;
10299708SZhen.W@Sun.COM 				}
10305574Smx205022 			}
10315574Smx205022 			ngep->chipinfo.vendor_addr.set = 1;
10325574Smx205022 	}
10335574Smx205022 	pci_config_put8(ngep->cfg_handle, PCI_CONF_CACHE_LINESZ,
10345574Smx205022 	    ngep->chipinfo.clsize);
10355574Smx205022 	pci_config_put8(ngep->cfg_handle, PCI_CONF_LATENCY_TIMER,
10365574Smx205022 	    ngep->chipinfo.latency);
10375574Smx205022 
10385848Sjj146644 
10395848Sjj146644 	if (ngep->dev_spec_param.advanced_pm) {
10405574Smx205022 
10415574Smx205022 		/* Program software misc register */
10425574Smx205022 		soft_misc.misc_val = nge_reg_get32(ngep, NGE_SOFT_MISC);
10435574Smx205022 		soft_misc.misc_bits.rx_clk_vx_rst = NGE_SET;
10445574Smx205022 		soft_misc.misc_bits.tx_clk_vx_rst = NGE_SET;
10455574Smx205022 		soft_misc.misc_bits.clk12m_vx_rst = NGE_SET;
10465574Smx205022 		soft_misc.misc_bits.fpci_clk_vx_rst = NGE_SET;
10475574Smx205022 		soft_misc.misc_bits.rx_clk_vc_rst = NGE_SET;
10485574Smx205022 		soft_misc.misc_bits.tx_clk_vc_rst = NGE_SET;
10495574Smx205022 		soft_misc.misc_bits.fs_clk_vc_rst = NGE_SET;
10505574Smx205022 		soft_misc.misc_bits.rst_ex_m2pintf = NGE_SET;
10515574Smx205022 		nge_reg_put32(ngep, NGE_SOFT_MISC, soft_misc.misc_val);
10525574Smx205022 
10535848Sjj146644 		/* wait for 32 us */
10545848Sjj146644 		drv_usecwait(32);
10555574Smx205022 
10565574Smx205022 		soft_misc.misc_val = nge_reg_get32(ngep, NGE_SOFT_MISC);
10575574Smx205022 		soft_misc.misc_bits.rx_clk_vx_rst = NGE_CLEAR;
10585574Smx205022 		soft_misc.misc_bits.tx_clk_vx_rst = NGE_CLEAR;
10595574Smx205022 		soft_misc.misc_bits.clk12m_vx_rst = NGE_CLEAR;
10605574Smx205022 		soft_misc.misc_bits.fpci_clk_vx_rst = NGE_CLEAR;
10615574Smx205022 		soft_misc.misc_bits.rx_clk_vc_rst = NGE_CLEAR;
10625574Smx205022 		soft_misc.misc_bits.tx_clk_vc_rst = NGE_CLEAR;
10635574Smx205022 		soft_misc.misc_bits.fs_clk_vc_rst = NGE_CLEAR;
10645574Smx205022 		soft_misc.misc_bits.rst_ex_m2pintf = NGE_CLEAR;
10655574Smx205022 		nge_reg_put32(ngep, NGE_SOFT_MISC, soft_misc.misc_val);
10665574Smx205022 
10675574Smx205022 		/* Program PMU registers */
10685574Smx205022 		pmu_cntl0.cntl0_val = nge_reg_get32(ngep, NGE_PMU_CNTL0);
10695574Smx205022 		pmu_cntl0.cntl0_bits.core_spd10_fp =
10705574Smx205022 		    NGE_PMU_CORE_SPD10_BUSY;
10715574Smx205022 		pmu_cntl0.cntl0_bits.core_spd10_idle =
10725574Smx205022 		    NGE_PMU_CORE_SPD10_IDLE;
10735574Smx205022 		pmu_cntl0.cntl0_bits.core_spd100_fp =
10745574Smx205022 		    NGE_PMU_CORE_SPD100_BUSY;
10755574Smx205022 		pmu_cntl0.cntl0_bits.core_spd100_idle =
10765574Smx205022 		    NGE_PMU_CORE_SPD100_IDLE;
10775574Smx205022 		pmu_cntl0.cntl0_bits.core_spd1000_fp =
10785574Smx205022 		    NGE_PMU_CORE_SPD1000_BUSY;
10795574Smx205022 		pmu_cntl0.cntl0_bits.core_spd1000_idle =
10805574Smx205022 		    NGE_PMU_CORE_SPD100_IDLE;
10815574Smx205022 		pmu_cntl0.cntl0_bits.core_spd10_idle =
10825574Smx205022 		    NGE_PMU_CORE_SPD10_IDLE;
10835574Smx205022 		nge_reg_put32(ngep, NGE_PMU_CNTL0, pmu_cntl0.cntl0_val);
10845574Smx205022 
10855574Smx205022 		/* Set the core idle limit value */
10865574Smx205022 		nge_reg_put32(ngep, NGE_PMU_CIDLE_LIMIT,
10875574Smx205022 		    NGE_PMU_CIDLE_LIMIT_DEF);
10885574Smx205022 
10895574Smx205022 		/* Set the device idle limit value */
10905574Smx205022 		nge_reg_put32(ngep, NGE_PMU_DIDLE_LIMIT,
10915574Smx205022 		    NGE_PMU_DIDLE_LIMIT_DEF);
10925574Smx205022 
10935574Smx205022 		/* Enable the core/device idle timer in PMU control 2 */
10945574Smx205022 		pmu_cntl2.cntl2_val = nge_reg_get32(ngep, NGE_PMU_CNTL2);
10955574Smx205022 		pmu_cntl2.cntl2_bits.cidle_timer = NGE_SET;
10965574Smx205022 		pmu_cntl2.cntl2_bits.didle_timer = NGE_SET;
10975574Smx205022 		pmu_cntl2.cntl2_bits.core_enable = NGE_SET;
10985574Smx205022 		pmu_cntl2.cntl2_bits.dev_enable = NGE_SET;
10995574Smx205022 		nge_reg_put32(ngep, NGE_PMU_CNTL2, pmu_cntl2.cntl2_val);
11005574Smx205022 	}
11015848Sjj146644 	/*
11025848Sjj146644 	 * Stop the chipset and clear buffer management
11035848Sjj146644 	 */
11045848Sjj146644 	err = nge_chip_stop(ngep, B_FALSE);
11055848Sjj146644 	if (err == DDI_FAILURE)
11065848Sjj146644 		return (err);
11075574Smx205022 	/*
11085574Smx205022 	 * Clear the power state bits for phy since interface no longer
11095574Smx205022 	 * works after rebooting from Windows on a multi-boot machine
11105574Smx205022 	 */
11115574Smx205022 	if (ngep->chipinfo.device == DEVICE_ID_MCP51_268 ||
11125574Smx205022 	    ngep->chipinfo.device == DEVICE_ID_MCP51_269 ||
11135574Smx205022 	    ngep->chipinfo.device == DEVICE_ID_MCP55_372 ||
11145574Smx205022 	    ngep->chipinfo.device == DEVICE_ID_MCP55_373 ||
11155574Smx205022 	    ngep->chipinfo.device == DEVICE_ID_MCP61_3EE ||
11169708SZhen.W@Sun.COM 	    ngep->chipinfo.device == DEVICE_ID_MCP61_3EF ||
11179906SZhen.W@Sun.COM 	    ngep->chipinfo.device == DEVICE_ID_MCP77_760 ||
11189906SZhen.W@Sun.COM 	    ngep->chipinfo.device == DEVICE_ID_MCP79_AB0) {
11195574Smx205022 
11205574Smx205022 		pm_cntl2.cntl_val = nge_reg_get32(ngep, NGE_PM_CNTL2);
11215574Smx205022 		/* bring phy out of coma mode */
11225574Smx205022 		pm_cntl2.cntl_bits.phy_coma_set = NGE_CLEAR;
11235574Smx205022 		/* disable auto reset coma bits */
11245574Smx205022 		pm_cntl2.cntl_bits.resv4 = NGE_CLEAR;
11255574Smx205022 		/* restore power to gated clocks */
11265574Smx205022 		pm_cntl2.cntl_bits.resv8_11 = NGE_CLEAR;
11275574Smx205022 		nge_reg_put32(ngep, NGE_PM_CNTL2, pm_cntl2.cntl_val);
11285574Smx205022 	}
11295574Smx205022 
11305574Smx205022 	ngep->nge_chip_state = NGE_CHIP_RESET;
11315574Smx205022 	return (DDI_SUCCESS);
11325574Smx205022 }
11335574Smx205022 
11345574Smx205022 int
nge_chip_start(nge_t * ngep)11355574Smx205022 nge_chip_start(nge_t *ngep)
11365574Smx205022 {
11375574Smx205022 	int err;
11385574Smx205022 	nge_itc itc;
11395574Smx205022 	nge_tx_cntl tx_cntl;
11405574Smx205022 	nge_rx_cntrl0 rx_cntl0;
11415574Smx205022 	nge_rx_cntl1 rx_cntl1;
11425574Smx205022 	nge_tx_en tx_en;
11435574Smx205022 	nge_rx_en rx_en;
11445574Smx205022 	nge_mii_cs mii_cs;
11455574Smx205022 	nge_swtr_cntl swtr_cntl;
11465574Smx205022 	nge_rx_fifo_wm rx_fifo;
11475574Smx205022 	nge_intr_mask intr_mask;
11485574Smx205022 	nge_mintr_mask mintr_mask;
11495574Smx205022 	nge_dev_spec_param_t	*dev_param_p;
11505574Smx205022 
11515574Smx205022 	NGE_TRACE(("nge_chip_start($%p)", (void *)ngep));
11525574Smx205022 
11535574Smx205022 	/*
11545574Smx205022 	 * Setup buffer management
11555574Smx205022 	 */
11565574Smx205022 	err = nge_buff_setup(ngep);
11575574Smx205022 	if (err == DDI_FAILURE)
11585574Smx205022 		return (err);
11595574Smx205022 
11605574Smx205022 	dev_param_p = &ngep->dev_spec_param;
11615574Smx205022 
11625574Smx205022 	/*
11635574Smx205022 	 * Enable polling attribute
11645574Smx205022 	 */
11655574Smx205022 	mii_cs.cs_val = nge_reg_get32(ngep, NGE_MII_CS);
11665574Smx205022 	mii_cs.cs_bits.ap_paddr = ngep->phy_xmii_addr;
11675574Smx205022 	mii_cs.cs_bits.ap_en = NGE_SET;
11685574Smx205022 	mii_cs.cs_bits.ap_intv = MII_POLL_INTV;
11695574Smx205022 	nge_reg_put32(ngep, NGE_MII_CS, mii_cs.cs_val);
11705574Smx205022 
11715574Smx205022 	/*
11725574Smx205022 	 * Setup link
11735574Smx205022 	 */
11745574Smx205022 	(*ngep->physops->phys_update)(ngep);
11755574Smx205022 
11765574Smx205022 	/*
11775574Smx205022 	 * Configure the tx's parameters
11785574Smx205022 	 */
11795574Smx205022 	tx_cntl.cntl_val = nge_reg_get32(ngep, NGE_TX_CNTL);
11805574Smx205022 	if (dev_param_p->tx_pause_frame)
11815574Smx205022 		tx_cntl.cntl_bits.paen = NGE_SET;
11825574Smx205022 	else
11835574Smx205022 		tx_cntl.cntl_bits.paen = NGE_CLEAR;
11845574Smx205022 	tx_cntl.cntl_bits.retry_en = NGE_SET;
11855574Smx205022 	tx_cntl.cntl_bits.pad_en = NGE_SET;
11865574Smx205022 	tx_cntl.cntl_bits.fappend_en = NGE_SET;
11875574Smx205022 	tx_cntl.cntl_bits.two_def_en = NGE_SET;
11885574Smx205022 	tx_cntl.cntl_bits.max_retry = 15;
11895574Smx205022 	tx_cntl.cntl_bits.burst_en = NGE_CLEAR;
11905574Smx205022 	tx_cntl.cntl_bits.uflo_err_mask = NGE_CLEAR;
11915574Smx205022 	tx_cntl.cntl_bits.tlcol_mask = NGE_CLEAR;
11925574Smx205022 	tx_cntl.cntl_bits.lcar_mask = NGE_CLEAR;
11935574Smx205022 	tx_cntl.cntl_bits.def_mask = NGE_CLEAR;
11945574Smx205022 	tx_cntl.cntl_bits.exdef_mask = NGE_SET;
11955574Smx205022 	tx_cntl.cntl_bits.lcar_mask = NGE_SET;
11965574Smx205022 	tx_cntl.cntl_bits.tlcol_mask = NGE_SET;
11975574Smx205022 	tx_cntl.cntl_bits.uflo_err_mask = NGE_SET;
11985574Smx205022 	tx_cntl.cntl_bits.jam_seq_en = NGE_CLEAR;
11995574Smx205022 	nge_reg_put32(ngep, NGE_TX_CNTL, tx_cntl.cntl_val);
12005574Smx205022 
12015574Smx205022 
12025574Smx205022 	/*
12035574Smx205022 	 * Configure the parameters of Rx's state machine
12045574Smx205022 	 * Enabe the parameters:
12055574Smx205022 	 * 1). Pad Strip
12065574Smx205022 	 * 2). FCS Relay
12075574Smx205022 	 * 3). Pause
12085574Smx205022 	 * 4). Address filter
12095574Smx205022 	 * 5). Runt Packet receive
12105574Smx205022 	 * 6). Broadcast
12115574Smx205022 	 * 7). Receive Deferral
12125574Smx205022 	 *
12135574Smx205022 	 * Disable the following parameters for decreasing
12145574Smx205022 	 * the number of interrupts:
12155574Smx205022 	 * 1). Runt Inerrupt.
12165574Smx205022 	 * 2). Rx's Late Collision interrupt.
12175574Smx205022 	 * 3). Rx's Max length Error Interrupt.
12185574Smx205022 	 * 4). Rx's Length Field error Interrupt.
12195574Smx205022 	 * 5). Rx's FCS error interrupt.
12205574Smx205022 	 * 6). Rx's overflow error interrupt.
12215574Smx205022 	 * 7). Rx's Frame alignment error interrupt.
12225574Smx205022 	 */
12235574Smx205022 	rx_cntl0.cntl_val = nge_reg_get32(ngep, NGE_RX_CNTL0);
12245574Smx205022 	rx_cntl0.cntl_bits.padsen = NGE_CLEAR;
12255574Smx205022 	rx_cntl0.cntl_bits.fcsren = NGE_CLEAR;
12265574Smx205022 	if (dev_param_p->rx_pause_frame)
12275574Smx205022 		rx_cntl0.cntl_bits.paen = NGE_SET;
12285574Smx205022 	else
12295574Smx205022 		rx_cntl0.cntl_bits.paen = NGE_CLEAR;
12305574Smx205022 	rx_cntl0.cntl_bits.lben = NGE_CLEAR;
12315574Smx205022 	rx_cntl0.cntl_bits.afen = NGE_SET;
12325574Smx205022 	rx_cntl0.cntl_bits.runten = NGE_CLEAR;
12335574Smx205022 	rx_cntl0.cntl_bits.brdis = NGE_CLEAR;
12345574Smx205022 	rx_cntl0.cntl_bits.rdfen = NGE_CLEAR;
12355574Smx205022 	rx_cntl0.cntl_bits.runtm = NGE_CLEAR;
12365574Smx205022 	rx_cntl0.cntl_bits.slfb = NGE_CLEAR;
12375574Smx205022 	rx_cntl0.cntl_bits.rlcolm = NGE_CLEAR;
12385574Smx205022 	rx_cntl0.cntl_bits.maxerm = NGE_CLEAR;
12395574Smx205022 	rx_cntl0.cntl_bits.lferm = NGE_CLEAR;
12405574Smx205022 	rx_cntl0.cntl_bits.crcm = NGE_CLEAR;
12415574Smx205022 	rx_cntl0.cntl_bits.ofolm = NGE_CLEAR;
12425574Smx205022 	rx_cntl0.cntl_bits.framerm = NGE_CLEAR;
12435574Smx205022 	nge_reg_put32(ngep, NGE_RX_CNTL0, rx_cntl0.cntl_val);
12445574Smx205022 
12455574Smx205022 	/*
12465574Smx205022 	 * Configure the watermark for the rx's statemachine
12475574Smx205022 	 */
12485574Smx205022 	rx_fifo.wm_val = nge_reg_get32(ngep, NGE_RX_FIFO_WM);
12495574Smx205022 	rx_fifo.wm_bits.data_hwm = ngep->rx_datahwm;
12505574Smx205022 	rx_fifo.wm_bits.prd_lwm = ngep->rx_prdlwm;
12515574Smx205022 	rx_fifo.wm_bits.prd_hwm = ngep->rx_prdhwm;
12525574Smx205022 	nge_reg_put32(ngep, NGE_RX_FIFO_WM, rx_fifo.wm_val);
12535574Smx205022 
12545574Smx205022 	/*
12555574Smx205022 	 * Configure the deffer time slot for rx's state machine
12565574Smx205022 	 */
12575574Smx205022 	nge_reg_put8(ngep, NGE_RX_DEf, ngep->rx_def);
12585574Smx205022 
12595574Smx205022 	/*
12605574Smx205022 	 * Configure the length of rx's packet
12615574Smx205022 	 */
12625574Smx205022 	rx_cntl1.cntl_val = nge_reg_get32(ngep, NGE_RX_CNTL1);
12635574Smx205022 	rx_cntl1.cntl_bits.length = ngep->max_sdu;
12645574Smx205022 	nge_reg_put32(ngep, NGE_RX_CNTL1, rx_cntl1.cntl_val);
12655574Smx205022 	/*
12665574Smx205022 	 * Enable Tx's state machine
12675574Smx205022 	 */
12685574Smx205022 	tx_en.val = nge_reg_get8(ngep, NGE_TX_EN);
12695574Smx205022 	tx_en.bits.tx_en = NGE_SET;
12705574Smx205022 	nge_reg_put8(ngep, NGE_TX_EN, tx_en.val);
12715574Smx205022 
12725574Smx205022 	/*
12735574Smx205022 	 * Enable Rx's state machine
12745574Smx205022 	 */
12755574Smx205022 	rx_en.val = nge_reg_get8(ngep, NGE_RX_EN);
12765574Smx205022 	rx_en.bits.rx_en = NGE_SET;
12775574Smx205022 	nge_reg_put8(ngep, NGE_RX_EN, rx_en.val);
12785574Smx205022 
12795574Smx205022 	itc.itc_val = nge_reg_get32(ngep, NGE_SWTR_ITC);
12805574Smx205022 	itc.itc_bits.sw_intv = ngep->sw_intr_intv;
12815574Smx205022 	nge_reg_put32(ngep, NGE_SWTR_ITC, itc.itc_val);
12825574Smx205022 
12835574Smx205022 	swtr_cntl.ctrl_val = nge_reg_get8(ngep, NGE_SWTR_CNTL);
12845574Smx205022 	swtr_cntl.cntl_bits.sten = NGE_SET;
12855574Smx205022 	swtr_cntl.cntl_bits.stren = NGE_SET;
12865574Smx205022 	nge_reg_put32(ngep, NGE_SWTR_CNTL, swtr_cntl.ctrl_val);
12875574Smx205022 
12885574Smx205022 	/*
12895574Smx205022 	 * Disable all mii read/write operation Interrupt
12905574Smx205022 	 */
12915574Smx205022 	mintr_mask.mask_val = nge_reg_get8(ngep, NGE_MINTR_MASK);
12925574Smx205022 	mintr_mask.mask_bits.mrei = NGE_CLEAR;
12935574Smx205022 	mintr_mask.mask_bits.mcc2 = NGE_CLEAR;
12945574Smx205022 	mintr_mask.mask_bits.mcc1 = NGE_CLEAR;
12955574Smx205022 	mintr_mask.mask_bits.mapi = NGE_SET;
12965574Smx205022 	mintr_mask.mask_bits.mpdi = NGE_SET;
12975574Smx205022 	nge_reg_put8(ngep, NGE_MINTR_MASK, mintr_mask.mask_val);
12985574Smx205022 
12995574Smx205022 	/*
13005574Smx205022 	 * Enable all interrupt event
13015574Smx205022 	 */
13025574Smx205022 	intr_mask.mask_val = nge_reg_get32(ngep, NGE_INTR_MASK);
13035574Smx205022 	intr_mask.mask_bits.reint = NGE_SET;
13045574Smx205022 	intr_mask.mask_bits.rcint = NGE_SET;
13055574Smx205022 	intr_mask.mask_bits.miss = NGE_SET;
1306*10615SZhen.W@Sun.COM 	intr_mask.mask_bits.teint = NGE_SET;
1307*10615SZhen.W@Sun.COM 	intr_mask.mask_bits.tcint = NGE_CLEAR;
13085574Smx205022 	intr_mask.mask_bits.stint = NGE_CLEAR;
13095574Smx205022 	intr_mask.mask_bits.mint = NGE_CLEAR;
13105574Smx205022 	intr_mask.mask_bits.rfint = NGE_CLEAR;
1311*10615SZhen.W@Sun.COM 	intr_mask.mask_bits.tfint = NGE_SET;
13125574Smx205022 	intr_mask.mask_bits.feint = NGE_SET;
13135574Smx205022 	intr_mask.mask_bits.resv10 = NGE_CLEAR;
13145574Smx205022 	intr_mask.mask_bits.resv11 = NGE_CLEAR;
13155574Smx205022 	intr_mask.mask_bits.resv12 = NGE_CLEAR;
13165574Smx205022 	intr_mask.mask_bits.resv13 = NGE_CLEAR;
13175574Smx205022 	intr_mask.mask_bits.phyint = NGE_CLEAR;
13185574Smx205022 	ngep->intr_masks = intr_mask.mask_val;
13195574Smx205022 	nge_reg_put32(ngep, NGE_INTR_MASK, intr_mask.mask_val);
13205574Smx205022 	ngep->nge_chip_state = NGE_CHIP_RUNNING;
13215574Smx205022 	return (DDI_SUCCESS);
13225574Smx205022 }
13235574Smx205022 
13245574Smx205022 /*
13255574Smx205022  * nge_chip_sync() -- program the chip with the unicast MAC address,
13265574Smx205022  * the multicast hash table, the required level of promiscuity.
13275574Smx205022  */
13285574Smx205022 void
nge_chip_sync(nge_t * ngep)13295574Smx205022 nge_chip_sync(nge_t *ngep)
13305574Smx205022 {
13315574Smx205022 	uint8_t i;
13325574Smx205022 	uint64_t macaddr;
13335574Smx205022 	uint64_t mul_addr;
13345574Smx205022 	uint64_t mul_mask;
13355574Smx205022 	nge_rx_cntrl0 rx_cntl;
13365574Smx205022 	nge_uni_addr1 uni_adr1;
13375574Smx205022 
13385574Smx205022 	NGE_TRACE(("nge_chip_sync($%p)", (void *)ngep));
13395574Smx205022 
13405574Smx205022 	macaddr = 0x0ull;
13415574Smx205022 	mul_addr = 0x0ull;
13425574Smx205022 	mul_mask = 0x0ull;
13435574Smx205022 	rx_cntl.cntl_val = nge_reg_get32(ngep, NGE_RX_CNTL0);
13445574Smx205022 
13455574Smx205022 	if (ngep->promisc) {
13465574Smx205022 		rx_cntl.cntl_bits.afen = NGE_CLEAR;
13475574Smx205022 		rx_cntl.cntl_bits.brdis = NGE_SET;
13485574Smx205022 	} else {
13495574Smx205022 		rx_cntl.cntl_bits.afen = NGE_SET;
13505574Smx205022 		rx_cntl.cntl_bits.brdis = NGE_CLEAR;
13515574Smx205022 	}
13525574Smx205022 
13535574Smx205022 	/*
13545574Smx205022 	 * Transform the MAC address from host to chip format, the unicast
13555574Smx205022 	 * MAC address(es) ...
13565574Smx205022 	 */
13575574Smx205022 	for (i = ETHERADDRL, macaddr = 0ull; i != 0; --i) {
13585574Smx205022 		macaddr |= ngep->cur_uni_addr.addr[i-1];
13595574Smx205022 		macaddr <<= (i > 1) ? 8 : 0;
13605574Smx205022 	}
13615574Smx205022 
13625574Smx205022 	nge_reg_put32(ngep, NGE_UNI_ADDR0, (uint32_t)macaddr);
13635574Smx205022 	macaddr = macaddr >>32;
13645574Smx205022 	uni_adr1.addr_val = nge_reg_get32(ngep, NGE_UNI_ADDR1);
13655574Smx205022 	uni_adr1.addr_bits.addr = (uint16_t)macaddr;
13665574Smx205022 	uni_adr1.addr_bits.resv16_31 = (uint16_t)0;
13675574Smx205022 	nge_reg_put32(ngep, NGE_UNI_ADDR1, uni_adr1.addr_val);
13685574Smx205022 
13695574Smx205022 	/*
13705574Smx205022 	 * Reprogram the  multicast address table ...
13715574Smx205022 	 */
13725574Smx205022 	for (i = ETHERADDRL, mul_addr = 0ull; i != 0; --i) {
13735574Smx205022 		mul_addr |= ngep->cur_mul_addr.addr[i-1];
13745574Smx205022 		mul_addr <<= (i > 1) ? 8 : 0;
13755574Smx205022 		mul_mask |= ngep->cur_mul_mask.addr[i-1];
13765574Smx205022 		mul_mask <<= (i > 1) ? 8 : 0;
13775574Smx205022 	}
13785574Smx205022 	nge_reg_put32(ngep, NGE_MUL_ADDR0, (uint32_t)mul_addr);
13795574Smx205022 	mul_addr >>= 32;
13805574Smx205022 	nge_reg_put32(ngep, NGE_MUL_ADDR1, mul_addr);
13815574Smx205022 	nge_reg_put32(ngep, NGE_MUL_MASK, (uint32_t)mul_mask);
13825574Smx205022 	mul_mask >>= 32;
13835574Smx205022 	nge_reg_put32(ngep, NGE_MUL_MASK1, mul_mask);
13845574Smx205022 	/*
13855574Smx205022 	 * Set or clear the PROMISCUOUS mode bit
13865574Smx205022 	 */
13875574Smx205022 	nge_reg_put32(ngep, NGE_RX_CNTL0, rx_cntl.cntl_val);
13885574Smx205022 	/*
13895574Smx205022 	 * For internal PHY loopback, the link will
13905574Smx205022 	 * not be up, so it need to sync mac modes directly.
13915574Smx205022 	 */
13925574Smx205022 	if (ngep->param_loop_mode == NGE_LOOP_INTERNAL_PHY)
13935574Smx205022 		nge_sync_mac_modes(ngep);
13945574Smx205022 }
13955574Smx205022 
13965574Smx205022 static void
nge_chip_err(nge_t * ngep)13975574Smx205022 nge_chip_err(nge_t *ngep)
13985574Smx205022 {
13995574Smx205022 	nge_reg010 reg010_ins;
14005574Smx205022 	nge_sw_statistics_t *psw_stat;
14015574Smx205022 	nge_intr_mask intr_mask;
14025574Smx205022 
14035574Smx205022 	NGE_TRACE(("nge_chip_err($%p)", (void *)ngep));
14045574Smx205022 
14055574Smx205022 	psw_stat = (nge_sw_statistics_t *)&ngep->statistics.sw_statistics;
14065574Smx205022 	reg010_ins.reg010_val = nge_reg_get32(ngep, NGE_REG010);
14075574Smx205022 	if (reg010_ins.reg010_bits.resv0)
14085574Smx205022 		psw_stat->fe_err.tso_err_mss ++;
14095574Smx205022 
14105574Smx205022 	if (reg010_ins.reg010_bits.resv1)
14115574Smx205022 		psw_stat->fe_err.tso_dis ++;
14125574Smx205022 
14135574Smx205022 	if (reg010_ins.reg010_bits.resv2)
14145574Smx205022 		psw_stat->fe_err.tso_err_nosum ++;
14155574Smx205022 
14165574Smx205022 	if (reg010_ins.reg010_bits.resv3)
14175574Smx205022 		psw_stat->fe_err.tso_err_hov ++;
14185574Smx205022 
14195574Smx205022 	if (reg010_ins.reg010_bits.resv4)
14205574Smx205022 		psw_stat->fe_err.tso_err_huf ++;
14215574Smx205022 
14225574Smx205022 	if (reg010_ins.reg010_bits.resv5)
14235574Smx205022 		psw_stat->fe_err.tso_err_l2 ++;
14245574Smx205022 
14255574Smx205022 	if (reg010_ins.reg010_bits.resv6)
14265574Smx205022 		psw_stat->fe_err.tso_err_ip ++;
14275574Smx205022 
14285574Smx205022 	if (reg010_ins.reg010_bits.resv7)
14295574Smx205022 		psw_stat->fe_err.tso_err_l4 ++;
14305574Smx205022 
14315574Smx205022 	if (reg010_ins.reg010_bits.resv8)
14325574Smx205022 		psw_stat->fe_err.tso_err_tcp ++;
14335574Smx205022 
14345574Smx205022 	if (reg010_ins.reg010_bits.resv9)
14355574Smx205022 		psw_stat->fe_err.hsum_err_ip ++;
14365574Smx205022 
14375574Smx205022 	if (reg010_ins.reg010_bits.resv10)
14385574Smx205022 		psw_stat->fe_err.hsum_err_l4 ++;
14395574Smx205022 
14405574Smx205022 	if (reg010_ins.reg010_val != 0) {
14415574Smx205022 
14425574Smx205022 		/*
14435574Smx205022 		 * Fatal error is triggered by malformed driver commands.
14445574Smx205022 		 * Disable unless debugging.
14455574Smx205022 		 */
14465574Smx205022 		intr_mask.mask_val = nge_reg_get32(ngep, NGE_INTR_MASK);
14475574Smx205022 		intr_mask.mask_bits.feint = NGE_CLEAR;
14485574Smx205022 		nge_reg_put32(ngep, NGE_INTR_MASK, intr_mask.mask_val);
14495574Smx205022 		ngep->intr_masks = intr_mask.mask_val;
14505574Smx205022 
14515574Smx205022 	}
14525574Smx205022 }
14535574Smx205022 
14545574Smx205022 static void
nge_sync_mac_modes(nge_t * ngep)14555574Smx205022 nge_sync_mac_modes(nge_t *ngep)
14565574Smx205022 {
14575574Smx205022 	nge_tx_def tx_def;
14585574Smx205022 	nge_tx_fifo_wm tx_fifo;
14595574Smx205022 	nge_bkoff_cntl bk_cntl;
14605574Smx205022 	nge_mac2phy m2p;
14615574Smx205022 	nge_rx_cntrl0 rx_cntl0;
146210496SLi-Zhen.You@Sun.COM 	nge_tx_cntl tx_cntl;
14635574Smx205022 	nge_dev_spec_param_t	*dev_param_p;
14645574Smx205022 
14655574Smx205022 	dev_param_p = &ngep->dev_spec_param;
14665574Smx205022 
14675574Smx205022 	tx_def.def_val = nge_reg_get32(ngep, NGE_TX_DEF);
14685574Smx205022 	m2p.m2p_val = nge_reg_get32(ngep, NGE_MAC2PHY);
14695574Smx205022 	tx_fifo.wm_val = nge_reg_get32(ngep, NGE_TX_FIFO_WM);
14705574Smx205022 	bk_cntl.cntl_val = nge_reg_get32(ngep, NGE_BKOFF_CNTL);
14715574Smx205022 	bk_cntl.bkoff_bits.rseed = BKOFF_RSEED;
14725574Smx205022 	switch (ngep->param_link_speed) {
14735574Smx205022 	case 10:
14745574Smx205022 		m2p.m2p_bits.speed = low_speed;
14755574Smx205022 		tx_def.def_bits.ifg1_def = TX_IFG1_DEFAULT;
14765574Smx205022 		if (ngep->phy_mode == RGMII_IN) {
14775574Smx205022 			tx_def.def_bits.ifg2_def = TX_IFG2_RGMII_10_100;
14785574Smx205022 			tx_def.def_bits.if_def = TX_IFG_RGMII_OTHER;
14795574Smx205022 		} else {
14805574Smx205022 			tx_def.def_bits.if_def = TX_TIFG_MII;
14815574Smx205022 			tx_def.def_bits.ifg2_def = TX_IFG2_MII;
14825574Smx205022 		}
14835574Smx205022 		tx_fifo.wm_bits.nbfb_wm = TX_FIFO_NOB_WM_MII;
14845574Smx205022 		bk_cntl.bkoff_bits.sltm = BKOFF_SLIM_MII;
14855574Smx205022 		break;
14865574Smx205022 
14875574Smx205022 	case 100:
14885574Smx205022 		m2p.m2p_bits.speed = fast_speed;
14895574Smx205022 		tx_def.def_bits.ifg1_def = TX_IFG1_DEFAULT;
14905574Smx205022 		if (ngep->phy_mode == RGMII_IN) {
14915574Smx205022 			tx_def.def_bits.ifg2_def = TX_IFG2_RGMII_10_100;
14925574Smx205022 			tx_def.def_bits.if_def = TX_IFG_RGMII_OTHER;
14935574Smx205022 		} else {
14945574Smx205022 			tx_def.def_bits.if_def = TX_TIFG_MII;
14955574Smx205022 			tx_def.def_bits.ifg2_def = TX_IFG2_MII;
14965574Smx205022 		}
14975574Smx205022 		tx_fifo.wm_bits.nbfb_wm = TX_FIFO_NOB_WM_MII;
14985574Smx205022 		bk_cntl.bkoff_bits.sltm = BKOFF_SLIM_MII;
14995574Smx205022 		break;
15005574Smx205022 
15015574Smx205022 	case 1000:
15025574Smx205022 		m2p.m2p_bits.speed = giga_speed;
15035574Smx205022 		tx_def.def_bits.ifg1_def = TX_IFG1_DEFAULT;
15045574Smx205022 		if (ngep->param_link_duplex == LINK_DUPLEX_FULL) {
15055574Smx205022 			tx_def.def_bits.ifg2_def = TX_IFG2_RGMII_1000;
15065574Smx205022 			tx_def.def_bits.if_def = TX_IFG_RGMII_1000_FD;
15075574Smx205022 		} else {
15085574Smx205022 			tx_def.def_bits.ifg2_def = TX_IFG2_RGMII_1000;
15095574Smx205022 			tx_def.def_bits.if_def = TX_IFG_RGMII_OTHER;
15105574Smx205022 		}
15115574Smx205022 
15125574Smx205022 		tx_fifo.wm_bits.nbfb_wm = TX_FIFO_NOB_WM_GMII;
15135574Smx205022 		bk_cntl.bkoff_bits.sltm = BKOFF_SLIM_GMII;
15145574Smx205022 		break;
15155574Smx205022 	}
15165574Smx205022 
15175574Smx205022 	if (ngep->chipinfo.device == DEVICE_ID_MCP55_373 ||
15185574Smx205022 	    ngep->chipinfo.device == DEVICE_ID_MCP55_372) {
15195574Smx205022 		m2p.m2p_bits.phyintr = NGE_CLEAR;
15205574Smx205022 		m2p.m2p_bits.phyintrlvl = NGE_CLEAR;
15215574Smx205022 	}
15225574Smx205022 	if (ngep->param_link_duplex == LINK_DUPLEX_HALF) {
15235574Smx205022 		m2p.m2p_bits.hdup_en = NGE_SET;
15245574Smx205022 	}
15255574Smx205022 	else
15265574Smx205022 		m2p.m2p_bits.hdup_en = NGE_CLEAR;
15275574Smx205022 	nge_reg_put32(ngep, NGE_MAC2PHY, m2p.m2p_val);
15285574Smx205022 	nge_reg_put32(ngep, NGE_TX_DEF, tx_def.def_val);
15295574Smx205022 
15305574Smx205022 	tx_fifo.wm_bits.data_lwm = TX_FIFO_DATA_LWM;
15315574Smx205022 	tx_fifo.wm_bits.prd_lwm = TX_FIFO_PRD_LWM;
15325574Smx205022 	tx_fifo.wm_bits.uprd_hwm = TX_FIFO_PRD_HWM;
15335574Smx205022 	tx_fifo.wm_bits.fb_wm = TX_FIFO_TBFW;
15345574Smx205022 	nge_reg_put32(ngep, NGE_TX_FIFO_WM, tx_fifo.wm_val);
15355574Smx205022 
15365574Smx205022 	nge_reg_put32(ngep, NGE_BKOFF_CNTL, bk_cntl.cntl_val);
15375574Smx205022 
15385574Smx205022 	rx_cntl0.cntl_val = nge_reg_get32(ngep, NGE_RX_CNTL0);
153910496SLi-Zhen.You@Sun.COM 	if (ngep->param_link_rx_pause && dev_param_p->rx_pause_frame) {
154010496SLi-Zhen.You@Sun.COM 		if (rx_cntl0.cntl_bits.paen == NGE_CLEAR) {
154110496SLi-Zhen.You@Sun.COM 			rx_cntl0.cntl_bits.paen = NGE_SET;
154210496SLi-Zhen.You@Sun.COM 			nge_reg_put32(ngep, NGE_RX_CNTL0, rx_cntl0.cntl_val);
154310496SLi-Zhen.You@Sun.COM 	}
154410496SLi-Zhen.You@Sun.COM 	} else {
154510496SLi-Zhen.You@Sun.COM 		if (rx_cntl0.cntl_bits.paen == NGE_SET) {
154610496SLi-Zhen.You@Sun.COM 			rx_cntl0.cntl_bits.paen = NGE_CLEAR;
154710496SLi-Zhen.You@Sun.COM 			nge_reg_put32(ngep, NGE_RX_CNTL0, rx_cntl0.cntl_val);
154810496SLi-Zhen.You@Sun.COM 		}
154910496SLi-Zhen.You@Sun.COM 	}
155010496SLi-Zhen.You@Sun.COM 
155110496SLi-Zhen.You@Sun.COM 	tx_cntl.cntl_val = nge_reg_get32(ngep, NGE_TX_CNTL);
155210496SLi-Zhen.You@Sun.COM 	if (ngep->param_link_tx_pause && dev_param_p->tx_pause_frame) {
155310496SLi-Zhen.You@Sun.COM 		if (tx_cntl.cntl_bits.paen == NGE_CLEAR) {
155410496SLi-Zhen.You@Sun.COM 			tx_cntl.cntl_bits.paen = NGE_SET;
155510496SLi-Zhen.You@Sun.COM 			nge_reg_put32(ngep, NGE_TX_CNTL, tx_cntl.cntl_val);
155610496SLi-Zhen.You@Sun.COM 		}
155710496SLi-Zhen.You@Sun.COM 	} else {
155810496SLi-Zhen.You@Sun.COM 		if (tx_cntl.cntl_bits.paen == NGE_SET) {
155910496SLi-Zhen.You@Sun.COM 			tx_cntl.cntl_bits.paen = NGE_CLEAR;
156010496SLi-Zhen.You@Sun.COM 			nge_reg_put32(ngep, NGE_TX_CNTL, tx_cntl.cntl_val);
156110496SLi-Zhen.You@Sun.COM 		}
156210496SLi-Zhen.You@Sun.COM 	}
15635574Smx205022 }
15645574Smx205022 
15655574Smx205022 /*
15665574Smx205022  * Handler for hardware link state change.
15675574Smx205022  *
15685574Smx205022  * When this routine is called, the hardware link state has changed
15695574Smx205022  * and the new state is reflected in the param_* variables.  Here
15705574Smx205022  * we must update the softstate, reprogram the MAC to match, and
15715574Smx205022  * record the change in the log and/or on the console.
15725574Smx205022  */
15735574Smx205022 static void
nge_factotum_link_handler(nge_t * ngep)15745574Smx205022 nge_factotum_link_handler(nge_t *ngep)
15755574Smx205022 {
15765574Smx205022 	/*
15775574Smx205022 	 * Update the s/w link_state
15785574Smx205022 	 */
15795574Smx205022 	if (ngep->param_link_up)
15805574Smx205022 		ngep->link_state = LINK_STATE_UP;
15815574Smx205022 	else
15825574Smx205022 		ngep->link_state = LINK_STATE_DOWN;
15835574Smx205022 
15845574Smx205022 	/*
15855574Smx205022 	 * Reprogram the MAC modes to match
15865574Smx205022 	 */
15875574Smx205022 	nge_sync_mac_modes(ngep);
15885574Smx205022 }
15895574Smx205022 
15905574Smx205022 static boolean_t
nge_factotum_link_check(nge_t * ngep)15915574Smx205022 nge_factotum_link_check(nge_t *ngep)
15925574Smx205022 {
15935574Smx205022 	boolean_t lchg;
15945574Smx205022 	boolean_t check;
15955574Smx205022 
15965574Smx205022 	ASSERT(mutex_owned(ngep->genlock));
15975574Smx205022 
15985574Smx205022 	(*ngep->physops->phys_check)(ngep);
15995574Smx205022 	switch (ngep->link_state) {
16005574Smx205022 	case LINK_STATE_UP:
16015574Smx205022 		lchg = (ngep->param_link_up == B_FALSE);
16025574Smx205022 		check = (ngep->param_link_up == B_FALSE);
16035574Smx205022 		break;
16045574Smx205022 
16055574Smx205022 	case LINK_STATE_DOWN:
16065574Smx205022 		lchg = (ngep->param_link_up == B_TRUE);
16075574Smx205022 		check = (ngep->param_link_up == B_TRUE);
16085574Smx205022 		break;
16095574Smx205022 
16105574Smx205022 	default:
16115574Smx205022 		check = B_TRUE;
16125574Smx205022 		break;
16135574Smx205022 	}
16145574Smx205022 
16155574Smx205022 	/*
16165574Smx205022 	 * If <check> is false, we're sure the link hasn't changed.
16175574Smx205022 	 * If true, however, it's not yet definitive; we have to call
16185574Smx205022 	 * nge_phys_check() to determine whether the link has settled
16195574Smx205022 	 * into a new state yet ... and if it has, then call the link
16205574Smx205022 	 * state change handler.But when the chip is 5700 in Dell 6650
16215574Smx205022 	 * ,even if check is false, the link may have changed.So we
16225574Smx205022 	 * have to call nge_phys_check() to determine the link state.
16235574Smx205022 	 */
16245574Smx205022 	if (check)
16255574Smx205022 		nge_factotum_link_handler(ngep);
16265574Smx205022 
16275574Smx205022 	return (lchg);
16285574Smx205022 }
16295574Smx205022 
16305574Smx205022 /*
16315574Smx205022  * Factotum routine to check for Tx stall, using the 'watchdog' counter
16325574Smx205022  */
16335574Smx205022 static boolean_t nge_factotum_stall_check(nge_t *ngep);
16345574Smx205022 
16355574Smx205022 static boolean_t
nge_factotum_stall_check(nge_t * ngep)16365574Smx205022 nge_factotum_stall_check(nge_t *ngep)
16375574Smx205022 {
16385574Smx205022 	uint32_t dogval;
1639*10615SZhen.W@Sun.COM 	send_ring_t *srp;
1640*10615SZhen.W@Sun.COM 	srp = ngep->send;
16415574Smx205022 	/*
16425574Smx205022 	 * Specific check for Tx stall ...
16435574Smx205022 	 *
16445574Smx205022 	 * The 'watchdog' counter is incremented whenever a packet
16455574Smx205022 	 * is queued, reset to 1 when some (but not all) buffers
16465574Smx205022 	 * are reclaimed, reset to 0 (disabled) when all buffers
16475574Smx205022 	 * are reclaimed, and shifted left here.  If it exceeds the
16485574Smx205022 	 * threshold value, the chip is assumed to have stalled and
16495574Smx205022 	 * is put into the ERROR state.  The factotum will then reset
16505574Smx205022 	 * it on the next pass.
16515574Smx205022 	 *
16525574Smx205022 	 * All of which should ensure that we don't get into a state
16535574Smx205022 	 * where packets are left pending indefinitely!
16545574Smx205022 	 */
1655*10615SZhen.W@Sun.COM 	if (ngep->watchdog == 0 &&
1656*10615SZhen.W@Sun.COM 	    srp->tx_free < srp->desc.nslots)
1657*10615SZhen.W@Sun.COM 		ngep->watchdog = 1;
16585574Smx205022 	dogval = nge_atomic_shl32(&ngep->watchdog, 1);
1659*10615SZhen.W@Sun.COM 	if (dogval >= nge_watchdog_check)
1660*10615SZhen.W@Sun.COM 		nge_tx_recycle(ngep, B_FALSE);
1661*10615SZhen.W@Sun.COM 	if (dogval < nge_watchdog_count)
16625574Smx205022 		return (B_FALSE);
1663*10615SZhen.W@Sun.COM 	else {
16645574Smx205022 		ngep->statistics.sw_statistics.tx_stall++;
16655574Smx205022 		return (B_TRUE);
16665574Smx205022 	}
16675574Smx205022 }
16685574Smx205022 
16695574Smx205022 
16705574Smx205022 /*
16715574Smx205022  * The factotum is woken up when there's something to do that we'd rather
16725574Smx205022  * not do from inside a hardware interrupt handler or high-level cyclic.
16735574Smx205022  * Its two main tasks are:
16745574Smx205022  *	reset & restart the chip after an error
16755574Smx205022  *	check the link status whenever necessary
16765574Smx205022  */
16775574Smx205022 /* ARGSUSED */
16785574Smx205022 uint_t
nge_chip_factotum(caddr_t args1,caddr_t args2)16795574Smx205022 nge_chip_factotum(caddr_t args1, caddr_t args2)
16805574Smx205022 {
16815574Smx205022 	uint_t result;
16825574Smx205022 	nge_t *ngep;
16835574Smx205022 	boolean_t err;
16845574Smx205022 	boolean_t linkchg;
16855574Smx205022 
16865574Smx205022 	ngep = (nge_t *)args1;
16875574Smx205022 
16885574Smx205022 	NGE_TRACE(("nge_chip_factotum($%p)", (void *)ngep));
16895574Smx205022 
16905574Smx205022 	mutex_enter(ngep->softlock);
16915574Smx205022 	if (ngep->factotum_flag == 0) {
16925574Smx205022 		mutex_exit(ngep->softlock);
16935574Smx205022 		return (DDI_INTR_UNCLAIMED);
16945574Smx205022 	}
16955574Smx205022 	ngep->factotum_flag = 0;
16965574Smx205022 	mutex_exit(ngep->softlock);
16975574Smx205022 	err = B_FALSE;
16985574Smx205022 	linkchg = B_FALSE;
16995574Smx205022 	result = DDI_INTR_CLAIMED;
17005574Smx205022 
17015574Smx205022 	mutex_enter(ngep->genlock);
17025574Smx205022 	switch (ngep->nge_chip_state) {
17035574Smx205022 	default:
17045574Smx205022 		break;
17055574Smx205022 
17065574Smx205022 	case NGE_CHIP_RUNNING:
17075574Smx205022 		linkchg = nge_factotum_link_check(ngep);
17085574Smx205022 		err = nge_factotum_stall_check(ngep);
17095574Smx205022 		break;
17105574Smx205022 
17115574Smx205022 	case NGE_CHIP_FAULT:
17125574Smx205022 		(void) nge_restart(ngep);
17135574Smx205022 		NGE_REPORT((ngep, "automatic recovery activated"));
17145574Smx205022 		break;
17155574Smx205022 	}
17165574Smx205022 
17175574Smx205022 	if (err)
17185574Smx205022 		(void) nge_chip_stop(ngep, B_TRUE);
17195574Smx205022 	mutex_exit(ngep->genlock);
17205574Smx205022 
17215574Smx205022 	/*
17225574Smx205022 	 * If the link state changed, tell the world about it (if
17235574Smx205022 	 * this version of MAC supports link state notification).
17245574Smx205022 	 * Note: can't do this while still holding the mutex.
17255574Smx205022 	 */
17265574Smx205022 	if (linkchg)
17275574Smx205022 		mac_link_update(ngep->mh, ngep->link_state);
17285574Smx205022 
17295574Smx205022 	return (result);
17305574Smx205022 
17315574Smx205022 }
17325574Smx205022 
17335574Smx205022 static void
nge_intr_handle(nge_t * ngep,nge_intr_src * pintr_src)17345574Smx205022 nge_intr_handle(nge_t *ngep, nge_intr_src *pintr_src)
17355574Smx205022 {
17365574Smx205022 	boolean_t brx;
17375574Smx205022 	boolean_t btx;
17385574Smx205022 	nge_mintr_src mintr_src;
17395574Smx205022 
17405574Smx205022 	brx = B_FALSE;
17415574Smx205022 	btx = B_FALSE;
17425574Smx205022 	ngep->statistics.sw_statistics.intr_count++;
17435574Smx205022 	ngep->statistics.sw_statistics.intr_lval = pintr_src->intr_val;
17445574Smx205022 	brx = (pintr_src->int_bits.reint | pintr_src->int_bits.miss
17455574Smx205022 	    | pintr_src->int_bits.rcint | pintr_src->int_bits.stint)
17465690Sjj146644 	    != 0 ? B_TRUE : B_FALSE;
17475574Smx205022 	if (pintr_src->int_bits.reint)
17485574Smx205022 		ngep->statistics.sw_statistics.rx_err++;
17495574Smx205022 	if (pintr_src->int_bits.miss)
17505574Smx205022 		ngep->statistics.sw_statistics.rx_nobuffer++;
17515574Smx205022 
1752*10615SZhen.W@Sun.COM 	btx = (pintr_src->int_bits.teint | pintr_src->int_bits.tfint)
17535690Sjj146644 	    != 0 ? B_TRUE : B_FALSE;
17545690Sjj146644 	if (btx)
17555690Sjj146644 		nge_tx_recycle(ngep, B_TRUE);
17565574Smx205022 	if (brx)
17575574Smx205022 		nge_receive(ngep);
17585574Smx205022 	if (pintr_src->int_bits.teint)
17595574Smx205022 		ngep->statistics.sw_statistics.tx_stop_err++;
17605659Sjj146644 	if (ngep->intr_moderation && brx) {
17615659Sjj146644 		if (ngep->poll) {
17625659Sjj146644 			if (ngep->recv_count < ngep->param_rx_intr_hwater) {
17635659Sjj146644 				ngep->quiet_time++;
17645659Sjj146644 				if (ngep->quiet_time ==
17655659Sjj146644 				    ngep->param_poll_quiet_time) {
17665659Sjj146644 					ngep->poll = B_FALSE;
17675659Sjj146644 					ngep->quiet_time = 0;
17685659Sjj146644 				}
17695659Sjj146644 			} else
17705659Sjj146644 				ngep->quiet_time = 0;
17715659Sjj146644 		} else {
17725659Sjj146644 			if (ngep->recv_count > ngep->param_rx_intr_lwater) {
17735659Sjj146644 				ngep->busy_time++;
17745659Sjj146644 				if (ngep->busy_time ==
17755659Sjj146644 				    ngep->param_poll_busy_time) {
17765659Sjj146644 					ngep->poll = B_TRUE;
17775659Sjj146644 					ngep->busy_time = 0;
17785659Sjj146644 				}
17795659Sjj146644 			} else
17805659Sjj146644 				ngep->busy_time = 0;
17815574Smx205022 		}
17825574Smx205022 	}
17835659Sjj146644 	ngep->recv_count = 0;
17845574Smx205022 	if (pintr_src->int_bits.feint)
17855574Smx205022 		nge_chip_err(ngep);
17865574Smx205022 	/* link interrupt, check the link state */
17875574Smx205022 	if (pintr_src->int_bits.mint) {
17885574Smx205022 		mintr_src.src_val = nge_reg_get32(ngep, NGE_MINTR_SRC);
17895574Smx205022 		nge_reg_put32(ngep, NGE_MINTR_SRC, mintr_src.src_val);
17905574Smx205022 		nge_wake_factotum(ngep);
17915574Smx205022 	}
17925574Smx205022 }
17935574Smx205022 
17945574Smx205022 /*
17955574Smx205022  *	nge_chip_intr() -- handle chip interrupts
17965574Smx205022  */
17975574Smx205022 /* ARGSUSED */
17985574Smx205022 uint_t
nge_chip_intr(caddr_t arg1,caddr_t arg2)17995574Smx205022 nge_chip_intr(caddr_t arg1, caddr_t arg2)
18005574Smx205022 {
18015574Smx205022 	nge_t *ngep = (nge_t *)arg1;
18025574Smx205022 	nge_intr_src intr_src;
18035574Smx205022 	nge_intr_mask intr_mask;
18045574Smx205022 
18055574Smx205022 	mutex_enter(ngep->genlock);
18065574Smx205022 
18075869Smx205022 	if (ngep->suspended) {
18085869Smx205022 		mutex_exit(ngep->genlock);
18095869Smx205022 		return (DDI_INTR_UNCLAIMED);
18105869Smx205022 	}
18115869Smx205022 
18125574Smx205022 	/*
18135574Smx205022 	 * Check whether chip's says it's asserting #INTA;
18145574Smx205022 	 * if not, don't process or claim the interrupt.
18155574Smx205022 	 */
18165574Smx205022 	intr_src.intr_val = nge_reg_get32(ngep, NGE_INTR_SRC);
18175574Smx205022 	if (intr_src.intr_val == 0) {
18185574Smx205022 		mutex_exit(ngep->genlock);
18195574Smx205022 		return (DDI_INTR_UNCLAIMED);
18205574Smx205022 	}
18215574Smx205022 	/*
18225574Smx205022 	 * Ack the interrupt
18235574Smx205022 	 */
18245574Smx205022 	nge_reg_put32(ngep, NGE_INTR_SRC, intr_src.intr_val);
18255574Smx205022 
18265574Smx205022 	if (ngep->nge_chip_state != NGE_CHIP_RUNNING) {
18275574Smx205022 		mutex_exit(ngep->genlock);
18285574Smx205022 		return (DDI_INTR_CLAIMED);
18295574Smx205022 	}
18305574Smx205022 	nge_intr_handle(ngep, &intr_src);
18315574Smx205022 	if (ngep->poll && !ngep->ch_intr_mode) {
18325574Smx205022 		intr_mask.mask_val = nge_reg_get32(ngep, NGE_INTR_MASK);
18335574Smx205022 		intr_mask.mask_bits.stint = NGE_SET;
18345659Sjj146644 		intr_mask.mask_bits.rcint = NGE_CLEAR;
18355574Smx205022 		nge_reg_put32(ngep, NGE_INTR_MASK, intr_mask.mask_val);
18365574Smx205022 		ngep->ch_intr_mode = B_TRUE;
18375574Smx205022 	} else if ((ngep->ch_intr_mode) && (!ngep->poll)) {
18385574Smx205022 		nge_reg_put32(ngep, NGE_INTR_MASK, ngep->intr_masks);
18395574Smx205022 		ngep->ch_intr_mode = B_FALSE;
18405574Smx205022 	}
18415574Smx205022 	mutex_exit(ngep->genlock);
18425574Smx205022 	return (DDI_INTR_CLAIMED);
18435574Smx205022 }
18445574Smx205022 
18455574Smx205022 static enum ioc_reply
nge_pp_ioctl(nge_t * ngep,int cmd,mblk_t * mp,struct iocblk * iocp)18465574Smx205022 nge_pp_ioctl(nge_t *ngep, int cmd, mblk_t *mp, struct iocblk *iocp)
18475574Smx205022 {
18485574Smx205022 	int err;
18495574Smx205022 	uint64_t sizemask;
18505574Smx205022 	uint64_t mem_va;
18515574Smx205022 	uint64_t maxoff;
18525574Smx205022 	boolean_t peek;
18535574Smx205022 	nge_peekpoke_t *ppd;
18545574Smx205022 	int (*ppfn)(nge_t *ngep, nge_peekpoke_t *ppd);
18555574Smx205022 
18565574Smx205022 	switch (cmd) {
18575574Smx205022 	default:
18585574Smx205022 		return (IOC_INVAL);
18595574Smx205022 
18605574Smx205022 	case NGE_PEEK:
18615574Smx205022 		peek = B_TRUE;
18625574Smx205022 		break;
18635574Smx205022 
18645574Smx205022 	case NGE_POKE:
18655574Smx205022 		peek = B_FALSE;
18665574Smx205022 		break;
18675574Smx205022 	}
18685574Smx205022 
18695574Smx205022 	/*
18705574Smx205022 	 * Validate format of ioctl
18715574Smx205022 	 */
18725574Smx205022 	if (iocp->ioc_count != sizeof (nge_peekpoke_t))
18735574Smx205022 		return (IOC_INVAL);
18745574Smx205022 	if (mp->b_cont == NULL)
18755574Smx205022 		return (IOC_INVAL);
18765574Smx205022 	ppd = (nge_peekpoke_t *)mp->b_cont->b_rptr;
18775574Smx205022 
18785574Smx205022 	/*
18795574Smx205022 	 * Validate request parameters
18805574Smx205022 	 */
18815574Smx205022 	switch (ppd->pp_acc_space) {
18825574Smx205022 	default:
18835574Smx205022 		return (IOC_INVAL);
18845574Smx205022 
18855574Smx205022 	case NGE_PP_SPACE_CFG:
18865574Smx205022 		/*
18875574Smx205022 		 * Config space
18885574Smx205022 		 */
18895574Smx205022 		sizemask = 8|4|2|1;
18905574Smx205022 		mem_va = 0;
18915574Smx205022 		maxoff = PCI_CONF_HDR_SIZE;
18925574Smx205022 		ppfn = peek ? nge_chip_peek_cfg : nge_chip_poke_cfg;
18935574Smx205022 		break;
18945574Smx205022 
18955574Smx205022 	case NGE_PP_SPACE_REG:
18965574Smx205022 		/*
18975574Smx205022 		 * Memory-mapped I/O space
18985574Smx205022 		 */
18995574Smx205022 		sizemask = 8|4|2|1;
19005574Smx205022 		mem_va = 0;
19015574Smx205022 		maxoff = NGE_REG_SIZE;
19025574Smx205022 		ppfn = peek ? nge_chip_peek_reg : nge_chip_poke_reg;
19035574Smx205022 		break;
19045574Smx205022 
19055574Smx205022 	case NGE_PP_SPACE_MII:
19065574Smx205022 		sizemask = 4|2|1;
19075574Smx205022 		mem_va = 0;
19085574Smx205022 		maxoff = NGE_MII_SIZE;
19095574Smx205022 		ppfn = peek ? nge_chip_peek_mii : nge_chip_poke_mii;
19105574Smx205022 		break;
19115574Smx205022 
19125574Smx205022 	case NGE_PP_SPACE_SEEPROM:
19135574Smx205022 		sizemask = 4|2|1;
19145574Smx205022 		mem_va = 0;
19155574Smx205022 		maxoff = NGE_SEEROM_SIZE;
19165574Smx205022 		ppfn = peek ? nge_chip_peek_seeprom : nge_chip_poke_seeprom;
19175574Smx205022 		break;
19185574Smx205022 	}
19195574Smx205022 
19205574Smx205022 	switch (ppd->pp_acc_size) {
19215574Smx205022 	default:
19225574Smx205022 		return (IOC_INVAL);
19235574Smx205022 
19245574Smx205022 	case 8:
19255574Smx205022 	case 4:
19265574Smx205022 	case 2:
19275574Smx205022 	case 1:
19285574Smx205022 		if ((ppd->pp_acc_size & sizemask) == 0)
19295574Smx205022 			return (IOC_INVAL);
19305574Smx205022 		break;
19315574Smx205022 	}
19325574Smx205022 
19335574Smx205022 	if ((ppd->pp_acc_offset % ppd->pp_acc_size) != 0)
19345574Smx205022 		return (IOC_INVAL);
19355574Smx205022 
19365574Smx205022 	if (ppd->pp_acc_offset >= maxoff)
19375574Smx205022 		return (IOC_INVAL);
19385574Smx205022 
19395574Smx205022 	if (ppd->pp_acc_offset+ppd->pp_acc_size > maxoff)
19405574Smx205022 		return (IOC_INVAL);
19415574Smx205022 
19425574Smx205022 	/*
19435574Smx205022 	 * All OK - go do it!
19445574Smx205022 	 */
19455574Smx205022 	ppd->pp_acc_offset += mem_va;
19465574Smx205022 	if (ppfn)
19475574Smx205022 		err = (*ppfn)(ngep, ppd);
19485574Smx205022 	if (err != DDI_SUCCESS)
19495574Smx205022 		return (IOC_INVAL);
19505574Smx205022 	return (peek ? IOC_REPLY : IOC_ACK);
19515574Smx205022 }
19525574Smx205022 
19535574Smx205022 static enum ioc_reply nge_diag_ioctl(nge_t *ngep, int cmd, mblk_t *mp,
19545574Smx205022 					struct iocblk *iocp);
19555574Smx205022 #pragma	no_inline(nge_diag_ioctl)
19565574Smx205022 
19575574Smx205022 static enum ioc_reply
nge_diag_ioctl(nge_t * ngep,int cmd,mblk_t * mp,struct iocblk * iocp)19585574Smx205022 nge_diag_ioctl(nge_t *ngep, int cmd, mblk_t *mp, struct iocblk *iocp)
19595574Smx205022 {
19605574Smx205022 	ASSERT(mutex_owned(ngep->genlock));
19615574Smx205022 
19625574Smx205022 	switch (cmd) {
19635574Smx205022 	default:
19645574Smx205022 		nge_error(ngep, "nge_diag_ioctl: invalid cmd 0x%x", cmd);
19655574Smx205022 		return (IOC_INVAL);
19665574Smx205022 
19675574Smx205022 	case NGE_DIAG:
19685574Smx205022 		return (IOC_ACK);
19695574Smx205022 
19705574Smx205022 	case NGE_PEEK:
19715574Smx205022 	case NGE_POKE:
19725574Smx205022 		return (nge_pp_ioctl(ngep, cmd, mp, iocp));
19735574Smx205022 
19745574Smx205022 	case NGE_PHY_RESET:
19755574Smx205022 		return (IOC_RESTART_ACK);
19765574Smx205022 
19775574Smx205022 	case NGE_SOFT_RESET:
19785574Smx205022 	case NGE_HARD_RESET:
19795574Smx205022 		return (IOC_ACK);
19805574Smx205022 	}
19815574Smx205022 
19825574Smx205022 	/* NOTREACHED */
19835574Smx205022 }
19845574Smx205022 
19855574Smx205022 enum ioc_reply
nge_chip_ioctl(nge_t * ngep,mblk_t * mp,struct iocblk * iocp)19865574Smx205022 nge_chip_ioctl(nge_t *ngep, mblk_t *mp, struct iocblk *iocp)
19875574Smx205022 {
19885574Smx205022 	int cmd;
19895574Smx205022 
19905574Smx205022 	ASSERT(mutex_owned(ngep->genlock));
19915574Smx205022 
19925574Smx205022 	cmd = iocp->ioc_cmd;
19935574Smx205022 
19945574Smx205022 	switch (cmd) {
19955574Smx205022 	default:
19965574Smx205022 		return (IOC_INVAL);
19975574Smx205022 
19985574Smx205022 	case NGE_DIAG:
19995574Smx205022 	case NGE_PEEK:
20005574Smx205022 	case NGE_POKE:
20015574Smx205022 	case NGE_PHY_RESET:
20025574Smx205022 	case NGE_SOFT_RESET:
20035574Smx205022 	case NGE_HARD_RESET:
20045574Smx205022 #if	NGE_DEBUGGING
20055574Smx205022 		return (nge_diag_ioctl(ngep, cmd, mp, iocp));
20065574Smx205022 #else
20075574Smx205022 		return (IOC_INVAL);
20085574Smx205022 #endif
20095574Smx205022 
20105574Smx205022 	case NGE_MII_READ:
20115574Smx205022 	case NGE_MII_WRITE:
20125574Smx205022 		return (IOC_INVAL);
20135574Smx205022 
20145574Smx205022 #if	NGE_SEE_IO32
20155574Smx205022 	case NGE_SEE_READ:
20165574Smx205022 	case NGE_SEE_WRITE:
20175574Smx205022 		return (IOC_INVAL);
20185574Smx205022 #endif
20195574Smx205022 
20205574Smx205022 #if	NGE_FLASH_IO32
20215574Smx205022 	case NGE_FLASH_READ:
20225574Smx205022 	case NGE_FLASH_WRITE:
20235574Smx205022 		return (IOC_INVAL);
20245574Smx205022 #endif
20255574Smx205022 	}
20265574Smx205022 }
2027