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