16f3e57acSmx205022 /* 247693af9Smx205022 * CDDL HEADER START 347693af9Smx205022 * 447693af9Smx205022 * The contents of this file are subject to the terms of the 547693af9Smx205022 * Common Development and Distribution License (the "License"). 647693af9Smx205022 * You may not use this file except in compliance with the License. 747693af9Smx205022 * 847693af9Smx205022 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 947693af9Smx205022 * or http://www.opensolaris.org/os/licensing. 1047693af9Smx205022 * See the License for the specific language governing permissions 1147693af9Smx205022 * and limitations under the License. 1247693af9Smx205022 * 1347693af9Smx205022 * When distributing Covered Code, include this CDDL HEADER in each 1447693af9Smx205022 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1547693af9Smx205022 * If applicable, add the following below this CDDL HEADER, with the 1647693af9Smx205022 * fields enclosed by brackets "[]" replaced with your own identifying 1747693af9Smx205022 * information: Portions Copyright [yyyy] [name of copyright owner] 1847693af9Smx205022 * 1947693af9Smx205022 * CDDL HEADER END 206f3e57acSmx205022 */ 216f3e57acSmx205022 226f3e57acSmx205022 /* 23d635b452SWinson Wang - Sun Microsystems - Beijing China * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 2447693af9Smx205022 * Use is subject to license terms. 256f3e57acSmx205022 */ 266f3e57acSmx205022 276f3e57acSmx205022 #include "nge.h" 28*51fc88a8SWinson Wang - Sun Microsystems - Beijing China static uint32_t nge_watchdog_count = 1 << 5; 29*51fc88a8SWinson Wang - Sun Microsystems - Beijing China static uint32_t nge_watchdog_check = 1 << 3; 306f3e57acSmx205022 extern boolean_t nge_enable_msi; 316f3e57acSmx205022 static void nge_sync_mac_modes(nge_t *); 326f3e57acSmx205022 336f3e57acSmx205022 #undef NGE_DBG 346f3e57acSmx205022 #define NGE_DBG NGE_DBG_CHIP 356f3e57acSmx205022 366f3e57acSmx205022 /* 376f3e57acSmx205022 * Operating register get/set access routines 386f3e57acSmx205022 */ 396f3e57acSmx205022 uint8_t nge_reg_get8(nge_t *ngep, nge_regno_t regno); 406f3e57acSmx205022 #pragma inline(nge_reg_get8) 416f3e57acSmx205022 426f3e57acSmx205022 uint8_t 436f3e57acSmx205022 nge_reg_get8(nge_t *ngep, nge_regno_t regno) 446f3e57acSmx205022 { 456f3e57acSmx205022 NGE_TRACE(("nge_reg_get8($%p, 0x%lx)", (void *)ngep, regno)); 466f3e57acSmx205022 476f3e57acSmx205022 return (ddi_get8(ngep->io_handle, PIO_ADDR(ngep, regno))); 486f3e57acSmx205022 } 496f3e57acSmx205022 506f3e57acSmx205022 void nge_reg_put8(nge_t *ngep, nge_regno_t regno, uint8_t data); 516f3e57acSmx205022 #pragma inline(nge_reg_put8) 526f3e57acSmx205022 536f3e57acSmx205022 void 546f3e57acSmx205022 nge_reg_put8(nge_t *ngep, nge_regno_t regno, uint8_t data) 556f3e57acSmx205022 { 566f3e57acSmx205022 NGE_TRACE(("nge_reg_put8($%p, 0x%lx, 0x%x)", 576f3e57acSmx205022 (void *)ngep, regno, data)); 586f3e57acSmx205022 ddi_put8(ngep->io_handle, PIO_ADDR(ngep, regno), data); 596f3e57acSmx205022 606f3e57acSmx205022 } 616f3e57acSmx205022 626f3e57acSmx205022 uint16_t nge_reg_get16(nge_t *ngep, nge_regno_t regno); 636f3e57acSmx205022 #pragma inline(nge_reg_get16) 646f3e57acSmx205022 656f3e57acSmx205022 uint16_t 666f3e57acSmx205022 nge_reg_get16(nge_t *ngep, nge_regno_t regno) 676f3e57acSmx205022 { 686f3e57acSmx205022 NGE_TRACE(("nge_reg_get16($%p, 0x%lx)", (void *)ngep, regno)); 696f3e57acSmx205022 return (ddi_get16(ngep->io_handle, PIO_ADDR(ngep, regno))); 706f3e57acSmx205022 } 716f3e57acSmx205022 726f3e57acSmx205022 void nge_reg_put16(nge_t *ngep, nge_regno_t regno, uint16_t data); 736f3e57acSmx205022 #pragma inline(nge_reg_put16) 746f3e57acSmx205022 756f3e57acSmx205022 void 766f3e57acSmx205022 nge_reg_put16(nge_t *ngep, nge_regno_t regno, uint16_t data) 776f3e57acSmx205022 { 786f3e57acSmx205022 NGE_TRACE(("nge_reg_put16($%p, 0x%lx, 0x%x)", 796f3e57acSmx205022 (void *)ngep, regno, data)); 806f3e57acSmx205022 ddi_put16(ngep->io_handle, PIO_ADDR(ngep, regno), data); 816f3e57acSmx205022 826f3e57acSmx205022 } 836f3e57acSmx205022 846f3e57acSmx205022 uint32_t nge_reg_get32(nge_t *ngep, nge_regno_t regno); 856f3e57acSmx205022 #pragma inline(nge_reg_get32) 866f3e57acSmx205022 876f3e57acSmx205022 uint32_t 886f3e57acSmx205022 nge_reg_get32(nge_t *ngep, nge_regno_t regno) 896f3e57acSmx205022 { 906f3e57acSmx205022 NGE_TRACE(("nge_reg_get32($%p, 0x%lx)", (void *)ngep, regno)); 916f3e57acSmx205022 return (ddi_get32(ngep->io_handle, PIO_ADDR(ngep, regno))); 926f3e57acSmx205022 } 936f3e57acSmx205022 946f3e57acSmx205022 void nge_reg_put32(nge_t *ngep, nge_regno_t regno, uint32_t data); 956f3e57acSmx205022 #pragma inline(nge_reg_put32) 966f3e57acSmx205022 976f3e57acSmx205022 void 986f3e57acSmx205022 nge_reg_put32(nge_t *ngep, nge_regno_t regno, uint32_t data) 996f3e57acSmx205022 { 1006f3e57acSmx205022 NGE_TRACE(("nge_reg_put32($%p, 0x%lx, 0x%x)", 1016f3e57acSmx205022 (void *)ngep, regno, data)); 1026f3e57acSmx205022 ddi_put32(ngep->io_handle, PIO_ADDR(ngep, regno), data); 1036f3e57acSmx205022 1046f3e57acSmx205022 } 1056f3e57acSmx205022 1066f3e57acSmx205022 1076f3e57acSmx205022 static int nge_chip_peek_cfg(nge_t *ngep, nge_peekpoke_t *ppd); 1086f3e57acSmx205022 #pragma no_inline(nge_chip_peek_cfg) 1096f3e57acSmx205022 1106f3e57acSmx205022 static int 1116f3e57acSmx205022 nge_chip_peek_cfg(nge_t *ngep, nge_peekpoke_t *ppd) 1126f3e57acSmx205022 { 1136f3e57acSmx205022 int err; 1146f3e57acSmx205022 uint64_t regval; 1156f3e57acSmx205022 uint64_t regno; 1166f3e57acSmx205022 1176f3e57acSmx205022 NGE_TRACE(("nge_chip_peek_cfg($%p, $%p)", 1186f3e57acSmx205022 (void *)ngep, (void *)ppd)); 1196f3e57acSmx205022 1206f3e57acSmx205022 err = DDI_SUCCESS; 1216f3e57acSmx205022 regno = ppd->pp_acc_offset; 1226f3e57acSmx205022 1236f3e57acSmx205022 switch (ppd->pp_acc_size) { 1246f3e57acSmx205022 case 1: 1256f3e57acSmx205022 regval = pci_config_get8(ngep->cfg_handle, regno); 1266f3e57acSmx205022 break; 1276f3e57acSmx205022 1286f3e57acSmx205022 case 2: 1296f3e57acSmx205022 regval = pci_config_get16(ngep->cfg_handle, regno); 1306f3e57acSmx205022 break; 1316f3e57acSmx205022 1326f3e57acSmx205022 case 4: 1336f3e57acSmx205022 regval = pci_config_get32(ngep->cfg_handle, regno); 1346f3e57acSmx205022 break; 1356f3e57acSmx205022 1366f3e57acSmx205022 case 8: 1376f3e57acSmx205022 regval = pci_config_get64(ngep->cfg_handle, regno); 1386f3e57acSmx205022 break; 1396f3e57acSmx205022 } 1406f3e57acSmx205022 ppd->pp_acc_data = regval; 1416f3e57acSmx205022 return (err); 1426f3e57acSmx205022 } 1436f3e57acSmx205022 1446f3e57acSmx205022 static int nge_chip_poke_cfg(nge_t *ngep, nge_peekpoke_t *ppd); 1456f3e57acSmx205022 1466f3e57acSmx205022 static int 1476f3e57acSmx205022 nge_chip_poke_cfg(nge_t *ngep, nge_peekpoke_t *ppd) 1486f3e57acSmx205022 { 1496f3e57acSmx205022 int err; 1506f3e57acSmx205022 uint64_t regval; 1516f3e57acSmx205022 uint64_t regno; 1526f3e57acSmx205022 1536f3e57acSmx205022 NGE_TRACE(("nge_chip_poke_cfg($%p, $%p)", 1546f3e57acSmx205022 (void *)ngep, (void *)ppd)); 1556f3e57acSmx205022 1566f3e57acSmx205022 err = DDI_SUCCESS; 1576f3e57acSmx205022 regno = ppd->pp_acc_offset; 1586f3e57acSmx205022 regval = ppd->pp_acc_data; 1596f3e57acSmx205022 1606f3e57acSmx205022 switch (ppd->pp_acc_size) { 1616f3e57acSmx205022 case 1: 1626f3e57acSmx205022 pci_config_put8(ngep->cfg_handle, regno, regval); 1636f3e57acSmx205022 break; 1646f3e57acSmx205022 1656f3e57acSmx205022 case 2: 1666f3e57acSmx205022 pci_config_put16(ngep->cfg_handle, regno, regval); 1676f3e57acSmx205022 break; 1686f3e57acSmx205022 1696f3e57acSmx205022 case 4: 1706f3e57acSmx205022 pci_config_put32(ngep->cfg_handle, regno, regval); 1716f3e57acSmx205022 break; 1726f3e57acSmx205022 1736f3e57acSmx205022 case 8: 1746f3e57acSmx205022 pci_config_put64(ngep->cfg_handle, regno, regval); 1756f3e57acSmx205022 break; 1766f3e57acSmx205022 } 1776f3e57acSmx205022 1786f3e57acSmx205022 return (err); 1796f3e57acSmx205022 1806f3e57acSmx205022 } 1816f3e57acSmx205022 1826f3e57acSmx205022 static int nge_chip_peek_reg(nge_t *ngep, nge_peekpoke_t *ppd); 1836f3e57acSmx205022 1846f3e57acSmx205022 static int 1856f3e57acSmx205022 nge_chip_peek_reg(nge_t *ngep, nge_peekpoke_t *ppd) 1866f3e57acSmx205022 { 1876f3e57acSmx205022 int err; 1886f3e57acSmx205022 uint64_t regval; 1896f3e57acSmx205022 void *regaddr; 1906f3e57acSmx205022 1916f3e57acSmx205022 NGE_TRACE(("nge_chip_peek_reg($%p, $%p)", 1926f3e57acSmx205022 (void *)ngep, (void *)ppd)); 1936f3e57acSmx205022 1946f3e57acSmx205022 err = DDI_SUCCESS; 1956f3e57acSmx205022 regaddr = PIO_ADDR(ngep, ppd->pp_acc_offset); 1966f3e57acSmx205022 1976f3e57acSmx205022 switch (ppd->pp_acc_size) { 1986f3e57acSmx205022 case 1: 1996f3e57acSmx205022 regval = ddi_get8(ngep->io_handle, regaddr); 2006f3e57acSmx205022 break; 2016f3e57acSmx205022 2026f3e57acSmx205022 case 2: 2036f3e57acSmx205022 regval = ddi_get16(ngep->io_handle, regaddr); 2046f3e57acSmx205022 break; 2056f3e57acSmx205022 2066f3e57acSmx205022 case 4: 2076f3e57acSmx205022 regval = ddi_get32(ngep->io_handle, regaddr); 2086f3e57acSmx205022 break; 2096f3e57acSmx205022 2106f3e57acSmx205022 case 8: 2116f3e57acSmx205022 regval = ddi_get64(ngep->io_handle, regaddr); 2126f3e57acSmx205022 break; 2136f3e57acSmx205022 2146f3e57acSmx205022 default: 2156f3e57acSmx205022 regval = 0x0ull; 2166f3e57acSmx205022 break; 2176f3e57acSmx205022 } 2186f3e57acSmx205022 ppd->pp_acc_data = regval; 2196f3e57acSmx205022 return (err); 2206f3e57acSmx205022 } 2216f3e57acSmx205022 2226f3e57acSmx205022 static int nge_chip_poke_reg(nge_t *ngep, nge_peekpoke_t *ppd); 2236f3e57acSmx205022 2246f3e57acSmx205022 static int 2256f3e57acSmx205022 nge_chip_poke_reg(nge_t *ngep, nge_peekpoke_t *ppd) 2266f3e57acSmx205022 { 2276f3e57acSmx205022 int err; 2286f3e57acSmx205022 uint64_t regval; 2296f3e57acSmx205022 void *regaddr; 2306f3e57acSmx205022 2316f3e57acSmx205022 NGE_TRACE(("nge_chip_poke_reg($%p, $%p)", 2326f3e57acSmx205022 (void *)ngep, (void *)ppd)); 2336f3e57acSmx205022 2346f3e57acSmx205022 err = DDI_SUCCESS; 2356f3e57acSmx205022 regaddr = PIO_ADDR(ngep, ppd->pp_acc_offset); 2366f3e57acSmx205022 regval = ppd->pp_acc_data; 2376f3e57acSmx205022 2386f3e57acSmx205022 switch (ppd->pp_acc_size) { 2396f3e57acSmx205022 case 1: 2406f3e57acSmx205022 ddi_put8(ngep->io_handle, regaddr, regval); 2416f3e57acSmx205022 break; 2426f3e57acSmx205022 2436f3e57acSmx205022 case 2: 2446f3e57acSmx205022 ddi_put16(ngep->io_handle, regaddr, regval); 2456f3e57acSmx205022 break; 2466f3e57acSmx205022 2476f3e57acSmx205022 case 4: 2486f3e57acSmx205022 ddi_put32(ngep->io_handle, regaddr, regval); 2496f3e57acSmx205022 break; 2506f3e57acSmx205022 2516f3e57acSmx205022 case 8: 2526f3e57acSmx205022 ddi_put64(ngep->io_handle, regaddr, regval); 2536f3e57acSmx205022 break; 2546f3e57acSmx205022 } 2556f3e57acSmx205022 return (err); 2566f3e57acSmx205022 } 2576f3e57acSmx205022 2586f3e57acSmx205022 static int nge_chip_peek_mii(nge_t *ngep, nge_peekpoke_t *ppd); 2596f3e57acSmx205022 #pragma no_inline(nge_chip_peek_mii) 2606f3e57acSmx205022 2616f3e57acSmx205022 static int 2626f3e57acSmx205022 nge_chip_peek_mii(nge_t *ngep, nge_peekpoke_t *ppd) 2636f3e57acSmx205022 { 2646f3e57acSmx205022 int err; 2656f3e57acSmx205022 2666f3e57acSmx205022 err = DDI_SUCCESS; 2676f3e57acSmx205022 ppd->pp_acc_data = nge_mii_get16(ngep, ppd->pp_acc_offset/2); 2686f3e57acSmx205022 return (err); 2696f3e57acSmx205022 } 2706f3e57acSmx205022 2716f3e57acSmx205022 static int nge_chip_poke_mii(nge_t *ngep, nge_peekpoke_t *ppd); 2726f3e57acSmx205022 #pragma no_inline(nge_chip_poke_mii) 2736f3e57acSmx205022 2746f3e57acSmx205022 static int 2756f3e57acSmx205022 nge_chip_poke_mii(nge_t *ngep, nge_peekpoke_t *ppd) 2766f3e57acSmx205022 { 2776f3e57acSmx205022 int err; 2786f3e57acSmx205022 err = DDI_SUCCESS; 2796f3e57acSmx205022 nge_mii_put16(ngep, ppd->pp_acc_offset/2, ppd->pp_acc_data); 2806f3e57acSmx205022 return (err); 2816f3e57acSmx205022 } 2826f3e57acSmx205022 2836f3e57acSmx205022 /* 2846f3e57acSmx205022 * Basic SEEPROM get/set access routine 2856f3e57acSmx205022 * 2866f3e57acSmx205022 * This uses the chip's SEEPROM auto-access method, controlled by the 2876f3e57acSmx205022 * Serial EEPROM Address/Data Registers at 0x504h, so the CPU 2886f3e57acSmx205022 * doesn't have to fiddle with the individual bits. 2896f3e57acSmx205022 * 2906f3e57acSmx205022 * The caller should hold <genlock> and *also* have already acquired 2916f3e57acSmx205022 * the right to access the SEEPROM. 2926f3e57acSmx205022 * 2936f3e57acSmx205022 * Return value: 2946f3e57acSmx205022 * 0 on success, 2956f3e57acSmx205022 * ENODATA on access timeout (maybe retryable: device may just be busy) 2966f3e57acSmx205022 * EPROTO on other h/w or s/w errors. 2976f3e57acSmx205022 * 2986f3e57acSmx205022 * <*dp> is an input to a SEEPROM_ACCESS_WRITE operation, or an output 2996f3e57acSmx205022 * from a (successful) SEEPROM_ACCESS_READ. 3006f3e57acSmx205022 */ 3016f3e57acSmx205022 3026f3e57acSmx205022 static int 3036f3e57acSmx205022 nge_seeprom_access(nge_t *ngep, uint32_t cmd, nge_regno_t addr, uint16_t *dp) 3046f3e57acSmx205022 { 3056f3e57acSmx205022 uint32_t tries; 3066f3e57acSmx205022 nge_ep_cmd cmd_reg; 3076f3e57acSmx205022 nge_ep_data data_reg; 3086f3e57acSmx205022 3096f3e57acSmx205022 NGE_TRACE(("nge_seeprom_access($%p, %d, %x, $%p)", 3106f3e57acSmx205022 (void *)ngep, cmd, addr, (void *)dp)); 3116f3e57acSmx205022 3126f3e57acSmx205022 ASSERT(mutex_owned(ngep->genlock)); 3136f3e57acSmx205022 3146f3e57acSmx205022 /* 3156f3e57acSmx205022 * Check there's no command in progress. 3166f3e57acSmx205022 * 3176f3e57acSmx205022 * Note: this *shouldn't* ever find that there is a command 3186f3e57acSmx205022 * in progress, because we already hold the <genlock> mutex. 3196f3e57acSmx205022 * Also, to ensure we don't have a conflict with the chip's 3206f3e57acSmx205022 * internal firmware or a process accessing the same (shared) 3216f3e57acSmx205022 * So this is just a final consistency check: we shouldn't 3226f3e57acSmx205022 * see EITHER the START bit (command started but not complete) 3236f3e57acSmx205022 * OR the COMPLETE bit (command completed but not cleared). 3246f3e57acSmx205022 */ 3256f3e57acSmx205022 cmd_reg.cmd_val = nge_reg_get32(ngep, NGE_EP_CMD); 3266f3e57acSmx205022 for (tries = 0; tries < 30; tries++) { 3276f3e57acSmx205022 if (cmd_reg.cmd_bits.sts == SEEPROM_READY) 3286f3e57acSmx205022 break; 3296f3e57acSmx205022 drv_usecwait(10); 3306f3e57acSmx205022 cmd_reg.cmd_val = nge_reg_get32(ngep, NGE_EP_CMD); 3316f3e57acSmx205022 } 3326f3e57acSmx205022 3336f3e57acSmx205022 /* 3346f3e57acSmx205022 * This should not happen. If so, we have to restart eeprom 3356f3e57acSmx205022 * state machine 3366f3e57acSmx205022 */ 3376f3e57acSmx205022 if (tries == 30) { 3386f3e57acSmx205022 cmd_reg.cmd_bits.sts = SEEPROM_READY; 3396f3e57acSmx205022 nge_reg_put32(ngep, NGE_EP_CMD, cmd_reg.cmd_val); 3406f3e57acSmx205022 drv_usecwait(10); 3416f3e57acSmx205022 /* 3426f3e57acSmx205022 * Polling the status bit to make assure the eeprom is ready 3436f3e57acSmx205022 */ 3446f3e57acSmx205022 cmd_reg.cmd_val = nge_reg_get32(ngep, NGE_EP_CMD); 3456f3e57acSmx205022 for (tries = 0; tries < 30; tries++) { 3466f3e57acSmx205022 if (cmd_reg.cmd_bits.sts == SEEPROM_READY) 3476f3e57acSmx205022 break; 3486f3e57acSmx205022 drv_usecwait(10); 3496f3e57acSmx205022 cmd_reg.cmd_val = nge_reg_get32(ngep, NGE_EP_CMD); 3506f3e57acSmx205022 } 3516f3e57acSmx205022 } 3526f3e57acSmx205022 3536f3e57acSmx205022 /* 3546f3e57acSmx205022 * Assemble the command ... 3556f3e57acSmx205022 */ 356a55f7119SMiles Xu, Sun Microsystems cmd_reg.cmd_bits.addr = (uint32_t)addr; 3576f3e57acSmx205022 cmd_reg.cmd_bits.cmd = cmd; 3586f3e57acSmx205022 cmd_reg.cmd_bits.sts = 0; 3596f3e57acSmx205022 3606f3e57acSmx205022 nge_reg_put32(ngep, NGE_EP_CMD, cmd_reg.cmd_val); 3616f3e57acSmx205022 3626f3e57acSmx205022 /* 3636f3e57acSmx205022 * Polling whether the access is successful. 3646f3e57acSmx205022 * 3656f3e57acSmx205022 */ 3666f3e57acSmx205022 cmd_reg.cmd_val = nge_reg_get32(ngep, NGE_EP_CMD); 3676f3e57acSmx205022 for (tries = 0; tries < 30; tries++) { 3686f3e57acSmx205022 if (cmd_reg.cmd_bits.sts == SEEPROM_READY) 3696f3e57acSmx205022 break; 3706f3e57acSmx205022 drv_usecwait(10); 3716f3e57acSmx205022 cmd_reg.cmd_val = nge_reg_get32(ngep, NGE_EP_CMD); 3726f3e57acSmx205022 } 3736f3e57acSmx205022 3746f3e57acSmx205022 if (tries == 30) { 3756f3e57acSmx205022 nge_report(ngep, NGE_HW_ROM); 3766f3e57acSmx205022 return (DDI_FAILURE); 3776f3e57acSmx205022 } 3786f3e57acSmx205022 switch (cmd) { 3796f3e57acSmx205022 default: 3806f3e57acSmx205022 case SEEPROM_CMD_WRITE_ENABLE: 3816f3e57acSmx205022 case SEEPROM_CMD_ERASE: 3826f3e57acSmx205022 case SEEPROM_CMD_ERALSE_ALL: 3836f3e57acSmx205022 case SEEPROM_CMD_WRITE_DIS: 3846f3e57acSmx205022 break; 3856f3e57acSmx205022 3866f3e57acSmx205022 case SEEPROM_CMD_READ: 3876f3e57acSmx205022 data_reg.data_val = nge_reg_get32(ngep, NGE_EP_DATA); 3886f3e57acSmx205022 *dp = data_reg.data_bits.data; 3896f3e57acSmx205022 break; 3906f3e57acSmx205022 3916f3e57acSmx205022 case SEEPROM_CMD_WRITE: 3926f3e57acSmx205022 data_reg.data_val = nge_reg_get32(ngep, NGE_EP_DATA); 3936f3e57acSmx205022 data_reg.data_bits.data = *dp; 3946f3e57acSmx205022 nge_reg_put32(ngep, NGE_EP_DATA, data_reg.data_val); 3956f3e57acSmx205022 break; 3966f3e57acSmx205022 } 3976f3e57acSmx205022 3986f3e57acSmx205022 return (DDI_SUCCESS); 3996f3e57acSmx205022 } 4006f3e57acSmx205022 4016f3e57acSmx205022 4026f3e57acSmx205022 static int 4036f3e57acSmx205022 nge_chip_peek_seeprom(nge_t *ngep, nge_peekpoke_t *ppd) 4046f3e57acSmx205022 { 4056f3e57acSmx205022 uint16_t data; 4066f3e57acSmx205022 int err; 4076f3e57acSmx205022 4086f3e57acSmx205022 err = nge_seeprom_access(ngep, SEEPROM_CMD_READ, 4096f3e57acSmx205022 ppd->pp_acc_offset, &data); 4106f3e57acSmx205022 ppd->pp_acc_data = data; 4116f3e57acSmx205022 return (err); 4126f3e57acSmx205022 } 4136f3e57acSmx205022 4146f3e57acSmx205022 static int 4156f3e57acSmx205022 nge_chip_poke_seeprom(nge_t *ngep, nge_peekpoke_t *ppd) 4166f3e57acSmx205022 { 4176f3e57acSmx205022 uint16_t data; 4186f3e57acSmx205022 int err; 4196f3e57acSmx205022 4206f3e57acSmx205022 data = ppd->pp_acc_data; 4216f3e57acSmx205022 err = nge_seeprom_access(ngep, SEEPROM_CMD_WRITE, 4226f3e57acSmx205022 ppd->pp_acc_offset, &data); 4236f3e57acSmx205022 return (err); 4246f3e57acSmx205022 } 4256f3e57acSmx205022 4266f3e57acSmx205022 void 4276f3e57acSmx205022 nge_init_dev_spec_param(nge_t *ngep) 4286f3e57acSmx205022 { 4296f3e57acSmx205022 nge_dev_spec_param_t *dev_param_p; 4306f3e57acSmx205022 chip_info_t *infop; 4316f3e57acSmx205022 4326f3e57acSmx205022 dev_param_p = &ngep->dev_spec_param; 4336f3e57acSmx205022 infop = (chip_info_t *)&ngep->chipinfo; 4346f3e57acSmx205022 4356f3e57acSmx205022 switch (infop->device) { 4366f3e57acSmx205022 case DEVICE_ID_NF3_E6: 4376f3e57acSmx205022 case DEVICE_ID_NF3_DF: 4386f3e57acSmx205022 case DEVICE_ID_MCP04_37: 4396f3e57acSmx205022 case DEVICE_ID_MCP04_38: 4406f3e57acSmx205022 dev_param_p->msi = B_FALSE; 4416f3e57acSmx205022 dev_param_p->msi_x = B_FALSE; 4426f3e57acSmx205022 dev_param_p->vlan = B_FALSE; 4439ae6bcf1Sjj146644 dev_param_p->advanced_pm = B_FALSE; 444d27d4a13SMiles Xu, Sun Microsystems dev_param_p->mac_addr_order = B_FALSE; 4456f3e57acSmx205022 dev_param_p->tx_pause_frame = B_FALSE; 4466f3e57acSmx205022 dev_param_p->rx_pause_frame = B_FALSE; 4476f3e57acSmx205022 dev_param_p->jumbo = B_FALSE; 4486f3e57acSmx205022 dev_param_p->tx_rx_64byte = B_FALSE; 4496f3e57acSmx205022 dev_param_p->rx_hw_checksum = B_FALSE; 4506f3e57acSmx205022 dev_param_p->tx_hw_checksum = 0; 4516f3e57acSmx205022 dev_param_p->desc_type = DESC_OFFLOAD; 4526f3e57acSmx205022 dev_param_p->rx_desc_num = NGE_RECV_SLOTS_DESC_1024; 4536f3e57acSmx205022 dev_param_p->tx_desc_num = NGE_SEND_SLOTS_DESC_1024; 4546f3e57acSmx205022 dev_param_p->nge_split = NGE_SPLIT_32; 4556f3e57acSmx205022 break; 4566f3e57acSmx205022 4576f3e57acSmx205022 case DEVICE_ID_CK804_56: 4586f3e57acSmx205022 case DEVICE_ID_CK804_57: 4596f3e57acSmx205022 dev_param_p->msi = B_TRUE; 4606f3e57acSmx205022 dev_param_p->msi_x = B_TRUE; 4616f3e57acSmx205022 dev_param_p->vlan = B_FALSE; 4629ae6bcf1Sjj146644 dev_param_p->advanced_pm = B_FALSE; 463d27d4a13SMiles Xu, Sun Microsystems dev_param_p->mac_addr_order = B_FALSE; 4646f3e57acSmx205022 dev_param_p->tx_pause_frame = B_FALSE; 4656f3e57acSmx205022 dev_param_p->rx_pause_frame = B_TRUE; 4666f3e57acSmx205022 dev_param_p->jumbo = B_TRUE; 4676f3e57acSmx205022 dev_param_p->tx_rx_64byte = B_FALSE; 4686f3e57acSmx205022 dev_param_p->rx_hw_checksum = B_TRUE; 4696f3e57acSmx205022 dev_param_p->tx_hw_checksum = HCKSUM_IPHDRCKSUM; 4706f3e57acSmx205022 dev_param_p->desc_type = DESC_HOT; 4716f3e57acSmx205022 dev_param_p->rx_desc_num = NGE_RECV_SLOTS_DESC_3072; 4726f3e57acSmx205022 dev_param_p->tx_desc_num = NGE_SEND_SLOTS_DESC_3072; 4736f3e57acSmx205022 dev_param_p->nge_split = NGE_SPLIT_96; 4746f3e57acSmx205022 break; 4756f3e57acSmx205022 4766f3e57acSmx205022 case DEVICE_ID_MCP51_268: 4776f3e57acSmx205022 case DEVICE_ID_MCP51_269: 4786f3e57acSmx205022 dev_param_p->msi = B_FALSE; 4796f3e57acSmx205022 dev_param_p->msi_x = B_FALSE; 4806f3e57acSmx205022 dev_param_p->vlan = B_FALSE; 4819ae6bcf1Sjj146644 dev_param_p->advanced_pm = B_TRUE; 482d27d4a13SMiles Xu, Sun Microsystems dev_param_p->mac_addr_order = B_FALSE; 4836f3e57acSmx205022 dev_param_p->tx_pause_frame = B_FALSE; 4846f3e57acSmx205022 dev_param_p->rx_pause_frame = B_FALSE; 4856f3e57acSmx205022 dev_param_p->jumbo = B_FALSE; 4866f3e57acSmx205022 dev_param_p->tx_rx_64byte = B_TRUE; 4876f3e57acSmx205022 dev_param_p->rx_hw_checksum = B_FALSE; 4886f3e57acSmx205022 dev_param_p->tx_hw_checksum = 0; 4896f3e57acSmx205022 dev_param_p->desc_type = DESC_OFFLOAD; 4906f3e57acSmx205022 dev_param_p->rx_desc_num = NGE_RECV_SLOTS_DESC_1024; 4916f3e57acSmx205022 dev_param_p->tx_desc_num = NGE_SEND_SLOTS_DESC_1024; 4926f3e57acSmx205022 dev_param_p->nge_split = NGE_SPLIT_32; 4936f3e57acSmx205022 break; 4946f3e57acSmx205022 4956f3e57acSmx205022 case DEVICE_ID_MCP55_372: 4966f3e57acSmx205022 case DEVICE_ID_MCP55_373: 4976f3e57acSmx205022 dev_param_p->msi = B_TRUE; 4986f3e57acSmx205022 dev_param_p->msi_x = B_TRUE; 4996f3e57acSmx205022 dev_param_p->vlan = B_TRUE; 5009ae6bcf1Sjj146644 dev_param_p->advanced_pm = B_TRUE; 501d27d4a13SMiles Xu, Sun Microsystems dev_param_p->mac_addr_order = B_FALSE; 5026f3e57acSmx205022 dev_param_p->tx_pause_frame = B_TRUE; 5036f3e57acSmx205022 dev_param_p->rx_pause_frame = B_TRUE; 5046f3e57acSmx205022 dev_param_p->jumbo = B_TRUE; 5056f3e57acSmx205022 dev_param_p->tx_rx_64byte = B_TRUE; 5066f3e57acSmx205022 dev_param_p->rx_hw_checksum = B_TRUE; 5076f3e57acSmx205022 dev_param_p->tx_hw_checksum = HCKSUM_IPHDRCKSUM; 5086f3e57acSmx205022 dev_param_p->desc_type = DESC_HOT; 5096f3e57acSmx205022 dev_param_p->rx_desc_num = NGE_RECV_SLOTS_DESC_3072; 5106f3e57acSmx205022 dev_param_p->tx_desc_num = NGE_SEND_SLOTS_DESC_3072; 5116f3e57acSmx205022 dev_param_p->nge_split = NGE_SPLIT_96; 5126f3e57acSmx205022 break; 5136f3e57acSmx205022 514d27d4a13SMiles Xu, Sun Microsystems case DEVICE_ID_MCP61_3EE: 515d27d4a13SMiles Xu, Sun Microsystems case DEVICE_ID_MCP61_3EF: 516d27d4a13SMiles Xu, Sun Microsystems dev_param_p->msi = B_FALSE; 517d27d4a13SMiles Xu, Sun Microsystems dev_param_p->msi_x = B_FALSE; 518d27d4a13SMiles Xu, Sun Microsystems dev_param_p->vlan = B_FALSE; 519d27d4a13SMiles Xu, Sun Microsystems dev_param_p->advanced_pm = B_TRUE; 520d27d4a13SMiles Xu, Sun Microsystems dev_param_p->mac_addr_order = B_TRUE; 521d27d4a13SMiles Xu, Sun Microsystems dev_param_p->tx_pause_frame = B_FALSE; 522d27d4a13SMiles Xu, Sun Microsystems dev_param_p->rx_pause_frame = B_FALSE; 523d27d4a13SMiles Xu, Sun Microsystems dev_param_p->jumbo = B_FALSE; 524d27d4a13SMiles Xu, Sun Microsystems dev_param_p->tx_rx_64byte = B_TRUE; 525d27d4a13SMiles Xu, Sun Microsystems dev_param_p->rx_hw_checksum = B_FALSE; 526d27d4a13SMiles Xu, Sun Microsystems dev_param_p->tx_hw_checksum = 0; 527d27d4a13SMiles Xu, Sun Microsystems dev_param_p->desc_type = DESC_OFFLOAD; 528d27d4a13SMiles Xu, Sun Microsystems dev_param_p->rx_desc_num = NGE_RECV_SLOTS_DESC_1024; 529d27d4a13SMiles Xu, Sun Microsystems dev_param_p->tx_desc_num = NGE_SEND_SLOTS_DESC_1024; 530d27d4a13SMiles Xu, Sun Microsystems dev_param_p->nge_split = NGE_SPLIT_32; 531d27d4a13SMiles Xu, Sun Microsystems break; 532d27d4a13SMiles Xu, Sun Microsystems 533a01a4735SWinson Wang - Sun Microsystems - Beijing China case DEVICE_ID_MCP77_760: 5349fa05d92SWinson Wang - Sun Microsystems - Beijing China case DEVICE_ID_MCP79_AB0: 535a01a4735SWinson Wang - Sun Microsystems - Beijing China dev_param_p->msi = B_FALSE; 536a01a4735SWinson Wang - Sun Microsystems - Beijing China dev_param_p->msi_x = B_FALSE; 537a01a4735SWinson Wang - Sun Microsystems - Beijing China dev_param_p->vlan = B_FALSE; 538a01a4735SWinson Wang - Sun Microsystems - Beijing China dev_param_p->advanced_pm = B_TRUE; 539a01a4735SWinson Wang - Sun Microsystems - Beijing China dev_param_p->mac_addr_order = B_TRUE; 540a01a4735SWinson Wang - Sun Microsystems - Beijing China dev_param_p->tx_pause_frame = B_FALSE; 541a01a4735SWinson Wang - Sun Microsystems - Beijing China dev_param_p->rx_pause_frame = B_FALSE; 542a01a4735SWinson Wang - Sun Microsystems - Beijing China dev_param_p->jumbo = B_FALSE; 543a01a4735SWinson Wang - Sun Microsystems - Beijing China dev_param_p->tx_rx_64byte = B_TRUE; 544a01a4735SWinson Wang - Sun Microsystems - Beijing China dev_param_p->rx_hw_checksum = B_FALSE; 545a01a4735SWinson Wang - Sun Microsystems - Beijing China dev_param_p->tx_hw_checksum = 0; 546a01a4735SWinson Wang - Sun Microsystems - Beijing China dev_param_p->desc_type = DESC_HOT; 547a01a4735SWinson Wang - Sun Microsystems - Beijing China dev_param_p->rx_desc_num = NGE_RECV_SLOTS_DESC_1024; 548a01a4735SWinson Wang - Sun Microsystems - Beijing China dev_param_p->tx_desc_num = NGE_SEND_SLOTS_DESC_1024; 549a01a4735SWinson Wang - Sun Microsystems - Beijing China dev_param_p->nge_split = NGE_SPLIT_32; 550a01a4735SWinson Wang - Sun Microsystems - Beijing China break; 551a01a4735SWinson Wang - Sun Microsystems - Beijing China 5526f3e57acSmx205022 default: 5536f3e57acSmx205022 dev_param_p->msi = B_FALSE; 5546f3e57acSmx205022 dev_param_p->msi_x = B_FALSE; 5556f3e57acSmx205022 dev_param_p->vlan = B_FALSE; 5569ae6bcf1Sjj146644 dev_param_p->advanced_pm = B_FALSE; 557d27d4a13SMiles Xu, Sun Microsystems dev_param_p->mac_addr_order = B_FALSE; 5586f3e57acSmx205022 dev_param_p->tx_pause_frame = B_FALSE; 5596f3e57acSmx205022 dev_param_p->rx_pause_frame = B_FALSE; 5606f3e57acSmx205022 dev_param_p->jumbo = B_FALSE; 5616f3e57acSmx205022 dev_param_p->tx_rx_64byte = B_FALSE; 5626f3e57acSmx205022 dev_param_p->rx_hw_checksum = B_FALSE; 5636f3e57acSmx205022 dev_param_p->tx_hw_checksum = 0; 5646f3e57acSmx205022 dev_param_p->desc_type = DESC_OFFLOAD; 5656f3e57acSmx205022 dev_param_p->rx_desc_num = NGE_RECV_SLOTS_DESC_1024; 5666f3e57acSmx205022 dev_param_p->tx_desc_num = NGE_SEND_SLOTS_DESC_1024; 5676f3e57acSmx205022 dev_param_p->nge_split = NGE_SPLIT_32; 5686f3e57acSmx205022 return; 5696f3e57acSmx205022 } 5706f3e57acSmx205022 } 5716f3e57acSmx205022 /* 5726f3e57acSmx205022 * Perform first-stage chip (re-)initialisation, using only config-space 5736f3e57acSmx205022 * accesses: 5746f3e57acSmx205022 * 5756f3e57acSmx205022 * + Read the vendor/device/revision/subsystem/cache-line-size registers, 5766f3e57acSmx205022 * returning the data in the structure pointed to by <infop>. 5776f3e57acSmx205022 */ 5786f3e57acSmx205022 void nge_chip_cfg_init(nge_t *ngep, chip_info_t *infop, boolean_t reset); 5796f3e57acSmx205022 #pragma no_inline(nge_chip_cfg_init) 5806f3e57acSmx205022 5816f3e57acSmx205022 void 5826f3e57acSmx205022 nge_chip_cfg_init(nge_t *ngep, chip_info_t *infop, boolean_t reset) 5836f3e57acSmx205022 { 5846f3e57acSmx205022 uint16_t command; 5856f3e57acSmx205022 ddi_acc_handle_t handle; 5866f3e57acSmx205022 nge_interbus_conf interbus_conf; 5876f3e57acSmx205022 nge_msi_mask_conf msi_mask_conf; 5886f3e57acSmx205022 nge_msi_map_cap_conf cap_conf; 5896f3e57acSmx205022 5906f3e57acSmx205022 NGE_TRACE(("nge_chip_cfg_init($%p, $%p, %d)", 5916f3e57acSmx205022 (void *)ngep, (void *)infop, reset)); 5926f3e57acSmx205022 5936f3e57acSmx205022 /* 5946f3e57acSmx205022 * save PCI cache line size and subsystem vendor ID 5956f3e57acSmx205022 * 5966f3e57acSmx205022 * Read all the config-space registers that characterise the 5976f3e57acSmx205022 * chip, specifically vendor/device/revision/subsystem vendor 5986f3e57acSmx205022 * and subsystem device id. We expect (but don't check) that 5996f3e57acSmx205022 */ 6006f3e57acSmx205022 handle = ngep->cfg_handle; 6016f3e57acSmx205022 /* reading the vendor information once */ 6026f3e57acSmx205022 if (reset == B_FALSE) { 6036f3e57acSmx205022 infop->command = pci_config_get16(handle, 6046f3e57acSmx205022 PCI_CONF_COMM); 6056f3e57acSmx205022 infop->vendor = pci_config_get16(handle, 6066f3e57acSmx205022 PCI_CONF_VENID); 6076f3e57acSmx205022 infop->device = pci_config_get16(handle, 6086f3e57acSmx205022 PCI_CONF_DEVID); 6096f3e57acSmx205022 infop->subven = pci_config_get16(handle, 6106f3e57acSmx205022 PCI_CONF_SUBVENID); 6116f3e57acSmx205022 infop->subdev = pci_config_get16(handle, 6126f3e57acSmx205022 PCI_CONF_SUBSYSID); 6136f3e57acSmx205022 infop->class_code = pci_config_get8(handle, 6146f3e57acSmx205022 PCI_CONF_BASCLASS); 6156f3e57acSmx205022 infop->revision = pci_config_get8(handle, 6166f3e57acSmx205022 PCI_CONF_REVID); 6176f3e57acSmx205022 infop->clsize = pci_config_get8(handle, 6186f3e57acSmx205022 PCI_CONF_CACHE_LINESZ); 6196f3e57acSmx205022 infop->latency = pci_config_get8(handle, 6206f3e57acSmx205022 PCI_CONF_LATENCY_TIMER); 6216f3e57acSmx205022 } 6226f3e57acSmx205022 if (nge_enable_msi) { 6236f3e57acSmx205022 /* Disable the hidden for MSI support */ 6246f3e57acSmx205022 interbus_conf.conf_val = pci_config_get32(handle, 6256f3e57acSmx205022 PCI_CONF_HT_INTERNAL); 6266f3e57acSmx205022 if ((infop->device == DEVICE_ID_MCP55_373) || 6276f3e57acSmx205022 (infop->device == DEVICE_ID_MCP55_372)) 6286f3e57acSmx205022 interbus_conf.conf_bits.msix_off = NGE_SET; 6296f3e57acSmx205022 interbus_conf.conf_bits.msi_off = NGE_CLEAR; 6306f3e57acSmx205022 pci_config_put32(handle, PCI_CONF_HT_INTERNAL, 6316f3e57acSmx205022 interbus_conf.conf_val); 6326f3e57acSmx205022 6336f3e57acSmx205022 if ((infop->device == DEVICE_ID_MCP55_373) || 6346f3e57acSmx205022 (infop->device == DEVICE_ID_MCP55_372)) { 6356f3e57acSmx205022 6366f3e57acSmx205022 /* Disable the vector off for mcp55 */ 6376f3e57acSmx205022 msi_mask_conf.msi_mask_conf_val = 6386f3e57acSmx205022 pci_config_get32(handle, PCI_CONF_HT_MSI_MASK); 6396f3e57acSmx205022 msi_mask_conf.msi_mask_bits.vec0_off = NGE_CLEAR; 6406f3e57acSmx205022 msi_mask_conf.msi_mask_bits.vec1_off = NGE_CLEAR; 6416f3e57acSmx205022 msi_mask_conf.msi_mask_bits.vec2_off = NGE_CLEAR; 6426f3e57acSmx205022 msi_mask_conf.msi_mask_bits.vec3_off = NGE_CLEAR; 6436f3e57acSmx205022 msi_mask_conf.msi_mask_bits.vec4_off = NGE_CLEAR; 6446f3e57acSmx205022 msi_mask_conf.msi_mask_bits.vec5_off = NGE_CLEAR; 6456f3e57acSmx205022 msi_mask_conf.msi_mask_bits.vec6_off = NGE_CLEAR; 6466f3e57acSmx205022 msi_mask_conf.msi_mask_bits.vec7_off = NGE_CLEAR; 6476f3e57acSmx205022 pci_config_put32(handle, PCI_CONF_HT_MSI_MASK, 6486f3e57acSmx205022 msi_mask_conf.msi_mask_conf_val); 6496f3e57acSmx205022 6506f3e57acSmx205022 /* Enable the MSI mapping */ 6516f3e57acSmx205022 cap_conf.msi_map_cap_conf_val = 6526f3e57acSmx205022 pci_config_get32(handle, PCI_CONF_HT_MSI_MAP_CAP); 6536f3e57acSmx205022 cap_conf.map_cap_conf_bits.map_en = NGE_SET; 6546f3e57acSmx205022 pci_config_put32(handle, PCI_CONF_HT_MSI_MAP_CAP, 6556f3e57acSmx205022 cap_conf.msi_map_cap_conf_val); 6566f3e57acSmx205022 } 6576f3e57acSmx205022 } else { 6586f3e57acSmx205022 interbus_conf.conf_val = pci_config_get32(handle, 6596f3e57acSmx205022 PCI_CONF_HT_INTERNAL); 6606f3e57acSmx205022 interbus_conf.conf_bits.msi_off = NGE_SET; 6616f3e57acSmx205022 pci_config_put32(handle, PCI_CONF_HT_INTERNAL, 6626f3e57acSmx205022 interbus_conf.conf_val); 6636f3e57acSmx205022 } 6646f3e57acSmx205022 command = infop->command | PCI_COMM_MAE; 6656f3e57acSmx205022 command &= ~PCI_COMM_MEMWR_INVAL; 6666f3e57acSmx205022 command |= PCI_COMM_ME; 6676f3e57acSmx205022 pci_config_put16(handle, PCI_CONF_COMM, command); 6686f3e57acSmx205022 pci_config_put16(handle, PCI_CONF_STAT, ~0); 6696f3e57acSmx205022 6706f3e57acSmx205022 } 6716f3e57acSmx205022 6726f3e57acSmx205022 int 6736f3e57acSmx205022 nge_chip_stop(nge_t *ngep, boolean_t fault) 6746f3e57acSmx205022 { 6756f3e57acSmx205022 int err; 6766f3e57acSmx205022 uint32_t reg_val; 6776f3e57acSmx205022 uint32_t tries; 6786f3e57acSmx205022 nge_mintr_src mintr_src; 6796f3e57acSmx205022 nge_mii_cs mii_cs; 6806f3e57acSmx205022 nge_rx_poll rx_poll; 6816f3e57acSmx205022 nge_tx_poll tx_poll; 6826f3e57acSmx205022 nge_rx_en rx_en; 6836f3e57acSmx205022 nge_tx_en tx_en; 6846f3e57acSmx205022 nge_tx_sta tx_sta; 6856f3e57acSmx205022 nge_rx_sta rx_sta; 6866f3e57acSmx205022 nge_mode_cntl mode; 6876f3e57acSmx205022 nge_pmu_cntl2 pmu_cntl2; 6886f3e57acSmx205022 6896f3e57acSmx205022 NGE_TRACE(("nge_chip_stop($%p, %d)", (void *)ngep, fault)); 6906f3e57acSmx205022 6916f3e57acSmx205022 err = DDI_SUCCESS; 6929ae6bcf1Sjj146644 6939ae6bcf1Sjj146644 /* Clear any pending PHY interrupt */ 6946f3e57acSmx205022 mintr_src.src_val = nge_reg_get8(ngep, NGE_MINTR_SRC); 6956f3e57acSmx205022 nge_reg_put8(ngep, NGE_MINTR_SRC, mintr_src.src_val); 6966f3e57acSmx205022 6976f3e57acSmx205022 /* Mask all interrupts */ 6986f3e57acSmx205022 reg_val = nge_reg_get32(ngep, NGE_INTR_MASK); 6996f3e57acSmx205022 reg_val &= ~NGE_INTR_ALL_EN; 7006f3e57acSmx205022 nge_reg_put32(ngep, NGE_INTR_MASK, reg_val); 7016f3e57acSmx205022 7026f3e57acSmx205022 /* Disable auto-polling of phy */ 7036f3e57acSmx205022 mii_cs.cs_val = nge_reg_get32(ngep, NGE_MII_CS); 7046f3e57acSmx205022 mii_cs.cs_bits.ap_en = NGE_CLEAR; 7056f3e57acSmx205022 nge_reg_put32(ngep, NGE_MII_CS, mii_cs.cs_val); 7066f3e57acSmx205022 7076f3e57acSmx205022 /* Reset buffer management & DMA */ 7086f3e57acSmx205022 mode.mode_val = nge_reg_get32(ngep, NGE_MODE_CNTL); 7096f3e57acSmx205022 mode.mode_bits.dma_dis = NGE_SET; 7106f3e57acSmx205022 mode.mode_bits.desc_type = ngep->desc_mode; 7116f3e57acSmx205022 nge_reg_put32(ngep, NGE_MODE_CNTL, mode.mode_val); 7126f3e57acSmx205022 7136de4f663Smx205022 for (tries = 0; tries < 10000; tries++) { 7146f3e57acSmx205022 drv_usecwait(10); 7156f3e57acSmx205022 mode.mode_val = nge_reg_get32(ngep, NGE_MODE_CNTL); 7166f3e57acSmx205022 if (mode.mode_bits.dma_status == NGE_SET) 7176f3e57acSmx205022 break; 7186f3e57acSmx205022 } 7196de4f663Smx205022 if (tries == 10000) { 720a01a4735SWinson Wang - Sun Microsystems - Beijing China ngep->nge_chip_state = NGE_CHIP_ERROR; 7216f3e57acSmx205022 return (DDI_FAILURE); 7226f3e57acSmx205022 } 7236f3e57acSmx205022 7246f3e57acSmx205022 /* Disable rx's machine */ 7256f3e57acSmx205022 rx_en.val = nge_reg_get8(ngep, NGE_RX_EN); 7266f3e57acSmx205022 rx_en.bits.rx_en = NGE_CLEAR; 7276f3e57acSmx205022 nge_reg_put8(ngep, NGE_RX_EN, rx_en.val); 7286f3e57acSmx205022 7296f3e57acSmx205022 /* Disable tx's machine */ 7306f3e57acSmx205022 tx_en.val = nge_reg_get8(ngep, NGE_TX_EN); 7316f3e57acSmx205022 tx_en.bits.tx_en = NGE_CLEAR; 7326f3e57acSmx205022 nge_reg_put8(ngep, NGE_TX_EN, tx_en.val); 7336f3e57acSmx205022 7346f3e57acSmx205022 /* 7356f3e57acSmx205022 * Clean the status of tx's state machine 7366f3e57acSmx205022 * and Make assure the tx's channel is idle 7376f3e57acSmx205022 */ 7386f3e57acSmx205022 tx_sta.sta_val = nge_reg_get32(ngep, NGE_TX_STA); 7396f3e57acSmx205022 for (tries = 0; tries < 1000; tries++) { 7406f3e57acSmx205022 if (tx_sta.sta_bits.tx_chan_sta == NGE_CLEAR) 7416f3e57acSmx205022 break; 7426f3e57acSmx205022 drv_usecwait(10); 7436f3e57acSmx205022 tx_sta.sta_val = nge_reg_get32(ngep, NGE_TX_STA); 7446f3e57acSmx205022 } 7456f3e57acSmx205022 if (tries == 1000) { 746a01a4735SWinson Wang - Sun Microsystems - Beijing China ngep->nge_chip_state = NGE_CHIP_ERROR; 7476f3e57acSmx205022 return (DDI_FAILURE); 7486f3e57acSmx205022 } 7496f3e57acSmx205022 nge_reg_put32(ngep, NGE_TX_STA, tx_sta.sta_val); 7506f3e57acSmx205022 7516f3e57acSmx205022 /* 7526f3e57acSmx205022 * Clean the status of rx's state machine 7536f3e57acSmx205022 * and Make assure the tx's channel is idle 7546f3e57acSmx205022 */ 7556f3e57acSmx205022 rx_sta.sta_val = nge_reg_get32(ngep, NGE_RX_STA); 7566f3e57acSmx205022 for (tries = 0; tries < 1000; tries++) { 7576f3e57acSmx205022 if (rx_sta.sta_bits.rx_chan_sta == NGE_CLEAR) 7586f3e57acSmx205022 break; 7596f3e57acSmx205022 drv_usecwait(10); 7606f3e57acSmx205022 rx_sta.sta_val = nge_reg_get32(ngep, NGE_RX_STA); 7616f3e57acSmx205022 } 7626f3e57acSmx205022 if (tries == 1000) { 763a01a4735SWinson Wang - Sun Microsystems - Beijing China ngep->nge_chip_state = NGE_CHIP_ERROR; 7646f3e57acSmx205022 return (DDI_FAILURE); 7656f3e57acSmx205022 } 7666f3e57acSmx205022 nge_reg_put32(ngep, NGE_RX_STA, rx_sta.sta_val); 7676f3e57acSmx205022 7689ae6bcf1Sjj146644 /* Disable auto-poll of rx's state machine */ 7699ae6bcf1Sjj146644 rx_poll.poll_val = nge_reg_get32(ngep, NGE_RX_POLL); 7709ae6bcf1Sjj146644 rx_poll.poll_bits.rpen = NGE_CLEAR; 7719ae6bcf1Sjj146644 rx_poll.poll_bits.rpi = NGE_CLEAR; 7729ae6bcf1Sjj146644 nge_reg_put32(ngep, NGE_RX_POLL, rx_poll.poll_val); 7739ae6bcf1Sjj146644 7749ae6bcf1Sjj146644 /* Disable auto-polling of tx's state machine */ 7759ae6bcf1Sjj146644 tx_poll.poll_val = nge_reg_get32(ngep, NGE_TX_POLL); 7769ae6bcf1Sjj146644 tx_poll.poll_bits.tpen = NGE_CLEAR; 7779ae6bcf1Sjj146644 tx_poll.poll_bits.tpi = NGE_CLEAR; 7789ae6bcf1Sjj146644 nge_reg_put32(ngep, NGE_TX_POLL, tx_poll.poll_val); 7799ae6bcf1Sjj146644 7809ae6bcf1Sjj146644 /* Restore buffer management */ 7819ae6bcf1Sjj146644 mode.mode_val = nge_reg_get32(ngep, NGE_MODE_CNTL); 7829ae6bcf1Sjj146644 mode.mode_bits.bm_reset = NGE_SET; 7839ae6bcf1Sjj146644 mode.mode_bits.tx_rcom_en = NGE_SET; 7849ae6bcf1Sjj146644 nge_reg_put32(ngep, NGE_MODE_CNTL, mode.mode_val); 7859ae6bcf1Sjj146644 7869ae6bcf1Sjj146644 if (ngep->dev_spec_param.advanced_pm) { 7876f3e57acSmx205022 7886f3e57acSmx205022 nge_reg_put32(ngep, NGE_PMU_CIDLE_LIMIT, 0); 7896f3e57acSmx205022 nge_reg_put32(ngep, NGE_PMU_DIDLE_LIMIT, 0); 7906f3e57acSmx205022 7916f3e57acSmx205022 pmu_cntl2.cntl2_val = nge_reg_get32(ngep, NGE_PMU_CNTL2); 7926f3e57acSmx205022 pmu_cntl2.cntl2_bits.cidle_timer = NGE_CLEAR; 7936f3e57acSmx205022 pmu_cntl2.cntl2_bits.didle_timer = NGE_CLEAR; 7946f3e57acSmx205022 nge_reg_put32(ngep, NGE_PMU_CNTL2, pmu_cntl2.cntl2_val); 7956f3e57acSmx205022 } 7966f3e57acSmx205022 if (fault) 7976f3e57acSmx205022 ngep->nge_chip_state = NGE_CHIP_FAULT; 7986f3e57acSmx205022 else 7996f3e57acSmx205022 ngep->nge_chip_state = NGE_CHIP_STOPPED; 8006f3e57acSmx205022 8016f3e57acSmx205022 return (err); 8026f3e57acSmx205022 } 8036f3e57acSmx205022 8046f3e57acSmx205022 static void 8056f3e57acSmx205022 nge_rx_setup(nge_t *ngep) 8066f3e57acSmx205022 { 8076f3e57acSmx205022 uint64_t desc_addr; 8086f3e57acSmx205022 nge_rxtx_dlen dlen; 8096f3e57acSmx205022 nge_rx_poll rx_poll; 8106f3e57acSmx205022 8116f3e57acSmx205022 /* 8126f3e57acSmx205022 * Filling the address and length of rx's descriptors 8136f3e57acSmx205022 */ 8146f3e57acSmx205022 desc_addr = ngep->recv->desc.cookie.dmac_laddress; 8156f3e57acSmx205022 nge_reg_put32(ngep, NGE_RX_DADR, desc_addr); 8166f3e57acSmx205022 nge_reg_put32(ngep, NGE_RX_DADR_HI, desc_addr >> 32); 8176f3e57acSmx205022 dlen.dlen_val = nge_reg_get32(ngep, NGE_RXTX_DLEN); 8186f3e57acSmx205022 dlen.dlen_bits.rdlen = ngep->recv->desc.nslots - 1; 8196f3e57acSmx205022 nge_reg_put32(ngep, NGE_RXTX_DLEN, dlen.dlen_val); 8206f3e57acSmx205022 8216f3e57acSmx205022 rx_poll.poll_val = nge_reg_get32(ngep, NGE_RX_POLL); 8226f3e57acSmx205022 rx_poll.poll_bits.rpi = RX_POLL_INTV_1G; 8236f3e57acSmx205022 rx_poll.poll_bits.rpen = NGE_SET; 8246f3e57acSmx205022 nge_reg_put32(ngep, NGE_RX_POLL, rx_poll.poll_val); 8256f3e57acSmx205022 } 8266f3e57acSmx205022 8276f3e57acSmx205022 static void 8286f3e57acSmx205022 nge_tx_setup(nge_t *ngep) 8296f3e57acSmx205022 { 8306f3e57acSmx205022 uint64_t desc_addr; 8316f3e57acSmx205022 nge_rxtx_dlen dlen; 8326f3e57acSmx205022 8336f3e57acSmx205022 /* 8346f3e57acSmx205022 * Filling the address and length of tx's descriptors 8356f3e57acSmx205022 */ 8366f3e57acSmx205022 desc_addr = ngep->send->desc.cookie.dmac_laddress; 8376f3e57acSmx205022 nge_reg_put32(ngep, NGE_TX_DADR, desc_addr); 8386f3e57acSmx205022 nge_reg_put32(ngep, NGE_TX_DADR_HI, desc_addr >> 32); 8396f3e57acSmx205022 dlen.dlen_val = nge_reg_get32(ngep, NGE_RXTX_DLEN); 8406f3e57acSmx205022 dlen.dlen_bits.tdlen = ngep->send->desc.nslots - 1; 8416f3e57acSmx205022 nge_reg_put32(ngep, NGE_RXTX_DLEN, dlen.dlen_val); 8426f3e57acSmx205022 } 8436f3e57acSmx205022 8446f3e57acSmx205022 static int 8456f3e57acSmx205022 nge_buff_setup(nge_t *ngep) 8466f3e57acSmx205022 { 8476f3e57acSmx205022 nge_mode_cntl mode_cntl; 8486f3e57acSmx205022 nge_dev_spec_param_t *dev_param_p; 8496f3e57acSmx205022 8506f3e57acSmx205022 dev_param_p = &ngep->dev_spec_param; 8516f3e57acSmx205022 8526f3e57acSmx205022 /* 8536f3e57acSmx205022 * Configure Rx&Tx's buffer 8546f3e57acSmx205022 */ 8556f3e57acSmx205022 nge_rx_setup(ngep); 8566f3e57acSmx205022 nge_tx_setup(ngep); 8576f3e57acSmx205022 8586f3e57acSmx205022 /* 8596f3e57acSmx205022 * Configure buffer attribute 8606f3e57acSmx205022 */ 8616f3e57acSmx205022 mode_cntl.mode_val = nge_reg_get32(ngep, NGE_MODE_CNTL); 8626f3e57acSmx205022 8636f3e57acSmx205022 /* 8646f3e57acSmx205022 * Enable Dma access request 8656f3e57acSmx205022 */ 8666f3e57acSmx205022 mode_cntl.mode_bits.dma_dis = NGE_CLEAR; 8676f3e57acSmx205022 8686f3e57acSmx205022 /* 8696f3e57acSmx205022 * Enbale Buffer management 8706f3e57acSmx205022 */ 8716f3e57acSmx205022 mode_cntl.mode_bits.bm_reset = NGE_CLEAR; 8726f3e57acSmx205022 8736f3e57acSmx205022 /* 8746f3e57acSmx205022 * Support Standoffload Descriptor 8756f3e57acSmx205022 */ 8766f3e57acSmx205022 mode_cntl.mode_bits.desc_type = ngep->desc_mode; 8776f3e57acSmx205022 8786f3e57acSmx205022 /* 8796f3e57acSmx205022 * Support receive hardware checksum 8806f3e57acSmx205022 */ 8816f3e57acSmx205022 if (dev_param_p->rx_hw_checksum) { 8826f3e57acSmx205022 mode_cntl.mode_bits.rx_sum_en = NGE_SET; 8836f3e57acSmx205022 } else 8846f3e57acSmx205022 mode_cntl.mode_bits.rx_sum_en = NGE_CLEAR; 8856f3e57acSmx205022 8866f3e57acSmx205022 /* 8876f3e57acSmx205022 * Disable Tx PRD coarse update 8886f3e57acSmx205022 */ 8896f3e57acSmx205022 mode_cntl.mode_bits.tx_prd_cu_en = NGE_CLEAR; 8906f3e57acSmx205022 8916f3e57acSmx205022 /* 8926f3e57acSmx205022 * Disable 64-byte access 8936f3e57acSmx205022 */ 8946f3e57acSmx205022 mode_cntl.mode_bits.w64_dis = NGE_SET; 8956f3e57acSmx205022 8966f3e57acSmx205022 /* 8976f3e57acSmx205022 * Skip Rx Error Frame is not supported and if 8986f3e57acSmx205022 * enable it, jumbo frame does not work any more. 8996f3e57acSmx205022 */ 9006f3e57acSmx205022 mode_cntl.mode_bits.rx_filter_en = NGE_CLEAR; 9016f3e57acSmx205022 9026f3e57acSmx205022 /* 9036f3e57acSmx205022 * Can not support hot mode now 9046f3e57acSmx205022 */ 9056f3e57acSmx205022 mode_cntl.mode_bits.resv15 = NGE_CLEAR; 9066f3e57acSmx205022 9076f3e57acSmx205022 if (dev_param_p->vlan) { 9086f3e57acSmx205022 /* Disable the vlan strip for devices which support vlan */ 9096f3e57acSmx205022 mode_cntl.mode_bits.vlan_strip = NGE_CLEAR; 9106f3e57acSmx205022 9116f3e57acSmx205022 /* Disable the vlan insert for devices which supprot vlan */ 9126f3e57acSmx205022 mode_cntl.mode_bits.vlan_ins = NGE_CLEAR; 9136f3e57acSmx205022 } 9146f3e57acSmx205022 9156f3e57acSmx205022 if (dev_param_p->tx_rx_64byte) { 9166f3e57acSmx205022 9176f3e57acSmx205022 /* Set the maximum TX PRD fetch size to 64 bytes */ 9186f3e57acSmx205022 mode_cntl.mode_bits.tx_fetch_prd = NGE_SET; 9196f3e57acSmx205022 9206f3e57acSmx205022 /* Set the maximum RX PRD fetch size to 64 bytes */ 9216f3e57acSmx205022 mode_cntl.mode_bits.rx_fetch_prd = NGE_SET; 9226f3e57acSmx205022 } 9236f3e57acSmx205022 /* 9246f3e57acSmx205022 * Upload Rx data as it arrives, rather than waiting for full frame 9256f3e57acSmx205022 */ 9266f3e57acSmx205022 mode_cntl.mode_bits.resv16 = NGE_CLEAR; 9276f3e57acSmx205022 9286f3e57acSmx205022 /* 9296f3e57acSmx205022 * Normal HOT table accesses 9306f3e57acSmx205022 */ 9316f3e57acSmx205022 mode_cntl.mode_bits.resv17 = NGE_CLEAR; 9326f3e57acSmx205022 9336f3e57acSmx205022 /* 9346f3e57acSmx205022 * Normal HOT buffer requesting 9356f3e57acSmx205022 */ 9366f3e57acSmx205022 mode_cntl.mode_bits.resv18 = NGE_CLEAR; 9376f3e57acSmx205022 nge_reg_put32(ngep, NGE_MODE_CNTL, mode_cntl.mode_val); 9386f3e57acSmx205022 9396f3e57acSmx205022 /* 9406f3e57acSmx205022 * Signal controller to check for new Rx descriptors 9416f3e57acSmx205022 */ 9426f3e57acSmx205022 mode_cntl.mode_val = nge_reg_get32(ngep, NGE_MODE_CNTL); 9436f3e57acSmx205022 mode_cntl.mode_bits.rxdm = NGE_SET; 9446f3e57acSmx205022 mode_cntl.mode_bits.tx_rcom_en = NGE_SET; 9456f3e57acSmx205022 nge_reg_put32(ngep, NGE_MODE_CNTL, mode_cntl.mode_val); 9466f3e57acSmx205022 9476f3e57acSmx205022 9486f3e57acSmx205022 return (DDI_SUCCESS); 9496f3e57acSmx205022 } 9506f3e57acSmx205022 9516f3e57acSmx205022 /* 9526f3e57acSmx205022 * When chipset resets, the chipset can not restore the orignial 9536f3e57acSmx205022 * mac address to the mac address registers. 9546f3e57acSmx205022 * 9556f3e57acSmx205022 * When the driver is dettached, the function will write the orignial 9566f3e57acSmx205022 * mac address to the mac address registers. 9576f3e57acSmx205022 */ 9586f3e57acSmx205022 9596f3e57acSmx205022 void 9606f3e57acSmx205022 nge_restore_mac_addr(nge_t *ngep) 9616f3e57acSmx205022 { 9626f3e57acSmx205022 uint32_t mac_addr; 9636f3e57acSmx205022 9646f3e57acSmx205022 mac_addr = (uint32_t)ngep->chipinfo.hw_mac_addr; 9656f3e57acSmx205022 nge_reg_put32(ngep, NGE_UNI_ADDR0, mac_addr); 9666f3e57acSmx205022 mac_addr = (uint32_t)(ngep->chipinfo.hw_mac_addr >> 32); 9676f3e57acSmx205022 nge_reg_put32(ngep, NGE_UNI_ADDR1, mac_addr); 9686f3e57acSmx205022 } 9696f3e57acSmx205022 9706f3e57acSmx205022 int 9716f3e57acSmx205022 nge_chip_reset(nge_t *ngep) 9726f3e57acSmx205022 { 9736f3e57acSmx205022 int err; 9746f3e57acSmx205022 uint8_t i; 9756f3e57acSmx205022 uint32_t regno; 976d27d4a13SMiles Xu, Sun Microsystems uint64_t mac = 0; 9776f3e57acSmx205022 nge_uni_addr1 uaddr1; 9786f3e57acSmx205022 nge_cp_cntl ee_cntl; 9796f3e57acSmx205022 nge_soft_misc soft_misc; 9806f3e57acSmx205022 nge_pmu_cntl0 pmu_cntl0; 9816f3e57acSmx205022 nge_pmu_cntl2 pmu_cntl2; 9826f3e57acSmx205022 nge_pm_cntl2 pm_cntl2; 9836f3e57acSmx205022 const nge_ksindex_t *ksip; 9846f3e57acSmx205022 9856f3e57acSmx205022 NGE_TRACE(("nge_chip_reset($%p)", (void *)ngep)); 9866f3e57acSmx205022 9876f3e57acSmx205022 /* 9886f3e57acSmx205022 * Clear the statistics by reading the statistics register 9896f3e57acSmx205022 */ 9906f3e57acSmx205022 for (ksip = nge_statistics; ksip->name != NULL; ++ksip) { 9916f3e57acSmx205022 regno = KS_BASE + ksip->index * sizeof (uint32_t); 9926f3e57acSmx205022 (void) nge_reg_get32(ngep, regno); 9936f3e57acSmx205022 } 9946f3e57acSmx205022 9956f3e57acSmx205022 /* 9966f3e57acSmx205022 * Setup seeprom control 9976f3e57acSmx205022 */ 9986f3e57acSmx205022 ee_cntl.cntl_val = nge_reg_get32(ngep, NGE_EP_CNTL); 9996f3e57acSmx205022 ee_cntl.cntl_bits.clkdiv = EEPROM_CLKDIV; 10006f3e57acSmx205022 ee_cntl.cntl_bits.rom_size = EEPROM_32K; 10016f3e57acSmx205022 ee_cntl.cntl_bits.word_wid = ACCESS_16BIT; 10026f3e57acSmx205022 ee_cntl.cntl_bits.wait_slots = EEPROM_WAITCLK; 10036f3e57acSmx205022 nge_reg_put32(ngep, NGE_EP_CNTL, ee_cntl.cntl_val); 10046f3e57acSmx205022 10056f3e57acSmx205022 /* 10066f3e57acSmx205022 * Reading the unicast mac address table 10076f3e57acSmx205022 */ 10086f3e57acSmx205022 if (ngep->nge_chip_state == NGE_CHIP_INITIAL) { 10096f3e57acSmx205022 uaddr1.addr_val = nge_reg_get32(ngep, NGE_UNI_ADDR1); 10106f3e57acSmx205022 mac = uaddr1.addr_bits.addr; 10116f3e57acSmx205022 mac <<= 32; 10126f3e57acSmx205022 mac |= nge_reg_get32(ngep, NGE_UNI_ADDR0); 1013a01a4735SWinson Wang - Sun Microsystems - Beijing China ngep->chipinfo.hw_mac_addr = mac; 1014a01a4735SWinson Wang - Sun Microsystems - Beijing China if (ngep->dev_spec_param.mac_addr_order) { 1015d27d4a13SMiles Xu, Sun Microsystems for (i = 0; i < ETHERADDRL; i++) { 1016a01a4735SWinson Wang - Sun Microsystems - Beijing China ngep->chipinfo.vendor_addr.addr[i] = 1017a01a4735SWinson Wang - Sun Microsystems - Beijing China (uchar_t)mac; 1018a01a4735SWinson Wang - Sun Microsystems - Beijing China ngep->cur_uni_addr.addr[i] = 1019a01a4735SWinson Wang - Sun Microsystems - Beijing China (uchar_t)mac; 1020d27d4a13SMiles Xu, Sun Microsystems mac >>= 8; 1021d27d4a13SMiles Xu, Sun Microsystems } 1022a01a4735SWinson Wang - Sun Microsystems - Beijing China } else { 10236f3e57acSmx205022 for (i = ETHERADDRL; i-- != 0; ) { 10246f3e57acSmx205022 ngep->chipinfo.vendor_addr.addr[i] = 10256f3e57acSmx205022 (uchar_t)mac; 1026a01a4735SWinson Wang - Sun Microsystems - Beijing China ngep->cur_uni_addr.addr[i] = 1027a01a4735SWinson Wang - Sun Microsystems - Beijing China (uchar_t)mac; 10286f3e57acSmx205022 mac >>= 8; 10296f3e57acSmx205022 } 10306f3e57acSmx205022 } 1031a01a4735SWinson Wang - Sun Microsystems - Beijing China ngep->chipinfo.vendor_addr.set = 1; 10326f3e57acSmx205022 } 10336f3e57acSmx205022 pci_config_put8(ngep->cfg_handle, PCI_CONF_CACHE_LINESZ, 10346f3e57acSmx205022 ngep->chipinfo.clsize); 10356f3e57acSmx205022 pci_config_put8(ngep->cfg_handle, PCI_CONF_LATENCY_TIMER, 10366f3e57acSmx205022 ngep->chipinfo.latency); 10376f3e57acSmx205022 10389ae6bcf1Sjj146644 10399ae6bcf1Sjj146644 if (ngep->dev_spec_param.advanced_pm) { 10406f3e57acSmx205022 10416f3e57acSmx205022 /* Program software misc register */ 10426f3e57acSmx205022 soft_misc.misc_val = nge_reg_get32(ngep, NGE_SOFT_MISC); 10436f3e57acSmx205022 soft_misc.misc_bits.rx_clk_vx_rst = NGE_SET; 10446f3e57acSmx205022 soft_misc.misc_bits.tx_clk_vx_rst = NGE_SET; 10456f3e57acSmx205022 soft_misc.misc_bits.clk12m_vx_rst = NGE_SET; 10466f3e57acSmx205022 soft_misc.misc_bits.fpci_clk_vx_rst = NGE_SET; 10476f3e57acSmx205022 soft_misc.misc_bits.rx_clk_vc_rst = NGE_SET; 10486f3e57acSmx205022 soft_misc.misc_bits.tx_clk_vc_rst = NGE_SET; 10496f3e57acSmx205022 soft_misc.misc_bits.fs_clk_vc_rst = NGE_SET; 10506f3e57acSmx205022 soft_misc.misc_bits.rst_ex_m2pintf = NGE_SET; 10516f3e57acSmx205022 nge_reg_put32(ngep, NGE_SOFT_MISC, soft_misc.misc_val); 10526f3e57acSmx205022 10539ae6bcf1Sjj146644 /* wait for 32 us */ 10549ae6bcf1Sjj146644 drv_usecwait(32); 10556f3e57acSmx205022 10566f3e57acSmx205022 soft_misc.misc_val = nge_reg_get32(ngep, NGE_SOFT_MISC); 10576f3e57acSmx205022 soft_misc.misc_bits.rx_clk_vx_rst = NGE_CLEAR; 10586f3e57acSmx205022 soft_misc.misc_bits.tx_clk_vx_rst = NGE_CLEAR; 10596f3e57acSmx205022 soft_misc.misc_bits.clk12m_vx_rst = NGE_CLEAR; 10606f3e57acSmx205022 soft_misc.misc_bits.fpci_clk_vx_rst = NGE_CLEAR; 10616f3e57acSmx205022 soft_misc.misc_bits.rx_clk_vc_rst = NGE_CLEAR; 10626f3e57acSmx205022 soft_misc.misc_bits.tx_clk_vc_rst = NGE_CLEAR; 10636f3e57acSmx205022 soft_misc.misc_bits.fs_clk_vc_rst = NGE_CLEAR; 10646f3e57acSmx205022 soft_misc.misc_bits.rst_ex_m2pintf = NGE_CLEAR; 10656f3e57acSmx205022 nge_reg_put32(ngep, NGE_SOFT_MISC, soft_misc.misc_val); 10666f3e57acSmx205022 10676f3e57acSmx205022 /* Program PMU registers */ 10686f3e57acSmx205022 pmu_cntl0.cntl0_val = nge_reg_get32(ngep, NGE_PMU_CNTL0); 10696f3e57acSmx205022 pmu_cntl0.cntl0_bits.core_spd10_fp = 10706f3e57acSmx205022 NGE_PMU_CORE_SPD10_BUSY; 10716f3e57acSmx205022 pmu_cntl0.cntl0_bits.core_spd10_idle = 10726f3e57acSmx205022 NGE_PMU_CORE_SPD10_IDLE; 10736f3e57acSmx205022 pmu_cntl0.cntl0_bits.core_spd100_fp = 10746f3e57acSmx205022 NGE_PMU_CORE_SPD100_BUSY; 10756f3e57acSmx205022 pmu_cntl0.cntl0_bits.core_spd100_idle = 10766f3e57acSmx205022 NGE_PMU_CORE_SPD100_IDLE; 10776f3e57acSmx205022 pmu_cntl0.cntl0_bits.core_spd1000_fp = 10786f3e57acSmx205022 NGE_PMU_CORE_SPD1000_BUSY; 10796f3e57acSmx205022 pmu_cntl0.cntl0_bits.core_spd1000_idle = 10806f3e57acSmx205022 NGE_PMU_CORE_SPD100_IDLE; 10816f3e57acSmx205022 pmu_cntl0.cntl0_bits.core_spd10_idle = 10826f3e57acSmx205022 NGE_PMU_CORE_SPD10_IDLE; 10836f3e57acSmx205022 nge_reg_put32(ngep, NGE_PMU_CNTL0, pmu_cntl0.cntl0_val); 10846f3e57acSmx205022 10856f3e57acSmx205022 /* Set the core idle limit value */ 10866f3e57acSmx205022 nge_reg_put32(ngep, NGE_PMU_CIDLE_LIMIT, 10876f3e57acSmx205022 NGE_PMU_CIDLE_LIMIT_DEF); 10886f3e57acSmx205022 10896f3e57acSmx205022 /* Set the device idle limit value */ 10906f3e57acSmx205022 nge_reg_put32(ngep, NGE_PMU_DIDLE_LIMIT, 10916f3e57acSmx205022 NGE_PMU_DIDLE_LIMIT_DEF); 10926f3e57acSmx205022 10936f3e57acSmx205022 /* Enable the core/device idle timer in PMU control 2 */ 10946f3e57acSmx205022 pmu_cntl2.cntl2_val = nge_reg_get32(ngep, NGE_PMU_CNTL2); 10956f3e57acSmx205022 pmu_cntl2.cntl2_bits.cidle_timer = NGE_SET; 10966f3e57acSmx205022 pmu_cntl2.cntl2_bits.didle_timer = NGE_SET; 10976f3e57acSmx205022 pmu_cntl2.cntl2_bits.core_enable = NGE_SET; 10986f3e57acSmx205022 pmu_cntl2.cntl2_bits.dev_enable = NGE_SET; 10996f3e57acSmx205022 nge_reg_put32(ngep, NGE_PMU_CNTL2, pmu_cntl2.cntl2_val); 11006f3e57acSmx205022 } 11019ae6bcf1Sjj146644 /* 11029ae6bcf1Sjj146644 * Stop the chipset and clear buffer management 11039ae6bcf1Sjj146644 */ 11049ae6bcf1Sjj146644 err = nge_chip_stop(ngep, B_FALSE); 11059ae6bcf1Sjj146644 if (err == DDI_FAILURE) 11069ae6bcf1Sjj146644 return (err); 11076f3e57acSmx205022 /* 11086f3e57acSmx205022 * Clear the power state bits for phy since interface no longer 11096f3e57acSmx205022 * works after rebooting from Windows on a multi-boot machine 11106f3e57acSmx205022 */ 11116f3e57acSmx205022 if (ngep->chipinfo.device == DEVICE_ID_MCP51_268 || 11126f3e57acSmx205022 ngep->chipinfo.device == DEVICE_ID_MCP51_269 || 11136f3e57acSmx205022 ngep->chipinfo.device == DEVICE_ID_MCP55_372 || 11146f3e57acSmx205022 ngep->chipinfo.device == DEVICE_ID_MCP55_373 || 11156f3e57acSmx205022 ngep->chipinfo.device == DEVICE_ID_MCP61_3EE || 1116a01a4735SWinson Wang - Sun Microsystems - Beijing China ngep->chipinfo.device == DEVICE_ID_MCP61_3EF || 11179fa05d92SWinson Wang - Sun Microsystems - Beijing China ngep->chipinfo.device == DEVICE_ID_MCP77_760 || 11189fa05d92SWinson Wang - Sun Microsystems - Beijing China ngep->chipinfo.device == DEVICE_ID_MCP79_AB0) { 11196f3e57acSmx205022 11206f3e57acSmx205022 pm_cntl2.cntl_val = nge_reg_get32(ngep, NGE_PM_CNTL2); 11216f3e57acSmx205022 /* bring phy out of coma mode */ 11226f3e57acSmx205022 pm_cntl2.cntl_bits.phy_coma_set = NGE_CLEAR; 11236f3e57acSmx205022 /* disable auto reset coma bits */ 11246f3e57acSmx205022 pm_cntl2.cntl_bits.resv4 = NGE_CLEAR; 11256f3e57acSmx205022 /* restore power to gated clocks */ 11266f3e57acSmx205022 pm_cntl2.cntl_bits.resv8_11 = NGE_CLEAR; 11276f3e57acSmx205022 nge_reg_put32(ngep, NGE_PM_CNTL2, pm_cntl2.cntl_val); 11286f3e57acSmx205022 } 11296f3e57acSmx205022 11306f3e57acSmx205022 ngep->nge_chip_state = NGE_CHIP_RESET; 11316f3e57acSmx205022 return (DDI_SUCCESS); 11326f3e57acSmx205022 } 11336f3e57acSmx205022 11346f3e57acSmx205022 int 11356f3e57acSmx205022 nge_chip_start(nge_t *ngep) 11366f3e57acSmx205022 { 11376f3e57acSmx205022 int err; 11386f3e57acSmx205022 nge_itc itc; 11396f3e57acSmx205022 nge_tx_cntl tx_cntl; 11406f3e57acSmx205022 nge_rx_cntrl0 rx_cntl0; 11416f3e57acSmx205022 nge_rx_cntl1 rx_cntl1; 11426f3e57acSmx205022 nge_tx_en tx_en; 11436f3e57acSmx205022 nge_rx_en rx_en; 11446f3e57acSmx205022 nge_mii_cs mii_cs; 11456f3e57acSmx205022 nge_swtr_cntl swtr_cntl; 11466f3e57acSmx205022 nge_rx_fifo_wm rx_fifo; 11476f3e57acSmx205022 nge_intr_mask intr_mask; 11486f3e57acSmx205022 nge_mintr_mask mintr_mask; 11496f3e57acSmx205022 nge_dev_spec_param_t *dev_param_p; 11506f3e57acSmx205022 11516f3e57acSmx205022 NGE_TRACE(("nge_chip_start($%p)", (void *)ngep)); 11526f3e57acSmx205022 11536f3e57acSmx205022 /* 11546f3e57acSmx205022 * Setup buffer management 11556f3e57acSmx205022 */ 11566f3e57acSmx205022 err = nge_buff_setup(ngep); 11576f3e57acSmx205022 if (err == DDI_FAILURE) 11586f3e57acSmx205022 return (err); 11596f3e57acSmx205022 11606f3e57acSmx205022 dev_param_p = &ngep->dev_spec_param; 11616f3e57acSmx205022 11626f3e57acSmx205022 /* 11636f3e57acSmx205022 * Enable polling attribute 11646f3e57acSmx205022 */ 11656f3e57acSmx205022 mii_cs.cs_val = nge_reg_get32(ngep, NGE_MII_CS); 11666f3e57acSmx205022 mii_cs.cs_bits.ap_paddr = ngep->phy_xmii_addr; 11676f3e57acSmx205022 mii_cs.cs_bits.ap_en = NGE_SET; 11686f3e57acSmx205022 mii_cs.cs_bits.ap_intv = MII_POLL_INTV; 11696f3e57acSmx205022 nge_reg_put32(ngep, NGE_MII_CS, mii_cs.cs_val); 11706f3e57acSmx205022 11716f3e57acSmx205022 /* 11726f3e57acSmx205022 * Setup link 11736f3e57acSmx205022 */ 11746f3e57acSmx205022 (*ngep->physops->phys_update)(ngep); 11756f3e57acSmx205022 11766f3e57acSmx205022 /* 11776f3e57acSmx205022 * Configure the tx's parameters 11786f3e57acSmx205022 */ 11796f3e57acSmx205022 tx_cntl.cntl_val = nge_reg_get32(ngep, NGE_TX_CNTL); 11806f3e57acSmx205022 if (dev_param_p->tx_pause_frame) 11816f3e57acSmx205022 tx_cntl.cntl_bits.paen = NGE_SET; 11826f3e57acSmx205022 else 11836f3e57acSmx205022 tx_cntl.cntl_bits.paen = NGE_CLEAR; 11846f3e57acSmx205022 tx_cntl.cntl_bits.retry_en = NGE_SET; 11856f3e57acSmx205022 tx_cntl.cntl_bits.pad_en = NGE_SET; 11866f3e57acSmx205022 tx_cntl.cntl_bits.fappend_en = NGE_SET; 11876f3e57acSmx205022 tx_cntl.cntl_bits.two_def_en = NGE_SET; 11886f3e57acSmx205022 tx_cntl.cntl_bits.max_retry = 15; 11896f3e57acSmx205022 tx_cntl.cntl_bits.burst_en = NGE_CLEAR; 11906f3e57acSmx205022 tx_cntl.cntl_bits.uflo_err_mask = NGE_CLEAR; 11916f3e57acSmx205022 tx_cntl.cntl_bits.tlcol_mask = NGE_CLEAR; 11926f3e57acSmx205022 tx_cntl.cntl_bits.lcar_mask = NGE_CLEAR; 11936f3e57acSmx205022 tx_cntl.cntl_bits.def_mask = NGE_CLEAR; 11946f3e57acSmx205022 tx_cntl.cntl_bits.exdef_mask = NGE_SET; 11956f3e57acSmx205022 tx_cntl.cntl_bits.lcar_mask = NGE_SET; 11966f3e57acSmx205022 tx_cntl.cntl_bits.tlcol_mask = NGE_SET; 11976f3e57acSmx205022 tx_cntl.cntl_bits.uflo_err_mask = NGE_SET; 11986f3e57acSmx205022 tx_cntl.cntl_bits.jam_seq_en = NGE_CLEAR; 11996f3e57acSmx205022 nge_reg_put32(ngep, NGE_TX_CNTL, tx_cntl.cntl_val); 12006f3e57acSmx205022 12016f3e57acSmx205022 12026f3e57acSmx205022 /* 12036f3e57acSmx205022 * Configure the parameters of Rx's state machine 12046f3e57acSmx205022 * Enabe the parameters: 12056f3e57acSmx205022 * 1). Pad Strip 12066f3e57acSmx205022 * 2). FCS Relay 12076f3e57acSmx205022 * 3). Pause 12086f3e57acSmx205022 * 4). Address filter 12096f3e57acSmx205022 * 5). Runt Packet receive 12106f3e57acSmx205022 * 6). Broadcast 12116f3e57acSmx205022 * 7). Receive Deferral 12126f3e57acSmx205022 * 12136f3e57acSmx205022 * Disable the following parameters for decreasing 12146f3e57acSmx205022 * the number of interrupts: 12156f3e57acSmx205022 * 1). Runt Inerrupt. 12166f3e57acSmx205022 * 2). Rx's Late Collision interrupt. 12176f3e57acSmx205022 * 3). Rx's Max length Error Interrupt. 12186f3e57acSmx205022 * 4). Rx's Length Field error Interrupt. 12196f3e57acSmx205022 * 5). Rx's FCS error interrupt. 12206f3e57acSmx205022 * 6). Rx's overflow error interrupt. 12216f3e57acSmx205022 * 7). Rx's Frame alignment error interrupt. 12226f3e57acSmx205022 */ 12236f3e57acSmx205022 rx_cntl0.cntl_val = nge_reg_get32(ngep, NGE_RX_CNTL0); 12246f3e57acSmx205022 rx_cntl0.cntl_bits.padsen = NGE_CLEAR; 12256f3e57acSmx205022 rx_cntl0.cntl_bits.fcsren = NGE_CLEAR; 12266f3e57acSmx205022 if (dev_param_p->rx_pause_frame) 12276f3e57acSmx205022 rx_cntl0.cntl_bits.paen = NGE_SET; 12286f3e57acSmx205022 else 12296f3e57acSmx205022 rx_cntl0.cntl_bits.paen = NGE_CLEAR; 12306f3e57acSmx205022 rx_cntl0.cntl_bits.lben = NGE_CLEAR; 12316f3e57acSmx205022 rx_cntl0.cntl_bits.afen = NGE_SET; 12326f3e57acSmx205022 rx_cntl0.cntl_bits.runten = NGE_CLEAR; 12336f3e57acSmx205022 rx_cntl0.cntl_bits.brdis = NGE_CLEAR; 12346f3e57acSmx205022 rx_cntl0.cntl_bits.rdfen = NGE_CLEAR; 12356f3e57acSmx205022 rx_cntl0.cntl_bits.runtm = NGE_CLEAR; 12366f3e57acSmx205022 rx_cntl0.cntl_bits.slfb = NGE_CLEAR; 12376f3e57acSmx205022 rx_cntl0.cntl_bits.rlcolm = NGE_CLEAR; 12386f3e57acSmx205022 rx_cntl0.cntl_bits.maxerm = NGE_CLEAR; 12396f3e57acSmx205022 rx_cntl0.cntl_bits.lferm = NGE_CLEAR; 12406f3e57acSmx205022 rx_cntl0.cntl_bits.crcm = NGE_CLEAR; 12416f3e57acSmx205022 rx_cntl0.cntl_bits.ofolm = NGE_CLEAR; 12426f3e57acSmx205022 rx_cntl0.cntl_bits.framerm = NGE_CLEAR; 12436f3e57acSmx205022 nge_reg_put32(ngep, NGE_RX_CNTL0, rx_cntl0.cntl_val); 12446f3e57acSmx205022 12456f3e57acSmx205022 /* 12466f3e57acSmx205022 * Configure the watermark for the rx's statemachine 12476f3e57acSmx205022 */ 12486f3e57acSmx205022 rx_fifo.wm_val = nge_reg_get32(ngep, NGE_RX_FIFO_WM); 12496f3e57acSmx205022 rx_fifo.wm_bits.data_hwm = ngep->rx_datahwm; 12506f3e57acSmx205022 rx_fifo.wm_bits.prd_lwm = ngep->rx_prdlwm; 12516f3e57acSmx205022 rx_fifo.wm_bits.prd_hwm = ngep->rx_prdhwm; 12526f3e57acSmx205022 nge_reg_put32(ngep, NGE_RX_FIFO_WM, rx_fifo.wm_val); 12536f3e57acSmx205022 12546f3e57acSmx205022 /* 12556f3e57acSmx205022 * Configure the deffer time slot for rx's state machine 12566f3e57acSmx205022 */ 12576f3e57acSmx205022 nge_reg_put8(ngep, NGE_RX_DEf, ngep->rx_def); 12586f3e57acSmx205022 12596f3e57acSmx205022 /* 12606f3e57acSmx205022 * Configure the length of rx's packet 12616f3e57acSmx205022 */ 12626f3e57acSmx205022 rx_cntl1.cntl_val = nge_reg_get32(ngep, NGE_RX_CNTL1); 12636f3e57acSmx205022 rx_cntl1.cntl_bits.length = ngep->max_sdu; 12646f3e57acSmx205022 nge_reg_put32(ngep, NGE_RX_CNTL1, rx_cntl1.cntl_val); 12656f3e57acSmx205022 /* 12666f3e57acSmx205022 * Enable Tx's state machine 12676f3e57acSmx205022 */ 12686f3e57acSmx205022 tx_en.val = nge_reg_get8(ngep, NGE_TX_EN); 12696f3e57acSmx205022 tx_en.bits.tx_en = NGE_SET; 12706f3e57acSmx205022 nge_reg_put8(ngep, NGE_TX_EN, tx_en.val); 12716f3e57acSmx205022 12726f3e57acSmx205022 /* 12736f3e57acSmx205022 * Enable Rx's state machine 12746f3e57acSmx205022 */ 12756f3e57acSmx205022 rx_en.val = nge_reg_get8(ngep, NGE_RX_EN); 12766f3e57acSmx205022 rx_en.bits.rx_en = NGE_SET; 12776f3e57acSmx205022 nge_reg_put8(ngep, NGE_RX_EN, rx_en.val); 12786f3e57acSmx205022 12796f3e57acSmx205022 itc.itc_val = nge_reg_get32(ngep, NGE_SWTR_ITC); 12806f3e57acSmx205022 itc.itc_bits.sw_intv = ngep->sw_intr_intv; 12816f3e57acSmx205022 nge_reg_put32(ngep, NGE_SWTR_ITC, itc.itc_val); 12826f3e57acSmx205022 12836f3e57acSmx205022 swtr_cntl.ctrl_val = nge_reg_get8(ngep, NGE_SWTR_CNTL); 12846f3e57acSmx205022 swtr_cntl.cntl_bits.sten = NGE_SET; 12856f3e57acSmx205022 swtr_cntl.cntl_bits.stren = NGE_SET; 12866f3e57acSmx205022 nge_reg_put32(ngep, NGE_SWTR_CNTL, swtr_cntl.ctrl_val); 12876f3e57acSmx205022 12886f3e57acSmx205022 /* 12896f3e57acSmx205022 * Disable all mii read/write operation Interrupt 12906f3e57acSmx205022 */ 12916f3e57acSmx205022 mintr_mask.mask_val = nge_reg_get8(ngep, NGE_MINTR_MASK); 12926f3e57acSmx205022 mintr_mask.mask_bits.mrei = NGE_CLEAR; 12936f3e57acSmx205022 mintr_mask.mask_bits.mcc2 = NGE_CLEAR; 12946f3e57acSmx205022 mintr_mask.mask_bits.mcc1 = NGE_CLEAR; 12956f3e57acSmx205022 mintr_mask.mask_bits.mapi = NGE_SET; 12966f3e57acSmx205022 mintr_mask.mask_bits.mpdi = NGE_SET; 12976f3e57acSmx205022 nge_reg_put8(ngep, NGE_MINTR_MASK, mintr_mask.mask_val); 12986f3e57acSmx205022 12996f3e57acSmx205022 /* 13006f3e57acSmx205022 * Enable all interrupt event 13016f3e57acSmx205022 */ 13026f3e57acSmx205022 intr_mask.mask_val = nge_reg_get32(ngep, NGE_INTR_MASK); 13036f3e57acSmx205022 intr_mask.mask_bits.reint = NGE_SET; 13046f3e57acSmx205022 intr_mask.mask_bits.rcint = NGE_SET; 13056f3e57acSmx205022 intr_mask.mask_bits.miss = NGE_SET; 1306*51fc88a8SWinson Wang - Sun Microsystems - Beijing China intr_mask.mask_bits.teint = NGE_SET; 1307*51fc88a8SWinson Wang - Sun Microsystems - Beijing China intr_mask.mask_bits.tcint = NGE_CLEAR; 13086f3e57acSmx205022 intr_mask.mask_bits.stint = NGE_CLEAR; 13096f3e57acSmx205022 intr_mask.mask_bits.mint = NGE_CLEAR; 13106f3e57acSmx205022 intr_mask.mask_bits.rfint = NGE_CLEAR; 1311*51fc88a8SWinson Wang - Sun Microsystems - Beijing China intr_mask.mask_bits.tfint = NGE_SET; 13126f3e57acSmx205022 intr_mask.mask_bits.feint = NGE_SET; 13136f3e57acSmx205022 intr_mask.mask_bits.resv10 = NGE_CLEAR; 13146f3e57acSmx205022 intr_mask.mask_bits.resv11 = NGE_CLEAR; 13156f3e57acSmx205022 intr_mask.mask_bits.resv12 = NGE_CLEAR; 13166f3e57acSmx205022 intr_mask.mask_bits.resv13 = NGE_CLEAR; 13176f3e57acSmx205022 intr_mask.mask_bits.phyint = NGE_CLEAR; 13186f3e57acSmx205022 ngep->intr_masks = intr_mask.mask_val; 13196f3e57acSmx205022 nge_reg_put32(ngep, NGE_INTR_MASK, intr_mask.mask_val); 13206f3e57acSmx205022 ngep->nge_chip_state = NGE_CHIP_RUNNING; 13216f3e57acSmx205022 return (DDI_SUCCESS); 13226f3e57acSmx205022 } 13236f3e57acSmx205022 13246f3e57acSmx205022 /* 13256f3e57acSmx205022 * nge_chip_sync() -- program the chip with the unicast MAC address, 13266f3e57acSmx205022 * the multicast hash table, the required level of promiscuity. 13276f3e57acSmx205022 */ 13286f3e57acSmx205022 void 13296f3e57acSmx205022 nge_chip_sync(nge_t *ngep) 13306f3e57acSmx205022 { 13316f3e57acSmx205022 uint8_t i; 13326f3e57acSmx205022 uint64_t macaddr; 13336f3e57acSmx205022 uint64_t mul_addr; 13346f3e57acSmx205022 uint64_t mul_mask; 13356f3e57acSmx205022 nge_rx_cntrl0 rx_cntl; 13366f3e57acSmx205022 nge_uni_addr1 uni_adr1; 13376f3e57acSmx205022 13386f3e57acSmx205022 NGE_TRACE(("nge_chip_sync($%p)", (void *)ngep)); 13396f3e57acSmx205022 13406f3e57acSmx205022 macaddr = 0x0ull; 13416f3e57acSmx205022 mul_addr = 0x0ull; 13426f3e57acSmx205022 mul_mask = 0x0ull; 13436f3e57acSmx205022 rx_cntl.cntl_val = nge_reg_get32(ngep, NGE_RX_CNTL0); 13446f3e57acSmx205022 13456f3e57acSmx205022 if (ngep->promisc) { 13466f3e57acSmx205022 rx_cntl.cntl_bits.afen = NGE_CLEAR; 13476f3e57acSmx205022 rx_cntl.cntl_bits.brdis = NGE_SET; 13486f3e57acSmx205022 } else { 13496f3e57acSmx205022 rx_cntl.cntl_bits.afen = NGE_SET; 13506f3e57acSmx205022 rx_cntl.cntl_bits.brdis = NGE_CLEAR; 13516f3e57acSmx205022 } 13526f3e57acSmx205022 13536f3e57acSmx205022 /* 13546f3e57acSmx205022 * Transform the MAC address from host to chip format, the unicast 13556f3e57acSmx205022 * MAC address(es) ... 13566f3e57acSmx205022 */ 13576f3e57acSmx205022 for (i = ETHERADDRL, macaddr = 0ull; i != 0; --i) { 13586f3e57acSmx205022 macaddr |= ngep->cur_uni_addr.addr[i-1]; 13596f3e57acSmx205022 macaddr <<= (i > 1) ? 8 : 0; 13606f3e57acSmx205022 } 13616f3e57acSmx205022 13626f3e57acSmx205022 nge_reg_put32(ngep, NGE_UNI_ADDR0, (uint32_t)macaddr); 13636f3e57acSmx205022 macaddr = macaddr >>32; 13646f3e57acSmx205022 uni_adr1.addr_val = nge_reg_get32(ngep, NGE_UNI_ADDR1); 13656f3e57acSmx205022 uni_adr1.addr_bits.addr = (uint16_t)macaddr; 13666f3e57acSmx205022 uni_adr1.addr_bits.resv16_31 = (uint16_t)0; 13676f3e57acSmx205022 nge_reg_put32(ngep, NGE_UNI_ADDR1, uni_adr1.addr_val); 13686f3e57acSmx205022 13696f3e57acSmx205022 /* 13706f3e57acSmx205022 * Reprogram the multicast address table ... 13716f3e57acSmx205022 */ 13726f3e57acSmx205022 for (i = ETHERADDRL, mul_addr = 0ull; i != 0; --i) { 13736f3e57acSmx205022 mul_addr |= ngep->cur_mul_addr.addr[i-1]; 13746f3e57acSmx205022 mul_addr <<= (i > 1) ? 8 : 0; 13756f3e57acSmx205022 mul_mask |= ngep->cur_mul_mask.addr[i-1]; 13766f3e57acSmx205022 mul_mask <<= (i > 1) ? 8 : 0; 13776f3e57acSmx205022 } 13786f3e57acSmx205022 nge_reg_put32(ngep, NGE_MUL_ADDR0, (uint32_t)mul_addr); 13796f3e57acSmx205022 mul_addr >>= 32; 13806f3e57acSmx205022 nge_reg_put32(ngep, NGE_MUL_ADDR1, mul_addr); 13816f3e57acSmx205022 nge_reg_put32(ngep, NGE_MUL_MASK, (uint32_t)mul_mask); 13826f3e57acSmx205022 mul_mask >>= 32; 13836f3e57acSmx205022 nge_reg_put32(ngep, NGE_MUL_MASK1, mul_mask); 13846f3e57acSmx205022 /* 13856f3e57acSmx205022 * Set or clear the PROMISCUOUS mode bit 13866f3e57acSmx205022 */ 13876f3e57acSmx205022 nge_reg_put32(ngep, NGE_RX_CNTL0, rx_cntl.cntl_val); 13886f3e57acSmx205022 /* 13896f3e57acSmx205022 * For internal PHY loopback, the link will 13906f3e57acSmx205022 * not be up, so it need to sync mac modes directly. 13916f3e57acSmx205022 */ 13926f3e57acSmx205022 if (ngep->param_loop_mode == NGE_LOOP_INTERNAL_PHY) 13936f3e57acSmx205022 nge_sync_mac_modes(ngep); 13946f3e57acSmx205022 } 13956f3e57acSmx205022 13966f3e57acSmx205022 static void 13976f3e57acSmx205022 nge_chip_err(nge_t *ngep) 13986f3e57acSmx205022 { 13996f3e57acSmx205022 nge_reg010 reg010_ins; 14006f3e57acSmx205022 nge_sw_statistics_t *psw_stat; 14016f3e57acSmx205022 nge_intr_mask intr_mask; 14026f3e57acSmx205022 14036f3e57acSmx205022 NGE_TRACE(("nge_chip_err($%p)", (void *)ngep)); 14046f3e57acSmx205022 14056f3e57acSmx205022 psw_stat = (nge_sw_statistics_t *)&ngep->statistics.sw_statistics; 14066f3e57acSmx205022 reg010_ins.reg010_val = nge_reg_get32(ngep, NGE_REG010); 14076f3e57acSmx205022 if (reg010_ins.reg010_bits.resv0) 14086f3e57acSmx205022 psw_stat->fe_err.tso_err_mss ++; 14096f3e57acSmx205022 14106f3e57acSmx205022 if (reg010_ins.reg010_bits.resv1) 14116f3e57acSmx205022 psw_stat->fe_err.tso_dis ++; 14126f3e57acSmx205022 14136f3e57acSmx205022 if (reg010_ins.reg010_bits.resv2) 14146f3e57acSmx205022 psw_stat->fe_err.tso_err_nosum ++; 14156f3e57acSmx205022 14166f3e57acSmx205022 if (reg010_ins.reg010_bits.resv3) 14176f3e57acSmx205022 psw_stat->fe_err.tso_err_hov ++; 14186f3e57acSmx205022 14196f3e57acSmx205022 if (reg010_ins.reg010_bits.resv4) 14206f3e57acSmx205022 psw_stat->fe_err.tso_err_huf ++; 14216f3e57acSmx205022 14226f3e57acSmx205022 if (reg010_ins.reg010_bits.resv5) 14236f3e57acSmx205022 psw_stat->fe_err.tso_err_l2 ++; 14246f3e57acSmx205022 14256f3e57acSmx205022 if (reg010_ins.reg010_bits.resv6) 14266f3e57acSmx205022 psw_stat->fe_err.tso_err_ip ++; 14276f3e57acSmx205022 14286f3e57acSmx205022 if (reg010_ins.reg010_bits.resv7) 14296f3e57acSmx205022 psw_stat->fe_err.tso_err_l4 ++; 14306f3e57acSmx205022 14316f3e57acSmx205022 if (reg010_ins.reg010_bits.resv8) 14326f3e57acSmx205022 psw_stat->fe_err.tso_err_tcp ++; 14336f3e57acSmx205022 14346f3e57acSmx205022 if (reg010_ins.reg010_bits.resv9) 14356f3e57acSmx205022 psw_stat->fe_err.hsum_err_ip ++; 14366f3e57acSmx205022 14376f3e57acSmx205022 if (reg010_ins.reg010_bits.resv10) 14386f3e57acSmx205022 psw_stat->fe_err.hsum_err_l4 ++; 14396f3e57acSmx205022 14406f3e57acSmx205022 if (reg010_ins.reg010_val != 0) { 14416f3e57acSmx205022 14426f3e57acSmx205022 /* 14436f3e57acSmx205022 * Fatal error is triggered by malformed driver commands. 14446f3e57acSmx205022 * Disable unless debugging. 14456f3e57acSmx205022 */ 14466f3e57acSmx205022 intr_mask.mask_val = nge_reg_get32(ngep, NGE_INTR_MASK); 14476f3e57acSmx205022 intr_mask.mask_bits.feint = NGE_CLEAR; 14486f3e57acSmx205022 nge_reg_put32(ngep, NGE_INTR_MASK, intr_mask.mask_val); 14496f3e57acSmx205022 ngep->intr_masks = intr_mask.mask_val; 14506f3e57acSmx205022 14516f3e57acSmx205022 } 14526f3e57acSmx205022 } 14536f3e57acSmx205022 14546f3e57acSmx205022 static void 14556f3e57acSmx205022 nge_sync_mac_modes(nge_t *ngep) 14566f3e57acSmx205022 { 14576f3e57acSmx205022 nge_tx_def tx_def; 14586f3e57acSmx205022 nge_tx_fifo_wm tx_fifo; 14596f3e57acSmx205022 nge_bkoff_cntl bk_cntl; 14606f3e57acSmx205022 nge_mac2phy m2p; 14616f3e57acSmx205022 nge_rx_cntrl0 rx_cntl0; 146286d6718fSLi-Zhen You nge_tx_cntl tx_cntl; 14636f3e57acSmx205022 nge_dev_spec_param_t *dev_param_p; 14646f3e57acSmx205022 14656f3e57acSmx205022 dev_param_p = &ngep->dev_spec_param; 14666f3e57acSmx205022 14676f3e57acSmx205022 tx_def.def_val = nge_reg_get32(ngep, NGE_TX_DEF); 14686f3e57acSmx205022 m2p.m2p_val = nge_reg_get32(ngep, NGE_MAC2PHY); 14696f3e57acSmx205022 tx_fifo.wm_val = nge_reg_get32(ngep, NGE_TX_FIFO_WM); 14706f3e57acSmx205022 bk_cntl.cntl_val = nge_reg_get32(ngep, NGE_BKOFF_CNTL); 14716f3e57acSmx205022 bk_cntl.bkoff_bits.rseed = BKOFF_RSEED; 14726f3e57acSmx205022 switch (ngep->param_link_speed) { 14736f3e57acSmx205022 case 10: 14746f3e57acSmx205022 m2p.m2p_bits.speed = low_speed; 14756f3e57acSmx205022 tx_def.def_bits.ifg1_def = TX_IFG1_DEFAULT; 14766f3e57acSmx205022 if (ngep->phy_mode == RGMII_IN) { 14776f3e57acSmx205022 tx_def.def_bits.ifg2_def = TX_IFG2_RGMII_10_100; 14786f3e57acSmx205022 tx_def.def_bits.if_def = TX_IFG_RGMII_OTHER; 14796f3e57acSmx205022 } else { 14806f3e57acSmx205022 tx_def.def_bits.if_def = TX_TIFG_MII; 14816f3e57acSmx205022 tx_def.def_bits.ifg2_def = TX_IFG2_MII; 14826f3e57acSmx205022 } 14836f3e57acSmx205022 tx_fifo.wm_bits.nbfb_wm = TX_FIFO_NOB_WM_MII; 14846f3e57acSmx205022 bk_cntl.bkoff_bits.sltm = BKOFF_SLIM_MII; 14856f3e57acSmx205022 break; 14866f3e57acSmx205022 14876f3e57acSmx205022 case 100: 14886f3e57acSmx205022 m2p.m2p_bits.speed = fast_speed; 14896f3e57acSmx205022 tx_def.def_bits.ifg1_def = TX_IFG1_DEFAULT; 14906f3e57acSmx205022 if (ngep->phy_mode == RGMII_IN) { 14916f3e57acSmx205022 tx_def.def_bits.ifg2_def = TX_IFG2_RGMII_10_100; 14926f3e57acSmx205022 tx_def.def_bits.if_def = TX_IFG_RGMII_OTHER; 14936f3e57acSmx205022 } else { 14946f3e57acSmx205022 tx_def.def_bits.if_def = TX_TIFG_MII; 14956f3e57acSmx205022 tx_def.def_bits.ifg2_def = TX_IFG2_MII; 14966f3e57acSmx205022 } 14976f3e57acSmx205022 tx_fifo.wm_bits.nbfb_wm = TX_FIFO_NOB_WM_MII; 14986f3e57acSmx205022 bk_cntl.bkoff_bits.sltm = BKOFF_SLIM_MII; 14996f3e57acSmx205022 break; 15006f3e57acSmx205022 15016f3e57acSmx205022 case 1000: 15026f3e57acSmx205022 m2p.m2p_bits.speed = giga_speed; 15036f3e57acSmx205022 tx_def.def_bits.ifg1_def = TX_IFG1_DEFAULT; 15046f3e57acSmx205022 if (ngep->param_link_duplex == LINK_DUPLEX_FULL) { 15056f3e57acSmx205022 tx_def.def_bits.ifg2_def = TX_IFG2_RGMII_1000; 15066f3e57acSmx205022 tx_def.def_bits.if_def = TX_IFG_RGMII_1000_FD; 15076f3e57acSmx205022 } else { 15086f3e57acSmx205022 tx_def.def_bits.ifg2_def = TX_IFG2_RGMII_1000; 15096f3e57acSmx205022 tx_def.def_bits.if_def = TX_IFG_RGMII_OTHER; 15106f3e57acSmx205022 } 15116f3e57acSmx205022 15126f3e57acSmx205022 tx_fifo.wm_bits.nbfb_wm = TX_FIFO_NOB_WM_GMII; 15136f3e57acSmx205022 bk_cntl.bkoff_bits.sltm = BKOFF_SLIM_GMII; 15146f3e57acSmx205022 break; 15156f3e57acSmx205022 } 15166f3e57acSmx205022 15176f3e57acSmx205022 if (ngep->chipinfo.device == DEVICE_ID_MCP55_373 || 15186f3e57acSmx205022 ngep->chipinfo.device == DEVICE_ID_MCP55_372) { 15196f3e57acSmx205022 m2p.m2p_bits.phyintr = NGE_CLEAR; 15206f3e57acSmx205022 m2p.m2p_bits.phyintrlvl = NGE_CLEAR; 15216f3e57acSmx205022 } 15226f3e57acSmx205022 if (ngep->param_link_duplex == LINK_DUPLEX_HALF) { 15236f3e57acSmx205022 m2p.m2p_bits.hdup_en = NGE_SET; 15246f3e57acSmx205022 } 15256f3e57acSmx205022 else 15266f3e57acSmx205022 m2p.m2p_bits.hdup_en = NGE_CLEAR; 15276f3e57acSmx205022 nge_reg_put32(ngep, NGE_MAC2PHY, m2p.m2p_val); 15286f3e57acSmx205022 nge_reg_put32(ngep, NGE_TX_DEF, tx_def.def_val); 15296f3e57acSmx205022 15306f3e57acSmx205022 tx_fifo.wm_bits.data_lwm = TX_FIFO_DATA_LWM; 15316f3e57acSmx205022 tx_fifo.wm_bits.prd_lwm = TX_FIFO_PRD_LWM; 15326f3e57acSmx205022 tx_fifo.wm_bits.uprd_hwm = TX_FIFO_PRD_HWM; 15336f3e57acSmx205022 tx_fifo.wm_bits.fb_wm = TX_FIFO_TBFW; 15346f3e57acSmx205022 nge_reg_put32(ngep, NGE_TX_FIFO_WM, tx_fifo.wm_val); 15356f3e57acSmx205022 15366f3e57acSmx205022 nge_reg_put32(ngep, NGE_BKOFF_CNTL, bk_cntl.cntl_val); 15376f3e57acSmx205022 15386f3e57acSmx205022 rx_cntl0.cntl_val = nge_reg_get32(ngep, NGE_RX_CNTL0); 153986d6718fSLi-Zhen You if (ngep->param_link_rx_pause && dev_param_p->rx_pause_frame) { 154086d6718fSLi-Zhen You if (rx_cntl0.cntl_bits.paen == NGE_CLEAR) { 15416f3e57acSmx205022 rx_cntl0.cntl_bits.paen = NGE_SET; 154286d6718fSLi-Zhen You nge_reg_put32(ngep, NGE_RX_CNTL0, rx_cntl0.cntl_val); 154386d6718fSLi-Zhen You } 154486d6718fSLi-Zhen You } else { 154586d6718fSLi-Zhen You if (rx_cntl0.cntl_bits.paen == NGE_SET) { 15466f3e57acSmx205022 rx_cntl0.cntl_bits.paen = NGE_CLEAR; 15476f3e57acSmx205022 nge_reg_put32(ngep, NGE_RX_CNTL0, rx_cntl0.cntl_val); 15486f3e57acSmx205022 } 154986d6718fSLi-Zhen You } 155086d6718fSLi-Zhen You 155186d6718fSLi-Zhen You tx_cntl.cntl_val = nge_reg_get32(ngep, NGE_TX_CNTL); 155286d6718fSLi-Zhen You if (ngep->param_link_tx_pause && dev_param_p->tx_pause_frame) { 155386d6718fSLi-Zhen You if (tx_cntl.cntl_bits.paen == NGE_CLEAR) { 155486d6718fSLi-Zhen You tx_cntl.cntl_bits.paen = NGE_SET; 155586d6718fSLi-Zhen You nge_reg_put32(ngep, NGE_TX_CNTL, tx_cntl.cntl_val); 155686d6718fSLi-Zhen You } 155786d6718fSLi-Zhen You } else { 155886d6718fSLi-Zhen You if (tx_cntl.cntl_bits.paen == NGE_SET) { 155986d6718fSLi-Zhen You tx_cntl.cntl_bits.paen = NGE_CLEAR; 156086d6718fSLi-Zhen You nge_reg_put32(ngep, NGE_TX_CNTL, tx_cntl.cntl_val); 156186d6718fSLi-Zhen You } 156286d6718fSLi-Zhen You } 156386d6718fSLi-Zhen You } 15646f3e57acSmx205022 15656f3e57acSmx205022 /* 15666f3e57acSmx205022 * Handler for hardware link state change. 15676f3e57acSmx205022 * 15686f3e57acSmx205022 * When this routine is called, the hardware link state has changed 15696f3e57acSmx205022 * and the new state is reflected in the param_* variables. Here 15706f3e57acSmx205022 * we must update the softstate, reprogram the MAC to match, and 15716f3e57acSmx205022 * record the change in the log and/or on the console. 15726f3e57acSmx205022 */ 15736f3e57acSmx205022 static void 15746f3e57acSmx205022 nge_factotum_link_handler(nge_t *ngep) 15756f3e57acSmx205022 { 15766f3e57acSmx205022 /* 15776f3e57acSmx205022 * Update the s/w link_state 15786f3e57acSmx205022 */ 15796f3e57acSmx205022 if (ngep->param_link_up) 15806f3e57acSmx205022 ngep->link_state = LINK_STATE_UP; 15816f3e57acSmx205022 else 15826f3e57acSmx205022 ngep->link_state = LINK_STATE_DOWN; 15836f3e57acSmx205022 15846f3e57acSmx205022 /* 15856f3e57acSmx205022 * Reprogram the MAC modes to match 15866f3e57acSmx205022 */ 15876f3e57acSmx205022 nge_sync_mac_modes(ngep); 15886f3e57acSmx205022 } 15896f3e57acSmx205022 15906f3e57acSmx205022 static boolean_t 15916f3e57acSmx205022 nge_factotum_link_check(nge_t *ngep) 15926f3e57acSmx205022 { 15936f3e57acSmx205022 boolean_t lchg; 15946f3e57acSmx205022 boolean_t check; 15956f3e57acSmx205022 15966f3e57acSmx205022 ASSERT(mutex_owned(ngep->genlock)); 15976f3e57acSmx205022 15986f3e57acSmx205022 (*ngep->physops->phys_check)(ngep); 15996f3e57acSmx205022 switch (ngep->link_state) { 16006f3e57acSmx205022 case LINK_STATE_UP: 16016f3e57acSmx205022 lchg = (ngep->param_link_up == B_FALSE); 16026f3e57acSmx205022 check = (ngep->param_link_up == B_FALSE); 16036f3e57acSmx205022 break; 16046f3e57acSmx205022 16056f3e57acSmx205022 case LINK_STATE_DOWN: 16066f3e57acSmx205022 lchg = (ngep->param_link_up == B_TRUE); 16076f3e57acSmx205022 check = (ngep->param_link_up == B_TRUE); 16086f3e57acSmx205022 break; 16096f3e57acSmx205022 16106f3e57acSmx205022 default: 16116f3e57acSmx205022 check = B_TRUE; 16126f3e57acSmx205022 break; 16136f3e57acSmx205022 } 16146f3e57acSmx205022 16156f3e57acSmx205022 /* 16166f3e57acSmx205022 * If <check> is false, we're sure the link hasn't changed. 16176f3e57acSmx205022 * If true, however, it's not yet definitive; we have to call 16186f3e57acSmx205022 * nge_phys_check() to determine whether the link has settled 16196f3e57acSmx205022 * into a new state yet ... and if it has, then call the link 16206f3e57acSmx205022 * state change handler.But when the chip is 5700 in Dell 6650 16216f3e57acSmx205022 * ,even if check is false, the link may have changed.So we 16226f3e57acSmx205022 * have to call nge_phys_check() to determine the link state. 16236f3e57acSmx205022 */ 16246f3e57acSmx205022 if (check) 16256f3e57acSmx205022 nge_factotum_link_handler(ngep); 16266f3e57acSmx205022 16276f3e57acSmx205022 return (lchg); 16286f3e57acSmx205022 } 16296f3e57acSmx205022 16306f3e57acSmx205022 /* 16316f3e57acSmx205022 * Factotum routine to check for Tx stall, using the 'watchdog' counter 16326f3e57acSmx205022 */ 16336f3e57acSmx205022 static boolean_t nge_factotum_stall_check(nge_t *ngep); 16346f3e57acSmx205022 16356f3e57acSmx205022 static boolean_t 16366f3e57acSmx205022 nge_factotum_stall_check(nge_t *ngep) 16376f3e57acSmx205022 { 16386f3e57acSmx205022 uint32_t dogval; 1639*51fc88a8SWinson Wang - Sun Microsystems - Beijing China send_ring_t *srp; 1640*51fc88a8SWinson Wang - Sun Microsystems - Beijing China srp = ngep->send; 16416f3e57acSmx205022 /* 16426f3e57acSmx205022 * Specific check for Tx stall ... 16436f3e57acSmx205022 * 16446f3e57acSmx205022 * The 'watchdog' counter is incremented whenever a packet 16456f3e57acSmx205022 * is queued, reset to 1 when some (but not all) buffers 16466f3e57acSmx205022 * are reclaimed, reset to 0 (disabled) when all buffers 16476f3e57acSmx205022 * are reclaimed, and shifted left here. If it exceeds the 16486f3e57acSmx205022 * threshold value, the chip is assumed to have stalled and 16496f3e57acSmx205022 * is put into the ERROR state. The factotum will then reset 16506f3e57acSmx205022 * it on the next pass. 16516f3e57acSmx205022 * 16526f3e57acSmx205022 * All of which should ensure that we don't get into a state 16536f3e57acSmx205022 * where packets are left pending indefinitely! 16546f3e57acSmx205022 */ 1655*51fc88a8SWinson Wang - Sun Microsystems - Beijing China if (ngep->watchdog == 0 && 1656*51fc88a8SWinson Wang - Sun Microsystems - Beijing China srp->tx_free < srp->desc.nslots) 1657*51fc88a8SWinson Wang - Sun Microsystems - Beijing China ngep->watchdog = 1; 16586f3e57acSmx205022 dogval = nge_atomic_shl32(&ngep->watchdog, 1); 1659*51fc88a8SWinson Wang - Sun Microsystems - Beijing China if (dogval >= nge_watchdog_check) 1660*51fc88a8SWinson Wang - Sun Microsystems - Beijing China nge_tx_recycle(ngep, B_FALSE); 1661*51fc88a8SWinson Wang - Sun Microsystems - Beijing China if (dogval < nge_watchdog_count) 16626f3e57acSmx205022 return (B_FALSE); 1663*51fc88a8SWinson Wang - Sun Microsystems - Beijing China else { 16646f3e57acSmx205022 ngep->statistics.sw_statistics.tx_stall++; 16656f3e57acSmx205022 return (B_TRUE); 16666f3e57acSmx205022 } 16676f3e57acSmx205022 } 16686f3e57acSmx205022 16696f3e57acSmx205022 16706f3e57acSmx205022 /* 16716f3e57acSmx205022 * The factotum is woken up when there's something to do that we'd rather 16726f3e57acSmx205022 * not do from inside a hardware interrupt handler or high-level cyclic. 16736f3e57acSmx205022 * Its two main tasks are: 16746f3e57acSmx205022 * reset & restart the chip after an error 16756f3e57acSmx205022 * check the link status whenever necessary 16766f3e57acSmx205022 */ 16776f3e57acSmx205022 /* ARGSUSED */ 16786f3e57acSmx205022 uint_t 16796f3e57acSmx205022 nge_chip_factotum(caddr_t args1, caddr_t args2) 16806f3e57acSmx205022 { 16816f3e57acSmx205022 uint_t result; 16826f3e57acSmx205022 nge_t *ngep; 16836f3e57acSmx205022 boolean_t err; 16846f3e57acSmx205022 boolean_t linkchg; 16856f3e57acSmx205022 16866f3e57acSmx205022 ngep = (nge_t *)args1; 16876f3e57acSmx205022 16886f3e57acSmx205022 NGE_TRACE(("nge_chip_factotum($%p)", (void *)ngep)); 16896f3e57acSmx205022 16906f3e57acSmx205022 mutex_enter(ngep->softlock); 16916f3e57acSmx205022 if (ngep->factotum_flag == 0) { 16926f3e57acSmx205022 mutex_exit(ngep->softlock); 16936f3e57acSmx205022 return (DDI_INTR_UNCLAIMED); 16946f3e57acSmx205022 } 16956f3e57acSmx205022 ngep->factotum_flag = 0; 16966f3e57acSmx205022 mutex_exit(ngep->softlock); 16976f3e57acSmx205022 err = B_FALSE; 16986f3e57acSmx205022 linkchg = B_FALSE; 16996f3e57acSmx205022 result = DDI_INTR_CLAIMED; 17006f3e57acSmx205022 17016f3e57acSmx205022 mutex_enter(ngep->genlock); 17026f3e57acSmx205022 switch (ngep->nge_chip_state) { 17036f3e57acSmx205022 default: 17046f3e57acSmx205022 break; 17056f3e57acSmx205022 17066f3e57acSmx205022 case NGE_CHIP_RUNNING: 17076f3e57acSmx205022 linkchg = nge_factotum_link_check(ngep); 17086f3e57acSmx205022 err = nge_factotum_stall_check(ngep); 17096f3e57acSmx205022 break; 17106f3e57acSmx205022 17116f3e57acSmx205022 case NGE_CHIP_FAULT: 17126f3e57acSmx205022 (void) nge_restart(ngep); 17136f3e57acSmx205022 NGE_REPORT((ngep, "automatic recovery activated")); 17146f3e57acSmx205022 break; 17156f3e57acSmx205022 } 17166f3e57acSmx205022 17176f3e57acSmx205022 if (err) 17186f3e57acSmx205022 (void) nge_chip_stop(ngep, B_TRUE); 17196f3e57acSmx205022 mutex_exit(ngep->genlock); 17206f3e57acSmx205022 17216f3e57acSmx205022 /* 17226f3e57acSmx205022 * If the link state changed, tell the world about it (if 17236f3e57acSmx205022 * this version of MAC supports link state notification). 17246f3e57acSmx205022 * Note: can't do this while still holding the mutex. 17256f3e57acSmx205022 */ 17266f3e57acSmx205022 if (linkchg) 17276f3e57acSmx205022 mac_link_update(ngep->mh, ngep->link_state); 17286f3e57acSmx205022 17296f3e57acSmx205022 return (result); 17306f3e57acSmx205022 17316f3e57acSmx205022 } 17326f3e57acSmx205022 17336f3e57acSmx205022 static void 17346f3e57acSmx205022 nge_intr_handle(nge_t *ngep, nge_intr_src *pintr_src) 17356f3e57acSmx205022 { 17366f3e57acSmx205022 boolean_t brx; 17376f3e57acSmx205022 boolean_t btx; 17386f3e57acSmx205022 nge_mintr_src mintr_src; 17396f3e57acSmx205022 17406f3e57acSmx205022 brx = B_FALSE; 17416f3e57acSmx205022 btx = B_FALSE; 17426f3e57acSmx205022 ngep->statistics.sw_statistics.intr_count++; 17436f3e57acSmx205022 ngep->statistics.sw_statistics.intr_lval = pintr_src->intr_val; 17446f3e57acSmx205022 brx = (pintr_src->int_bits.reint | pintr_src->int_bits.miss 17456f3e57acSmx205022 | pintr_src->int_bits.rcint | pintr_src->int_bits.stint) 1746b2fa2f2bSjj146644 != 0 ? B_TRUE : B_FALSE; 17476f3e57acSmx205022 if (pintr_src->int_bits.reint) 17486f3e57acSmx205022 ngep->statistics.sw_statistics.rx_err++; 17496f3e57acSmx205022 if (pintr_src->int_bits.miss) 17506f3e57acSmx205022 ngep->statistics.sw_statistics.rx_nobuffer++; 17516f3e57acSmx205022 1752*51fc88a8SWinson Wang - Sun Microsystems - Beijing China btx = (pintr_src->int_bits.teint | pintr_src->int_bits.tfint) 1753b2fa2f2bSjj146644 != 0 ? B_TRUE : B_FALSE; 17546f3e57acSmx205022 if (btx) 17556f3e57acSmx205022 nge_tx_recycle(ngep, B_TRUE); 1756b2fa2f2bSjj146644 if (brx) 1757b2fa2f2bSjj146644 nge_receive(ngep); 17586f3e57acSmx205022 if (pintr_src->int_bits.teint) 17596f3e57acSmx205022 ngep->statistics.sw_statistics.tx_stop_err++; 176002d51d0dSjj146644 if (ngep->intr_moderation && brx) { 176102d51d0dSjj146644 if (ngep->poll) { 176202d51d0dSjj146644 if (ngep->recv_count < ngep->param_rx_intr_hwater) { 176302d51d0dSjj146644 ngep->quiet_time++; 176402d51d0dSjj146644 if (ngep->quiet_time == 176502d51d0dSjj146644 ngep->param_poll_quiet_time) { 17666f3e57acSmx205022 ngep->poll = B_FALSE; 176702d51d0dSjj146644 ngep->quiet_time = 0; 176802d51d0dSjj146644 } 176902d51d0dSjj146644 } else 177002d51d0dSjj146644 ngep->quiet_time = 0; 177102d51d0dSjj146644 } else { 177202d51d0dSjj146644 if (ngep->recv_count > ngep->param_rx_intr_lwater) { 177302d51d0dSjj146644 ngep->busy_time++; 177402d51d0dSjj146644 if (ngep->busy_time == 177502d51d0dSjj146644 ngep->param_poll_busy_time) { 177602d51d0dSjj146644 ngep->poll = B_TRUE; 177702d51d0dSjj146644 ngep->busy_time = 0; 177802d51d0dSjj146644 } 177902d51d0dSjj146644 } else 178002d51d0dSjj146644 ngep->busy_time = 0; 178102d51d0dSjj146644 } 17826f3e57acSmx205022 } 17836f3e57acSmx205022 ngep->recv_count = 0; 17846f3e57acSmx205022 if (pintr_src->int_bits.feint) 17856f3e57acSmx205022 nge_chip_err(ngep); 17866f3e57acSmx205022 /* link interrupt, check the link state */ 17876f3e57acSmx205022 if (pintr_src->int_bits.mint) { 17886f3e57acSmx205022 mintr_src.src_val = nge_reg_get32(ngep, NGE_MINTR_SRC); 17896f3e57acSmx205022 nge_reg_put32(ngep, NGE_MINTR_SRC, mintr_src.src_val); 17906f3e57acSmx205022 nge_wake_factotum(ngep); 17916f3e57acSmx205022 } 17926f3e57acSmx205022 } 17936f3e57acSmx205022 17946f3e57acSmx205022 /* 17956f3e57acSmx205022 * nge_chip_intr() -- handle chip interrupts 17966f3e57acSmx205022 */ 17976f3e57acSmx205022 /* ARGSUSED */ 17986f3e57acSmx205022 uint_t 17996f3e57acSmx205022 nge_chip_intr(caddr_t arg1, caddr_t arg2) 18006f3e57acSmx205022 { 18016f3e57acSmx205022 nge_t *ngep = (nge_t *)arg1; 18026f3e57acSmx205022 nge_intr_src intr_src; 18036f3e57acSmx205022 nge_intr_mask intr_mask; 18046f3e57acSmx205022 18056f3e57acSmx205022 mutex_enter(ngep->genlock); 18066f3e57acSmx205022 18072d58516dSmx205022 if (ngep->suspended) { 18082d58516dSmx205022 mutex_exit(ngep->genlock); 18092d58516dSmx205022 return (DDI_INTR_UNCLAIMED); 18102d58516dSmx205022 } 18112d58516dSmx205022 18126f3e57acSmx205022 /* 18136f3e57acSmx205022 * Check whether chip's says it's asserting #INTA; 18146f3e57acSmx205022 * if not, don't process or claim the interrupt. 18156f3e57acSmx205022 */ 18166f3e57acSmx205022 intr_src.intr_val = nge_reg_get32(ngep, NGE_INTR_SRC); 18176f3e57acSmx205022 if (intr_src.intr_val == 0) { 18186f3e57acSmx205022 mutex_exit(ngep->genlock); 18196f3e57acSmx205022 return (DDI_INTR_UNCLAIMED); 18206f3e57acSmx205022 } 18216f3e57acSmx205022 /* 18226f3e57acSmx205022 * Ack the interrupt 18236f3e57acSmx205022 */ 18246f3e57acSmx205022 nge_reg_put32(ngep, NGE_INTR_SRC, intr_src.intr_val); 18256f3e57acSmx205022 18266f3e57acSmx205022 if (ngep->nge_chip_state != NGE_CHIP_RUNNING) { 18276f3e57acSmx205022 mutex_exit(ngep->genlock); 18286f3e57acSmx205022 return (DDI_INTR_CLAIMED); 18296f3e57acSmx205022 } 18306f3e57acSmx205022 nge_intr_handle(ngep, &intr_src); 18316f3e57acSmx205022 if (ngep->poll && !ngep->ch_intr_mode) { 18326f3e57acSmx205022 intr_mask.mask_val = nge_reg_get32(ngep, NGE_INTR_MASK); 18336f3e57acSmx205022 intr_mask.mask_bits.stint = NGE_SET; 183402d51d0dSjj146644 intr_mask.mask_bits.rcint = NGE_CLEAR; 18356f3e57acSmx205022 nge_reg_put32(ngep, NGE_INTR_MASK, intr_mask.mask_val); 18366f3e57acSmx205022 ngep->ch_intr_mode = B_TRUE; 18376f3e57acSmx205022 } else if ((ngep->ch_intr_mode) && (!ngep->poll)) { 18386f3e57acSmx205022 nge_reg_put32(ngep, NGE_INTR_MASK, ngep->intr_masks); 18396f3e57acSmx205022 ngep->ch_intr_mode = B_FALSE; 18406f3e57acSmx205022 } 18416f3e57acSmx205022 mutex_exit(ngep->genlock); 18426f3e57acSmx205022 return (DDI_INTR_CLAIMED); 18436f3e57acSmx205022 } 18446f3e57acSmx205022 18456f3e57acSmx205022 static enum ioc_reply 18466f3e57acSmx205022 nge_pp_ioctl(nge_t *ngep, int cmd, mblk_t *mp, struct iocblk *iocp) 18476f3e57acSmx205022 { 18486f3e57acSmx205022 int err; 18496f3e57acSmx205022 uint64_t sizemask; 18506f3e57acSmx205022 uint64_t mem_va; 18516f3e57acSmx205022 uint64_t maxoff; 18526f3e57acSmx205022 boolean_t peek; 18536f3e57acSmx205022 nge_peekpoke_t *ppd; 18546f3e57acSmx205022 int (*ppfn)(nge_t *ngep, nge_peekpoke_t *ppd); 18556f3e57acSmx205022 18566f3e57acSmx205022 switch (cmd) { 18576f3e57acSmx205022 default: 18586f3e57acSmx205022 return (IOC_INVAL); 18596f3e57acSmx205022 18606f3e57acSmx205022 case NGE_PEEK: 18616f3e57acSmx205022 peek = B_TRUE; 18626f3e57acSmx205022 break; 18636f3e57acSmx205022 18646f3e57acSmx205022 case NGE_POKE: 18656f3e57acSmx205022 peek = B_FALSE; 18666f3e57acSmx205022 break; 18676f3e57acSmx205022 } 18686f3e57acSmx205022 18696f3e57acSmx205022 /* 18706f3e57acSmx205022 * Validate format of ioctl 18716f3e57acSmx205022 */ 18726f3e57acSmx205022 if (iocp->ioc_count != sizeof (nge_peekpoke_t)) 18736f3e57acSmx205022 return (IOC_INVAL); 18746f3e57acSmx205022 if (mp->b_cont == NULL) 18756f3e57acSmx205022 return (IOC_INVAL); 18766f3e57acSmx205022 ppd = (nge_peekpoke_t *)mp->b_cont->b_rptr; 18776f3e57acSmx205022 18786f3e57acSmx205022 /* 18796f3e57acSmx205022 * Validate request parameters 18806f3e57acSmx205022 */ 18816f3e57acSmx205022 switch (ppd->pp_acc_space) { 18826f3e57acSmx205022 default: 18836f3e57acSmx205022 return (IOC_INVAL); 18846f3e57acSmx205022 18856f3e57acSmx205022 case NGE_PP_SPACE_CFG: 18866f3e57acSmx205022 /* 18876f3e57acSmx205022 * Config space 18886f3e57acSmx205022 */ 18896f3e57acSmx205022 sizemask = 8|4|2|1; 18906f3e57acSmx205022 mem_va = 0; 18916f3e57acSmx205022 maxoff = PCI_CONF_HDR_SIZE; 18926f3e57acSmx205022 ppfn = peek ? nge_chip_peek_cfg : nge_chip_poke_cfg; 18936f3e57acSmx205022 break; 18946f3e57acSmx205022 18956f3e57acSmx205022 case NGE_PP_SPACE_REG: 18966f3e57acSmx205022 /* 18976f3e57acSmx205022 * Memory-mapped I/O space 18986f3e57acSmx205022 */ 18996f3e57acSmx205022 sizemask = 8|4|2|1; 19006f3e57acSmx205022 mem_va = 0; 19016f3e57acSmx205022 maxoff = NGE_REG_SIZE; 19026f3e57acSmx205022 ppfn = peek ? nge_chip_peek_reg : nge_chip_poke_reg; 19036f3e57acSmx205022 break; 19046f3e57acSmx205022 19056f3e57acSmx205022 case NGE_PP_SPACE_MII: 19066f3e57acSmx205022 sizemask = 4|2|1; 19076f3e57acSmx205022 mem_va = 0; 19086f3e57acSmx205022 maxoff = NGE_MII_SIZE; 19096f3e57acSmx205022 ppfn = peek ? nge_chip_peek_mii : nge_chip_poke_mii; 19106f3e57acSmx205022 break; 19116f3e57acSmx205022 19126f3e57acSmx205022 case NGE_PP_SPACE_SEEPROM: 19136f3e57acSmx205022 sizemask = 4|2|1; 19146f3e57acSmx205022 mem_va = 0; 19156f3e57acSmx205022 maxoff = NGE_SEEROM_SIZE; 19166f3e57acSmx205022 ppfn = peek ? nge_chip_peek_seeprom : nge_chip_poke_seeprom; 19176f3e57acSmx205022 break; 19186f3e57acSmx205022 } 19196f3e57acSmx205022 19206f3e57acSmx205022 switch (ppd->pp_acc_size) { 19216f3e57acSmx205022 default: 19226f3e57acSmx205022 return (IOC_INVAL); 19236f3e57acSmx205022 19246f3e57acSmx205022 case 8: 19256f3e57acSmx205022 case 4: 19266f3e57acSmx205022 case 2: 19276f3e57acSmx205022 case 1: 19286f3e57acSmx205022 if ((ppd->pp_acc_size & sizemask) == 0) 19296f3e57acSmx205022 return (IOC_INVAL); 19306f3e57acSmx205022 break; 19316f3e57acSmx205022 } 19326f3e57acSmx205022 19336f3e57acSmx205022 if ((ppd->pp_acc_offset % ppd->pp_acc_size) != 0) 19346f3e57acSmx205022 return (IOC_INVAL); 19356f3e57acSmx205022 19366f3e57acSmx205022 if (ppd->pp_acc_offset >= maxoff) 19376f3e57acSmx205022 return (IOC_INVAL); 19386f3e57acSmx205022 19396f3e57acSmx205022 if (ppd->pp_acc_offset+ppd->pp_acc_size > maxoff) 19406f3e57acSmx205022 return (IOC_INVAL); 19416f3e57acSmx205022 19426f3e57acSmx205022 /* 19436f3e57acSmx205022 * All OK - go do it! 19446f3e57acSmx205022 */ 19456f3e57acSmx205022 ppd->pp_acc_offset += mem_va; 19466f3e57acSmx205022 if (ppfn) 19476f3e57acSmx205022 err = (*ppfn)(ngep, ppd); 19486f3e57acSmx205022 if (err != DDI_SUCCESS) 19496f3e57acSmx205022 return (IOC_INVAL); 19506f3e57acSmx205022 return (peek ? IOC_REPLY : IOC_ACK); 19516f3e57acSmx205022 } 19526f3e57acSmx205022 19536f3e57acSmx205022 static enum ioc_reply nge_diag_ioctl(nge_t *ngep, int cmd, mblk_t *mp, 19546f3e57acSmx205022 struct iocblk *iocp); 19556f3e57acSmx205022 #pragma no_inline(nge_diag_ioctl) 19566f3e57acSmx205022 19576f3e57acSmx205022 static enum ioc_reply 19586f3e57acSmx205022 nge_diag_ioctl(nge_t *ngep, int cmd, mblk_t *mp, struct iocblk *iocp) 19596f3e57acSmx205022 { 19606f3e57acSmx205022 ASSERT(mutex_owned(ngep->genlock)); 19616f3e57acSmx205022 19626f3e57acSmx205022 switch (cmd) { 19636f3e57acSmx205022 default: 19646f3e57acSmx205022 nge_error(ngep, "nge_diag_ioctl: invalid cmd 0x%x", cmd); 19656f3e57acSmx205022 return (IOC_INVAL); 19666f3e57acSmx205022 19676f3e57acSmx205022 case NGE_DIAG: 19686f3e57acSmx205022 return (IOC_ACK); 19696f3e57acSmx205022 19706f3e57acSmx205022 case NGE_PEEK: 19716f3e57acSmx205022 case NGE_POKE: 19726f3e57acSmx205022 return (nge_pp_ioctl(ngep, cmd, mp, iocp)); 19736f3e57acSmx205022 19746f3e57acSmx205022 case NGE_PHY_RESET: 19756f3e57acSmx205022 return (IOC_RESTART_ACK); 19766f3e57acSmx205022 19776f3e57acSmx205022 case NGE_SOFT_RESET: 19786f3e57acSmx205022 case NGE_HARD_RESET: 19796f3e57acSmx205022 return (IOC_ACK); 19806f3e57acSmx205022 } 19816f3e57acSmx205022 19826f3e57acSmx205022 /* NOTREACHED */ 19836f3e57acSmx205022 } 19846f3e57acSmx205022 19856f3e57acSmx205022 enum ioc_reply 19866f3e57acSmx205022 nge_chip_ioctl(nge_t *ngep, mblk_t *mp, struct iocblk *iocp) 19876f3e57acSmx205022 { 19886f3e57acSmx205022 int cmd; 19896f3e57acSmx205022 19906f3e57acSmx205022 ASSERT(mutex_owned(ngep->genlock)); 19916f3e57acSmx205022 19926f3e57acSmx205022 cmd = iocp->ioc_cmd; 19936f3e57acSmx205022 19946f3e57acSmx205022 switch (cmd) { 19956f3e57acSmx205022 default: 19966f3e57acSmx205022 return (IOC_INVAL); 19976f3e57acSmx205022 19986f3e57acSmx205022 case NGE_DIAG: 19996f3e57acSmx205022 case NGE_PEEK: 20006f3e57acSmx205022 case NGE_POKE: 20016f3e57acSmx205022 case NGE_PHY_RESET: 20026f3e57acSmx205022 case NGE_SOFT_RESET: 20036f3e57acSmx205022 case NGE_HARD_RESET: 20046f3e57acSmx205022 #if NGE_DEBUGGING 20056f3e57acSmx205022 return (nge_diag_ioctl(ngep, cmd, mp, iocp)); 20066f3e57acSmx205022 #else 20076f3e57acSmx205022 return (IOC_INVAL); 20086f3e57acSmx205022 #endif 20096f3e57acSmx205022 20106f3e57acSmx205022 case NGE_MII_READ: 20116f3e57acSmx205022 case NGE_MII_WRITE: 20126f3e57acSmx205022 return (IOC_INVAL); 20136f3e57acSmx205022 20146f3e57acSmx205022 #if NGE_SEE_IO32 20156f3e57acSmx205022 case NGE_SEE_READ: 20166f3e57acSmx205022 case NGE_SEE_WRITE: 20176f3e57acSmx205022 return (IOC_INVAL); 20186f3e57acSmx205022 #endif 20196f3e57acSmx205022 20206f3e57acSmx205022 #if NGE_FLASH_IO32 20216f3e57acSmx205022 case NGE_FLASH_READ: 20226f3e57acSmx205022 case NGE_FLASH_WRITE: 20236f3e57acSmx205022 return (IOC_INVAL); 20246f3e57acSmx205022 #endif 20256f3e57acSmx205022 } 20266f3e57acSmx205022 } 2027