15256Slh155975 /* 2*11878SVenu.Iyer@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 35256Slh155975 * Use is subject to license terms. 45256Slh155975 */ 55256Slh155975 65256Slh155975 /* 75256Slh155975 * Copyright (c) 2001-2006 Advanced Micro Devices, Inc. All rights reserved. 85256Slh155975 * 95256Slh155975 * Redistribution and use in source and binary forms, with or without 105256Slh155975 * modification, are permitted provided that the following conditions are met: 115256Slh155975 * 125256Slh155975 * + Redistributions of source code must retain the above copyright notice, 135256Slh155975 * + this list of conditions and the following disclaimer. 145256Slh155975 * 155256Slh155975 * + Redistributions in binary form must reproduce the above copyright 165256Slh155975 * + notice, this list of conditions and the following disclaimer in the 175256Slh155975 * + documentation and/or other materials provided with the distribution. 185256Slh155975 * 195256Slh155975 * + Neither the name of Advanced Micro Devices, Inc. nor the names of its 205256Slh155975 * + contributors may be used to endorse or promote products derived from 215256Slh155975 * + this software without specific prior written permission. 225256Slh155975 * 235256Slh155975 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 245256Slh155975 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 255256Slh155975 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265256Slh155975 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 275256Slh155975 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. OR 285256Slh155975 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 295256Slh155975 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 305256Slh155975 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 315256Slh155975 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 325256Slh155975 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 335256Slh155975 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 345256Slh155975 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 355256Slh155975 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 365256Slh155975 * 375256Slh155975 * Import/Export/Re-Export/Use/Release/Transfer Restrictions and 385256Slh155975 * Compliance with Applicable Laws. Notice is hereby given that 395256Slh155975 * the software may be subject to restrictions on use, release, 405256Slh155975 * transfer, importation, exportation and/or re-exportation under 415256Slh155975 * the laws and regulations of the United States or other 425256Slh155975 * countries ("Applicable Laws"), which include but are not 435256Slh155975 * limited to U.S. export control laws such as the Export 445256Slh155975 * Administration Regulations and national security controls as 455256Slh155975 * defined thereunder, as well as State Department controls under 465256Slh155975 * the U.S. Munitions List. Permission to use and/or 475256Slh155975 * redistribute the software is conditioned upon compliance with 485256Slh155975 * all Applicable Laws, including U.S. export control laws 495256Slh155975 * regarding specifically designated persons, countries and 505256Slh155975 * nationals of countries subject to national security controls. 515256Slh155975 */ 525256Slh155975 535256Slh155975 /* include files */ 545256Slh155975 #include <sys/disp.h> 555256Slh155975 #include <sys/atomic.h> 565895Syz147064 #include <sys/vlan.h> 575256Slh155975 #include "amd8111s_main.h" 585256Slh155975 595256Slh155975 /* Global macro Definations */ 605256Slh155975 #define ROUNDUP(x, a) (((x) + (a) - 1) & ~((a) - 1)) 615256Slh155975 #define INTERFACE_NAME "amd8111s" 625256Slh155975 #define AMD8111S_SPLIT 128 635256Slh155975 #define AMD8111S_SEND_MAX 64 645256Slh155975 657656SSherry.Moore@Sun.COM static char ident[] = "AMD8111 10/100M Ethernet"; 665256Slh155975 675256Slh155975 /* 685256Slh155975 * Driver Entry Points 695256Slh155975 */ 705256Slh155975 static int amd8111s_attach(dev_info_t *, ddi_attach_cmd_t); 715256Slh155975 static int amd8111s_detach(dev_info_t *, ddi_detach_cmd_t); 725256Slh155975 735256Slh155975 /* 745256Slh155975 * GLD Entry points prototype 755256Slh155975 */ 765256Slh155975 static int amd8111s_m_unicst(void *, const uint8_t *); 775256Slh155975 static int amd8111s_m_promisc(void *, boolean_t); 785256Slh155975 static int amd8111s_m_stat(void *, uint_t, uint64_t *); 795256Slh155975 static void amd8111s_m_ioctl(void *, queue_t *, mblk_t *); 805256Slh155975 static int amd8111s_m_multicst(void *, boolean_t, const uint8_t *addr); 815256Slh155975 static int amd8111s_m_start(void *); 825256Slh155975 static void amd8111s_m_stop(void *); 835256Slh155975 static mblk_t *amd8111s_m_tx(void *, mblk_t *mp); 845256Slh155975 static uint_t amd8111s_intr(caddr_t); 855256Slh155975 865256Slh155975 static int amd8111s_unattach(dev_info_t *, struct LayerPointers *); 875256Slh155975 885256Slh155975 static boolean_t amd8111s_allocate_buffers(struct LayerPointers *); 895256Slh155975 static int amd8111s_odlInit(struct LayerPointers *); 905256Slh155975 static boolean_t amd8111s_allocate_descriptors(struct LayerPointers *); 915256Slh155975 static void amd8111s_free_descriptors(struct LayerPointers *); 925256Slh155975 static boolean_t amd8111s_alloc_dma_ringbuf(struct LayerPointers *, 935256Slh155975 struct amd8111s_dma_ringbuf *, uint32_t, uint32_t); 945256Slh155975 static void amd8111s_free_dma_ringbuf(struct amd8111s_dma_ringbuf *); 955256Slh155975 965256Slh155975 975256Slh155975 static void amd8111s_log(struct LayerPointers *adapter, int level, 985256Slh155975 char *fmt, ...); 995256Slh155975 1005256Slh155975 static struct cb_ops amd8111s_cb_ops = { 1015256Slh155975 nulldev, 1025256Slh155975 nulldev, 1035256Slh155975 nodev, 1045256Slh155975 nodev, 1055256Slh155975 nodev, 1065256Slh155975 nodev, 1075256Slh155975 nodev, 1085256Slh155975 nodev, 1095256Slh155975 nodev, 1105256Slh155975 nodev, 1115256Slh155975 nodev, 1125256Slh155975 nochpoll, 1135256Slh155975 ddi_prop_op, 1145256Slh155975 NULL, 1155256Slh155975 D_NEW | D_MP, 1165256Slh155975 CB_REV, /* cb_rev */ 1175256Slh155975 nodev, /* cb_aread */ 1185256Slh155975 nodev /* cb_awrite */ 1195256Slh155975 }; 1205256Slh155975 1215256Slh155975 static struct dev_ops amd8111s_dev_ops = { 1225256Slh155975 DEVO_REV, /* devo_rev */ 1235256Slh155975 0, /* devo_refcnt */ 1245256Slh155975 NULL, /* devo_getinfo */ 1255256Slh155975 nulldev, /* devo_identify */ 1265256Slh155975 nulldev, /* devo_probe */ 1275256Slh155975 amd8111s_attach, /* devo_attach */ 1285256Slh155975 amd8111s_detach, /* devo_detach */ 1295256Slh155975 nodev, /* devo_reset */ 1305256Slh155975 &amd8111s_cb_ops, /* devo_cb_ops */ 1315256Slh155975 NULL, /* devo_bus_ops */ 1327656SSherry.Moore@Sun.COM nodev, /* devo_power */ 1337656SSherry.Moore@Sun.COM ddi_quiesce_not_supported, /* devo_quiesce */ 1345256Slh155975 }; 1355256Slh155975 1365256Slh155975 struct modldrv amd8111s_modldrv = { 1375256Slh155975 &mod_driverops, /* Type of module. This one is a driver */ 1385256Slh155975 ident, /* short description */ 1395256Slh155975 &amd8111s_dev_ops /* driver specific ops */ 1405256Slh155975 }; 1415256Slh155975 1425256Slh155975 struct modlinkage amd8111s_modlinkage = { 1435256Slh155975 MODREV_1, (void *)&amd8111s_modldrv, NULL 1445256Slh155975 }; 1455256Slh155975 1465256Slh155975 /* 1475256Slh155975 * Global Variables 1485256Slh155975 */ 1495256Slh155975 struct LayerPointers *amd8111sadapter; 1505256Slh155975 1515256Slh155975 static ddi_dma_attr_t pcn_buff_dma_attr_t = { 1525256Slh155975 DMA_ATTR_V0, /* dma_attr_version */ 1535256Slh155975 (uint64_t)0, /* dma_attr_addr_lo */ 1545256Slh155975 (uint64_t)0xFFFFFFFF, /* dma_attr_addr_hi */ 1555256Slh155975 (uint64_t)0xFFFFFFFF, /* dma_attr_count_max */ 1565256Slh155975 (uint64_t)1, /* dma_attr_align */ 1575256Slh155975 (uint_t)0x7F, /* dma_attr_burstsizes */ 1585256Slh155975 (uint32_t)1, /* dma_attr_minxfer */ 1595256Slh155975 (uint64_t)0xFFFFFFFF, /* dma_attr_maxxfer */ 1605256Slh155975 (uint64_t)0xFFFFFFFF, /* dma_attr_seg */ 1615256Slh155975 (int)1, /* dma_attr_sgllen */ 1625256Slh155975 (uint32_t)1, /* granularity */ 1635256Slh155975 (uint_t)0 /* dma_attr_flags */ 1645256Slh155975 }; 1655256Slh155975 1665256Slh155975 static ddi_dma_attr_t pcn_desc_dma_attr_t = { 1675256Slh155975 DMA_ATTR_V0, /* dma_attr_version */ 1685256Slh155975 (uint64_t)0, /* dma_attr_addr_lo */ 1695256Slh155975 (uint64_t)0xFFFFFFFF, /* dma_attr_addr_hi */ 1705256Slh155975 (uint64_t)0x7FFFFFFF, /* dma_attr_count_max */ 1715256Slh155975 (uint64_t)0x10, /* dma_attr_align */ 1725256Slh155975 (uint_t)0xFFFFFFFFU, /* dma_attr_burstsizes */ 1735256Slh155975 (uint32_t)1, /* dma_attr_minxfer */ 1745256Slh155975 (uint64_t)0xFFFFFFFF, /* dma_attr_maxxfer */ 1755256Slh155975 (uint64_t)0xFFFFFFFF, /* dma_attr_seg */ 1765256Slh155975 (int)1, /* dma_attr_sgllen */ 1775256Slh155975 (uint32_t)1, /* granularity */ 1785256Slh155975 (uint_t)0 /* dma_attr_flags */ 1795256Slh155975 }; 1805256Slh155975 1815256Slh155975 /* PIO access attributes for registers */ 1825256Slh155975 static ddi_device_acc_attr_t pcn_acc_attr = { 1835256Slh155975 DDI_DEVICE_ATTR_V0, 1845256Slh155975 DDI_STRUCTURE_LE_ACC, 1855256Slh155975 DDI_STRICTORDER_ACC 1865256Slh155975 }; 1875256Slh155975 1885256Slh155975 1895256Slh155975 static mac_callbacks_t amd8111s_m_callbacks = { 1908275SEric Cheng MC_IOCTL, 1915256Slh155975 amd8111s_m_stat, 1925256Slh155975 amd8111s_m_start, 1935256Slh155975 amd8111s_m_stop, 1945256Slh155975 amd8111s_m_promisc, 1955256Slh155975 amd8111s_m_multicst, 1965256Slh155975 amd8111s_m_unicst, 1975256Slh155975 amd8111s_m_tx, 198*11878SVenu.Iyer@Sun.COM NULL, 1995256Slh155975 amd8111s_m_ioctl 2005256Slh155975 }; 2015256Slh155975 2025256Slh155975 2035256Slh155975 /* 2045256Slh155975 * Standard Driver Load Entry Point 2055256Slh155975 * It will be called at load time of driver. 2065256Slh155975 */ 2075256Slh155975 int 2085256Slh155975 _init() 2095256Slh155975 { 2105256Slh155975 int status; 2115256Slh155975 mac_init_ops(&amd8111s_dev_ops, "amd8111s"); 2125256Slh155975 2135256Slh155975 status = mod_install(&amd8111s_modlinkage); 2145256Slh155975 if (status != DDI_SUCCESS) { 2155256Slh155975 mac_fini_ops(&amd8111s_dev_ops); 2165256Slh155975 } 2175256Slh155975 2185256Slh155975 return (status); 2195256Slh155975 } 2205256Slh155975 2215256Slh155975 /* 2225256Slh155975 * Standard Driver Entry Point for Query. 2235256Slh155975 * It will be called at any time to get Driver info. 2245256Slh155975 */ 2255256Slh155975 int 2265256Slh155975 _info(struct modinfo *modinfop) 2275256Slh155975 { 2285256Slh155975 return (mod_info(&amd8111s_modlinkage, modinfop)); 2295256Slh155975 } 2305256Slh155975 2315256Slh155975 /* 2325256Slh155975 * Standard Driver Entry Point for Unload. 2335256Slh155975 * It will be called at unload time of driver. 2345256Slh155975 */ 2355256Slh155975 int 2365256Slh155975 _fini() 2375256Slh155975 { 2385256Slh155975 int status; 2395256Slh155975 2405256Slh155975 status = mod_remove(&amd8111s_modlinkage); 2415256Slh155975 if (status == DDI_SUCCESS) { 2425256Slh155975 mac_fini_ops(&amd8111s_dev_ops); 2435256Slh155975 } 2445256Slh155975 2455256Slh155975 return (status); 2465256Slh155975 } 2475256Slh155975 2485256Slh155975 /* 2495256Slh155975 * Loopback Support 2505256Slh155975 */ 2515256Slh155975 static lb_property_t loopmodes[] = { 2525256Slh155975 { normal, "normal", AMD8111S_LB_NONE }, 2535256Slh155975 { external, "100Mbps", AMD8111S_LB_EXTERNAL_100 }, 2545256Slh155975 { external, "10Mbps", AMD8111S_LB_EXTERNAL_10 }, 2555256Slh155975 { internal, "MAC", AMD8111S_LB_INTERNAL_MAC } 2565256Slh155975 }; 2575256Slh155975 2585256Slh155975 static void 2595256Slh155975 amd8111s_set_loop_mode(struct LayerPointers *adapter, uint32_t mode) 2605256Slh155975 { 2615256Slh155975 2625256Slh155975 /* 2635256Slh155975 * If the mode isn't being changed, there's nothing to do ... 2645256Slh155975 */ 2655256Slh155975 if (mode == adapter->pOdl->loopback_mode) 2665256Slh155975 return; 2675256Slh155975 2685256Slh155975 /* 2695256Slh155975 * Validate the requested mode and prepare a suitable message 2705256Slh155975 * to explain the link down/up cycle that the change will 2715256Slh155975 * probably induce ... 2725256Slh155975 */ 2735256Slh155975 switch (mode) { 2745256Slh155975 default: 2755256Slh155975 return; 2765256Slh155975 2775256Slh155975 case AMD8111S_LB_NONE: 2785256Slh155975 mdlStopChip(adapter); 2795256Slh155975 if (adapter->pOdl->loopback_mode == AMD8111S_LB_INTERNAL_MAC) { 2805256Slh155975 cmn_err(CE_NOTE, "LB_NONE restored from Interanl LB"); 2815256Slh155975 WRITE_REG32(adapter, adapter->pMdl->Mem_Address + CMD2, 2825256Slh155975 INLOOP); 2835256Slh155975 WRITE_REG32(adapter, adapter->pMdl->Mem_Address + CMD3, 2845256Slh155975 FORCE_FULL_DUPLEX | FORCE_LINK_STATUS); 2855256Slh155975 } else { 2865256Slh155975 cmn_err(CE_NOTE, "LB_NONE restored from Exteranl LB"); 2875256Slh155975 WRITE_REG32(adapter, adapter->pMdl->Mem_Address + CMD2, 2885256Slh155975 EXLOOP); 2895256Slh155975 } 2905256Slh155975 2915256Slh155975 amd8111s_reset(adapter); 2925256Slh155975 adapter->pOdl->LinkStatus = LINK_STATE_DOWN; 2935256Slh155975 adapter->pOdl->rx_fcs_stripped = B_FALSE; 2945256Slh155975 mdlStartChip(adapter); 2955256Slh155975 break; 2965256Slh155975 2975256Slh155975 case AMD8111S_LB_EXTERNAL_100: 2985256Slh155975 cmn_err(CE_NOTE, "amd8111s_set_loop_mode LB_EXTERNAL_100"); 2995256Slh155975 mdlStopChip(adapter); 3005256Slh155975 amd8111s_reset(adapter); 3015256Slh155975 SetIntrCoalesc(adapter, B_FALSE); 3025256Slh155975 mdlPHYAutoNegotiation(adapter, PHY_FORCE_FD_100); 3035256Slh155975 WRITE_REG32(adapter, adapter->pMdl->Mem_Address + CMD2, 3045256Slh155975 VAL0 | EXLOOP); 3055256Slh155975 adapter->pOdl->LinkStatus = LINK_STATE_UP; 3065256Slh155975 adapter->pMdl->Speed = 100; 3075256Slh155975 adapter->pMdl->FullDuplex = B_TRUE; 3085256Slh155975 /* Tell GLD the state of the physical link. */ 3095256Slh155975 mac_link_update(adapter->pOdl->mh, LINK_STATE_UP); 3105256Slh155975 3115256Slh155975 adapter->pOdl->rx_fcs_stripped = B_TRUE; 3125256Slh155975 3135256Slh155975 mdlStartChip(adapter); 3145256Slh155975 break; 3155256Slh155975 3165256Slh155975 case AMD8111S_LB_EXTERNAL_10: 3175256Slh155975 cmn_err(CE_NOTE, "amd8111s_set_loop_mode LB_EXTERNAL_10"); 3185256Slh155975 mdlStopChip(adapter); 3195256Slh155975 amd8111s_reset(adapter); 3205256Slh155975 SetIntrCoalesc(adapter, B_FALSE); 3215256Slh155975 mdlPHYAutoNegotiation(adapter, PHY_FORCE_FD_10); 3225256Slh155975 WRITE_REG32(adapter, adapter->pMdl->Mem_Address + CMD2, 3235256Slh155975 VAL0 | EXLOOP); 3245256Slh155975 adapter->pOdl->LinkStatus = LINK_STATE_UP; 3255256Slh155975 adapter->pMdl->Speed = 10; 3265256Slh155975 adapter->pMdl->FullDuplex = B_TRUE; 3275256Slh155975 /* Tell GLD the state of the physical link. */ 3285256Slh155975 mac_link_update(adapter->pOdl->mh, LINK_STATE_UP); 3295256Slh155975 3305256Slh155975 adapter->pOdl->rx_fcs_stripped = B_TRUE; 3315256Slh155975 3325256Slh155975 mdlStartChip(adapter); 3335256Slh155975 break; 3345256Slh155975 3355256Slh155975 case AMD8111S_LB_INTERNAL_MAC: 3365256Slh155975 cmn_err(CE_NOTE, "amd8111s_set_loop_mode LB_INTERNAL_MAC"); 3375256Slh155975 mdlStopChip(adapter); 3385256Slh155975 amd8111s_reset(adapter); 3395256Slh155975 SetIntrCoalesc(adapter, B_FALSE); 3405256Slh155975 /* Disable Port Manager */ 3415256Slh155975 WRITE_REG32(adapter, adapter->pMdl->Mem_Address + CMD3, 3425256Slh155975 EN_PMGR); 3435256Slh155975 WRITE_REG32(adapter, adapter->pMdl->Mem_Address + CMD2, 3445256Slh155975 VAL0 | INLOOP); 3455256Slh155975 3465256Slh155975 WRITE_REG32(adapter, adapter->pMdl->Mem_Address + CMD3, 3475256Slh155975 VAL1 | FORCE_FULL_DUPLEX | FORCE_LINK_STATUS); 3485256Slh155975 3495256Slh155975 adapter->pOdl->LinkStatus = LINK_STATE_UP; 3505256Slh155975 adapter->pMdl->FullDuplex = B_TRUE; 3515256Slh155975 /* Tell GLD the state of the physical link. */ 3525256Slh155975 mac_link_update(adapter->pOdl->mh, LINK_STATE_UP); 3535256Slh155975 3545256Slh155975 adapter->pOdl->rx_fcs_stripped = B_TRUE; 3555256Slh155975 3565256Slh155975 mdlStartChip(adapter); 3575256Slh155975 break; 3585256Slh155975 } 3595256Slh155975 3605256Slh155975 /* 3615256Slh155975 * All OK; tell the caller to reprogram 3625256Slh155975 * the PHY and/or MAC for the new mode ... 3635256Slh155975 */ 3645256Slh155975 adapter->pOdl->loopback_mode = mode; 3655256Slh155975 } 3665256Slh155975 3675256Slh155975 static enum ioc_reply 3685256Slh155975 amd8111s_loopback_ioctl(struct LayerPointers *adapter, struct iocblk *iocp, 3695256Slh155975 mblk_t *mp) 3705256Slh155975 { 3715256Slh155975 lb_info_sz_t *lbsp; 3725256Slh155975 lb_property_t *lbpp; 3735256Slh155975 uint32_t *lbmp; 3745256Slh155975 int cmd; 3755256Slh155975 3765256Slh155975 /* 3775256Slh155975 * Validate format of ioctl 3785256Slh155975 */ 3795256Slh155975 if (mp->b_cont == NULL) 3805256Slh155975 return (IOC_INVAL); 3815256Slh155975 3825256Slh155975 cmd = iocp->ioc_cmd; 3835256Slh155975 switch (cmd) { 3845256Slh155975 default: 3855256Slh155975 /* NOTREACHED */ 3865256Slh155975 amd8111s_log(adapter, CE_NOTE, 3875256Slh155975 "amd8111s_loop_ioctl: invalid cmd 0x%x", cmd); 3885256Slh155975 return (IOC_INVAL); 3895256Slh155975 3905256Slh155975 case LB_GET_INFO_SIZE: 3915256Slh155975 if (iocp->ioc_count != sizeof (lb_info_sz_t)) { 3925256Slh155975 amd8111s_log(adapter, CE_NOTE, 3935256Slh155975 "wrong LB_GET_INFO_SIZE size"); 3945256Slh155975 return (IOC_INVAL); 3955256Slh155975 } 3966990Sgd78059 lbsp = (void *)mp->b_cont->b_rptr; 3975256Slh155975 *lbsp = sizeof (loopmodes); 3985256Slh155975 break; 3995256Slh155975 4005256Slh155975 case LB_GET_INFO: 4015256Slh155975 if (iocp->ioc_count != sizeof (loopmodes)) { 4025256Slh155975 amd8111s_log(adapter, CE_NOTE, 4035256Slh155975 "Wrong LB_GET_INFO size"); 4045256Slh155975 return (IOC_INVAL); 4055256Slh155975 } 4066990Sgd78059 lbpp = (void *)mp->b_cont->b_rptr; 4075256Slh155975 bcopy(loopmodes, lbpp, sizeof (loopmodes)); 4085256Slh155975 break; 4095256Slh155975 4105256Slh155975 case LB_GET_MODE: 4115256Slh155975 if (iocp->ioc_count != sizeof (uint32_t)) { 4125256Slh155975 amd8111s_log(adapter, CE_NOTE, 4135256Slh155975 "Wrong LB_GET_MODE size"); 4145256Slh155975 return (IOC_INVAL); 4155256Slh155975 } 4166990Sgd78059 lbmp = (void *)mp->b_cont->b_rptr; 4175256Slh155975 *lbmp = adapter->pOdl->loopback_mode; 4185256Slh155975 break; 4195256Slh155975 4205256Slh155975 case LB_SET_MODE: 4215256Slh155975 if (iocp->ioc_count != sizeof (uint32_t)) { 4225256Slh155975 amd8111s_log(adapter, CE_NOTE, 4235256Slh155975 "Wrong LB_SET_MODE size"); 4245256Slh155975 return (IOC_INVAL); 4255256Slh155975 } 4266990Sgd78059 lbmp = (void *)mp->b_cont->b_rptr; 4275256Slh155975 amd8111s_set_loop_mode(adapter, *lbmp); 4285256Slh155975 break; 4295256Slh155975 } 4305256Slh155975 return (IOC_REPLY); 4315256Slh155975 } 4325256Slh155975 4335256Slh155975 static void 4345256Slh155975 amd8111s_m_ioctl(void *arg, queue_t *q, mblk_t *mp) 4355256Slh155975 { 4365256Slh155975 struct iocblk *iocp; 4375256Slh155975 struct LayerPointers *adapter; 4385256Slh155975 enum ioc_reply status; 4395256Slh155975 4406990Sgd78059 iocp = (void *)mp->b_rptr; 4415256Slh155975 iocp->ioc_error = 0; 4426990Sgd78059 adapter = arg; 4435256Slh155975 4445256Slh155975 ASSERT(adapter); 4455256Slh155975 if (adapter == NULL) { 4465256Slh155975 miocnak(q, mp, 0, EINVAL); 4475256Slh155975 return; 4485256Slh155975 } 4495256Slh155975 4505256Slh155975 switch (iocp->ioc_cmd) { 4515256Slh155975 4525256Slh155975 case LB_GET_INFO_SIZE: 4535256Slh155975 case LB_GET_INFO: 4545256Slh155975 case LB_GET_MODE: 4555256Slh155975 case LB_SET_MODE: 4565256Slh155975 status = amd8111s_loopback_ioctl(adapter, iocp, mp); 4575256Slh155975 break; 4585256Slh155975 4595256Slh155975 default: 4605256Slh155975 status = IOC_INVAL; 4615256Slh155975 break; 4625256Slh155975 } 4635256Slh155975 4645256Slh155975 /* 4655256Slh155975 * Decide how to reply 4665256Slh155975 */ 4675256Slh155975 switch (status) { 4685256Slh155975 default: 4695256Slh155975 case IOC_INVAL: 4705256Slh155975 /* 4715256Slh155975 * Error, reply with a NAK and EINVAL or the specified error 4725256Slh155975 */ 4735256Slh155975 miocnak(q, mp, 0, iocp->ioc_error == 0 ? 4745256Slh155975 EINVAL : iocp->ioc_error); 4755256Slh155975 break; 4765256Slh155975 4775256Slh155975 case IOC_DONE: 4785256Slh155975 /* 4795256Slh155975 * OK, reply already sent 4805256Slh155975 */ 4815256Slh155975 break; 4825256Slh155975 4835256Slh155975 case IOC_ACK: 4845256Slh155975 /* 4855256Slh155975 * OK, reply with an ACK 4865256Slh155975 */ 4875256Slh155975 miocack(q, mp, 0, 0); 4885256Slh155975 break; 4895256Slh155975 4905256Slh155975 case IOC_REPLY: 4915256Slh155975 /* 4925256Slh155975 * OK, send prepared reply as ACK or NAK 4935256Slh155975 */ 4945256Slh155975 mp->b_datap->db_type = iocp->ioc_error == 0 ? 4955256Slh155975 M_IOCACK : M_IOCNAK; 4965256Slh155975 qreply(q, mp); 4975256Slh155975 break; 4985256Slh155975 } 4995256Slh155975 } 5005256Slh155975 5015256Slh155975 /* 5025256Slh155975 * Copy one packet from dma memory to mblk. Inc dma descriptor pointer. 5035256Slh155975 */ 5045256Slh155975 static boolean_t 5055256Slh155975 amd8111s_recv_copy(struct LayerPointers *pLayerPointers, mblk_t **last_mp) 5065256Slh155975 { 5075256Slh155975 int length = 0; 5085256Slh155975 mblk_t *mp; 5095256Slh155975 struct rx_desc *descriptor; 5105256Slh155975 struct odl *pOdl = pLayerPointers->pOdl; 5115256Slh155975 struct amd8111s_statistics *statistics = &pOdl->statistics; 5125256Slh155975 struct nonphysical *pNonphysical = pLayerPointers->pMil 5135256Slh155975 ->pNonphysical; 5145256Slh155975 5155256Slh155975 mutex_enter(&pOdl->mdlRcvLock); 5165256Slh155975 descriptor = pNonphysical->RxBufDescQRead->descriptor; 5175256Slh155975 (void) ddi_dma_sync(pOdl->rx_desc_dma_handle, 5185256Slh155975 pNonphysical->RxBufDescQRead->descriptor - 5195256Slh155975 pNonphysical->RxBufDescQStart->descriptor, 5205256Slh155975 sizeof (struct rx_desc), DDI_DMA_SYNC_FORCPU); 5215256Slh155975 if ((descriptor->Rx_OWN) == 0) { 5225256Slh155975 /* 5235256Slh155975 * If the frame is received with errors, then set MCNT 5245256Slh155975 * of that pkt in ReceiveArray to 0. This packet would 5255256Slh155975 * be discarded later and not indicated to OS. 5265256Slh155975 */ 5275256Slh155975 if (descriptor->Rx_ERR) { 5285256Slh155975 statistics->rx_desc_err ++; 5295256Slh155975 descriptor->Rx_ERR = 0; 5305256Slh155975 if (descriptor->Rx_FRAM == 1) { 5315256Slh155975 statistics->rx_desc_err_FRAM ++; 5325256Slh155975 descriptor->Rx_FRAM = 0; 5335256Slh155975 } 5345256Slh155975 if (descriptor->Rx_OFLO == 1) { 5355256Slh155975 statistics->rx_desc_err_OFLO ++; 5365256Slh155975 descriptor->Rx_OFLO = 0; 5375256Slh155975 pOdl->rx_overflow_counter ++; 5385256Slh155975 if ((pOdl->rx_overflow_counter > 5) && 5395256Slh155975 (pOdl->pause_interval == 0)) { 5405256Slh155975 statistics->rx_double_overflow ++; 5415256Slh155975 mdlSendPause(pLayerPointers); 5425256Slh155975 pOdl->rx_overflow_counter = 0; 5435256Slh155975 pOdl->pause_interval = 25; 5445256Slh155975 } 5455256Slh155975 } 5465256Slh155975 if (descriptor->Rx_CRC == 1) { 5475256Slh155975 statistics->rx_desc_err_CRC ++; 5485256Slh155975 descriptor->Rx_CRC = 0; 5495256Slh155975 } 5505256Slh155975 if (descriptor->Rx_BUFF == 1) { 5515256Slh155975 statistics->rx_desc_err_BUFF ++; 5525256Slh155975 descriptor->Rx_BUFF = 0; 5535256Slh155975 } 5545256Slh155975 goto Next_Descriptor; 5555256Slh155975 } 5565256Slh155975 5575256Slh155975 /* Length of incoming packet */ 5585256Slh155975 if (pOdl->rx_fcs_stripped) { 5595256Slh155975 length = descriptor->Rx_MCNT -4; 5605256Slh155975 } else { 5615256Slh155975 length = descriptor->Rx_MCNT; 5625256Slh155975 } 5635256Slh155975 if (length < 62) { 5645256Slh155975 statistics->rx_error_zerosize ++; 5655256Slh155975 } 5665256Slh155975 5675256Slh155975 if ((mp = allocb(length, BPRI_MED)) == NULL) { 5685256Slh155975 statistics->rx_allocfail ++; 5695256Slh155975 goto failed; 5705256Slh155975 } 5715256Slh155975 /* Copy from virtual address of incoming packet */ 5725256Slh155975 bcopy((long *)*(pNonphysical->RxBufDescQRead->USpaceMap), 5735256Slh155975 mp->b_rptr, length); 5745256Slh155975 mp->b_wptr = mp->b_rptr + length; 5755256Slh155975 statistics->rx_ok_packets ++; 5765256Slh155975 if (*last_mp == NULL) { 5775256Slh155975 *last_mp = mp; 5785256Slh155975 } else { 5795256Slh155975 (*last_mp)->b_next = mp; 5805256Slh155975 *last_mp = mp; 5815256Slh155975 } 5825256Slh155975 5835256Slh155975 Next_Descriptor: 5845256Slh155975 descriptor->Rx_MCNT = 0; 5855256Slh155975 descriptor->Rx_SOP = 0; 5865256Slh155975 descriptor->Rx_EOP = 0; 5875256Slh155975 descriptor->Rx_PAM = 0; 5885256Slh155975 descriptor->Rx_BAM = 0; 5895256Slh155975 descriptor->TT = 0; 5905256Slh155975 descriptor->Rx_OWN = 1; 5915256Slh155975 pNonphysical->RxBufDescQRead->descriptor++; 5925256Slh155975 pNonphysical->RxBufDescQRead->USpaceMap++; 5935256Slh155975 if (pNonphysical->RxBufDescQRead->descriptor > 5945256Slh155975 pNonphysical->RxBufDescQEnd->descriptor) { 5955256Slh155975 pNonphysical->RxBufDescQRead->descriptor = 5965256Slh155975 pNonphysical->RxBufDescQStart->descriptor; 5975256Slh155975 pNonphysical->RxBufDescQRead->USpaceMap = 5985256Slh155975 pNonphysical->RxBufDescQStart->USpaceMap; 5995256Slh155975 } 6005256Slh155975 mutex_exit(&pOdl->mdlRcvLock); 6015256Slh155975 6025256Slh155975 return (B_TRUE); 6035256Slh155975 } 6045256Slh155975 6055256Slh155975 failed: 6065256Slh155975 mutex_exit(&pOdl->mdlRcvLock); 6075256Slh155975 return (B_FALSE); 6085256Slh155975 } 6095256Slh155975 6105256Slh155975 /* 6115256Slh155975 * Get the received packets from NIC card and send them to GLD. 6125256Slh155975 */ 6135256Slh155975 static void 6145256Slh155975 amd8111s_receive(struct LayerPointers *pLayerPointers) 6155256Slh155975 { 6165256Slh155975 int numOfPkts = 0; 6175256Slh155975 struct odl *pOdl; 6185256Slh155975 mblk_t *ret_mp = NULL, *last_mp = NULL; 6195256Slh155975 6205256Slh155975 pOdl = pLayerPointers->pOdl; 6215256Slh155975 6225256Slh155975 rw_enter(&pOdl->chip_lock, RW_READER); 6235256Slh155975 if (!pLayerPointers->run) { 6245256Slh155975 rw_exit(&pOdl->chip_lock); 6255256Slh155975 return; 6265256Slh155975 } 6275256Slh155975 6285256Slh155975 if (pOdl->pause_interval > 0) 6295256Slh155975 pOdl->pause_interval --; 6305256Slh155975 6315256Slh155975 while (numOfPkts < RX_RING_SIZE) { 6325256Slh155975 6335256Slh155975 if (!amd8111s_recv_copy(pLayerPointers, &last_mp)) { 6345256Slh155975 break; 6355256Slh155975 } 6365256Slh155975 if (ret_mp == NULL) 6375256Slh155975 ret_mp = last_mp; 6385256Slh155975 numOfPkts++; 6395256Slh155975 } 6405256Slh155975 6415256Slh155975 if (ret_mp) { 6428275SEric Cheng mac_rx(pOdl->mh, NULL, ret_mp); 6435256Slh155975 } 6445256Slh155975 6455256Slh155975 (void) ddi_dma_sync(pOdl->rx_desc_dma_handle, 0, 0, 6465256Slh155975 DDI_DMA_SYNC_FORDEV); 6475256Slh155975 6485256Slh155975 mdlReceive(pLayerPointers); 6495256Slh155975 6505256Slh155975 rw_exit(&pOdl->chip_lock); 6515256Slh155975 6525256Slh155975 } 6535256Slh155975 6545256Slh155975 /* 6555256Slh155975 * Print message in release-version driver. 6565256Slh155975 */ 6575256Slh155975 static void 6585256Slh155975 amd8111s_log(struct LayerPointers *adapter, int level, char *fmt, ...) 6595256Slh155975 { 6605256Slh155975 auto char name[32]; 6615256Slh155975 auto char buf[256]; 6625256Slh155975 va_list ap; 6635256Slh155975 6645256Slh155975 if (adapter != NULL) { 6655256Slh155975 (void) sprintf(name, "amd8111s%d", 6665256Slh155975 ddi_get_instance(adapter->pOdl->devinfo)); 6675256Slh155975 } else { 6685256Slh155975 (void) sprintf(name, "amd8111s"); 6695256Slh155975 } 6705256Slh155975 va_start(ap, fmt); 6715256Slh155975 (void) vsprintf(buf, fmt, ap); 6725256Slh155975 va_end(ap); 6735256Slh155975 cmn_err(level, "%s: %s", name, buf); 6745256Slh155975 } 6755256Slh155975 6765256Slh155975 /* 6775256Slh155975 * To allocate & initilize all resources. 6785256Slh155975 * Called by amd8111s_attach(). 6795256Slh155975 */ 6805256Slh155975 static int 6815256Slh155975 amd8111s_odlInit(struct LayerPointers *pLayerPointers) 6825256Slh155975 { 6835256Slh155975 unsigned long mem_req_array[MEM_REQ_MAX]; 6845256Slh155975 unsigned long mem_set_array[MEM_REQ_MAX]; 6855256Slh155975 unsigned long *pmem_req_array; 6865256Slh155975 unsigned long *pmem_set_array; 6875256Slh155975 int i, size; 6885256Slh155975 6895256Slh155975 for (i = 0; i < MEM_REQ_MAX; i++) { 6905256Slh155975 mem_req_array[i] = 0; 6915256Slh155975 mem_set_array[i] = 0; 6925256Slh155975 } 6935256Slh155975 6945256Slh155975 milRequestResources(mem_req_array); 6955256Slh155975 6965256Slh155975 pmem_req_array = mem_req_array; 6975256Slh155975 pmem_set_array = mem_set_array; 6985256Slh155975 while (*pmem_req_array) { 6995256Slh155975 switch (*pmem_req_array) { 7005256Slh155975 case VIRTUAL: 7015256Slh155975 *pmem_set_array = VIRTUAL; 7025256Slh155975 pmem_req_array++; 7035256Slh155975 pmem_set_array++; 7045256Slh155975 *(pmem_set_array) = *(pmem_req_array); 7055256Slh155975 pmem_set_array++; 7065256Slh155975 *(pmem_set_array) = (unsigned long) kmem_zalloc( 7075256Slh155975 *(pmem_req_array), KM_NOSLEEP); 7085256Slh155975 if (*pmem_set_array == NULL) 7095256Slh155975 goto odl_init_failure; 7105256Slh155975 break; 7115256Slh155975 } 7125256Slh155975 pmem_req_array++; 7135256Slh155975 pmem_set_array++; 7145256Slh155975 } 7155256Slh155975 7165256Slh155975 /* 7175256Slh155975 * Initilize memory on lower layers 7185256Slh155975 */ 7195256Slh155975 milSetResources(pLayerPointers, mem_set_array); 7205256Slh155975 7215256Slh155975 /* Allocate Rx/Tx descriptors */ 7225256Slh155975 if (amd8111s_allocate_descriptors(pLayerPointers) != B_TRUE) { 7235256Slh155975 *pmem_set_array = NULL; 7245256Slh155975 goto odl_init_failure; 7255256Slh155975 } 7265256Slh155975 7275256Slh155975 /* 7285256Slh155975 * Allocate Rx buffer for each Rx descriptor. Then call mil layer 7295256Slh155975 * routine to fill physical address of Rx buffer into Rx descriptor. 7305256Slh155975 */ 7315256Slh155975 if (amd8111s_allocate_buffers(pLayerPointers) == B_FALSE) { 7325256Slh155975 amd8111s_free_descriptors(pLayerPointers); 7335256Slh155975 *pmem_set_array = NULL; 7345256Slh155975 goto odl_init_failure; 7355256Slh155975 } 7365256Slh155975 milInitGlbds(pLayerPointers); 7375256Slh155975 7385256Slh155975 return (0); 7395256Slh155975 7405256Slh155975 odl_init_failure: 7415256Slh155975 /* 7425256Slh155975 * Free All memory allocated so far 7435256Slh155975 */ 7445256Slh155975 pmem_req_array = mem_set_array; 7455256Slh155975 while ((*pmem_req_array) && (pmem_req_array != pmem_set_array)) { 7465256Slh155975 switch (*pmem_req_array) { 7475256Slh155975 case VIRTUAL: 7485256Slh155975 pmem_req_array++; /* Size */ 7495256Slh155975 size = *(pmem_req_array); 7505256Slh155975 pmem_req_array++; /* Virtual Address */ 7515256Slh155975 if (pmem_req_array == NULL) 7525256Slh155975 return (1); 7535256Slh155975 kmem_free((int *)*pmem_req_array, size); 7545256Slh155975 break; 7555256Slh155975 } 7565256Slh155975 pmem_req_array++; 7575256Slh155975 } 7585256Slh155975 return (1); 7595256Slh155975 } 7605256Slh155975 7615256Slh155975 /* 7625256Slh155975 * Allocate and initialize Tx/Rx descriptors 7635256Slh155975 */ 7645256Slh155975 static boolean_t 7655256Slh155975 amd8111s_allocate_descriptors(struct LayerPointers *pLayerPointers) 7665256Slh155975 { 7675256Slh155975 struct odl *pOdl = pLayerPointers->pOdl; 7685256Slh155975 struct mil *pMil = pLayerPointers->pMil; 7695256Slh155975 dev_info_t *devinfo = pOdl->devinfo; 7705256Slh155975 uint_t length, count, i; 7715256Slh155975 size_t real_length; 7725256Slh155975 7735256Slh155975 /* 7745256Slh155975 * Allocate Rx descriptors 7755256Slh155975 */ 7765256Slh155975 if (ddi_dma_alloc_handle(devinfo, &pcn_desc_dma_attr_t, DDI_DMA_SLEEP, 7775256Slh155975 NULL, &pOdl->rx_desc_dma_handle) != DDI_SUCCESS) { 7785256Slh155975 amd8111s_log(pLayerPointers, CE_WARN, 7795256Slh155975 "ddi_dma_alloc_handle for Rx desc failed"); 7805256Slh155975 pOdl->rx_desc_dma_handle = NULL; 7815256Slh155975 return (B_FALSE); 7825256Slh155975 } 7835256Slh155975 7845256Slh155975 length = sizeof (struct rx_desc) * RX_RING_SIZE + ALIGNMENT; 7855256Slh155975 if (ddi_dma_mem_alloc(pOdl->rx_desc_dma_handle, length, 7865256Slh155975 &pcn_acc_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 7875256Slh155975 NULL, (caddr_t *)&pMil->Rx_desc_original, &real_length, 7885256Slh155975 &pOdl->rx_desc_acc_handle) != DDI_SUCCESS) { 7895256Slh155975 7905256Slh155975 amd8111s_log(pLayerPointers, CE_WARN, 7915256Slh155975 "ddi_dma_mem_handle for Rx desc failed"); 7925256Slh155975 ddi_dma_free_handle(&pOdl->rx_desc_dma_handle); 7935256Slh155975 pOdl->rx_desc_dma_handle = NULL; 7945256Slh155975 return (B_FALSE); 7955256Slh155975 } 7965256Slh155975 7975256Slh155975 if (ddi_dma_addr_bind_handle(pOdl->rx_desc_dma_handle, 7985256Slh155975 NULL, (caddr_t)pMil->Rx_desc_original, real_length, 7995256Slh155975 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 8005256Slh155975 NULL, &pOdl->rx_desc_dma_cookie, 8015256Slh155975 &count) != DDI_SUCCESS) { 8025256Slh155975 8035256Slh155975 amd8111s_log(pLayerPointers, CE_WARN, 8045256Slh155975 "ddi_dma_addr_bind_handle for Rx desc failed"); 8055256Slh155975 ddi_dma_mem_free(&pOdl->rx_desc_acc_handle); 8065256Slh155975 ddi_dma_free_handle(&pOdl->rx_desc_dma_handle); 8075256Slh155975 pOdl->rx_desc_dma_handle = NULL; 8085256Slh155975 return (B_FALSE); 8095256Slh155975 } 8105256Slh155975 ASSERT(count == 1); 8115256Slh155975 8125256Slh155975 /* Initialize Rx descriptors related variables */ 8135256Slh155975 pMil->Rx_desc = (struct rx_desc *) 8145256Slh155975 ((pMil->Rx_desc_original + ALIGNMENT) & ~ALIGNMENT); 8155256Slh155975 pMil->Rx_desc_pa = (unsigned int) 8165256Slh155975 ((pOdl->rx_desc_dma_cookie.dmac_laddress + ALIGNMENT) & ~ALIGNMENT); 8175256Slh155975 8185256Slh155975 pLayerPointers->pMdl->init_blk->RDRA = pMil->Rx_desc_pa; 8195256Slh155975 8205256Slh155975 8215256Slh155975 /* 8225256Slh155975 * Allocate Tx descriptors 8235256Slh155975 */ 8245256Slh155975 if (ddi_dma_alloc_handle(devinfo, &pcn_desc_dma_attr_t, DDI_DMA_SLEEP, 8255256Slh155975 NULL, &pOdl->tx_desc_dma_handle) != DDI_SUCCESS) { 8265256Slh155975 amd8111s_log(pLayerPointers, CE_WARN, 8275256Slh155975 "ddi_dma_alloc_handle for Tx desc failed"); 8285256Slh155975 goto allocate_desc_fail; 8295256Slh155975 } 8305256Slh155975 8315256Slh155975 length = sizeof (struct tx_desc) * TX_RING_SIZE + ALIGNMENT; 8325256Slh155975 if (ddi_dma_mem_alloc(pOdl->tx_desc_dma_handle, length, 8335256Slh155975 &pcn_acc_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 8345256Slh155975 NULL, (caddr_t *)&pMil->Tx_desc_original, &real_length, 8355256Slh155975 &pOdl->tx_desc_acc_handle) != DDI_SUCCESS) { 8365256Slh155975 8375256Slh155975 amd8111s_log(pLayerPointers, CE_WARN, 8385256Slh155975 "ddi_dma_mem_handle for Tx desc failed"); 8395256Slh155975 ddi_dma_free_handle(&pOdl->tx_desc_dma_handle); 8405256Slh155975 goto allocate_desc_fail; 8415256Slh155975 } 8425256Slh155975 8435256Slh155975 if (ddi_dma_addr_bind_handle(pOdl->tx_desc_dma_handle, 8445256Slh155975 NULL, (caddr_t)pMil->Tx_desc_original, real_length, 8455256Slh155975 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 8465256Slh155975 NULL, &pOdl->tx_desc_dma_cookie, 8475256Slh155975 &count) != DDI_SUCCESS) { 8485256Slh155975 8495256Slh155975 amd8111s_log(pLayerPointers, CE_WARN, 8505256Slh155975 "ddi_dma_addr_bind_handle for Tx desc failed"); 8515256Slh155975 ddi_dma_mem_free(&pOdl->tx_desc_acc_handle); 8525256Slh155975 ddi_dma_free_handle(&pOdl->tx_desc_dma_handle); 8535256Slh155975 goto allocate_desc_fail; 8545256Slh155975 } 8555256Slh155975 ASSERT(count == 1); 8565256Slh155975 /* Set the DMA area to all zeros */ 8575256Slh155975 bzero((caddr_t)pMil->Tx_desc_original, length); 8585256Slh155975 8595256Slh155975 /* Initialize Tx descriptors related variables */ 8605256Slh155975 pMil->Tx_desc = (struct tx_desc *) 8615256Slh155975 ((pMil->Tx_desc_original + ALIGNMENT) & ~ALIGNMENT); 8625256Slh155975 pMil->pNonphysical->TxDescQRead = pMil->Tx_desc; 8635256Slh155975 pMil->pNonphysical->TxDescQWrite = pMil->Tx_desc; 8645256Slh155975 pMil->pNonphysical->TxDescQStart = pMil->Tx_desc; 8655256Slh155975 pMil->pNonphysical->TxDescQEnd = &(pMil->Tx_desc[TX_RING_SIZE -1]); 8665256Slh155975 8675256Slh155975 /* Physical Addr of Tx_desc_original & Tx_desc */ 8685256Slh155975 pLayerPointers->pMil->Tx_desc_pa = 8695256Slh155975 ((pOdl->tx_desc_dma_cookie.dmac_laddress + ALIGNMENT) & 8705256Slh155975 ~ALIGNMENT); 8715256Slh155975 8725256Slh155975 /* Setting the reserved bits in the tx descriptors */ 8735256Slh155975 for (i = 0; i < TX_RING_SIZE; i++) { 8745256Slh155975 pMil->pNonphysical->TxDescQWrite->Tx_RES0 = 0x0f; 8755256Slh155975 pMil->pNonphysical->TxDescQWrite->Tx_OWN = 0; 8765256Slh155975 pMil->pNonphysical->TxDescQWrite++; 8775256Slh155975 } 8785256Slh155975 pMil->pNonphysical->TxDescQWrite = pMil->pNonphysical->TxDescQStart; 8795256Slh155975 8805256Slh155975 pLayerPointers->pMdl->init_blk->TDRA = pMil->Tx_desc_pa; 8815256Slh155975 8825256Slh155975 return (B_TRUE); 8835256Slh155975 8845256Slh155975 allocate_desc_fail: 8855256Slh155975 pOdl->tx_desc_dma_handle = NULL; 8865256Slh155975 (void) ddi_dma_unbind_handle(pOdl->rx_desc_dma_handle); 8875256Slh155975 ddi_dma_mem_free(&pOdl->rx_desc_acc_handle); 8885256Slh155975 ddi_dma_free_handle(&pOdl->rx_desc_dma_handle); 8895256Slh155975 pOdl->rx_desc_dma_handle = NULL; 8905256Slh155975 return (B_FALSE); 8915256Slh155975 } 8925256Slh155975 8935256Slh155975 /* 8945256Slh155975 * Free Tx/Rx descriptors 8955256Slh155975 */ 8965256Slh155975 static void 8975256Slh155975 amd8111s_free_descriptors(struct LayerPointers *pLayerPointers) 8985256Slh155975 { 8995256Slh155975 struct odl *pOdl = pLayerPointers->pOdl; 9005256Slh155975 9015256Slh155975 /* Free Rx descriptors */ 9025256Slh155975 if (pOdl->rx_desc_dma_handle) { 9035256Slh155975 (void) ddi_dma_unbind_handle(pOdl->rx_desc_dma_handle); 9045256Slh155975 ddi_dma_mem_free(&pOdl->rx_desc_acc_handle); 9055256Slh155975 ddi_dma_free_handle(&pOdl->rx_desc_dma_handle); 9065256Slh155975 pOdl->rx_desc_dma_handle = NULL; 9075256Slh155975 } 9085256Slh155975 9095256Slh155975 /* Free Rx descriptors */ 9105256Slh155975 if (pOdl->tx_desc_dma_handle) { 9115256Slh155975 (void) ddi_dma_unbind_handle(pOdl->tx_desc_dma_handle); 9125256Slh155975 ddi_dma_mem_free(&pOdl->tx_desc_acc_handle); 9135256Slh155975 ddi_dma_free_handle(&pOdl->tx_desc_dma_handle); 9145256Slh155975 pOdl->tx_desc_dma_handle = NULL; 9155256Slh155975 } 9165256Slh155975 } 9175256Slh155975 9185256Slh155975 /* 9195256Slh155975 * Allocate Tx/Rx Ring buffer 9205256Slh155975 */ 9215256Slh155975 static boolean_t 9225256Slh155975 amd8111s_alloc_dma_ringbuf(struct LayerPointers *pLayerPointers, 9235256Slh155975 struct amd8111s_dma_ringbuf *pRing, 9245256Slh155975 uint32_t ring_size, uint32_t msg_size) 9255256Slh155975 { 9265256Slh155975 uint32_t idx, msg_idx = 0, msg_acc; 9275256Slh155975 dev_info_t *devinfo = pLayerPointers->pOdl->devinfo; 9285256Slh155975 size_t real_length; 9295256Slh155975 uint_t count = 0; 9305256Slh155975 9315256Slh155975 ASSERT(pcn_buff_dma_attr_t.dma_attr_align == 1); 9325256Slh155975 pRing->dma_buf_sz = msg_size; 9335256Slh155975 pRing->ring_size = ring_size; 9345256Slh155975 pRing->trunk_num = AMD8111S_SPLIT; 9355256Slh155975 pRing->buf_sz = msg_size * ring_size; 9365256Slh155975 if (ring_size < pRing->trunk_num) 9375256Slh155975 pRing->trunk_num = ring_size; 9385256Slh155975 ASSERT((pRing->buf_sz % pRing->trunk_num) == 0); 9395256Slh155975 9405256Slh155975 pRing->trunk_sz = pRing->buf_sz / pRing->trunk_num; 9415256Slh155975 ASSERT((pRing->trunk_sz % pRing->dma_buf_sz) == 0); 9425256Slh155975 9435256Slh155975 pRing->msg_buf = kmem_zalloc(sizeof (struct amd8111s_msgbuf) * 9445256Slh155975 ring_size, KM_NOSLEEP); 9455256Slh155975 pRing->dma_hdl = kmem_zalloc(sizeof (ddi_dma_handle_t) * 9465256Slh155975 pRing->trunk_num, KM_NOSLEEP); 9475256Slh155975 pRing->acc_hdl = kmem_zalloc(sizeof (ddi_acc_handle_t) * 9485256Slh155975 pRing->trunk_num, KM_NOSLEEP); 9495256Slh155975 pRing->dma_cookie = kmem_zalloc(sizeof (ddi_dma_cookie_t) * 9505256Slh155975 pRing->trunk_num, KM_NOSLEEP); 9515256Slh155975 pRing->trunk_addr = kmem_zalloc(sizeof (caddr_t) * 9525256Slh155975 pRing->trunk_num, KM_NOSLEEP); 9535256Slh155975 if (pRing->msg_buf == NULL || pRing->dma_hdl == NULL || 9545256Slh155975 pRing->acc_hdl == NULL || pRing->trunk_addr == NULL || 9555256Slh155975 pRing->dma_cookie == NULL) { 9565256Slh155975 amd8111s_log(pLayerPointers, CE_NOTE, 9575256Slh155975 "kmem_zalloc failed"); 9585256Slh155975 goto failed; 9595256Slh155975 } 9605256Slh155975 9615256Slh155975 for (idx = 0; idx < pRing->trunk_num; ++idx) { 9625256Slh155975 if (ddi_dma_alloc_handle(devinfo, &pcn_buff_dma_attr_t, 9635256Slh155975 DDI_DMA_SLEEP, NULL, &(pRing->dma_hdl[idx])) 9645256Slh155975 != DDI_SUCCESS) { 9655256Slh155975 9665256Slh155975 amd8111s_log(pLayerPointers, CE_WARN, 9675256Slh155975 "ddi_dma_alloc_handle failed"); 9685256Slh155975 goto failed; 9695256Slh155975 } else if (ddi_dma_mem_alloc(pRing->dma_hdl[idx], 9705256Slh155975 pRing->trunk_sz, &pcn_acc_attr, DDI_DMA_STREAMING, 9715256Slh155975 DDI_DMA_SLEEP, NULL, 9725256Slh155975 (caddr_t *)&(pRing->trunk_addr[idx]), 9735256Slh155975 (size_t *)(&real_length), &pRing->acc_hdl[idx]) 9745256Slh155975 != DDI_SUCCESS) { 9755256Slh155975 9765256Slh155975 amd8111s_log(pLayerPointers, CE_WARN, 9775256Slh155975 "ddi_dma_mem_alloc failed"); 9785256Slh155975 goto failed; 9795256Slh155975 } else if (real_length != pRing->trunk_sz) { 9805256Slh155975 amd8111s_log(pLayerPointers, CE_WARN, 9815256Slh155975 "ddi_dma_mem_alloc failed"); 9825256Slh155975 goto failed; 9835256Slh155975 } else if (ddi_dma_addr_bind_handle(pRing->dma_hdl[idx], 9845256Slh155975 NULL, (caddr_t)pRing->trunk_addr[idx], real_length, 9855256Slh155975 DDI_DMA_WRITE | DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, 9865256Slh155975 &pRing->dma_cookie[idx], &count) != DDI_DMA_MAPPED) { 9875256Slh155975 9885256Slh155975 amd8111s_log(pLayerPointers, CE_WARN, 9895256Slh155975 "ddi_dma_addr_bind_handle failed"); 9905256Slh155975 goto failed; 9915256Slh155975 } else { 9925256Slh155975 for (msg_acc = 0; 9935256Slh155975 msg_acc < pRing->trunk_sz / pRing->dma_buf_sz; 9945256Slh155975 ++ msg_acc) { 9955256Slh155975 pRing->msg_buf[msg_idx].offset = 9965256Slh155975 msg_acc * pRing->dma_buf_sz; 9975256Slh155975 pRing->msg_buf[msg_idx].vir_addr = 9985256Slh155975 pRing->trunk_addr[idx] + 9995256Slh155975 pRing->msg_buf[msg_idx].offset; 10005256Slh155975 pRing->msg_buf[msg_idx].phy_addr = 10015256Slh155975 pRing->dma_cookie[idx].dmac_laddress + 10025256Slh155975 pRing->msg_buf[msg_idx].offset; 10035256Slh155975 pRing->msg_buf[msg_idx].p_hdl = 10045256Slh155975 pRing->dma_hdl[idx]; 10055256Slh155975 msg_idx ++; 10065256Slh155975 } 10075256Slh155975 } 10085256Slh155975 } 10095256Slh155975 10105256Slh155975 pRing->free = pRing->msg_buf; 10115256Slh155975 pRing->next = pRing->msg_buf; 10125256Slh155975 pRing->curr = pRing->msg_buf; 10135256Slh155975 10145256Slh155975 return (B_TRUE); 10155256Slh155975 failed: 10165256Slh155975 amd8111s_free_dma_ringbuf(pRing); 10175256Slh155975 return (B_FALSE); 10185256Slh155975 } 10195256Slh155975 10205256Slh155975 /* 10215256Slh155975 * Free Tx/Rx ring buffer 10225256Slh155975 */ 10235256Slh155975 static void 10245256Slh155975 amd8111s_free_dma_ringbuf(struct amd8111s_dma_ringbuf *pRing) 10255256Slh155975 { 10265256Slh155975 int idx; 10275256Slh155975 10285256Slh155975 if (pRing->dma_cookie != NULL) { 10295256Slh155975 for (idx = 0; idx < pRing->trunk_num; idx ++) { 10305256Slh155975 if (pRing->dma_cookie[idx].dmac_laddress == 0) { 10315256Slh155975 break; 10325256Slh155975 } 10335256Slh155975 (void) ddi_dma_unbind_handle(pRing->dma_hdl[idx]); 10345256Slh155975 } 10355256Slh155975 kmem_free(pRing->dma_cookie, 10365256Slh155975 sizeof (ddi_dma_cookie_t) * pRing->trunk_num); 10375256Slh155975 } 10385256Slh155975 10395256Slh155975 if (pRing->acc_hdl != NULL) { 10405256Slh155975 for (idx = 0; idx < pRing->trunk_num; idx ++) { 10415256Slh155975 if (pRing->acc_hdl[idx] == NULL) 10425256Slh155975 break; 10435256Slh155975 ddi_dma_mem_free(&pRing->acc_hdl[idx]); 10445256Slh155975 } 10455256Slh155975 kmem_free(pRing->acc_hdl, 10465256Slh155975 sizeof (ddi_acc_handle_t) * pRing->trunk_num); 10475256Slh155975 } 10485256Slh155975 10495256Slh155975 if (pRing->dma_hdl != NULL) { 10505256Slh155975 for (idx = 0; idx < pRing->trunk_num; idx ++) { 10515256Slh155975 if (pRing->dma_hdl[idx] == 0) { 10525256Slh155975 break; 10535256Slh155975 } 10545256Slh155975 ddi_dma_free_handle(&pRing->dma_hdl[idx]); 10555256Slh155975 } 10565256Slh155975 kmem_free(pRing->dma_hdl, 10575256Slh155975 sizeof (ddi_dma_handle_t) * pRing->trunk_num); 10585256Slh155975 } 10595256Slh155975 10605256Slh155975 if (pRing->msg_buf != NULL) { 10615256Slh155975 kmem_free(pRing->msg_buf, 10625256Slh155975 sizeof (struct amd8111s_msgbuf) * pRing->ring_size); 10635256Slh155975 } 10645256Slh155975 10655256Slh155975 if (pRing->trunk_addr != NULL) { 10665256Slh155975 kmem_free(pRing->trunk_addr, 10675256Slh155975 sizeof (caddr_t) * pRing->trunk_num); 10685256Slh155975 } 10695256Slh155975 10705256Slh155975 bzero(pRing, sizeof (*pRing)); 10715256Slh155975 } 10725256Slh155975 10735256Slh155975 10745256Slh155975 /* 10755256Slh155975 * Allocate all Tx buffer. 10765256Slh155975 * Allocate a Rx buffer for each Rx descriptor. Then 10775256Slh155975 * call mil routine to fill physical address of Rx 10785256Slh155975 * buffer into Rx descriptors 10795256Slh155975 */ 10805256Slh155975 static boolean_t 10815256Slh155975 amd8111s_allocate_buffers(struct LayerPointers *pLayerPointers) 10825256Slh155975 { 10835256Slh155975 struct odl *pOdl = pLayerPointers->pOdl; 10845256Slh155975 10855256Slh155975 /* 10865256Slh155975 * Allocate rx Buffers 10875256Slh155975 */ 10885256Slh155975 if (amd8111s_alloc_dma_ringbuf(pLayerPointers, &pOdl->rx_buf, 10895256Slh155975 RX_RING_SIZE, RX_BUF_SIZE) == B_FALSE) { 10905256Slh155975 amd8111s_log(pLayerPointers, CE_WARN, 10915256Slh155975 "amd8111s_alloc_dma_ringbuf for tx failed"); 10925256Slh155975 goto allocate_buf_fail; 10935256Slh155975 } 10945256Slh155975 10955256Slh155975 /* 10965256Slh155975 * Allocate Tx buffers 10975256Slh155975 */ 10985256Slh155975 if (amd8111s_alloc_dma_ringbuf(pLayerPointers, &pOdl->tx_buf, 10995256Slh155975 TX_COALESC_SIZE, TX_BUF_SIZE) == B_FALSE) { 11005256Slh155975 amd8111s_log(pLayerPointers, CE_WARN, 11015256Slh155975 "amd8111s_alloc_dma_ringbuf for tx failed"); 11025256Slh155975 goto allocate_buf_fail; 11035256Slh155975 } 11045256Slh155975 11055256Slh155975 /* 11065256Slh155975 * Initilize the mil Queues 11075256Slh155975 */ 11085256Slh155975 milInitGlbds(pLayerPointers); 11095256Slh155975 11105256Slh155975 milInitRxQ(pLayerPointers); 11115256Slh155975 11125256Slh155975 return (B_TRUE); 11135256Slh155975 11145256Slh155975 allocate_buf_fail: 11155256Slh155975 11165256Slh155975 amd8111s_log(pLayerPointers, CE_WARN, 11175256Slh155975 "amd8111s_allocate_buffers failed"); 11185256Slh155975 return (B_FALSE); 11195256Slh155975 } 11205256Slh155975 11215256Slh155975 /* 11225256Slh155975 * Free all Rx/Tx buffer 11235256Slh155975 */ 11245256Slh155975 11255256Slh155975 static void 11265256Slh155975 amd8111s_free_buffers(struct LayerPointers *pLayerPointers) 11275256Slh155975 { 11285256Slh155975 /* Free Tx buffers */ 11295256Slh155975 amd8111s_free_dma_ringbuf(&pLayerPointers->pOdl->tx_buf); 11305256Slh155975 11315256Slh155975 /* Free Rx Buffers */ 11325256Slh155975 amd8111s_free_dma_ringbuf(&pLayerPointers->pOdl->rx_buf); 11335256Slh155975 } 11345256Slh155975 11355256Slh155975 /* 11365256Slh155975 * Try to recycle all the descriptors and Tx buffers 11375256Slh155975 * which are already freed by hardware. 11385256Slh155975 */ 11395256Slh155975 static int 11405256Slh155975 amd8111s_recycle_tx(struct LayerPointers *pLayerPointers) 11415256Slh155975 { 11425256Slh155975 struct nonphysical *pNonphysical; 11435256Slh155975 uint32_t count = 0; 11445256Slh155975 11455256Slh155975 pNonphysical = pLayerPointers->pMil->pNonphysical; 11465256Slh155975 while (pNonphysical->TxDescQRead->Tx_OWN == 0 && 11475256Slh155975 pNonphysical->TxDescQRead != pNonphysical->TxDescQWrite) { 11485256Slh155975 pLayerPointers->pOdl->tx_buf.free = 11495256Slh155975 NEXT(pLayerPointers->pOdl->tx_buf, free); 11505256Slh155975 pNonphysical->TxDescQRead++; 11515256Slh155975 if (pNonphysical->TxDescQRead > pNonphysical->TxDescQEnd) { 11525256Slh155975 pNonphysical->TxDescQRead = pNonphysical->TxDescQStart; 11535256Slh155975 } 11545256Slh155975 count ++; 11555256Slh155975 } 11565256Slh155975 11575256Slh155975 if (pLayerPointers->pMil->tx_reschedule) 11585256Slh155975 ddi_trigger_softintr(pLayerPointers->pOdl->drain_id); 11595256Slh155975 11605256Slh155975 return (count); 11615256Slh155975 } 11625256Slh155975 11635256Slh155975 /* 11645256Slh155975 * Get packets in the Tx buffer, then copy them to the send buffer. 11655256Slh155975 * Trigger hardware to send out packets. 11665256Slh155975 */ 11675256Slh155975 static void 11685256Slh155975 amd8111s_send_serial(struct LayerPointers *pLayerPointers) 11695256Slh155975 { 11705256Slh155975 struct nonphysical *pNonphysical; 11715256Slh155975 uint32_t count; 11725256Slh155975 11735256Slh155975 pNonphysical = pLayerPointers->pMil->pNonphysical; 11745256Slh155975 11755256Slh155975 mutex_enter(&pLayerPointers->pOdl->mdlSendLock); 11765256Slh155975 11775256Slh155975 for (count = 0; count < AMD8111S_SEND_MAX; count ++) { 11785256Slh155975 if (pLayerPointers->pOdl->tx_buf.curr == 11795256Slh155975 pLayerPointers->pOdl->tx_buf.next) { 11805256Slh155975 break; 11815256Slh155975 } 11825256Slh155975 /* to verify if it needs to recycle the tx Buf */ 11835256Slh155975 if (((pNonphysical->TxDescQWrite + 1 > 11845256Slh155975 pNonphysical->TxDescQEnd) ? pNonphysical->TxDescQStart : 11855256Slh155975 (pNonphysical->TxDescQWrite + 1)) == 11865256Slh155975 pNonphysical->TxDescQRead) 11875256Slh155975 if (amd8111s_recycle_tx(pLayerPointers) == 0) { 11885256Slh155975 pLayerPointers->pOdl 11895256Slh155975 ->statistics.tx_no_descriptor ++; 11905256Slh155975 break; 11915256Slh155975 } 11925256Slh155975 11935256Slh155975 /* Fill packet length */ 11945256Slh155975 pNonphysical->TxDescQWrite->Tx_BCNT = (uint16_t)pLayerPointers 11955256Slh155975 ->pOdl->tx_buf.curr->msg_size; 11965256Slh155975 11975256Slh155975 /* Fill physical buffer address */ 11985256Slh155975 pNonphysical->TxDescQWrite->Tx_Base_Addr = (unsigned int) 11995256Slh155975 pLayerPointers->pOdl->tx_buf.curr->phy_addr; 12005256Slh155975 12015256Slh155975 pNonphysical->TxDescQWrite->Tx_SOP = 1; 12025256Slh155975 pNonphysical->TxDescQWrite->Tx_EOP = 1; 12035256Slh155975 pNonphysical->TxDescQWrite->Tx_ADD_FCS = 1; 12045256Slh155975 pNonphysical->TxDescQWrite->Tx_LTINT = 1; 12055256Slh155975 pNonphysical->TxDescQWrite->Tx_USPACE = 0; 12065256Slh155975 pNonphysical->TxDescQWrite->Tx_OWN = 1; 12075256Slh155975 12085256Slh155975 pNonphysical->TxDescQWrite++; 12095256Slh155975 if (pNonphysical->TxDescQWrite > pNonphysical->TxDescQEnd) { 12105256Slh155975 pNonphysical->TxDescQWrite = pNonphysical->TxDescQStart; 12115256Slh155975 } 12125256Slh155975 12135256Slh155975 pLayerPointers->pOdl->tx_buf.curr = 12145256Slh155975 NEXT(pLayerPointers->pOdl->tx_buf, curr); 12155256Slh155975 12165256Slh155975 } 12175256Slh155975 12185256Slh155975 pLayerPointers->pOdl->statistics.tx_ok_packets += count; 12195256Slh155975 12205256Slh155975 mutex_exit(&pLayerPointers->pOdl->mdlSendLock); 12215256Slh155975 12225256Slh155975 /* Call mdlTransmit to send the pkt out on the network */ 12235256Slh155975 mdlTransmit(pLayerPointers); 12245256Slh155975 12255256Slh155975 } 12265256Slh155975 12275256Slh155975 /* 12285256Slh155975 * Softintr entrance. try to send out packets in the Tx buffer. 12295256Slh155975 * If reschedule is True, call mac_tx_update to re-enable the 12305256Slh155975 * transmit 12315256Slh155975 */ 12325256Slh155975 static uint_t 12335256Slh155975 amd8111s_send_drain(caddr_t arg) 12345256Slh155975 { 12356990Sgd78059 struct LayerPointers *pLayerPointers = (void *)arg; 12365256Slh155975 12375256Slh155975 amd8111s_send_serial(pLayerPointers); 12385256Slh155975 12395256Slh155975 if (pLayerPointers->pMil->tx_reschedule && 12405256Slh155975 NEXT(pLayerPointers->pOdl->tx_buf, next) != 12415256Slh155975 pLayerPointers->pOdl->tx_buf.free) { 12425256Slh155975 mac_tx_update(pLayerPointers->pOdl->mh); 12435256Slh155975 pLayerPointers->pMil->tx_reschedule = B_FALSE; 12445256Slh155975 } 12455256Slh155975 12465256Slh155975 return (DDI_INTR_CLAIMED); 12475256Slh155975 } 12485256Slh155975 12495256Slh155975 /* 12505256Slh155975 * Get a Tx buffer 12515256Slh155975 */ 12525256Slh155975 static struct amd8111s_msgbuf * 12535256Slh155975 amd8111s_getTxbuf(struct LayerPointers *pLayerPointers) 12545256Slh155975 { 12555256Slh155975 struct amd8111s_msgbuf *tmp, *next; 12565256Slh155975 12575256Slh155975 mutex_enter(&pLayerPointers->pOdl->mdlSendLock); 12585256Slh155975 next = NEXT(pLayerPointers->pOdl->tx_buf, next); 12595256Slh155975 if (next == pLayerPointers->pOdl->tx_buf.free) { 12605256Slh155975 tmp = NULL; 12615256Slh155975 } else { 12625256Slh155975 tmp = pLayerPointers->pOdl->tx_buf.next; 12635256Slh155975 pLayerPointers->pOdl->tx_buf.next = next; 12645256Slh155975 } 12655256Slh155975 mutex_exit(&pLayerPointers->pOdl->mdlSendLock); 12665256Slh155975 12675256Slh155975 return (tmp); 12685256Slh155975 } 12695256Slh155975 12705256Slh155975 static boolean_t 12715256Slh155975 amd8111s_send(struct LayerPointers *pLayerPointers, mblk_t *mp) 12725256Slh155975 { 12735256Slh155975 struct odl *pOdl; 12745256Slh155975 size_t frag_len; 12755256Slh155975 mblk_t *tmp; 12765256Slh155975 struct amd8111s_msgbuf *txBuf; 12775256Slh155975 uint8_t *pMsg; 12785256Slh155975 12795256Slh155975 pOdl = pLayerPointers->pOdl; 12805256Slh155975 12815256Slh155975 /* alloc send buffer */ 12825256Slh155975 txBuf = amd8111s_getTxbuf(pLayerPointers); 12835256Slh155975 if (txBuf == NULL) { 12845256Slh155975 pOdl->statistics.tx_no_buffer ++; 12855256Slh155975 pLayerPointers->pMil->tx_reschedule = B_TRUE; 12865256Slh155975 amd8111s_send_serial(pLayerPointers); 12875256Slh155975 return (B_FALSE); 12885256Slh155975 } 12895256Slh155975 12905256Slh155975 /* copy packet to send buffer */ 12915256Slh155975 txBuf->msg_size = 0; 12925256Slh155975 pMsg = (uint8_t *)txBuf->vir_addr; 12935256Slh155975 for (tmp = mp; tmp; tmp = tmp->b_cont) { 12945256Slh155975 frag_len = MBLKL(tmp); 12955256Slh155975 bcopy(tmp->b_rptr, pMsg, frag_len); 12965256Slh155975 txBuf->msg_size += frag_len; 12975256Slh155975 pMsg += frag_len; 12985256Slh155975 } 12995256Slh155975 freemsg(mp); 13005256Slh155975 13015256Slh155975 amd8111s_send_serial(pLayerPointers); 13025256Slh155975 13035256Slh155975 return (B_TRUE); 13045256Slh155975 } 13055256Slh155975 13065256Slh155975 /* 13075256Slh155975 * (GLD Entry Point) Send the message block to lower layer 13085256Slh155975 */ 13095256Slh155975 static mblk_t * 13105256Slh155975 amd8111s_m_tx(void *arg, mblk_t *mp) 13115256Slh155975 { 13125256Slh155975 struct LayerPointers *pLayerPointers = arg; 13135256Slh155975 mblk_t *next; 13145256Slh155975 13155256Slh155975 rw_enter(&pLayerPointers->pOdl->chip_lock, RW_READER); 13165256Slh155975 if (!pLayerPointers->run) { 13175256Slh155975 pLayerPointers->pOdl->statistics.tx_afterunplumb ++; 13185256Slh155975 freemsgchain(mp); 13195256Slh155975 mp = NULL; 13205256Slh155975 } 13215256Slh155975 13225256Slh155975 while (mp != NULL) { 13235256Slh155975 next = mp->b_next; 13245256Slh155975 mp->b_next = NULL; 13255256Slh155975 if (!amd8111s_send(pLayerPointers, mp)) { 13265256Slh155975 /* Send fail */ 13275256Slh155975 mp->b_next = next; 13285256Slh155975 break; 13295256Slh155975 } 13305256Slh155975 mp = next; 13315256Slh155975 } 13325256Slh155975 13335256Slh155975 rw_exit(&pLayerPointers->pOdl->chip_lock); 13345256Slh155975 return (mp); 13355256Slh155975 } 13365256Slh155975 13375256Slh155975 /* 13385256Slh155975 * (GLD Entry Point) Interrupt Service Routine 13395256Slh155975 */ 13405256Slh155975 static uint_t 13415256Slh155975 amd8111s_intr(caddr_t arg) 13425256Slh155975 { 13435256Slh155975 unsigned int intrCauses; 13446990Sgd78059 struct LayerPointers *pLayerPointers = (void *)arg; 13455256Slh155975 13465256Slh155975 /* Read the interrupt status from mdl */ 13475256Slh155975 intrCauses = mdlReadInterrupt(pLayerPointers); 13485256Slh155975 13495256Slh155975 if (intrCauses == 0) { 13505256Slh155975 pLayerPointers->pOdl->statistics.intr_OTHER ++; 13515256Slh155975 return (DDI_INTR_UNCLAIMED); 13525256Slh155975 } 13535256Slh155975 13545256Slh155975 if (intrCauses & LCINT) { 13555256Slh155975 if (mdlReadLink(pLayerPointers) == LINK_UP) { 13565256Slh155975 mdlGetActiveMediaInfo(pLayerPointers); 13575256Slh155975 /* Link status changed */ 13585256Slh155975 if (pLayerPointers->pOdl->LinkStatus != 13595256Slh155975 LINK_STATE_UP) { 13605256Slh155975 pLayerPointers->pOdl->LinkStatus = 13615256Slh155975 LINK_STATE_UP; 13625256Slh155975 mac_link_update(pLayerPointers->pOdl->mh, 13635256Slh155975 LINK_STATE_UP); 13645256Slh155975 } 13655256Slh155975 } else { 13665256Slh155975 if (pLayerPointers->pOdl->LinkStatus != 13675256Slh155975 LINK_STATE_DOWN) { 13685256Slh155975 pLayerPointers->pOdl->LinkStatus = 13695256Slh155975 LINK_STATE_DOWN; 13705256Slh155975 mac_link_update(pLayerPointers->pOdl->mh, 13715256Slh155975 LINK_STATE_DOWN); 13725256Slh155975 } 13735256Slh155975 } 13745256Slh155975 } 13755256Slh155975 /* 13765256Slh155975 * RINT0: Receive Interrupt is set by the controller after the last 13775256Slh155975 * descriptor of a receive frame for this ring has been updated by 13785256Slh155975 * writing a 0 to the OWNership bit. 13795256Slh155975 */ 13805256Slh155975 if (intrCauses & RINT0) { 13815256Slh155975 pLayerPointers->pOdl->statistics.intr_RINT0 ++; 13825256Slh155975 amd8111s_receive(pLayerPointers); 13835256Slh155975 } 13845256Slh155975 13855256Slh155975 /* 13865256Slh155975 * TINT0: Transmit Interrupt is set by the controller after the OWN bit 13875256Slh155975 * in the last descriptor of a transmit frame in this particular ring 13885256Slh155975 * has been cleared to indicate the frame has been copied to the 13895256Slh155975 * transmit FIFO. 13905256Slh155975 */ 13915256Slh155975 if (intrCauses & TINT0) { 13925256Slh155975 pLayerPointers->pOdl->statistics.intr_TINT0 ++; 13935256Slh155975 /* 13945256Slh155975 * if desc ring is NULL and tx buf is not NULL, it should 13955256Slh155975 * drain tx buffer 13965256Slh155975 */ 13975256Slh155975 amd8111s_send_serial(pLayerPointers); 13985256Slh155975 } 13995256Slh155975 14005256Slh155975 if (intrCauses & STINT) { 14015256Slh155975 pLayerPointers->pOdl->statistics.intr_STINT ++; 14025256Slh155975 } 14035256Slh155975 14045256Slh155975 14055256Slh155975 return (DDI_INTR_CLAIMED); 14065256Slh155975 } 14075256Slh155975 14085256Slh155975 /* 14095256Slh155975 * To re-initilize data structures. 14105256Slh155975 */ 14115256Slh155975 static void 14125256Slh155975 amd8111s_sw_reset(struct LayerPointers *pLayerPointers) 14135256Slh155975 { 14145256Slh155975 /* Reset all Tx/Rx queues and descriptors */ 14155256Slh155975 milResetTxQ(pLayerPointers); 14165256Slh155975 milInitRxQ(pLayerPointers); 14175256Slh155975 } 14185256Slh155975 14195256Slh155975 /* 14205256Slh155975 * Send all pending tx packets 14215256Slh155975 */ 14225256Slh155975 static void 14235256Slh155975 amd8111s_tx_drain(struct LayerPointers *adapter) 14245256Slh155975 { 14255256Slh155975 struct tx_desc *pTx_desc = adapter->pMil->pNonphysical->TxDescQStart; 14265256Slh155975 int i, desc_count = 0; 14275256Slh155975 for (i = 0; i < 30; i++) { 14285256Slh155975 while ((pTx_desc->Tx_OWN == 0) && (desc_count < TX_RING_SIZE)) { 14295256Slh155975 /* This packet has been transmitted */ 14305256Slh155975 pTx_desc ++; 14315256Slh155975 desc_count ++; 14325256Slh155975 } 14335256Slh155975 if (desc_count == TX_RING_SIZE) { 14345256Slh155975 break; 14355256Slh155975 } 14365256Slh155975 /* Wait 1 ms */ 14375256Slh155975 drv_usecwait(1000); 14385256Slh155975 } 14395256Slh155975 adapter->pOdl->statistics.tx_draintime = i; 14405256Slh155975 } 14415256Slh155975 14425256Slh155975 /* 14435256Slh155975 * (GLD Entry Point) To start card will be called at 14445256Slh155975 * ifconfig plumb 14455256Slh155975 */ 14465256Slh155975 static int 14475256Slh155975 amd8111s_m_start(void *arg) 14485256Slh155975 { 14495256Slh155975 struct LayerPointers *pLayerPointers = arg; 14505256Slh155975 struct odl *pOdl = pLayerPointers->pOdl; 14515256Slh155975 14525256Slh155975 amd8111s_sw_reset(pLayerPointers); 14535256Slh155975 mdlHWReset(pLayerPointers); 14545256Slh155975 rw_enter(&pOdl->chip_lock, RW_WRITER); 14555256Slh155975 pLayerPointers->run = B_TRUE; 14565256Slh155975 rw_exit(&pOdl->chip_lock); 14575256Slh155975 return (0); 14585256Slh155975 } 14595256Slh155975 14605256Slh155975 /* 14615256Slh155975 * (GLD Entry Point) To stop card will be called at 14625256Slh155975 * ifconfig unplumb 14635256Slh155975 */ 14645256Slh155975 static void 14655256Slh155975 amd8111s_m_stop(void *arg) 14665256Slh155975 { 14675256Slh155975 struct LayerPointers *pLayerPointers = (struct LayerPointers *)arg; 14685256Slh155975 struct odl *pOdl = pLayerPointers->pOdl; 14695256Slh155975 14705256Slh155975 /* Ensure send all pending tx packets */ 14715256Slh155975 amd8111s_tx_drain(pLayerPointers); 14725256Slh155975 /* 14735256Slh155975 * Stop the controller and disable the controller interrupt 14745256Slh155975 */ 14755256Slh155975 rw_enter(&pOdl->chip_lock, RW_WRITER); 14765256Slh155975 mdlStopChip(pLayerPointers); 14775256Slh155975 pLayerPointers->run = B_FALSE; 14785256Slh155975 rw_exit(&pOdl->chip_lock); 14795256Slh155975 } 14805256Slh155975 14815256Slh155975 /* 14825256Slh155975 * To clean up all 14835256Slh155975 */ 14845256Slh155975 static void 14855256Slh155975 amd8111s_free_resource(struct LayerPointers *pLayerPointers) 14865256Slh155975 { 14875256Slh155975 unsigned long mem_free_array[100]; 14885256Slh155975 unsigned long *pmem_free_array, size; 14895256Slh155975 14905256Slh155975 /* Free Rx/Tx descriptors */ 14915256Slh155975 amd8111s_free_descriptors(pLayerPointers); 14925256Slh155975 14935256Slh155975 /* Free memory on lower layers */ 14945256Slh155975 milFreeResources(pLayerPointers, mem_free_array); 14955256Slh155975 pmem_free_array = mem_free_array; 14965256Slh155975 while (*pmem_free_array) { 14975256Slh155975 switch (*pmem_free_array) { 14985256Slh155975 case VIRTUAL: 14995256Slh155975 size = *(++pmem_free_array); 15005256Slh155975 pmem_free_array++; 15015256Slh155975 kmem_free((void *)*(pmem_free_array), size); 15025256Slh155975 break; 15035256Slh155975 } 15045256Slh155975 pmem_free_array++; 15055256Slh155975 } 15065256Slh155975 15075256Slh155975 amd8111s_free_buffers(pLayerPointers); 15085256Slh155975 } 15095256Slh155975 15105256Slh155975 /* 15115256Slh155975 * (GLD Enty pointer) To add/delete multi cast addresses 15125256Slh155975 * 15135256Slh155975 */ 15145256Slh155975 static int 15155256Slh155975 amd8111s_m_multicst(void *arg, boolean_t add, const uint8_t *addr) 15165256Slh155975 { 15175256Slh155975 struct LayerPointers *pLayerPointers = arg; 15185256Slh155975 15195256Slh155975 if (add) { 15205256Slh155975 /* Add a multicast entry */ 15215256Slh155975 mdlAddMulticastAddress(pLayerPointers, (UCHAR *)addr); 15225256Slh155975 } else { 15235256Slh155975 /* Delete a multicast entry */ 15245256Slh155975 mdlDeleteMulticastAddress(pLayerPointers, (UCHAR *)addr); 15255256Slh155975 } 15265256Slh155975 15275256Slh155975 return (0); 15285256Slh155975 } 15295256Slh155975 15305256Slh155975 #ifdef AMD8111S_DEBUG 15315256Slh155975 /* 15325256Slh155975 * The size of MIB registers is only 32 bits. Dump them before one 15335256Slh155975 * of them overflows. 15345256Slh155975 */ 15355256Slh155975 static void 15365256Slh155975 amd8111s_dump_mib(struct LayerPointers *pLayerPointers) 15375256Slh155975 { 15385256Slh155975 struct amd8111s_statistics *adapterStat; 15395256Slh155975 15405256Slh155975 adapterStat = &pLayerPointers->pOdl->statistics; 15415256Slh155975 15425256Slh155975 adapterStat->mib_dump_counter ++; 15435256Slh155975 15445256Slh155975 /* 15455256Slh155975 * Rx Counters 15465256Slh155975 */ 15475256Slh155975 adapterStat->rx_mib_unicst_packets += 15485256Slh155975 mdlReadMib(pLayerPointers, RcvUniCastPkts); 15495256Slh155975 adapterStat->rx_mib_multicst_packets += 15505256Slh155975 mdlReadMib(pLayerPointers, RcvMultiCastPkts); 15515256Slh155975 adapterStat->rx_mib_broadcst_packets += 15525256Slh155975 mdlReadMib(pLayerPointers, RcvBroadCastPkts); 15535256Slh155975 adapterStat->rx_mib_macctrl_packets += 15545256Slh155975 mdlReadMib(pLayerPointers, RcvMACCtrl); 15555256Slh155975 adapterStat->rx_mib_flowctrl_packets += 15565256Slh155975 mdlReadMib(pLayerPointers, RcvFlowCtrl); 15575256Slh155975 15585256Slh155975 adapterStat->rx_mib_bytes += 15595256Slh155975 mdlReadMib(pLayerPointers, RcvOctets); 15605256Slh155975 adapterStat->rx_mib_good_bytes += 15615256Slh155975 mdlReadMib(pLayerPointers, RcvGoodOctets); 15625256Slh155975 15635256Slh155975 adapterStat->rx_mib_undersize_packets += 15645256Slh155975 mdlReadMib(pLayerPointers, RcvUndersizePkts); 15655256Slh155975 adapterStat->rx_mib_oversize_packets += 15665256Slh155975 mdlReadMib(pLayerPointers, RcvOversizePkts); 15675256Slh155975 15685256Slh155975 adapterStat->rx_mib_drop_packets += 15695256Slh155975 mdlReadMib(pLayerPointers, RcvDropPktsRing0); 15705256Slh155975 adapterStat->rx_mib_align_err_packets += 15715256Slh155975 mdlReadMib(pLayerPointers, RcvAlignmentErrors); 15725256Slh155975 adapterStat->rx_mib_fcs_err_packets += 15735256Slh155975 mdlReadMib(pLayerPointers, RcvFCSErrors); 15745256Slh155975 adapterStat->rx_mib_symbol_err_packets += 15755256Slh155975 mdlReadMib(pLayerPointers, RcvSymbolErrors); 15765256Slh155975 adapterStat->rx_mib_miss_packets += 15775256Slh155975 mdlReadMib(pLayerPointers, RcvMissPkts); 15785256Slh155975 15795256Slh155975 /* 15805256Slh155975 * Tx Counters 15815256Slh155975 */ 15825256Slh155975 adapterStat->tx_mib_packets += 15835256Slh155975 mdlReadMib(pLayerPointers, XmtPackets); 15845256Slh155975 adapterStat->tx_mib_multicst_packets += 15855256Slh155975 mdlReadMib(pLayerPointers, XmtMultiCastPkts); 15865256Slh155975 adapterStat->tx_mib_broadcst_packets += 15875256Slh155975 mdlReadMib(pLayerPointers, XmtBroadCastPkts); 15885256Slh155975 adapterStat->tx_mib_flowctrl_packets += 15895256Slh155975 mdlReadMib(pLayerPointers, XmtFlowCtrl); 15905256Slh155975 15915256Slh155975 adapterStat->tx_mib_bytes += 15925256Slh155975 mdlReadMib(pLayerPointers, XmtOctets); 15935256Slh155975 15945256Slh155975 adapterStat->tx_mib_defer_trans_packets += 15955256Slh155975 mdlReadMib(pLayerPointers, XmtDeferredTransmit); 15965256Slh155975 adapterStat->tx_mib_collision_packets += 15975256Slh155975 mdlReadMib(pLayerPointers, XmtCollisions); 15985256Slh155975 adapterStat->tx_mib_one_coll_packets += 15995256Slh155975 mdlReadMib(pLayerPointers, XmtOneCollision); 16005256Slh155975 adapterStat->tx_mib_multi_coll_packets += 16015256Slh155975 mdlReadMib(pLayerPointers, XmtMultipleCollision); 16025256Slh155975 adapterStat->tx_mib_late_coll_packets += 16035256Slh155975 mdlReadMib(pLayerPointers, XmtLateCollision); 16045256Slh155975 adapterStat->tx_mib_ex_coll_packets += 16055256Slh155975 mdlReadMib(pLayerPointers, XmtExcessiveCollision); 16065256Slh155975 16075256Slh155975 16085256Slh155975 /* Clear all MIB registers */ 16095256Slh155975 WRITE_REG16(pLayerPointers, pLayerPointers->pMdl->Mem_Address 16105256Slh155975 + MIB_ADDR, MIB_CLEAR); 16115256Slh155975 } 16125256Slh155975 #endif 16135256Slh155975 16145256Slh155975 /* 16155256Slh155975 * (GLD Entry Point) set/unset promiscus mode 16165256Slh155975 */ 16175256Slh155975 static int 16185256Slh155975 amd8111s_m_promisc(void *arg, boolean_t on) 16195256Slh155975 { 16205256Slh155975 struct LayerPointers *pLayerPointers = arg; 16215256Slh155975 16225256Slh155975 if (on) { 16235256Slh155975 mdlSetPromiscuous(pLayerPointers); 16245256Slh155975 } else { 16255256Slh155975 mdlDisablePromiscuous(pLayerPointers); 16265256Slh155975 } 16275256Slh155975 16285256Slh155975 return (0); 16295256Slh155975 } 16305256Slh155975 16315256Slh155975 /* 16325256Slh155975 * (Gld Entry point) Changes the Mac address of card 16335256Slh155975 */ 16345256Slh155975 static int 16355256Slh155975 amd8111s_m_unicst(void *arg, const uint8_t *macaddr) 16365256Slh155975 { 16375256Slh155975 struct LayerPointers *pLayerPointers = arg; 16385256Slh155975 16395256Slh155975 mdlDisableInterrupt(pLayerPointers); 16405256Slh155975 mdlSetMacAddress(pLayerPointers, (unsigned char *)macaddr); 16415256Slh155975 mdlEnableInterrupt(pLayerPointers); 16425256Slh155975 16435256Slh155975 return (0); 16445256Slh155975 } 16455256Slh155975 16465256Slh155975 /* 16475256Slh155975 * Reset the card 16485256Slh155975 */ 16495256Slh155975 void 16505256Slh155975 amd8111s_reset(struct LayerPointers *pLayerPointers) 16515256Slh155975 { 16525256Slh155975 amd8111s_sw_reset(pLayerPointers); 16535256Slh155975 mdlHWReset(pLayerPointers); 16545256Slh155975 } 16555256Slh155975 16565256Slh155975 /* 16575256Slh155975 * attach(9E) -- Attach a device to the system 16585256Slh155975 * 16595256Slh155975 * Called once for each board after successfully probed. 16605256Slh155975 * will do 16615256Slh155975 * a. creating minor device node for the instance. 16625256Slh155975 * b. allocate & Initilize four layers (call odlInit) 16635256Slh155975 * c. get MAC address 16645256Slh155975 * d. initilize pLayerPointers to gld private pointer 16655256Slh155975 * e. register with GLD 16665256Slh155975 * if any action fails does clean up & returns DDI_FAILURE 16675256Slh155975 * else retursn DDI_SUCCESS 16685256Slh155975 */ 16695256Slh155975 static int 16705256Slh155975 amd8111s_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) 16715256Slh155975 { 16725256Slh155975 mac_register_t *macp; 16735256Slh155975 struct LayerPointers *pLayerPointers; 16745256Slh155975 struct odl *pOdl; 16755256Slh155975 ddi_acc_handle_t *pci_handle; 16765256Slh155975 ddi_device_acc_attr_t dev_attr; 16775256Slh155975 caddr_t addrp = NULL; 16785256Slh155975 16795256Slh155975 switch (cmd) { 16805256Slh155975 case DDI_ATTACH: 16815256Slh155975 break; 16825256Slh155975 default: 16835256Slh155975 return (DDI_FAILURE); 16845256Slh155975 } 16855256Slh155975 16865256Slh155975 pLayerPointers = (struct LayerPointers *) 16875256Slh155975 kmem_zalloc(sizeof (struct LayerPointers), KM_SLEEP); 16885256Slh155975 amd8111sadapter = pLayerPointers; 16895256Slh155975 16905256Slh155975 /* Get device instance number */ 16915256Slh155975 pLayerPointers->instance = ddi_get_instance(devinfo); 16925256Slh155975 ddi_set_driver_private(devinfo, (caddr_t)pLayerPointers); 16935256Slh155975 16945256Slh155975 pOdl = (struct odl *)kmem_zalloc(sizeof (struct odl), KM_SLEEP); 16955256Slh155975 pLayerPointers->pOdl = pOdl; 16965256Slh155975 16975256Slh155975 pOdl->devinfo = devinfo; 16985256Slh155975 16995256Slh155975 /* 17005256Slh155975 * Here, we only allocate memory for struct odl and initilize it. 17015256Slh155975 * All other memory allocation & initilization will be done in odlInit 17025256Slh155975 * later on this routine. 17035256Slh155975 */ 17045256Slh155975 if (ddi_get_iblock_cookie(devinfo, 0, &pLayerPointers->pOdl->iblock) 17055256Slh155975 != DDI_SUCCESS) { 17065256Slh155975 amd8111s_log(pLayerPointers, CE_NOTE, 17075256Slh155975 "attach: get iblock cookies failed"); 17085256Slh155975 goto attach_failure; 17095256Slh155975 } 17105256Slh155975 17115256Slh155975 rw_init(&pOdl->chip_lock, NULL, RW_DRIVER, (void *)pOdl->iblock); 17125256Slh155975 mutex_init(&pOdl->mdlSendLock, "amd8111s Send Protection Lock", 17135256Slh155975 MUTEX_DRIVER, (void *)pOdl->iblock); 17145256Slh155975 mutex_init(&pOdl->mdlRcvLock, "amd8111s Rcv Protection Lock", 17155256Slh155975 MUTEX_DRIVER, (void *)pOdl->iblock); 17165256Slh155975 17175256Slh155975 /* Setup PCI space */ 17185256Slh155975 if (pci_config_setup(devinfo, &pOdl->pci_handle) != DDI_SUCCESS) { 17195256Slh155975 return (DDI_FAILURE); 17205256Slh155975 } 17215256Slh155975 pLayerPointers->attach_progress = AMD8111S_ATTACH_PCI; 17225256Slh155975 pci_handle = &pOdl->pci_handle; 17235256Slh155975 17245256Slh155975 pOdl->vendor_id = pci_config_get16(*pci_handle, PCI_CONF_VENID); 17255256Slh155975 pOdl->device_id = pci_config_get16(*pci_handle, PCI_CONF_DEVID); 17265256Slh155975 17275256Slh155975 /* 17285256Slh155975 * Allocate and initialize all resource and map device registers. 17295256Slh155975 * If failed, it returns a non-zero value. 17305256Slh155975 */ 17315256Slh155975 if (amd8111s_odlInit(pLayerPointers) != 0) { 17325256Slh155975 goto attach_failure; 17335256Slh155975 } 17345256Slh155975 pLayerPointers->attach_progress |= AMD8111S_ATTACH_RESOURCE; 17355256Slh155975 17365256Slh155975 dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 17375256Slh155975 dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; 17385256Slh155975 dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 17395256Slh155975 17405256Slh155975 if (ddi_regs_map_setup(devinfo, 1, &addrp, 0, 4096, &dev_attr, 17415256Slh155975 &(pLayerPointers->pOdl->MemBasehandle)) != 0) { 17425256Slh155975 amd8111s_log(pLayerPointers, CE_NOTE, 17435256Slh155975 "attach: ddi_regs_map_setup failed"); 17445256Slh155975 goto attach_failure; 17455256Slh155975 } 17465256Slh155975 pLayerPointers->pMdl->Mem_Address = (unsigned long)addrp; 17475256Slh155975 17485256Slh155975 /* Initialize HW */ 17495256Slh155975 mdlOpen(pLayerPointers); 17505256Slh155975 mdlGetActiveMediaInfo(pLayerPointers); 17515256Slh155975 pLayerPointers->attach_progress |= AMD8111S_ATTACH_REGS; 17525256Slh155975 17535256Slh155975 /* 17545256Slh155975 * Setup the interrupt 17555256Slh155975 */ 17565256Slh155975 if (ddi_add_intr(devinfo, 0, &pOdl->iblock, 0, amd8111s_intr, 17575256Slh155975 (caddr_t)pLayerPointers) != DDI_SUCCESS) { 17585256Slh155975 goto attach_failure; 17595256Slh155975 } 17605256Slh155975 pLayerPointers->attach_progress |= AMD8111S_ATTACH_INTRADDED; 17615256Slh155975 17625256Slh155975 /* 17635256Slh155975 * Setup soft intr 17645256Slh155975 */ 17655256Slh155975 if (ddi_add_softintr(devinfo, DDI_SOFTINT_LOW, &pOdl->drain_id, 17665256Slh155975 NULL, NULL, amd8111s_send_drain, 17675256Slh155975 (caddr_t)pLayerPointers) != DDI_SUCCESS) { 17685256Slh155975 goto attach_failure; 17695256Slh155975 } 17705256Slh155975 pLayerPointers->attach_progress |= AMD8111S_ATTACH_RESCHED; 17715256Slh155975 17725256Slh155975 /* 17735256Slh155975 * Initilize the mac structure 17745256Slh155975 */ 17755256Slh155975 if ((macp = mac_alloc(MAC_VERSION)) == NULL) 17765256Slh155975 goto attach_failure; 17775256Slh155975 17785256Slh155975 macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 17795256Slh155975 macp->m_driver = pLayerPointers; 17805256Slh155975 macp->m_dip = devinfo; 17815256Slh155975 /* Get MAC address */ 17825256Slh155975 mdlGetMacAddress(pLayerPointers, (unsigned char *)pOdl->MacAddress); 17835256Slh155975 macp->m_src_addr = pOdl->MacAddress; 17845256Slh155975 macp->m_callbacks = &amd8111s_m_callbacks; 17855256Slh155975 macp->m_min_sdu = 0; 17865256Slh155975 /* 1518 - 14 (ether header) - 4 (CRC) */ 17875256Slh155975 macp->m_max_sdu = ETHERMTU; 17885895Syz147064 macp->m_margin = VLAN_TAGSZ; 17895256Slh155975 17905256Slh155975 /* 17915256Slh155975 * Finally, we're ready to register ourselves with the MAC layer 17925256Slh155975 * interface; if this succeeds, we're ready to start. 17935256Slh155975 */ 17945256Slh155975 if (mac_register(macp, &pOdl->mh) != DDI_SUCCESS) { 17955256Slh155975 mac_free(macp); 17965256Slh155975 goto attach_failure; 17975256Slh155975 } 17985256Slh155975 mac_free(macp); 17995256Slh155975 18005256Slh155975 pLayerPointers->attach_progress |= AMD8111S_ATTACH_MACREGED; 18015256Slh155975 18025256Slh155975 return (DDI_SUCCESS); 18035256Slh155975 18045256Slh155975 attach_failure: 18055256Slh155975 (void) amd8111s_unattach(devinfo, pLayerPointers); 18065256Slh155975 return (DDI_FAILURE); 18075256Slh155975 18085256Slh155975 } 18095256Slh155975 18105256Slh155975 /* 18115256Slh155975 * detach(9E) -- Detach a device from the system 18125256Slh155975 * 18135256Slh155975 * It is called for each device instance when the system is preparing to 18145256Slh155975 * unload a dynamically unloadable driver. 18155256Slh155975 * will Do 18165256Slh155975 * a. check if any driver buffers are held by OS. 18175256Slh155975 * b. do clean up of all allocated memory if it is not in use by OS. 18185256Slh155975 * c. un register with GLD 18195256Slh155975 * d. return DDI_SUCCESS on succes full free & unregister 18205256Slh155975 * else GLD_FAILURE 18215256Slh155975 */ 18225256Slh155975 static int 18235256Slh155975 amd8111s_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) 18245256Slh155975 { 18255256Slh155975 struct LayerPointers *pLayerPointers; 18265256Slh155975 18275256Slh155975 switch (cmd) { 18285256Slh155975 case DDI_DETACH: 18295256Slh155975 break; 18305256Slh155975 default: 18315256Slh155975 return (DDI_FAILURE); 18325256Slh155975 } 18335256Slh155975 18345256Slh155975 /* 18355256Slh155975 * Get the driver private (struct LayerPointers *) structure 18365256Slh155975 */ 18375256Slh155975 if ((pLayerPointers = (struct LayerPointers *)ddi_get_driver_private 18385256Slh155975 (devinfo)) == NULL) { 18395256Slh155975 return (DDI_FAILURE); 18405256Slh155975 } 18415256Slh155975 18425256Slh155975 return (amd8111s_unattach(devinfo, pLayerPointers)); 18435256Slh155975 } 18445256Slh155975 18455256Slh155975 static int 18465256Slh155975 amd8111s_unattach(dev_info_t *devinfo, struct LayerPointers *pLayerPointers) 18475256Slh155975 { 18485256Slh155975 struct odl *pOdl = pLayerPointers->pOdl; 18495256Slh155975 18505256Slh155975 if (pLayerPointers->attach_progress & AMD8111S_ATTACH_MACREGED) { 18515256Slh155975 /* Unregister driver from the GLD interface */ 18525256Slh155975 if (mac_unregister(pOdl->mh) != DDI_SUCCESS) { 18535256Slh155975 return (DDI_FAILURE); 18545256Slh155975 } 18555256Slh155975 } 18565256Slh155975 18575256Slh155975 if (pLayerPointers->attach_progress & AMD8111S_ATTACH_INTRADDED) { 18585256Slh155975 ddi_remove_intr(devinfo, 0, pOdl->iblock); 18595256Slh155975 } 18605256Slh155975 18615256Slh155975 if (pLayerPointers->attach_progress & AMD8111S_ATTACH_RESCHED) { 18625256Slh155975 ddi_remove_softintr(pOdl->drain_id); 18635256Slh155975 } 18645256Slh155975 18655256Slh155975 if (pLayerPointers->attach_progress & AMD8111S_ATTACH_REGS) { 18665256Slh155975 /* Stop HW */ 18675256Slh155975 mdlStopChip(pLayerPointers); 18685256Slh155975 ddi_regs_map_free(&(pOdl->MemBasehandle)); 18695256Slh155975 } 18705256Slh155975 18715256Slh155975 if (pLayerPointers->attach_progress & AMD8111S_ATTACH_RESOURCE) { 18725256Slh155975 /* Free All memory allocated */ 18735256Slh155975 amd8111s_free_resource(pLayerPointers); 18745256Slh155975 } 18755256Slh155975 18765256Slh155975 if (pLayerPointers->attach_progress & AMD8111S_ATTACH_PCI) { 18775256Slh155975 pci_config_teardown(&pOdl->pci_handle); 18785256Slh155975 mutex_destroy(&pOdl->mdlSendLock); 18795256Slh155975 mutex_destroy(&pOdl->mdlRcvLock); 18805256Slh155975 rw_destroy(&pOdl->chip_lock); 18815256Slh155975 } 18825256Slh155975 18835256Slh155975 kmem_free(pOdl, sizeof (struct odl)); 18845256Slh155975 kmem_free(pLayerPointers, sizeof (struct LayerPointers)); 18855256Slh155975 18865256Slh155975 return (DDI_SUCCESS); 18875256Slh155975 } 18885256Slh155975 18895256Slh155975 /* 18905256Slh155975 * (GLD Entry Point)GLD will call this entry point perodicaly to 18915256Slh155975 * get driver statistices. 18925256Slh155975 */ 18935256Slh155975 static int 18945256Slh155975 amd8111s_m_stat(void *arg, uint_t stat, uint64_t *val) 18955256Slh155975 { 18965256Slh155975 struct LayerPointers *pLayerPointers = arg; 18975256Slh155975 struct amd8111s_statistics *adapterStat; 18985256Slh155975 18995256Slh155975 adapterStat = &pLayerPointers->pOdl->statistics; 19005256Slh155975 19015256Slh155975 switch (stat) { 19025256Slh155975 19035256Slh155975 /* 19045256Slh155975 * Current Status 19055256Slh155975 */ 19065256Slh155975 case MAC_STAT_IFSPEED: 19075256Slh155975 *val = pLayerPointers->pMdl->Speed * 1000000; 19085256Slh155975 break; 19095256Slh155975 19105256Slh155975 case ETHER_STAT_LINK_DUPLEX: 19115256Slh155975 if (pLayerPointers->pMdl->FullDuplex) { 19125256Slh155975 *val = LINK_DUPLEX_FULL; 19135256Slh155975 } else { 19145256Slh155975 *val = LINK_DUPLEX_HALF; 19155256Slh155975 } 19165256Slh155975 break; 19175256Slh155975 19185256Slh155975 /* 19195256Slh155975 * Capabilities 19205256Slh155975 */ 19215256Slh155975 case ETHER_STAT_CAP_1000FDX: 19225256Slh155975 *val = 0; 19235256Slh155975 break; 19245256Slh155975 19255256Slh155975 case ETHER_STAT_CAP_1000HDX: 19265256Slh155975 *val = 0; 19275256Slh155975 break; 19285256Slh155975 19295256Slh155975 case ETHER_STAT_CAP_100FDX: 19305256Slh155975 *val = 1; 19315256Slh155975 break; 19325256Slh155975 19335256Slh155975 case ETHER_STAT_CAP_100HDX: 19345256Slh155975 *val = 1; 19355256Slh155975 break; 19365256Slh155975 19375256Slh155975 case ETHER_STAT_CAP_10FDX: 19385256Slh155975 *val = 1; 19395256Slh155975 break; 19405256Slh155975 19415256Slh155975 case ETHER_STAT_CAP_10HDX: 19425256Slh155975 *val = 1; 19435256Slh155975 break; 19445256Slh155975 19455256Slh155975 case ETHER_STAT_CAP_ASMPAUSE: 19465256Slh155975 *val = 1; 19475256Slh155975 break; 19485256Slh155975 19495256Slh155975 case ETHER_STAT_CAP_PAUSE: 19505256Slh155975 *val = 1; 19515256Slh155975 break; 19525256Slh155975 19535256Slh155975 case ETHER_STAT_CAP_AUTONEG: 19545256Slh155975 *val = 1; 19555256Slh155975 break; 19565256Slh155975 19575256Slh155975 case ETHER_STAT_ADV_CAP_1000FDX: 19585256Slh155975 *val = 0; 19595256Slh155975 break; 19605256Slh155975 19615256Slh155975 case ETHER_STAT_ADV_CAP_1000HDX: 19625256Slh155975 *val = 0; 19635256Slh155975 break; 19645256Slh155975 19655256Slh155975 case ETHER_STAT_ADV_CAP_100FDX: 19665256Slh155975 *val = 1; 19675256Slh155975 break; 19685256Slh155975 19695256Slh155975 case ETHER_STAT_ADV_CAP_100HDX: 19705256Slh155975 *val = 1; 19715256Slh155975 break; 19725256Slh155975 19735256Slh155975 case ETHER_STAT_ADV_CAP_10FDX: 19745256Slh155975 *val = 1; 19755256Slh155975 break; 19765256Slh155975 19775256Slh155975 case ETHER_STAT_ADV_CAP_10HDX: 19785256Slh155975 *val = 1; 19795256Slh155975 break; 19805256Slh155975 19815256Slh155975 case ETHER_STAT_ADV_CAP_ASMPAUSE: 19825256Slh155975 *val = 1; 19835256Slh155975 break; 19845256Slh155975 19855256Slh155975 case ETHER_STAT_ADV_CAP_PAUSE: 19865256Slh155975 *val = 1; 19875256Slh155975 break; 19885256Slh155975 19895256Slh155975 case ETHER_STAT_ADV_CAP_AUTONEG: 19905256Slh155975 *val = 1; 19915256Slh155975 break; 19925256Slh155975 19935256Slh155975 /* 19945256Slh155975 * Rx Counters 19955256Slh155975 */ 19965256Slh155975 case MAC_STAT_IPACKETS: 19975256Slh155975 *val = adapterStat->rx_mib_unicst_packets + 19985256Slh155975 adapterStat->rx_mib_multicst_packets + 19995256Slh155975 adapterStat->rx_mib_broadcst_packets + 20005256Slh155975 mdlReadMib(pLayerPointers, RcvUniCastPkts) + 20015256Slh155975 mdlReadMib(pLayerPointers, RcvMultiCastPkts) + 20025256Slh155975 mdlReadMib(pLayerPointers, RcvBroadCastPkts); 20035256Slh155975 break; 20045256Slh155975 20055256Slh155975 case MAC_STAT_RBYTES: 20065256Slh155975 *val = adapterStat->rx_mib_bytes + 20075256Slh155975 mdlReadMib(pLayerPointers, RcvOctets); 20085256Slh155975 break; 20095256Slh155975 20105256Slh155975 case MAC_STAT_MULTIRCV: 20115256Slh155975 *val = adapterStat->rx_mib_multicst_packets + 20125256Slh155975 mdlReadMib(pLayerPointers, RcvMultiCastPkts); 20135256Slh155975 break; 20145256Slh155975 20155256Slh155975 case MAC_STAT_BRDCSTRCV: 20165256Slh155975 *val = adapterStat->rx_mib_broadcst_packets + 20175256Slh155975 mdlReadMib(pLayerPointers, RcvBroadCastPkts); 20185256Slh155975 break; 20195256Slh155975 20205256Slh155975 case MAC_STAT_NORCVBUF: 20215256Slh155975 *val = adapterStat->rx_allocfail + 20225256Slh155975 adapterStat->rx_mib_drop_packets + 20235256Slh155975 mdlReadMib(pLayerPointers, RcvDropPktsRing0); 20245256Slh155975 break; 20255256Slh155975 20265256Slh155975 case MAC_STAT_IERRORS: 20275256Slh155975 *val = adapterStat->rx_mib_align_err_packets + 20285256Slh155975 adapterStat->rx_mib_fcs_err_packets + 20295256Slh155975 adapterStat->rx_mib_symbol_err_packets + 20305256Slh155975 mdlReadMib(pLayerPointers, RcvAlignmentErrors) + 20315256Slh155975 mdlReadMib(pLayerPointers, RcvFCSErrors) + 20325256Slh155975 mdlReadMib(pLayerPointers, RcvSymbolErrors); 20335256Slh155975 break; 20345256Slh155975 20355256Slh155975 case ETHER_STAT_ALIGN_ERRORS: 20365256Slh155975 *val = adapterStat->rx_mib_align_err_packets + 20375256Slh155975 mdlReadMib(pLayerPointers, RcvAlignmentErrors); 20385256Slh155975 break; 20395256Slh155975 20405256Slh155975 case ETHER_STAT_FCS_ERRORS: 20415256Slh155975 *val = adapterStat->rx_mib_fcs_err_packets + 20425256Slh155975 mdlReadMib(pLayerPointers, RcvFCSErrors); 20435256Slh155975 break; 20445256Slh155975 20455256Slh155975 /* 20465256Slh155975 * Tx Counters 20475256Slh155975 */ 20485256Slh155975 case MAC_STAT_OPACKETS: 20495256Slh155975 *val = adapterStat->tx_mib_packets + 20505256Slh155975 mdlReadMib(pLayerPointers, XmtPackets); 20515256Slh155975 break; 20525256Slh155975 20535256Slh155975 case MAC_STAT_OBYTES: 20545256Slh155975 *val = adapterStat->tx_mib_bytes + 20555256Slh155975 mdlReadMib(pLayerPointers, XmtOctets); 20565256Slh155975 break; 20575256Slh155975 20585256Slh155975 case MAC_STAT_MULTIXMT: 20595256Slh155975 *val = adapterStat->tx_mib_multicst_packets + 20605256Slh155975 mdlReadMib(pLayerPointers, XmtMultiCastPkts); 20615256Slh155975 break; 20625256Slh155975 20635256Slh155975 case MAC_STAT_BRDCSTXMT: 20645256Slh155975 *val = adapterStat->tx_mib_broadcst_packets + 20655256Slh155975 mdlReadMib(pLayerPointers, XmtBroadCastPkts); 20665256Slh155975 break; 20675256Slh155975 20685256Slh155975 case MAC_STAT_NOXMTBUF: 20695256Slh155975 *val = adapterStat->tx_no_descriptor; 20705256Slh155975 break; 20715256Slh155975 20725256Slh155975 case MAC_STAT_OERRORS: 20735256Slh155975 *val = adapterStat->tx_mib_ex_coll_packets + 20745256Slh155975 mdlReadMib(pLayerPointers, XmtExcessiveCollision); 20755256Slh155975 break; 20765256Slh155975 20775256Slh155975 case MAC_STAT_COLLISIONS: 20785256Slh155975 *val = adapterStat->tx_mib_ex_coll_packets + 20795256Slh155975 mdlReadMib(pLayerPointers, XmtCollisions); 20805256Slh155975 break; 20815256Slh155975 20825256Slh155975 case ETHER_STAT_FIRST_COLLISIONS: 20835256Slh155975 *val = adapterStat->tx_mib_one_coll_packets + 20845256Slh155975 mdlReadMib(pLayerPointers, XmtOneCollision); 20855256Slh155975 break; 20865256Slh155975 20875256Slh155975 case ETHER_STAT_MULTI_COLLISIONS: 20885256Slh155975 *val = adapterStat->tx_mib_multi_coll_packets + 20895256Slh155975 mdlReadMib(pLayerPointers, XmtMultipleCollision); 20905256Slh155975 break; 20915256Slh155975 20925256Slh155975 case ETHER_STAT_EX_COLLISIONS: 20935256Slh155975 *val = adapterStat->tx_mib_ex_coll_packets + 20945256Slh155975 mdlReadMib(pLayerPointers, XmtExcessiveCollision); 20955256Slh155975 break; 20965256Slh155975 20975256Slh155975 case ETHER_STAT_TX_LATE_COLLISIONS: 20985256Slh155975 *val = adapterStat->tx_mib_late_coll_packets + 20995256Slh155975 mdlReadMib(pLayerPointers, XmtLateCollision); 21005256Slh155975 break; 21015256Slh155975 21025256Slh155975 case ETHER_STAT_DEFER_XMTS: 21035256Slh155975 *val = adapterStat->tx_mib_defer_trans_packets + 21045256Slh155975 mdlReadMib(pLayerPointers, XmtDeferredTransmit); 21055256Slh155975 break; 21065256Slh155975 21075256Slh155975 default: 21085256Slh155975 return (ENOTSUP); 21095256Slh155975 } 21105256Slh155975 return (0); 21115256Slh155975 } 21125256Slh155975 21135256Slh155975 /* 21145256Slh155975 * Memory Read Function Used by MDL to set card registers. 21155256Slh155975 */ 21165256Slh155975 unsigned char 21175256Slh155975 READ_REG8(struct LayerPointers *pLayerPointers, long x) 21185256Slh155975 { 21195256Slh155975 return (ddi_get8(pLayerPointers->pOdl->MemBasehandle, (uint8_t *)x)); 21205256Slh155975 } 21215256Slh155975 21225256Slh155975 int 21235256Slh155975 READ_REG16(struct LayerPointers *pLayerPointers, long x) 21245256Slh155975 { 21255256Slh155975 return (ddi_get16(pLayerPointers->pOdl->MemBasehandle, 21265256Slh155975 (uint16_t *)(x))); 21275256Slh155975 } 21285256Slh155975 21295256Slh155975 long 21305256Slh155975 READ_REG32(struct LayerPointers *pLayerPointers, long x) 21315256Slh155975 { 21325256Slh155975 return (ddi_get32(pLayerPointers->pOdl->MemBasehandle, 21335256Slh155975 (uint32_t *)(x))); 21345256Slh155975 } 21355256Slh155975 21365256Slh155975 void 21375256Slh155975 WRITE_REG8(struct LayerPointers *pLayerPointers, long x, int y) 21385256Slh155975 { 21395256Slh155975 ddi_put8(pLayerPointers->pOdl->MemBasehandle, (uint8_t *)(x), y); 21405256Slh155975 } 21415256Slh155975 21425256Slh155975 void 21435256Slh155975 WRITE_REG16(struct LayerPointers *pLayerPointers, long x, int y) 21445256Slh155975 { 21455256Slh155975 ddi_put16(pLayerPointers->pOdl->MemBasehandle, (uint16_t *)(x), y); 21465256Slh155975 } 21475256Slh155975 21485256Slh155975 void 21495256Slh155975 WRITE_REG32(struct LayerPointers *pLayerPointers, long x, int y) 21505256Slh155975 { 21515256Slh155975 ddi_put32(pLayerPointers->pOdl->MemBasehandle, (uint32_t *)(x), y); 21525256Slh155975 } 21535256Slh155975 21545256Slh155975 void 21555256Slh155975 WRITE_REG64(struct LayerPointers *pLayerPointers, long x, char *y) 21565256Slh155975 { 21575256Slh155975 int i; 21585256Slh155975 for (i = 0; i < 8; i++) { 21595256Slh155975 WRITE_REG8(pLayerPointers, (x + i), y[i]); 21605256Slh155975 } 21615256Slh155975 } 2162