1015a6ef6SSaurabh Misra /* 2015a6ef6SSaurabh Misra * CDDL HEADER START 3015a6ef6SSaurabh Misra * 4015a6ef6SSaurabh Misra * The contents of this file are subject to the terms of the 5015a6ef6SSaurabh Misra * Common Development and Distribution License (the "License"). 6015a6ef6SSaurabh Misra * You may not use this file except in compliance with the License. 7015a6ef6SSaurabh Misra * 8015a6ef6SSaurabh Misra * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9015a6ef6SSaurabh Misra * or http://www.opensolaris.org/os/licensing. 10015a6ef6SSaurabh Misra * See the License for the specific language governing permissions 11015a6ef6SSaurabh Misra * and limitations under the License. 12015a6ef6SSaurabh Misra * 13015a6ef6SSaurabh Misra * When distributing Covered Code, include this CDDL HEADER in each 14015a6ef6SSaurabh Misra * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15015a6ef6SSaurabh Misra * If applicable, add the following below this CDDL HEADER, with the 16015a6ef6SSaurabh Misra * fields enclosed by brackets "[]" replaced with your own identifying 17015a6ef6SSaurabh Misra * information: Portions Copyright [yyyy] [name of copyright owner] 18015a6ef6SSaurabh Misra * 19015a6ef6SSaurabh Misra * CDDL HEADER END 20015a6ef6SSaurabh Misra */ 21015a6ef6SSaurabh Misra 22015a6ef6SSaurabh Misra /* 23*5e8715b9SGary Mills * Copyright (c) 2012 Gary Mills 24*5e8715b9SGary Mills * 259d8d9e11SGarrett D'Amore * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 26015a6ef6SSaurabh Misra */ 27*5e8715b9SGary Mills /* 28*5e8715b9SGary Mills * Copyright (c) 2009, Pyun YongHyeon <yongari@FreeBSD.org> 29*5e8715b9SGary Mills * All rights reserved. 30*5e8715b9SGary Mills * 31*5e8715b9SGary Mills * Redistribution and use in source and binary forms, with or without 32*5e8715b9SGary Mills * modification, are permitted provided that the following conditions 33*5e8715b9SGary Mills * are met: 34*5e8715b9SGary Mills * 1. Redistributions of source code must retain the above copyright 35*5e8715b9SGary Mills * notice unmodified, this list of conditions, and the following 36*5e8715b9SGary Mills * disclaimer. 37*5e8715b9SGary Mills * 2. Redistributions in binary form must reproduce the above copyright 38*5e8715b9SGary Mills * notice, this list of conditions and the following disclaimer in the 39*5e8715b9SGary Mills * documentation and/or other materials provided with the distribution. 40*5e8715b9SGary Mills * 41*5e8715b9SGary Mills * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 42*5e8715b9SGary Mills * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43*5e8715b9SGary Mills * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44*5e8715b9SGary Mills * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45*5e8715b9SGary Mills * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46*5e8715b9SGary Mills * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47*5e8715b9SGary Mills * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48*5e8715b9SGary Mills * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49*5e8715b9SGary Mills * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50*5e8715b9SGary Mills * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51*5e8715b9SGary Mills * SUCH DAMAGE. 52*5e8715b9SGary Mills */ 53015a6ef6SSaurabh Misra 54015a6ef6SSaurabh Misra #include <sys/types.h> 55015a6ef6SSaurabh Misra #include <sys/stream.h> 56015a6ef6SSaurabh Misra #include <sys/strsun.h> 57015a6ef6SSaurabh Misra #include <sys/stat.h> 58015a6ef6SSaurabh Misra #include <sys/modctl.h> 59015a6ef6SSaurabh Misra #include <sys/kstat.h> 60015a6ef6SSaurabh Misra #include <sys/ethernet.h> 61015a6ef6SSaurabh Misra #include <sys/devops.h> 62015a6ef6SSaurabh Misra #include <sys/debug.h> 63015a6ef6SSaurabh Misra #include <sys/conf.h> 64015a6ef6SSaurabh Misra #include <sys/mii.h> 65015a6ef6SSaurabh Misra #include <sys/miiregs.h> 66015a6ef6SSaurabh Misra #include <sys/mac.h> 67015a6ef6SSaurabh Misra #include <sys/mac_provider.h> 68015a6ef6SSaurabh Misra #include <sys/mac_ether.h> 69015a6ef6SSaurabh Misra #include <sys/sysmacros.h> 70015a6ef6SSaurabh Misra #include <sys/dditypes.h> 71015a6ef6SSaurabh Misra #include <sys/ddi.h> 72015a6ef6SSaurabh Misra #include <sys/sunddi.h> 73015a6ef6SSaurabh Misra #include <sys/byteorder.h> 74015a6ef6SSaurabh Misra #include <sys/note.h> 75015a6ef6SSaurabh Misra #include <sys/vlan.h> 76015a6ef6SSaurabh Misra #include <sys/strsubr.h> 77015a6ef6SSaurabh Misra #include <sys/crc32.h> 78015a6ef6SSaurabh Misra #include <sys/sdt.h> 79015a6ef6SSaurabh Misra #include <sys/pci.h> 80015a6ef6SSaurabh Misra #include <sys/pci_cap.h> 81015a6ef6SSaurabh Misra 82015a6ef6SSaurabh Misra #include "atge.h" 83015a6ef6SSaurabh Misra #include "atge_cmn_reg.h" 84*5e8715b9SGary Mills #include "atge_l1c_reg.h" 85015a6ef6SSaurabh Misra #include "atge_l1e_reg.h" 860eb090a7SSaurabh Misra #include "atge_l1_reg.h" 87015a6ef6SSaurabh Misra 88015a6ef6SSaurabh Misra 89015a6ef6SSaurabh Misra /* 90*5e8715b9SGary Mills * Atheros/Attansic Ethernet chips are of four types - L1, L2, L1E and L1C. 91*5e8715b9SGary Mills * This driver is for L1E/L1/L1C but can be extended to support other chips. 920eb090a7SSaurabh Misra * L1E comes in 1Gigabit and Fast Ethernet flavors. L1 comes in 1Gigabit 93*5e8715b9SGary Mills * flavors only. L1C comes in both flavours. 94015a6ef6SSaurabh Misra * 95015a6ef6SSaurabh Misra * Atheros/Attansic Ethernet controllers have descriptor based TX and RX 96015a6ef6SSaurabh Misra * with an exception of L1E. L1E's RX side is not descriptor based ring. 97015a6ef6SSaurabh Misra * The L1E's RX uses pages (not to be confused with MMU pages) for 98015a6ef6SSaurabh Misra * receiving pkts. The header has four fields : 99015a6ef6SSaurabh Misra * 100015a6ef6SSaurabh Misra * uint32_t seqno; Sequence number of the frame. 101015a6ef6SSaurabh Misra * uint32_t length; Length of the frame. 102015a6ef6SSaurabh Misra * uint32_t flags; Flags 103015a6ef6SSaurabh Misra * uint32_t vtag; We don't use hardware VTAG. 104015a6ef6SSaurabh Misra * 105015a6ef6SSaurabh Misra * We use only one queue for RX (each queue can have two pages) and each 106015a6ef6SSaurabh Misra * page is L1E_RX_PAGE_SZ large in bytes. That's the reason we don't 107015a6ef6SSaurabh Misra * use zero-copy RX because we are limited to two pages and each page 108015a6ef6SSaurabh Misra * accomodates large number of pkts. 109015a6ef6SSaurabh Misra * 110015a6ef6SSaurabh Misra * The TX side on all three chips is descriptor based ring; and all the 111015a6ef6SSaurabh Misra * more reason to have one driver for these chips. 112015a6ef6SSaurabh Misra * 113015a6ef6SSaurabh Misra * We use two locks - atge_intr_lock and atge_tx_lock. Both the locks 114015a6ef6SSaurabh Misra * should be held if the operation has impact on the driver instance. 115015a6ef6SSaurabh Misra * 116015a6ef6SSaurabh Misra * All the three chips have hash-based multicast filter. 117015a6ef6SSaurabh Misra * 118015a6ef6SSaurabh Misra * We use CMB (Coalescing Message Block) for RX but not for TX as there 119015a6ef6SSaurabh Misra * are some issues with TX. RX CMB is used to get the last descriptor 120015a6ef6SSaurabh Misra * posted by the chip. Each CMB is for a RX page (one queue can have two 121015a6ef6SSaurabh Misra * pages) and are uint32_t (4 bytes) long. 122015a6ef6SSaurabh Misra * 123015a6ef6SSaurabh Misra * The descriptor table should have 32-bit physical address limit due to 124015a6ef6SSaurabh Misra * the limitation of having same high address for TX/RX/SMB/CMB. The 125015a6ef6SSaurabh Misra * TX/RX buffers can be 64-bit. 126015a6ef6SSaurabh Misra * 127015a6ef6SSaurabh Misra * Every DMA memory in atge is represented by atge_dma_t be it TX/RX Buffers 128015a6ef6SSaurabh Misra * or TX/RX descriptor table or SMB/CMB. To keep the code simple, we have 129015a6ef6SSaurabh Misra * kept sgl as 1 so that we get contingous pages from root complex. 1300eb090a7SSaurabh Misra * 1310eb090a7SSaurabh Misra * L1 chip (0x1048) uses descriptor based TX and RX ring. Most of registers are 1320eb090a7SSaurabh Misra * common with L1E chip (0x1026). 133015a6ef6SSaurabh Misra */ 134015a6ef6SSaurabh Misra 135015a6ef6SSaurabh Misra /* 136015a6ef6SSaurabh Misra * Function Prototypes for debugging. 137015a6ef6SSaurabh Misra */ 138015a6ef6SSaurabh Misra void atge_error(dev_info_t *, char *, ...); 139015a6ef6SSaurabh Misra void atge_debug_func(char *, ...); 140015a6ef6SSaurabh Misra 141015a6ef6SSaurabh Misra /* 142015a6ef6SSaurabh Misra * Function Prototypes for driver operations. 143015a6ef6SSaurabh Misra */ 144015a6ef6SSaurabh Misra static int atge_resume(dev_info_t *); 145015a6ef6SSaurabh Misra static int atge_add_intr(atge_t *); 146015a6ef6SSaurabh Misra static int atge_alloc_dma(atge_t *); 147015a6ef6SSaurabh Misra static void atge_remove_intr(atge_t *); 148015a6ef6SSaurabh Misra static void atge_free_dma(atge_t *); 149015a6ef6SSaurabh Misra static void atge_device_reset(atge_t *); 150015a6ef6SSaurabh Misra static void atge_device_init(atge_t *); 151015a6ef6SSaurabh Misra static void atge_device_start(atge_t *); 152015a6ef6SSaurabh Misra static void atge_disable_intrs(atge_t *); 153015a6ef6SSaurabh Misra atge_dma_t *atge_alloc_a_dma_blk(atge_t *, ddi_dma_attr_t *, int, int); 154015a6ef6SSaurabh Misra void atge_free_a_dma_blk(atge_dma_t *); 155015a6ef6SSaurabh Misra static void atge_rxfilter(atge_t *); 156015a6ef6SSaurabh Misra static void atge_device_reset_l1_l1e(atge_t *); 157015a6ef6SSaurabh Misra void atge_program_ether(atge_t *atgep); 158015a6ef6SSaurabh Misra void atge_device_restart(atge_t *); 1590eb090a7SSaurabh Misra void atge_device_stop(atge_t *); 160015a6ef6SSaurabh Misra static int atge_send_a_packet(atge_t *, mblk_t *); 161015a6ef6SSaurabh Misra static uint32_t atge_ether_crc(const uint8_t *, int); 162015a6ef6SSaurabh Misra 163015a6ef6SSaurabh Misra 164015a6ef6SSaurabh Misra /* 1650eb090a7SSaurabh Misra * L1E/L2E specific functions. 166015a6ef6SSaurabh Misra */ 167015a6ef6SSaurabh Misra void atge_l1e_device_reset(atge_t *); 168015a6ef6SSaurabh Misra void atge_l1e_stop_mac(atge_t *); 169015a6ef6SSaurabh Misra int atge_l1e_alloc_dma(atge_t *); 170015a6ef6SSaurabh Misra void atge_l1e_free_dma(atge_t *); 171015a6ef6SSaurabh Misra void atge_l1e_init_tx_ring(atge_t *); 172015a6ef6SSaurabh Misra void atge_l1e_init_rx_pages(atge_t *); 173015a6ef6SSaurabh Misra void atge_l1e_program_dma(atge_t *); 1740eb090a7SSaurabh Misra void atge_l1e_send_packet(atge_ring_t *); 175015a6ef6SSaurabh Misra mblk_t *atge_l1e_receive(atge_t *); 1760eb090a7SSaurabh Misra uint_t atge_l1e_interrupt(caddr_t, caddr_t); 177015a6ef6SSaurabh Misra void atge_l1e_gather_stats(atge_t *); 178015a6ef6SSaurabh Misra void atge_l1e_clear_stats(atge_t *); 179015a6ef6SSaurabh Misra 180015a6ef6SSaurabh Misra /* 1810eb090a7SSaurabh Misra * L1 specific functions. 1820eb090a7SSaurabh Misra */ 1830eb090a7SSaurabh Misra int atge_l1_alloc_dma(atge_t *); 184*5e8715b9SGary Mills void atge_l1_free_dma(atge_t *); 1850eb090a7SSaurabh Misra void atge_l1_init_tx_ring(atge_t *); 1860eb090a7SSaurabh Misra void atge_l1_init_rx_ring(atge_t *); 1870eb090a7SSaurabh Misra void atge_l1_init_rr_ring(atge_t *); 1880eb090a7SSaurabh Misra void atge_l1_init_cmb(atge_t *); 1890eb090a7SSaurabh Misra void atge_l1_init_smb(atge_t *); 1900eb090a7SSaurabh Misra void atge_l1_program_dma(atge_t *); 1910eb090a7SSaurabh Misra void atge_l1_stop_tx_mac(atge_t *); 1920eb090a7SSaurabh Misra void atge_l1_stop_rx_mac(atge_t *); 1930eb090a7SSaurabh Misra uint_t atge_l1_interrupt(caddr_t, caddr_t); 1940eb090a7SSaurabh Misra void atge_l1_send_packet(atge_ring_t *); 1950eb090a7SSaurabh Misra 196*5e8715b9SGary Mills /* 197*5e8715b9SGary Mills * L1C specific functions. 198*5e8715b9SGary Mills */ 199*5e8715b9SGary Mills int atge_l1c_alloc_dma(atge_t *); 200*5e8715b9SGary Mills void atge_l1c_free_dma(atge_t *); 201*5e8715b9SGary Mills void atge_l1c_init_tx_ring(atge_t *); 202*5e8715b9SGary Mills void atge_l1c_init_rx_ring(atge_t *); 203*5e8715b9SGary Mills void atge_l1c_init_rr_ring(atge_t *); 204*5e8715b9SGary Mills void atge_l1c_init_cmb(atge_t *); 205*5e8715b9SGary Mills void atge_l1c_init_smb(atge_t *); 206*5e8715b9SGary Mills void atge_l1c_program_dma(atge_t *); 207*5e8715b9SGary Mills void atge_l1c_stop_tx_mac(atge_t *); 208*5e8715b9SGary Mills void atge_l1c_stop_rx_mac(atge_t *); 209*5e8715b9SGary Mills uint_t atge_l1c_interrupt(caddr_t, caddr_t); 210*5e8715b9SGary Mills void atge_l1c_send_packet(atge_ring_t *); 211*5e8715b9SGary Mills void atge_l1c_gather_stats(atge_t *); 212*5e8715b9SGary Mills void atge_l1c_clear_stats(atge_t *); 2130eb090a7SSaurabh Misra 2140eb090a7SSaurabh Misra /* 215015a6ef6SSaurabh Misra * Function prototyps for MII operations. 216015a6ef6SSaurabh Misra */ 217015a6ef6SSaurabh Misra uint16_t atge_mii_read(void *, uint8_t, uint8_t); 218015a6ef6SSaurabh Misra void atge_mii_write(void *, uint8_t, uint8_t, uint16_t); 219*5e8715b9SGary Mills uint16_t atge_l1c_mii_read(void *, uint8_t, uint8_t); 220*5e8715b9SGary Mills void atge_l1c_mii_write(void *, uint8_t, uint8_t, uint16_t); 221015a6ef6SSaurabh Misra void atge_l1e_mii_reset(void *); 2220eb090a7SSaurabh Misra void atge_l1_mii_reset(void *); 223*5e8715b9SGary Mills void atge_l1c_mii_reset(void *); 224015a6ef6SSaurabh Misra static void atge_mii_notify(void *, link_state_t); 2250eb090a7SSaurabh Misra void atge_tx_reclaim(atge_t *atgep, int cons); 226015a6ef6SSaurabh Misra 2270eb090a7SSaurabh Misra /* 2280eb090a7SSaurabh Misra * L1E/L2E chip. 2290eb090a7SSaurabh Misra */ 230015a6ef6SSaurabh Misra static mii_ops_t atge_l1e_mii_ops = { 231015a6ef6SSaurabh Misra MII_OPS_VERSION, 232015a6ef6SSaurabh Misra atge_mii_read, 233015a6ef6SSaurabh Misra atge_mii_write, 234015a6ef6SSaurabh Misra atge_mii_notify, 235015a6ef6SSaurabh Misra atge_l1e_mii_reset 236015a6ef6SSaurabh Misra }; 237015a6ef6SSaurabh Misra 238015a6ef6SSaurabh Misra /* 2390eb090a7SSaurabh Misra * L1 chip. 2400eb090a7SSaurabh Misra */ 2410eb090a7SSaurabh Misra static mii_ops_t atge_l1_mii_ops = { 2420eb090a7SSaurabh Misra MII_OPS_VERSION, 2430eb090a7SSaurabh Misra atge_mii_read, 2440eb090a7SSaurabh Misra atge_mii_write, 2450eb090a7SSaurabh Misra atge_mii_notify, 2460eb090a7SSaurabh Misra atge_l1_mii_reset 2470eb090a7SSaurabh Misra }; 2480eb090a7SSaurabh Misra 2490eb090a7SSaurabh Misra /* 250*5e8715b9SGary Mills * L1C chip. 251*5e8715b9SGary Mills */ 252*5e8715b9SGary Mills static mii_ops_t atge_l1c_mii_ops = { 253*5e8715b9SGary Mills MII_OPS_VERSION, 254*5e8715b9SGary Mills atge_l1c_mii_read, 255*5e8715b9SGary Mills atge_l1c_mii_write, 256*5e8715b9SGary Mills atge_mii_notify, 257*5e8715b9SGary Mills NULL 258*5e8715b9SGary Mills }; 259*5e8715b9SGary Mills 260*5e8715b9SGary Mills /* 261015a6ef6SSaurabh Misra * Function Prototypes for MAC callbacks. 262015a6ef6SSaurabh Misra */ 263015a6ef6SSaurabh Misra static int atge_m_stat(void *, uint_t, uint64_t *); 264015a6ef6SSaurabh Misra static int atge_m_start(void *); 265015a6ef6SSaurabh Misra static void atge_m_stop(void *); 266015a6ef6SSaurabh Misra static int atge_m_getprop(void *, const char *, mac_prop_id_t, uint_t, 2670dc2366fSVenugopal Iyer void *); 268015a6ef6SSaurabh Misra static int atge_m_setprop(void *, const char *, mac_prop_id_t, uint_t, 269015a6ef6SSaurabh Misra const void *); 2700dc2366fSVenugopal Iyer static void atge_m_propinfo(void *, const char *, mac_prop_id_t, 2710dc2366fSVenugopal Iyer mac_prop_info_handle_t); 272015a6ef6SSaurabh Misra static int atge_m_unicst(void *, const uint8_t *); 273015a6ef6SSaurabh Misra static int atge_m_multicst(void *, boolean_t, const uint8_t *); 274015a6ef6SSaurabh Misra static int atge_m_promisc(void *, boolean_t); 275015a6ef6SSaurabh Misra static mblk_t *atge_m_tx(void *, mblk_t *); 276015a6ef6SSaurabh Misra 277015a6ef6SSaurabh Misra static mac_callbacks_t atge_m_callbacks = { 2780dc2366fSVenugopal Iyer MC_SETPROP | MC_GETPROP | MC_PROPINFO, 279015a6ef6SSaurabh Misra atge_m_stat, 280015a6ef6SSaurabh Misra atge_m_start, 281015a6ef6SSaurabh Misra atge_m_stop, 282015a6ef6SSaurabh Misra atge_m_promisc, 283015a6ef6SSaurabh Misra atge_m_multicst, 284015a6ef6SSaurabh Misra atge_m_unicst, 285015a6ef6SSaurabh Misra atge_m_tx, 2860dc2366fSVenugopal Iyer NULL, /* mc_reserved */ 287015a6ef6SSaurabh Misra NULL, /* mc_ioctl */ 288015a6ef6SSaurabh Misra NULL, /* mc_getcapab */ 289015a6ef6SSaurabh Misra NULL, /* mc_open */ 290015a6ef6SSaurabh Misra NULL, /* mc_close */ 291015a6ef6SSaurabh Misra atge_m_setprop, 292015a6ef6SSaurabh Misra atge_m_getprop, 2930dc2366fSVenugopal Iyer atge_m_propinfo 294015a6ef6SSaurabh Misra }; 295015a6ef6SSaurabh Misra 296015a6ef6SSaurabh Misra /* 297015a6ef6SSaurabh Misra * DMA Data access requirements. 298015a6ef6SSaurabh Misra */ 299015a6ef6SSaurabh Misra static struct ddi_device_acc_attr atge_dev_attr = { 300015a6ef6SSaurabh Misra DDI_DEVICE_ATTR_V0, 301015a6ef6SSaurabh Misra DDI_STRUCTURE_LE_ACC, 302015a6ef6SSaurabh Misra DDI_STRICTORDER_ACC 303015a6ef6SSaurabh Misra }; 304015a6ef6SSaurabh Misra 305015a6ef6SSaurabh Misra /* 306015a6ef6SSaurabh Misra * Buffers should be native endianness. 307015a6ef6SSaurabh Misra */ 308015a6ef6SSaurabh Misra static struct ddi_device_acc_attr atge_buf_attr = { 309015a6ef6SSaurabh Misra DDI_DEVICE_ATTR_V0, 310015a6ef6SSaurabh Misra DDI_NEVERSWAP_ACC, /* native endianness */ 311015a6ef6SSaurabh Misra DDI_STRICTORDER_ACC 312015a6ef6SSaurabh Misra }; 313015a6ef6SSaurabh Misra 314015a6ef6SSaurabh Misra /* 3150eb090a7SSaurabh Misra * DMA device attributes. Buffer can be 64-bit. 316015a6ef6SSaurabh Misra */ 317015a6ef6SSaurabh Misra static ddi_dma_attr_t atge_dma_attr_buf = { 318015a6ef6SSaurabh Misra DMA_ATTR_V0, /* dma_attr_version */ 319015a6ef6SSaurabh Misra 0, /* dma_attr_addr_lo */ 320015a6ef6SSaurabh Misra 0x00ffffffffffull, /* dma_attr_addr_hi */ 321015a6ef6SSaurabh Misra 0x000000003fffull, /* dma_attr_count_max */ 322015a6ef6SSaurabh Misra 8, /* dma_attr_align */ 323015a6ef6SSaurabh Misra 0x00003ffc, /* dma_attr_burstsizes */ 324015a6ef6SSaurabh Misra 1, /* dma_attr_minxfer */ 325015a6ef6SSaurabh Misra 0x0000000027ffull, /* dma_attr_maxxfer */ 326015a6ef6SSaurabh Misra 0x0000ffffffffull, /* dma_attr_seg */ 327015a6ef6SSaurabh Misra 1, /* dma_attr_sgllen */ 328015a6ef6SSaurabh Misra 1, /* dma_attr_granular */ 329015a6ef6SSaurabh Misra 0 /* dma_attr_flags */ 330015a6ef6SSaurabh Misra }; 331015a6ef6SSaurabh Misra 332015a6ef6SSaurabh Misra /* 333015a6ef6SSaurabh Misra * Table of supported devices. 334015a6ef6SSaurabh Misra */ 335015a6ef6SSaurabh Misra #define ATGE_VENDOR_ID 0x1969 336*5e8715b9SGary Mills #define ATGE_L1_STR "Attansic L1" 337*5e8715b9SGary Mills #define ATGE_L1CG_STR "Atheros AR8131 Gigabit Ethernet" 338*5e8715b9SGary Mills #define ATGE_L1CF_STR "Atheros AR8132 Fast Ethernet" 339015a6ef6SSaurabh Misra #define ATGE_L1E_STR "Atheros AR8121/8113/8114" 340*5e8715b9SGary Mills #define ATGE_AR8151V1_STR "Atheros AR8151 v1.0 Gigabit Ethernet" 341*5e8715b9SGary Mills #define ATGE_AR8151V2_STR "Atheros AR8151 v2.0 Gigabit Ethernet" 342*5e8715b9SGary Mills #define ATGE_AR8152V1_STR "Atheros AR8152 v1.1 Fast Ethernet" 343*5e8715b9SGary Mills #define ATGE_AR8152V2_STR "Atheros AR8152 v2.0 Fast Ethernet" 344015a6ef6SSaurabh Misra 345015a6ef6SSaurabh Misra static atge_cards_t atge_cards[] = { 346*5e8715b9SGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_AR8151V2_DEV_ID, ATGE_AR8151V2_STR, 347*5e8715b9SGary Mills ATGE_CHIP_L1C}, 348*5e8715b9SGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_AR8151V1_DEV_ID, ATGE_AR8151V1_STR, 349*5e8715b9SGary Mills ATGE_CHIP_L1C}, 350*5e8715b9SGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_AR8152V2_DEV_ID, ATGE_AR8152V2_STR, 351*5e8715b9SGary Mills ATGE_CHIP_L1C}, 352*5e8715b9SGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_AR8152V1_DEV_ID, ATGE_AR8152V1_STR, 353*5e8715b9SGary Mills ATGE_CHIP_L1C}, 354*5e8715b9SGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_L1CG_DEV_ID, ATGE_L1CG_STR, ATGE_CHIP_L1C}, 355*5e8715b9SGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_L1CF_DEV_ID, ATGE_L1CF_STR, ATGE_CHIP_L1C}, 356015a6ef6SSaurabh Misra {ATGE_VENDOR_ID, ATGE_CHIP_L1E_DEV_ID, ATGE_L1E_STR, ATGE_CHIP_L1E}, 357*5e8715b9SGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_L1_DEV_ID, ATGE_L1_STR, ATGE_CHIP_L1}, 358015a6ef6SSaurabh Misra }; 359015a6ef6SSaurabh Misra 360015a6ef6SSaurabh Misra /* 361015a6ef6SSaurabh Misra * Global Debugging flag. Developer level debugging is done only in DEBUG mode. 362015a6ef6SSaurabh Misra */ 363015a6ef6SSaurabh Misra int atge_debug = 1; 364015a6ef6SSaurabh Misra 365015a6ef6SSaurabh Misra /* 366015a6ef6SSaurabh Misra * Debugging and error reporting. 367015a6ef6SSaurabh Misra */ 368015a6ef6SSaurabh Misra void 369015a6ef6SSaurabh Misra atge_debug_func(char *fmt, ...) 370015a6ef6SSaurabh Misra { 371015a6ef6SSaurabh Misra va_list ap; 372015a6ef6SSaurabh Misra char buf[256]; 373015a6ef6SSaurabh Misra 374015a6ef6SSaurabh Misra va_start(ap, fmt); 375015a6ef6SSaurabh Misra (void) vsnprintf(buf, sizeof (buf), fmt, ap); 376015a6ef6SSaurabh Misra va_end(ap); 377015a6ef6SSaurabh Misra 378015a6ef6SSaurabh Misra DTRACE_PROBE1(atge__debug, char *, buf); 379015a6ef6SSaurabh Misra } 380015a6ef6SSaurabh Misra 381*5e8715b9SGary Mills static 382*5e8715b9SGary Mills void 383*5e8715b9SGary Mills atge_message(dev_info_t *dip, int level, char *fmt, va_list ap) 384*5e8715b9SGary Mills { 385*5e8715b9SGary Mills char buf[256]; 386*5e8715b9SGary Mills char *p = "!%s%d: %s"; 387*5e8715b9SGary Mills char *q = "!atge: %s"; 388*5e8715b9SGary Mills 389*5e8715b9SGary Mills (void) vsnprintf(buf, sizeof (buf), fmt, ap); 390*5e8715b9SGary Mills 391*5e8715b9SGary Mills if (level != CE_NOTE) { 392*5e8715b9SGary Mills p++; 393*5e8715b9SGary Mills q++; 394*5e8715b9SGary Mills } 395*5e8715b9SGary Mills 396*5e8715b9SGary Mills if (dip) { 397*5e8715b9SGary Mills cmn_err(level, p, 398*5e8715b9SGary Mills ddi_driver_name(dip), ddi_get_instance(dip), buf); 399*5e8715b9SGary Mills } else { 400*5e8715b9SGary Mills cmn_err(level, q, buf); 401*5e8715b9SGary Mills } 402*5e8715b9SGary Mills } 403*5e8715b9SGary Mills 404*5e8715b9SGary Mills void 405*5e8715b9SGary Mills atge_notice(dev_info_t *dip, char *fmt, ...) 406*5e8715b9SGary Mills { 407*5e8715b9SGary Mills va_list ap; 408*5e8715b9SGary Mills 409*5e8715b9SGary Mills va_start(ap, fmt); 410*5e8715b9SGary Mills (void) atge_message(dip, CE_NOTE, fmt, ap); 411*5e8715b9SGary Mills va_end(ap); 412*5e8715b9SGary Mills } 413*5e8715b9SGary Mills 414015a6ef6SSaurabh Misra void 415015a6ef6SSaurabh Misra atge_error(dev_info_t *dip, char *fmt, ...) 416015a6ef6SSaurabh Misra { 417015a6ef6SSaurabh Misra va_list ap; 418015a6ef6SSaurabh Misra 419015a6ef6SSaurabh Misra va_start(ap, fmt); 420*5e8715b9SGary Mills (void) atge_message(dip, CE_WARN, fmt, ap); 421015a6ef6SSaurabh Misra va_end(ap); 422015a6ef6SSaurabh Misra } 423015a6ef6SSaurabh Misra 424015a6ef6SSaurabh Misra void 425015a6ef6SSaurabh Misra atge_mac_config(atge_t *atgep) 426015a6ef6SSaurabh Misra { 427015a6ef6SSaurabh Misra uint32_t reg; 428015a6ef6SSaurabh Misra int speed; 429015a6ef6SSaurabh Misra link_duplex_t ld; 430015a6ef6SSaurabh Misra 431*5e8715b9SGary Mills /* Re-enable TX/RX MACs */ 432015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_MAC_CFG); 433015a6ef6SSaurabh Misra reg &= ~(ATGE_CFG_FULL_DUPLEX | ATGE_CFG_TX_FC | ATGE_CFG_RX_FC | 434015a6ef6SSaurabh Misra ATGE_CFG_SPEED_MASK); 435015a6ef6SSaurabh Misra 436*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 437*5e8715b9SGary Mills case ATGE_CHIP_L1C: 438*5e8715b9SGary Mills switch (ATGE_DID(atgep)) { 439*5e8715b9SGary Mills case ATGE_CHIP_AR8151V2_DEV_ID: 440*5e8715b9SGary Mills case ATGE_CHIP_AR8151V1_DEV_ID: 441*5e8715b9SGary Mills case ATGE_CHIP_AR8152V2_DEV_ID: 442*5e8715b9SGary Mills reg |= ATGE_CFG_HASH_ALG_CRC32 | ATGE_CFG_SPEED_MODE_SW; 443*5e8715b9SGary Mills break; 444*5e8715b9SGary Mills } 445*5e8715b9SGary Mills break; 446*5e8715b9SGary Mills } 447*5e8715b9SGary Mills 448015a6ef6SSaurabh Misra speed = mii_get_speed(atgep->atge_mii); 449015a6ef6SSaurabh Misra switch (speed) { 450015a6ef6SSaurabh Misra case 10: 451015a6ef6SSaurabh Misra case 100: 452015a6ef6SSaurabh Misra reg |= ATGE_CFG_SPEED_10_100; 453015a6ef6SSaurabh Misra break; 454015a6ef6SSaurabh Misra case 1000: 455015a6ef6SSaurabh Misra reg |= ATGE_CFG_SPEED_1000; 456015a6ef6SSaurabh Misra break; 457015a6ef6SSaurabh Misra } 458015a6ef6SSaurabh Misra 459015a6ef6SSaurabh Misra ld = mii_get_duplex(atgep->atge_mii); 460015a6ef6SSaurabh Misra if (ld == LINK_DUPLEX_FULL) 461015a6ef6SSaurabh Misra reg |= ATGE_CFG_FULL_DUPLEX; 462015a6ef6SSaurabh Misra 463015a6ef6SSaurabh Misra /* Re-enable TX/RX MACs */ 464*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 465*5e8715b9SGary Mills case ATGE_CHIP_L1E: 466015a6ef6SSaurabh Misra reg |= ATGE_CFG_TX_ENB | ATGE_CFG_RX_ENB | ATGE_CFG_RX_FC; 467*5e8715b9SGary Mills break; 468*5e8715b9SGary Mills case ATGE_CHIP_L1: 469*5e8715b9SGary Mills case ATGE_CHIP_L1C: 4700eb090a7SSaurabh Misra reg |= ATGE_CFG_TX_ENB | ATGE_CFG_RX_ENB; 471*5e8715b9SGary Mills break; 4720eb090a7SSaurabh Misra } 4730eb090a7SSaurabh Misra 474015a6ef6SSaurabh Misra OUTL(atgep, ATGE_MAC_CFG, reg); 475015a6ef6SSaurabh Misra 476*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 477*5e8715b9SGary Mills case ATGE_CHIP_L1E: 478015a6ef6SSaurabh Misra reg = ATGE_USECS(ATGE_IM_RX_TIMER_DEFAULT) << IM_TIMER_RX_SHIFT; 479015a6ef6SSaurabh Misra reg |= ATGE_USECS(ATGE_IM_TX_TIMER_DEFAULT) << 480015a6ef6SSaurabh Misra IM_TIMER_TX_SHIFT; 481015a6ef6SSaurabh Misra OUTL(atgep, ATGE_IM_TIMER, reg); 482*5e8715b9SGary Mills break; 483*5e8715b9SGary Mills case ATGE_CHIP_L1: 484*5e8715b9SGary Mills break; 485*5e8715b9SGary Mills case ATGE_CHIP_L1C: 486*5e8715b9SGary Mills /* Configure interrupt moderation timer. */ 487*5e8715b9SGary Mills reg = ATGE_USECS(atgep->atge_int_rx_mod) << IM_TIMER_RX_SHIFT; 488*5e8715b9SGary Mills reg |= ATGE_USECS(atgep->atge_int_tx_mod) << IM_TIMER_TX_SHIFT; 489*5e8715b9SGary Mills OUTL(atgep, ATGE_IM_TIMER, reg); 490*5e8715b9SGary Mills /* 491*5e8715b9SGary Mills * We don't want to automatic interrupt clear as task queue 492*5e8715b9SGary Mills * for the interrupt should know interrupt status. 493*5e8715b9SGary Mills */ 494*5e8715b9SGary Mills reg = 0; 495*5e8715b9SGary Mills if (ATGE_USECS(atgep->atge_int_rx_mod) != 0) 496*5e8715b9SGary Mills reg |= MASTER_IM_RX_TIMER_ENB; 497*5e8715b9SGary Mills if (ATGE_USECS(atgep->atge_int_tx_mod) != 0) 498*5e8715b9SGary Mills reg |= MASTER_IM_TX_TIMER_ENB; 499*5e8715b9SGary Mills OUTL(atgep, ATGE_MASTER_CFG, reg); 500*5e8715b9SGary Mills break; 501015a6ef6SSaurabh Misra } 502015a6ef6SSaurabh Misra 503015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() mac_cfg is : %x", 504015a6ef6SSaurabh Misra atgep->atge_name, __func__, INL(atgep, ATGE_MAC_CFG))); 505015a6ef6SSaurabh Misra } 506015a6ef6SSaurabh Misra 507015a6ef6SSaurabh Misra static void 508015a6ef6SSaurabh Misra atge_mii_notify(void *arg, link_state_t link) 509015a6ef6SSaurabh Misra { 510015a6ef6SSaurabh Misra atge_t *atgep = arg; 511015a6ef6SSaurabh Misra 512015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() LINK STATUS CHANGED from %x -> %x", 513015a6ef6SSaurabh Misra atgep->atge_name, __func__, atgep->atge_link_state, link)); 514015a6ef6SSaurabh Misra 515015a6ef6SSaurabh Misra mac_link_update(atgep->atge_mh, link); 516015a6ef6SSaurabh Misra 517015a6ef6SSaurabh Misra /* 518015a6ef6SSaurabh Misra * Reconfigure MAC if link status is UP now. 519015a6ef6SSaurabh Misra */ 520015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock); 521015a6ef6SSaurabh Misra if (link == LINK_STATE_UP) { 522015a6ef6SSaurabh Misra atgep->atge_link_state = LINK_STATE_UP; 5230eb090a7SSaurabh Misra atge_mac_config(atgep); 524015a6ef6SSaurabh Misra atgep->atge_tx_resched = 0; 525015a6ef6SSaurabh Misra } else { 526015a6ef6SSaurabh Misra atgep->atge_link_state = LINK_STATE_DOWN; 5270eb090a7SSaurabh Misra atgep->atge_flags |= ATGE_MII_CHECK; 528015a6ef6SSaurabh Misra } 529015a6ef6SSaurabh Misra 530015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock); 531015a6ef6SSaurabh Misra 532015a6ef6SSaurabh Misra if (link == LINK_STATE_UP) 533015a6ef6SSaurabh Misra mac_tx_update(atgep->atge_mh); 534015a6ef6SSaurabh Misra } 535015a6ef6SSaurabh Misra 5360eb090a7SSaurabh Misra void 5370eb090a7SSaurabh Misra atge_tx_reclaim(atge_t *atgep, int end) 538015a6ef6SSaurabh Misra { 5390eb090a7SSaurabh Misra atge_tx_desc_t *txd; 5400eb090a7SSaurabh Misra atge_ring_t *r = atgep->atge_tx_ring; 5410eb090a7SSaurabh Misra uchar_t *c; 5420eb090a7SSaurabh Misra int start; 543015a6ef6SSaurabh Misra 5440eb090a7SSaurabh Misra ASSERT(MUTEX_HELD(&atgep->atge_tx_lock)); 5450eb090a7SSaurabh Misra ASSERT(r != NULL); 546015a6ef6SSaurabh Misra 5470eb090a7SSaurabh Misra start = r->r_consumer; 548015a6ef6SSaurabh Misra 5490eb090a7SSaurabh Misra if (start == end) 5500eb090a7SSaurabh Misra return; 551015a6ef6SSaurabh Misra 5520eb090a7SSaurabh Misra while (start != end) { 5530eb090a7SSaurabh Misra r->r_avail_desc++; 5540eb090a7SSaurabh Misra if (r->r_avail_desc > ATGE_TX_RING_CNT) { 555015a6ef6SSaurabh Misra 556015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, 5570eb090a7SSaurabh Misra "Reclaim : TX descriptor error"); 558015a6ef6SSaurabh Misra 5590eb090a7SSaurabh Misra if (r->r_avail_desc > (ATGE_TX_RING_CNT + 5)) { 560015a6ef6SSaurabh Misra atge_device_stop(atgep); 5610eb090a7SSaurabh Misra break; 562015a6ef6SSaurabh Misra } 563015a6ef6SSaurabh Misra } 564015a6ef6SSaurabh Misra 5650eb090a7SSaurabh Misra c = (uchar_t *)r->r_desc_ring->addr; 5660eb090a7SSaurabh Misra c += (sizeof (atge_tx_desc_t) * start); 5670eb090a7SSaurabh Misra txd = (atge_tx_desc_t *)c; 568015a6ef6SSaurabh Misra 569015a6ef6SSaurabh Misra /* 5700eb090a7SSaurabh Misra * Clearing TX descriptor helps in debugging some strange 5710eb090a7SSaurabh Misra * problems. 572015a6ef6SSaurabh Misra */ 5730eb090a7SSaurabh Misra txd->addr = 0; 5740eb090a7SSaurabh Misra txd->len = 0; 5750eb090a7SSaurabh Misra txd->flags = 0; 576015a6ef6SSaurabh Misra 5770eb090a7SSaurabh Misra ATGE_INC_SLOT(start, ATGE_TX_RING_CNT); 578015a6ef6SSaurabh Misra } 579015a6ef6SSaurabh Misra 5800eb090a7SSaurabh Misra atgep->atge_tx_ring->r_consumer = start; 581015a6ef6SSaurabh Misra 5820eb090a7SSaurabh Misra DMA_SYNC(r->r_desc_ring, 0, ATGE_TX_RING_SZ, DDI_DMA_SYNC_FORDEV); 583015a6ef6SSaurabh Misra } 584015a6ef6SSaurabh Misra 585015a6ef6SSaurabh Misra /* 586015a6ef6SSaurabh Misra * Adds interrupt handler depending upon the type of interrupt supported by 587015a6ef6SSaurabh Misra * the chip. 588015a6ef6SSaurabh Misra */ 589015a6ef6SSaurabh Misra static int 590015a6ef6SSaurabh Misra atge_add_intr_handler(atge_t *atgep, int intr_type) 591015a6ef6SSaurabh Misra { 592015a6ef6SSaurabh Misra int err; 593015a6ef6SSaurabh Misra int count = 0; 594015a6ef6SSaurabh Misra int avail = 0; 595015a6ef6SSaurabh Misra int i; 596015a6ef6SSaurabh Misra int flag; 597015a6ef6SSaurabh Misra 598015a6ef6SSaurabh Misra if (intr_type != DDI_INTR_TYPE_FIXED) { 599015a6ef6SSaurabh Misra err = ddi_intr_get_nintrs(atgep->atge_dip, intr_type, &count); 600015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 601015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, 602015a6ef6SSaurabh Misra "ddi_intr_get_nintrs failed : %d", err); 6030eb090a7SSaurabh Misra return (DDI_FAILURE); 604015a6ef6SSaurabh Misra } 605015a6ef6SSaurabh Misra 606015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() count : %d", 607015a6ef6SSaurabh Misra atgep->atge_name, __func__, count)); 608015a6ef6SSaurabh Misra 609015a6ef6SSaurabh Misra err = ddi_intr_get_navail(atgep->atge_dip, intr_type, &avail); 610015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 611015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, 612015a6ef6SSaurabh Misra "ddi_intr_get_navail failed : %d", err); 6130eb090a7SSaurabh Misra return (DDI_FAILURE); 614015a6ef6SSaurabh Misra } 615015a6ef6SSaurabh Misra 616015a6ef6SSaurabh Misra if (avail < count) { 617015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "count :%d," 618015a6ef6SSaurabh Misra " avail : %d", count, avail); 619015a6ef6SSaurabh Misra } 620015a6ef6SSaurabh Misra 621015a6ef6SSaurabh Misra flag = DDI_INTR_ALLOC_STRICT; 622015a6ef6SSaurabh Misra } else { 623015a6ef6SSaurabh Misra /* 624015a6ef6SSaurabh Misra * DDI_INTR_TYPE_FIXED case. 625015a6ef6SSaurabh Misra */ 626015a6ef6SSaurabh Misra count = 1; 627015a6ef6SSaurabh Misra avail = 1; 628015a6ef6SSaurabh Misra flag = DDI_INTR_ALLOC_NORMAL; 629015a6ef6SSaurabh Misra } 630015a6ef6SSaurabh Misra 631015a6ef6SSaurabh Misra atgep->atge_intr_size = avail * sizeof (ddi_intr_handle_t); 632015a6ef6SSaurabh Misra atgep->atge_intr_handle = kmem_zalloc(atgep->atge_intr_size, KM_SLEEP); 633015a6ef6SSaurabh Misra 634015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() avail:%d, count : %d, type : %d", 635015a6ef6SSaurabh Misra atgep->atge_name, __func__, avail, count, 636015a6ef6SSaurabh Misra intr_type)); 637015a6ef6SSaurabh Misra 638015a6ef6SSaurabh Misra err = ddi_intr_alloc(atgep->atge_dip, atgep->atge_intr_handle, 639015a6ef6SSaurabh Misra intr_type, 0, avail, &atgep->atge_intr_cnt, flag); 640015a6ef6SSaurabh Misra 641015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 642015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "ddi_intr_alloc failed : %d", err); 643015a6ef6SSaurabh Misra kmem_free(atgep->atge_intr_handle, atgep->atge_intr_size); 6440eb090a7SSaurabh Misra return (DDI_FAILURE); 645015a6ef6SSaurabh Misra } 646015a6ef6SSaurabh Misra 647015a6ef6SSaurabh Misra ATGE_DB(("%s: atge_add_intr_handler() after alloc count" 648015a6ef6SSaurabh Misra " :%d, avail : %d", atgep->atge_name, count, avail)); 649015a6ef6SSaurabh Misra 650015a6ef6SSaurabh Misra err = ddi_intr_get_pri(atgep->atge_intr_handle[0], 651015a6ef6SSaurabh Misra &atgep->atge_intr_pri); 652015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 653015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "ddi_intr_get_pri failed:%d", err); 654015a6ef6SSaurabh Misra for (i = 0; i < atgep->atge_intr_cnt; i++) { 655015a6ef6SSaurabh Misra (void) ddi_intr_free(atgep->atge_intr_handle[i]); 656015a6ef6SSaurabh Misra } 657015a6ef6SSaurabh Misra kmem_free(atgep->atge_intr_handle, atgep->atge_intr_size); 658015a6ef6SSaurabh Misra 6590eb090a7SSaurabh Misra return (DDI_FAILURE); 660015a6ef6SSaurabh Misra } 661015a6ef6SSaurabh Misra 662015a6ef6SSaurabh Misra /* 663015a6ef6SSaurabh Misra * Add interrupt handler now. 664015a6ef6SSaurabh Misra */ 665015a6ef6SSaurabh Misra for (i = 0; i < atgep->atge_intr_cnt; i++) { 666*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 667*5e8715b9SGary Mills case ATGE_CHIP_L1E: 668015a6ef6SSaurabh Misra err = ddi_intr_add_handler(atgep->atge_intr_handle[i], 669015a6ef6SSaurabh Misra atge_l1e_interrupt, atgep, (caddr_t)(uintptr_t)i); 670*5e8715b9SGary Mills break; 671*5e8715b9SGary Mills case ATGE_CHIP_L1: 6720eb090a7SSaurabh Misra err = ddi_intr_add_handler(atgep->atge_intr_handle[i], 6730eb090a7SSaurabh Misra atge_l1_interrupt, atgep, (caddr_t)(uintptr_t)i); 674*5e8715b9SGary Mills break; 675*5e8715b9SGary Mills case ATGE_CHIP_L1C: 676*5e8715b9SGary Mills err = ddi_intr_add_handler(atgep->atge_intr_handle[i], 677*5e8715b9SGary Mills atge_l1c_interrupt, atgep, (caddr_t)(uintptr_t)i); 678*5e8715b9SGary Mills break; 6790eb090a7SSaurabh Misra } 680015a6ef6SSaurabh Misra 681015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 682015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, 683015a6ef6SSaurabh Misra "ddi_intr_add_handler failed : %d", err); 684015a6ef6SSaurabh Misra 685015a6ef6SSaurabh Misra (void) ddi_intr_free(atgep->atge_intr_handle[i]); 686015a6ef6SSaurabh Misra while (--i >= 0) { 687015a6ef6SSaurabh Misra (void) ddi_intr_remove_handler( 688015a6ef6SSaurabh Misra atgep->atge_intr_handle[i]); 689015a6ef6SSaurabh Misra (void) ddi_intr_free( 690015a6ef6SSaurabh Misra atgep->atge_intr_handle[i]); 691015a6ef6SSaurabh Misra } 692015a6ef6SSaurabh Misra 693015a6ef6SSaurabh Misra kmem_free(atgep->atge_intr_handle, 694015a6ef6SSaurabh Misra atgep->atge_intr_size); 695015a6ef6SSaurabh Misra 6960eb090a7SSaurabh Misra return (DDI_FAILURE); 697015a6ef6SSaurabh Misra } 698015a6ef6SSaurabh Misra } 699015a6ef6SSaurabh Misra 700015a6ef6SSaurabh Misra err = ddi_intr_get_cap(atgep->atge_intr_handle[0], 701015a6ef6SSaurabh Misra &atgep->atge_intr_cap); 702015a6ef6SSaurabh Misra 703015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 704015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, 705015a6ef6SSaurabh Misra "ddi_intr_get_cap failed : %d", err); 706015a6ef6SSaurabh Misra atge_remove_intr(atgep); 7070eb090a7SSaurabh Misra return (DDI_FAILURE); 708015a6ef6SSaurabh Misra } 709015a6ef6SSaurabh Misra 710015a6ef6SSaurabh Misra if (intr_type == DDI_INTR_TYPE_FIXED) 711015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_FIXED_TYPE; 712015a6ef6SSaurabh Misra else if (intr_type == DDI_INTR_TYPE_MSI) 713015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_MSI_TYPE; 714015a6ef6SSaurabh Misra else if (intr_type == DDI_INTR_TYPE_MSIX) 715015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_MSIX_TYPE; 716015a6ef6SSaurabh Misra 7170eb090a7SSaurabh Misra return (DDI_SUCCESS); 718015a6ef6SSaurabh Misra } 719015a6ef6SSaurabh Misra 720015a6ef6SSaurabh Misra void 721015a6ef6SSaurabh Misra atge_remove_intr(atge_t *atgep) 722015a6ef6SSaurabh Misra { 723015a6ef6SSaurabh Misra int i; 724015a6ef6SSaurabh Misra int cap = 0; 725015a6ef6SSaurabh Misra 726015a6ef6SSaurabh Misra if (atgep->atge_intr_handle == NULL) 727015a6ef6SSaurabh Misra return; 728015a6ef6SSaurabh Misra 729015a6ef6SSaurabh Misra if (atgep->atge_intr_cap & DDI_INTR_FLAG_BLOCK) { 730015a6ef6SSaurabh Misra (void) ddi_intr_block_disable(atgep->atge_intr_handle, 731015a6ef6SSaurabh Misra atgep->atge_intr_cnt); 732015a6ef6SSaurabh Misra 733015a6ef6SSaurabh Misra cap = 1; 734015a6ef6SSaurabh Misra } 735015a6ef6SSaurabh Misra 736015a6ef6SSaurabh Misra for (i = 0; i < atgep->atge_intr_cnt; i++) { 737015a6ef6SSaurabh Misra if (cap == 0) 738015a6ef6SSaurabh Misra (void) ddi_intr_disable(atgep->atge_intr_handle[i]); 739015a6ef6SSaurabh Misra 740015a6ef6SSaurabh Misra (void) ddi_intr_remove_handler(atgep->atge_intr_handle[i]); 741015a6ef6SSaurabh Misra (void) ddi_intr_free(atgep->atge_intr_handle[i]); 742015a6ef6SSaurabh Misra } 743015a6ef6SSaurabh Misra 744015a6ef6SSaurabh Misra kmem_free(atgep->atge_intr_handle, atgep->atge_intr_size); 745015a6ef6SSaurabh Misra } 746015a6ef6SSaurabh Misra 747015a6ef6SSaurabh Misra int 748015a6ef6SSaurabh Misra atge_enable_intrs(atge_t *atgep) 749015a6ef6SSaurabh Misra { 750015a6ef6SSaurabh Misra int err; 751015a6ef6SSaurabh Misra int i; 752015a6ef6SSaurabh Misra 753015a6ef6SSaurabh Misra if (atgep->atge_intr_cap & DDI_INTR_FLAG_BLOCK) { 754015a6ef6SSaurabh Misra /* 755015a6ef6SSaurabh Misra * Do block enable. 756015a6ef6SSaurabh Misra */ 757015a6ef6SSaurabh Misra err = ddi_intr_block_enable(atgep->atge_intr_handle, 758015a6ef6SSaurabh Misra atgep->atge_intr_cnt); 759015a6ef6SSaurabh Misra 760015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 761015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, 762015a6ef6SSaurabh Misra "Failed to block enable intrs %d", err); 7630eb090a7SSaurabh Misra err = DDI_FAILURE; 764015a6ef6SSaurabh Misra } else { 7650eb090a7SSaurabh Misra err = DDI_SUCCESS; 766015a6ef6SSaurabh Misra } 767015a6ef6SSaurabh Misra } else { 768015a6ef6SSaurabh Misra /* 769015a6ef6SSaurabh Misra * Call ddi_intr_enable() for MSI non-block enable. 770015a6ef6SSaurabh Misra */ 771015a6ef6SSaurabh Misra for (i = 0; i < atgep->atge_intr_cnt; i++) { 772015a6ef6SSaurabh Misra err = ddi_intr_enable(atgep->atge_intr_handle[i]); 773015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 774015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, 775015a6ef6SSaurabh Misra "Failed to enable intrs on %d with : %d", 776015a6ef6SSaurabh Misra i, err); 777015a6ef6SSaurabh Misra break; 778015a6ef6SSaurabh Misra } 779015a6ef6SSaurabh Misra } 780015a6ef6SSaurabh Misra 781015a6ef6SSaurabh Misra if (err == DDI_SUCCESS) 7820eb090a7SSaurabh Misra err = DDI_SUCCESS; 783015a6ef6SSaurabh Misra else 7840eb090a7SSaurabh Misra err = DDI_FAILURE; 785015a6ef6SSaurabh Misra } 786015a6ef6SSaurabh Misra 787015a6ef6SSaurabh Misra return (err); 788015a6ef6SSaurabh Misra } 789015a6ef6SSaurabh Misra 790015a6ef6SSaurabh Misra /* 791015a6ef6SSaurabh Misra * Adds interrupt handler depending on the supported interrupt type by the 792015a6ef6SSaurabh Misra * chip. 793015a6ef6SSaurabh Misra */ 794015a6ef6SSaurabh Misra static int 795015a6ef6SSaurabh Misra atge_add_intr(atge_t *atgep) 796015a6ef6SSaurabh Misra { 797015a6ef6SSaurabh Misra int err; 798015a6ef6SSaurabh Misra 799015a6ef6SSaurabh Misra /* 800015a6ef6SSaurabh Misra * Get the supported interrupt types. 801015a6ef6SSaurabh Misra */ 802015a6ef6SSaurabh Misra err = ddi_intr_get_supported_types(atgep->atge_dip, 803015a6ef6SSaurabh Misra &atgep->atge_intr_types); 804015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 805015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, 806015a6ef6SSaurabh Misra "ddi_intr_get_supported_types failed : %d", err); 8070eb090a7SSaurabh Misra return (DDI_FAILURE); 808015a6ef6SSaurabh Misra } 809015a6ef6SSaurabh Misra 810015a6ef6SSaurabh Misra ATGE_DB(("%s: ddi_intr_get_supported_types() returned : %d", 811015a6ef6SSaurabh Misra atgep->atge_name, atgep->atge_intr_types)); 812015a6ef6SSaurabh Misra 813015a6ef6SSaurabh Misra 814015a6ef6SSaurabh Misra if (atgep->atge_intr_types & DDI_INTR_TYPE_MSIX) { 815015a6ef6SSaurabh Misra err = atge_add_intr_handler(atgep, DDI_INTR_TYPE_MSIX); 8160eb090a7SSaurabh Misra if (err == DDI_SUCCESS) { 817015a6ef6SSaurabh Misra ATGE_DB(("%s: Using MSIx for interrupt", 818015a6ef6SSaurabh Misra atgep->atge_name)); 819015a6ef6SSaurabh Misra return (err); 820015a6ef6SSaurabh Misra } 821015a6ef6SSaurabh Misra } 822015a6ef6SSaurabh Misra 823015a6ef6SSaurabh Misra if (atgep->atge_intr_types & DDI_INTR_TYPE_MSI) { 824015a6ef6SSaurabh Misra err = atge_add_intr_handler(atgep, DDI_INTR_TYPE_MSI); 8250eb090a7SSaurabh Misra if (err == DDI_SUCCESS) { 826015a6ef6SSaurabh Misra ATGE_DB(("%s: Using MSI for interrupt", 827015a6ef6SSaurabh Misra atgep->atge_name)); 828015a6ef6SSaurabh Misra return (err); 829015a6ef6SSaurabh Misra } 830015a6ef6SSaurabh Misra } 831015a6ef6SSaurabh Misra 8320eb090a7SSaurabh Misra err = DDI_FAILURE; 833015a6ef6SSaurabh Misra if (atgep->atge_intr_types & DDI_INTR_TYPE_FIXED) { 834015a6ef6SSaurabh Misra err = atge_add_intr_handler(atgep, DDI_INTR_TYPE_FIXED); 8350eb090a7SSaurabh Misra if (err == DDI_SUCCESS) { 836015a6ef6SSaurabh Misra ATGE_DB(("%s: Using FIXED type for interrupt", 837015a6ef6SSaurabh Misra atgep->atge_name)); 838015a6ef6SSaurabh Misra return (err); 839015a6ef6SSaurabh Misra } 840015a6ef6SSaurabh Misra } 841015a6ef6SSaurabh Misra 842015a6ef6SSaurabh Misra return (err); 843015a6ef6SSaurabh Misra } 844015a6ef6SSaurabh Misra 845015a6ef6SSaurabh Misra int 846015a6ef6SSaurabh Misra atge_identify_hardware(atge_t *atgep) 847015a6ef6SSaurabh Misra { 848015a6ef6SSaurabh Misra uint16_t vid, did; 849015a6ef6SSaurabh Misra int i; 850015a6ef6SSaurabh Misra 851015a6ef6SSaurabh Misra vid = pci_config_get16(atgep->atge_conf_handle, PCI_CONF_VENID); 852015a6ef6SSaurabh Misra did = pci_config_get16(atgep->atge_conf_handle, PCI_CONF_DEVID); 853015a6ef6SSaurabh Misra 854015a6ef6SSaurabh Misra atgep->atge_model = 0; 855015a6ef6SSaurabh Misra for (i = 0; i < (sizeof (atge_cards) / sizeof (atge_cards_t)); i++) { 856015a6ef6SSaurabh Misra if (atge_cards[i].vendor_id == vid && 857015a6ef6SSaurabh Misra atge_cards[i].device_id == did) { 858015a6ef6SSaurabh Misra atgep->atge_model = atge_cards[i].model; 859*5e8715b9SGary Mills atgep->atge_vid = vid; 860*5e8715b9SGary Mills atgep->atge_did = did; 861015a6ef6SSaurabh Misra atgep->atge_revid = 862015a6ef6SSaurabh Misra pci_config_get8(atgep->atge_conf_handle, 863015a6ef6SSaurabh Misra PCI_CONF_REVID); 864*5e8715b9SGary Mills atge_notice(atgep->atge_dip, "PCI-ID pci%x,%x,%x: %s", 865*5e8715b9SGary Mills vid, did, atgep->atge_revid, 866*5e8715b9SGary Mills atge_cards[i].cardname); 867015a6ef6SSaurabh Misra ATGE_DB(("%s: %s : PCI-ID pci%x,%x and model : %d", 868015a6ef6SSaurabh Misra atgep->atge_name, __func__, vid, did, 869015a6ef6SSaurabh Misra atgep->atge_model)); 870015a6ef6SSaurabh Misra 8710eb090a7SSaurabh Misra return (DDI_SUCCESS); 872015a6ef6SSaurabh Misra } 873015a6ef6SSaurabh Misra } 874015a6ef6SSaurabh Misra 875015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "atge driver is attaching to unknown" 876*5e8715b9SGary Mills " pci%x,%x vendor/device-id card", vid, did); 877015a6ef6SSaurabh Misra 878015a6ef6SSaurabh Misra /* 879*5e8715b9SGary Mills * Assume it's L1C chip. 880015a6ef6SSaurabh Misra */ 881*5e8715b9SGary Mills atgep->atge_model = ATGE_CHIP_L1C; 882*5e8715b9SGary Mills atgep->atge_vid = vid; 883*5e8715b9SGary Mills atgep->atge_did = did; 884015a6ef6SSaurabh Misra atgep->atge_revid = pci_config_get8(atgep->atge_conf_handle, 885015a6ef6SSaurabh Misra PCI_CONF_REVID); 886015a6ef6SSaurabh Misra 887015a6ef6SSaurabh Misra /* 888015a6ef6SSaurabh Misra * We will leave the decision to caller. 889015a6ef6SSaurabh Misra */ 8900eb090a7SSaurabh Misra return (DDI_FAILURE); 891015a6ef6SSaurabh Misra } 892015a6ef6SSaurabh Misra 893015a6ef6SSaurabh Misra int 894015a6ef6SSaurabh Misra atge_get_macaddr(atge_t *atgep) 895015a6ef6SSaurabh Misra { 896015a6ef6SSaurabh Misra uint32_t reg; 897015a6ef6SSaurabh Misra 898015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_SPI_CTRL); 899015a6ef6SSaurabh Misra if ((reg & SPI_VPD_ENB) != 0) { 900015a6ef6SSaurabh Misra /* 901015a6ef6SSaurabh Misra * Get VPD stored in TWSI EEPROM. 902015a6ef6SSaurabh Misra */ 903015a6ef6SSaurabh Misra reg &= ~SPI_VPD_ENB; 904015a6ef6SSaurabh Misra OUTL(atgep, ATGE_SPI_CTRL, reg); 905015a6ef6SSaurabh Misra 906015a6ef6SSaurabh Misra ATGE_DB(("%s: %s called Get VPD", atgep->atge_name, __func__)); 907015a6ef6SSaurabh Misra } 908015a6ef6SSaurabh Misra 909015a6ef6SSaurabh Misra atgep->atge_ether_addr[5] = INB(atgep, ATGE_PAR0 + 0); 910015a6ef6SSaurabh Misra atgep->atge_ether_addr[4] = INB(atgep, ATGE_PAR0 + 1); 911015a6ef6SSaurabh Misra atgep->atge_ether_addr[3] = INB(atgep, ATGE_PAR0 + 2); 912015a6ef6SSaurabh Misra atgep->atge_ether_addr[2] = INB(atgep, ATGE_PAR0 + 3); 913015a6ef6SSaurabh Misra atgep->atge_ether_addr[1] = INB(atgep, ATGE_PAR1 + 0); 914015a6ef6SSaurabh Misra atgep->atge_ether_addr[0] = INB(atgep, ATGE_PAR1 + 1); 915015a6ef6SSaurabh Misra 916015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() Station Address - %x:%x:%x:%x:%x:%x", 917015a6ef6SSaurabh Misra atgep->atge_name, __func__, 918015a6ef6SSaurabh Misra atgep->atge_ether_addr[0], 919015a6ef6SSaurabh Misra atgep->atge_ether_addr[1], 920015a6ef6SSaurabh Misra atgep->atge_ether_addr[2], 921015a6ef6SSaurabh Misra atgep->atge_ether_addr[3], 922015a6ef6SSaurabh Misra atgep->atge_ether_addr[4], 923015a6ef6SSaurabh Misra atgep->atge_ether_addr[5])); 924015a6ef6SSaurabh Misra 925015a6ef6SSaurabh Misra bcopy(atgep->atge_ether_addr, atgep->atge_dev_addr, ETHERADDRL); 926015a6ef6SSaurabh Misra 9270eb090a7SSaurabh Misra return (DDI_SUCCESS); 928015a6ef6SSaurabh Misra } 929015a6ef6SSaurabh Misra 930015a6ef6SSaurabh Misra /* 931*5e8715b9SGary Mills * Reset functionality for L1, L1E, and L1C. It's same. 932015a6ef6SSaurabh Misra */ 933015a6ef6SSaurabh Misra static void 934015a6ef6SSaurabh Misra atge_device_reset(atge_t *atgep) 935015a6ef6SSaurabh Misra { 936*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 937*5e8715b9SGary Mills case ATGE_CHIP_L1E: 938*5e8715b9SGary Mills case ATGE_CHIP_L1: 939*5e8715b9SGary Mills case ATGE_CHIP_L1C: 940015a6ef6SSaurabh Misra atge_device_reset_l1_l1e(atgep); 941*5e8715b9SGary Mills break; 942*5e8715b9SGary Mills } 943015a6ef6SSaurabh Misra } 944015a6ef6SSaurabh Misra 945015a6ef6SSaurabh Misra void 946015a6ef6SSaurabh Misra atge_device_reset_l1_l1e(atge_t *atgep) 947015a6ef6SSaurabh Misra { 948015a6ef6SSaurabh Misra uint32_t reg; 949015a6ef6SSaurabh Misra int t; 950*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 951*5e8715b9SGary Mills case ATGE_CHIP_L1C: 952*5e8715b9SGary Mills OUTL(atgep, ATGE_MASTER_CFG, MASTER_RESET | 0x40); 953*5e8715b9SGary Mills break; 954*5e8715b9SGary Mills default: 955015a6ef6SSaurabh Misra OUTL(atgep, ATGE_MASTER_CFG, MASTER_RESET); 956*5e8715b9SGary Mills break; 957*5e8715b9SGary Mills } 958015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_MASTER_CFG); 959015a6ef6SSaurabh Misra for (t = ATGE_RESET_TIMEOUT; t > 0; t--) { 960015a6ef6SSaurabh Misra drv_usecwait(10); 961015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_MASTER_CFG); 962015a6ef6SSaurabh Misra if ((reg & MASTER_RESET) == 0) 963015a6ef6SSaurabh Misra break; 964015a6ef6SSaurabh Misra } 965015a6ef6SSaurabh Misra 966015a6ef6SSaurabh Misra if (t == 0) { 967015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, " master reset timeout reg : %x", 968015a6ef6SSaurabh Misra reg); 969015a6ef6SSaurabh Misra } 970015a6ef6SSaurabh Misra 971015a6ef6SSaurabh Misra for (t = ATGE_RESET_TIMEOUT; t > 0; t--) { 972015a6ef6SSaurabh Misra if ((reg = INL(atgep, ATGE_IDLE_STATUS)) == 0) 973015a6ef6SSaurabh Misra break; 974015a6ef6SSaurabh Misra 975015a6ef6SSaurabh Misra drv_usecwait(10); 976015a6ef6SSaurabh Misra } 977015a6ef6SSaurabh Misra 978015a6ef6SSaurabh Misra if (t == 0) { 979015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "device reset timeout reg : %x", 980015a6ef6SSaurabh Misra reg); 981015a6ef6SSaurabh Misra } 982015a6ef6SSaurabh Misra 983*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 984*5e8715b9SGary Mills case ATGE_CHIP_L1E: 985*5e8715b9SGary Mills case ATGE_CHIP_L1: 986015a6ef6SSaurabh Misra /* 987015a6ef6SSaurabh Misra * Initialize PCIe module. These values came from FreeBSD and 988015a6ef6SSaurabh Misra * we don't know the meaning of it. 989015a6ef6SSaurabh Misra */ 990*5e8715b9SGary Mills OUTL(atgep, ATGE_LTSSM_ID_CFG, 0x6500); 991015a6ef6SSaurabh Misra reg = INL(atgep, 0x1008) | 0x8000; 992015a6ef6SSaurabh Misra OUTL(atgep, 0x1008, reg); 993*5e8715b9SGary Mills break; 994*5e8715b9SGary Mills case ATGE_CHIP_L1C: 995*5e8715b9SGary Mills break; 996*5e8715b9SGary Mills } 997015a6ef6SSaurabh Misra 998015a6ef6SSaurabh Misra /* 999015a6ef6SSaurabh Misra * Get chip revision. 1000015a6ef6SSaurabh Misra */ 1001015a6ef6SSaurabh Misra atgep->atge_chip_rev = INL(atgep, ATGE_MASTER_CFG) >> 1002015a6ef6SSaurabh Misra MASTER_CHIP_REV_SHIFT; 1003015a6ef6SSaurabh Misra 1004015a6ef6SSaurabh Misra ATGE_DB(("%s: %s reset successfully rev : %x", atgep->atge_name, 1005015a6ef6SSaurabh Misra __func__, atgep->atge_chip_rev)); 1006015a6ef6SSaurabh Misra } 1007015a6ef6SSaurabh Misra 1008015a6ef6SSaurabh Misra /* 1009015a6ef6SSaurabh Misra * DMA allocation for L1 and L1E is bit different since L1E uses RX pages 1010015a6ef6SSaurabh Misra * instead of descriptor based RX model. 1011015a6ef6SSaurabh Misra */ 1012015a6ef6SSaurabh Misra static int 1013015a6ef6SSaurabh Misra atge_alloc_dma(atge_t *atgep) 1014015a6ef6SSaurabh Misra { 10150eb090a7SSaurabh Misra int err = DDI_FAILURE; 1016015a6ef6SSaurabh Misra 1017*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 1018*5e8715b9SGary Mills case ATGE_CHIP_L1E: 1019015a6ef6SSaurabh Misra err = atge_l1e_alloc_dma(atgep); 1020*5e8715b9SGary Mills break; 1021*5e8715b9SGary Mills case ATGE_CHIP_L1: 10220eb090a7SSaurabh Misra err = atge_l1_alloc_dma(atgep); 1023*5e8715b9SGary Mills break; 1024*5e8715b9SGary Mills case ATGE_CHIP_L1C: 1025*5e8715b9SGary Mills err = atge_l1c_alloc_dma(atgep); 1026*5e8715b9SGary Mills break; 1027015a6ef6SSaurabh Misra } 1028015a6ef6SSaurabh Misra 1029015a6ef6SSaurabh Misra return (err); 1030015a6ef6SSaurabh Misra } 1031015a6ef6SSaurabh Misra 1032015a6ef6SSaurabh Misra static void 1033015a6ef6SSaurabh Misra atge_free_dma(atge_t *atgep) 1034015a6ef6SSaurabh Misra { 1035*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 1036*5e8715b9SGary Mills case ATGE_CHIP_L1E: 1037015a6ef6SSaurabh Misra atge_l1e_free_dma(atgep); 1038*5e8715b9SGary Mills break; 1039*5e8715b9SGary Mills case ATGE_CHIP_L1: 1040*5e8715b9SGary Mills atge_l1_free_dma(atgep); 1041*5e8715b9SGary Mills break; 1042*5e8715b9SGary Mills case ATGE_CHIP_L1C: 1043*5e8715b9SGary Mills atge_l1c_free_dma(atgep); 1044*5e8715b9SGary Mills break; 1045015a6ef6SSaurabh Misra } 1046015a6ef6SSaurabh Misra } 1047015a6ef6SSaurabh Misra 1048015a6ef6SSaurabh Misra /* 1049015a6ef6SSaurabh Misra * Attach entry point in the driver. 1050015a6ef6SSaurabh Misra */ 1051015a6ef6SSaurabh Misra static int 1052015a6ef6SSaurabh Misra atge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) 1053015a6ef6SSaurabh Misra { 1054015a6ef6SSaurabh Misra atge_t *atgep; 1055015a6ef6SSaurabh Misra mac_register_t *macreg; 1056015a6ef6SSaurabh Misra int instance; 1057015a6ef6SSaurabh Misra uint16_t cap_ptr; 1058015a6ef6SSaurabh Misra uint16_t burst; 1059015a6ef6SSaurabh Misra int err; 1060015a6ef6SSaurabh Misra mii_ops_t *mii_ops; 1061015a6ef6SSaurabh Misra 1062015a6ef6SSaurabh Misra instance = ddi_get_instance(devinfo); 1063015a6ef6SSaurabh Misra 1064015a6ef6SSaurabh Misra switch (cmd) { 1065015a6ef6SSaurabh Misra case DDI_RESUME: 1066015a6ef6SSaurabh Misra return (atge_resume(devinfo)); 1067015a6ef6SSaurabh Misra 1068015a6ef6SSaurabh Misra case DDI_ATTACH: 1069015a6ef6SSaurabh Misra ddi_set_driver_private(devinfo, NULL); 1070015a6ef6SSaurabh Misra break; 1071*5e8715b9SGary Mills default: 1072*5e8715b9SGary Mills return (DDI_FAILURE); 1073*5e8715b9SGary Mills 1074015a6ef6SSaurabh Misra } 1075015a6ef6SSaurabh Misra 1076015a6ef6SSaurabh Misra atgep = kmem_zalloc(sizeof (atge_t), KM_SLEEP); 1077015a6ef6SSaurabh Misra ddi_set_driver_private(devinfo, atgep); 1078015a6ef6SSaurabh Misra atgep->atge_dip = devinfo; 1079015a6ef6SSaurabh Misra 1080015a6ef6SSaurabh Misra /* 1081015a6ef6SSaurabh Misra * Setup name and instance number to be used for debugging and 1082015a6ef6SSaurabh Misra * error reporting. 1083015a6ef6SSaurabh Misra */ 1084015a6ef6SSaurabh Misra (void) snprintf(atgep->atge_name, sizeof (atgep->atge_name), "%s%d", 1085015a6ef6SSaurabh Misra "atge", instance); 1086015a6ef6SSaurabh Misra 1087015a6ef6SSaurabh Misra 1088015a6ef6SSaurabh Misra /* 1089015a6ef6SSaurabh Misra * Map PCI config space. 1090015a6ef6SSaurabh Misra */ 1091015a6ef6SSaurabh Misra err = pci_config_setup(devinfo, &atgep->atge_conf_handle); 1092015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 1093015a6ef6SSaurabh Misra atge_error(devinfo, "pci_config_setup() failed"); 1094015a6ef6SSaurabh Misra goto fail1; 1095015a6ef6SSaurabh Misra } 1096015a6ef6SSaurabh Misra 1097015a6ef6SSaurabh Misra (void) atge_identify_hardware(atgep); 1098015a6ef6SSaurabh Misra 1099015a6ef6SSaurabh Misra /* 1100015a6ef6SSaurabh Misra * Map Device registers. 1101015a6ef6SSaurabh Misra */ 1102015a6ef6SSaurabh Misra err = ddi_regs_map_setup(devinfo, ATGE_PCI_REG_NUMBER, 1103015a6ef6SSaurabh Misra &atgep->atge_io_regs, 0, 0, &atge_dev_attr, &atgep->atge_io_handle); 1104015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 1105015a6ef6SSaurabh Misra atge_error(devinfo, "ddi_regs_map_setup() failed"); 1106015a6ef6SSaurabh Misra goto fail2; 1107015a6ef6SSaurabh Misra } 1108015a6ef6SSaurabh Misra 1109015a6ef6SSaurabh Misra /* 1110015a6ef6SSaurabh Misra * Add interrupt and its associated handler. 1111015a6ef6SSaurabh Misra */ 1112015a6ef6SSaurabh Misra err = atge_add_intr(atgep); 11130eb090a7SSaurabh Misra if (err != DDI_SUCCESS) { 1114015a6ef6SSaurabh Misra atge_error(devinfo, "Failed to add interrupt handler"); 1115015a6ef6SSaurabh Misra goto fail3; 1116015a6ef6SSaurabh Misra } 1117015a6ef6SSaurabh Misra 1118015a6ef6SSaurabh Misra mutex_init(&atgep->atge_intr_lock, NULL, MUTEX_DRIVER, 1119015a6ef6SSaurabh Misra DDI_INTR_PRI(atgep->atge_intr_pri)); 1120015a6ef6SSaurabh Misra 1121015a6ef6SSaurabh Misra mutex_init(&atgep->atge_tx_lock, NULL, MUTEX_DRIVER, 1122015a6ef6SSaurabh Misra DDI_INTR_PRI(atgep->atge_intr_pri)); 1123015a6ef6SSaurabh Misra 1124015a6ef6SSaurabh Misra mutex_init(&atgep->atge_rx_lock, NULL, MUTEX_DRIVER, 1125015a6ef6SSaurabh Misra DDI_INTR_PRI(atgep->atge_intr_pri)); 1126015a6ef6SSaurabh Misra 1127015a6ef6SSaurabh Misra mutex_init(&atgep->atge_mii_lock, NULL, MUTEX_DRIVER, NULL); 1128015a6ef6SSaurabh Misra 11290eb090a7SSaurabh Misra /* 11300eb090a7SSaurabh Misra * Used to lock down MBOX register on L1 chip since RX consumer, 11310eb090a7SSaurabh Misra * TX producer and RX return ring consumer are shared. 11320eb090a7SSaurabh Misra */ 11330eb090a7SSaurabh Misra mutex_init(&atgep->atge_mbox_lock, NULL, MUTEX_DRIVER, 11340eb090a7SSaurabh Misra DDI_INTR_PRI(atgep->atge_intr_pri)); 11350eb090a7SSaurabh Misra 1136015a6ef6SSaurabh Misra atgep->atge_link_state = LINK_STATE_DOWN; 1137015a6ef6SSaurabh Misra atgep->atge_mtu = ETHERMTU; 1138015a6ef6SSaurabh Misra 1139*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 1140*5e8715b9SGary Mills case ATGE_CHIP_L1E: 1141015a6ef6SSaurabh Misra if (atgep->atge_revid > 0xF0) { 1142015a6ef6SSaurabh Misra /* L2E Rev. B. AR8114 */ 1143015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_FLAG_FASTETHER; 1144015a6ef6SSaurabh Misra } else { 11450eb090a7SSaurabh Misra if ((INL(atgep, L1E_PHY_STATUS) & 11460eb090a7SSaurabh Misra PHY_STATUS_100M) != 0) { 1147015a6ef6SSaurabh Misra /* L1E AR8121 */ 1148015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_FLAG_JUMBO; 1149015a6ef6SSaurabh Misra } else { 1150015a6ef6SSaurabh Misra /* L2E Rev. A. AR8113 */ 1151015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_FLAG_FASTETHER; 1152015a6ef6SSaurabh Misra } 1153015a6ef6SSaurabh Misra } 1154*5e8715b9SGary Mills break; 1155*5e8715b9SGary Mills case ATGE_CHIP_L1: 1156*5e8715b9SGary Mills break; 1157*5e8715b9SGary Mills case ATGE_CHIP_L1C: 1158*5e8715b9SGary Mills /* 1159*5e8715b9SGary Mills * One odd thing is AR8132 uses the same PHY hardware(F1 1160*5e8715b9SGary Mills * gigabit PHY) of AR8131. So atphy(4) of AR8132 reports 1161*5e8715b9SGary Mills * the PHY supports 1000Mbps but that's not true. The PHY 1162*5e8715b9SGary Mills * used in AR8132 can't establish gigabit link even if it 1163*5e8715b9SGary Mills * shows the same PHY model/revision number of AR8131. 1164*5e8715b9SGary Mills * 1165*5e8715b9SGary Mills * It seems that AR813x/AR815x has silicon bug for SMB. In 1166*5e8715b9SGary Mills * addition, Atheros said that enabling SMB wouldn't improve 1167*5e8715b9SGary Mills * performance. However I think it's bad to access lots of 1168*5e8715b9SGary Mills * registers to extract MAC statistics. 1169*5e8715b9SGary Mills * 1170*5e8715b9SGary Mills * Don't use Tx CMB. It is known to have silicon bug. 1171*5e8715b9SGary Mills */ 1172*5e8715b9SGary Mills switch (ATGE_DID(atgep)) { 1173*5e8715b9SGary Mills case ATGE_CHIP_AR8152V2_DEV_ID: 1174*5e8715b9SGary Mills case ATGE_CHIP_AR8152V1_DEV_ID: 1175*5e8715b9SGary Mills atgep->atge_flags |= ATGE_FLAG_APS | 1176*5e8715b9SGary Mills ATGE_FLAG_FASTETHER | 1177*5e8715b9SGary Mills ATGE_FLAG_ASPM_MON | ATGE_FLAG_JUMBO | 1178*5e8715b9SGary Mills ATGE_FLAG_SMB_BUG | ATGE_FLAG_CMB_BUG; 1179*5e8715b9SGary Mills break; 1180*5e8715b9SGary Mills case ATGE_CHIP_AR8151V2_DEV_ID: 1181*5e8715b9SGary Mills case ATGE_CHIP_AR8151V1_DEV_ID: 1182*5e8715b9SGary Mills atgep->atge_flags |= ATGE_FLAG_APS | 1183*5e8715b9SGary Mills ATGE_FLAG_ASPM_MON | ATGE_FLAG_JUMBO | 1184*5e8715b9SGary Mills ATGE_FLAG_SMB_BUG | ATGE_FLAG_CMB_BUG; 1185*5e8715b9SGary Mills break; 1186*5e8715b9SGary Mills case ATGE_CHIP_L1CF_DEV_ID: 1187*5e8715b9SGary Mills atgep->atge_flags |= ATGE_FLAG_FASTETHER; 1188*5e8715b9SGary Mills break; 1189*5e8715b9SGary Mills case ATGE_CHIP_L1CG_DEV_ID: 1190*5e8715b9SGary Mills break; 1191*5e8715b9SGary Mills } 1192*5e8715b9SGary Mills break; 11930eb090a7SSaurabh Misra } 1194015a6ef6SSaurabh Misra 1195015a6ef6SSaurabh Misra /* 1196015a6ef6SSaurabh Misra * Get DMA parameters from PCIe device control register. 1197015a6ef6SSaurabh Misra */ 1198015a6ef6SSaurabh Misra err = PCI_CAP_LOCATE(atgep->atge_conf_handle, PCI_CAP_ID_PCI_E, 1199015a6ef6SSaurabh Misra &cap_ptr); 1200015a6ef6SSaurabh Misra 1201015a6ef6SSaurabh Misra if (err == DDI_FAILURE) { 1202015a6ef6SSaurabh Misra atgep->atge_dma_rd_burst = DMA_CFG_RD_BURST_128; 1203015a6ef6SSaurabh Misra atgep->atge_dma_wr_burst = DMA_CFG_WR_BURST_128; 1204015a6ef6SSaurabh Misra } else { 1205015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_FLAG_PCIE; 1206015a6ef6SSaurabh Misra burst = pci_config_get16(atgep->atge_conf_handle, 1207015a6ef6SSaurabh Misra cap_ptr + 0x08); 1208015a6ef6SSaurabh Misra 1209015a6ef6SSaurabh Misra /* 1210015a6ef6SSaurabh Misra * Max read request size. 1211015a6ef6SSaurabh Misra */ 1212015a6ef6SSaurabh Misra atgep->atge_dma_rd_burst = ((burst >> 12) & 0x07) << 1213015a6ef6SSaurabh Misra DMA_CFG_RD_BURST_SHIFT; 1214015a6ef6SSaurabh Misra 1215015a6ef6SSaurabh Misra /* 1216015a6ef6SSaurabh Misra * Max Payload Size. 1217015a6ef6SSaurabh Misra */ 1218015a6ef6SSaurabh Misra atgep->atge_dma_wr_burst = ((burst >> 5) & 0x07) << 1219015a6ef6SSaurabh Misra DMA_CFG_WR_BURST_SHIFT; 1220015a6ef6SSaurabh Misra 1221015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() MRR : %d, MPS : %d", 1222015a6ef6SSaurabh Misra atgep->atge_name, __func__, 1223015a6ef6SSaurabh Misra (128 << ((burst >> 12) & 0x07)), 1224015a6ef6SSaurabh Misra (128 << ((burst >> 5) & 0x07)))); 1225015a6ef6SSaurabh Misra } 1226015a6ef6SSaurabh Misra 1227*5e8715b9SGary Mills /* Clear data link and flow-control protocol error. */ 1228*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 1229*5e8715b9SGary Mills case ATGE_CHIP_L1E: 1230*5e8715b9SGary Mills break; 1231*5e8715b9SGary Mills case ATGE_CHIP_L1: 1232*5e8715b9SGary Mills break; 1233*5e8715b9SGary Mills case ATGE_CHIP_L1C: 1234*5e8715b9SGary Mills OUTL_AND(atgep, ATGE_PEX_UNC_ERR_SEV, 1235*5e8715b9SGary Mills ~(PEX_UNC_ERR_SEV_UC | PEX_UNC_ERR_SEV_FCP)); 1236*5e8715b9SGary Mills OUTL_AND(atgep, ATGE_LTSSM_ID_CFG, ~LTSSM_ID_WRO_ENB); 1237*5e8715b9SGary Mills OUTL_OR(atgep, ATGE_PCIE_PHYMISC, PCIE_PHYMISC_FORCE_RCV_DET); 1238*5e8715b9SGary Mills break; 1239*5e8715b9SGary Mills } 1240*5e8715b9SGary Mills 1241015a6ef6SSaurabh Misra /* 1242015a6ef6SSaurabh Misra * Allocate DMA resources. 1243015a6ef6SSaurabh Misra */ 1244015a6ef6SSaurabh Misra err = atge_alloc_dma(atgep); 12450eb090a7SSaurabh Misra if (err != DDI_SUCCESS) { 1246015a6ef6SSaurabh Misra atge_error(devinfo, "Failed to allocate DMA resources"); 1247015a6ef6SSaurabh Misra goto fail4; 1248015a6ef6SSaurabh Misra } 1249015a6ef6SSaurabh Misra 1250015a6ef6SSaurabh Misra /* 1251015a6ef6SSaurabh Misra * Get station address. 1252015a6ef6SSaurabh Misra */ 1253015a6ef6SSaurabh Misra (void) atge_get_macaddr(atgep); 1254015a6ef6SSaurabh Misra 1255015a6ef6SSaurabh Misra /* 1256015a6ef6SSaurabh Misra * Setup MII. 1257015a6ef6SSaurabh Misra */ 1258*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 1259*5e8715b9SGary Mills case ATGE_CHIP_L1E: 1260015a6ef6SSaurabh Misra mii_ops = &atge_l1e_mii_ops; 1261*5e8715b9SGary Mills break; 1262*5e8715b9SGary Mills case ATGE_CHIP_L1: 12630eb090a7SSaurabh Misra mii_ops = &atge_l1_mii_ops; 1264*5e8715b9SGary Mills break; 1265*5e8715b9SGary Mills case ATGE_CHIP_L1C: 1266*5e8715b9SGary Mills mii_ops = &atge_l1c_mii_ops; 1267*5e8715b9SGary Mills break; 1268015a6ef6SSaurabh Misra } 1269015a6ef6SSaurabh Misra 1270015a6ef6SSaurabh Misra if ((atgep->atge_mii = mii_alloc(atgep, devinfo, 1271015a6ef6SSaurabh Misra mii_ops)) == NULL) { 1272015a6ef6SSaurabh Misra atge_error(devinfo, "mii_alloc() failed"); 1273015a6ef6SSaurabh Misra goto fail4; 1274015a6ef6SSaurabh Misra } 1275015a6ef6SSaurabh Misra 1276015a6ef6SSaurabh Misra /* 1277015a6ef6SSaurabh Misra * Register with MAC layer. 1278015a6ef6SSaurabh Misra */ 1279015a6ef6SSaurabh Misra if ((macreg = mac_alloc(MAC_VERSION)) == NULL) { 1280015a6ef6SSaurabh Misra atge_error(devinfo, "mac_alloc() failed due to version"); 1281015a6ef6SSaurabh Misra goto fail4; 1282015a6ef6SSaurabh Misra } 1283015a6ef6SSaurabh Misra 1284015a6ef6SSaurabh Misra macreg->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 1285015a6ef6SSaurabh Misra macreg->m_driver = atgep; 1286015a6ef6SSaurabh Misra macreg->m_dip = devinfo; 1287015a6ef6SSaurabh Misra macreg->m_instance = instance; 1288015a6ef6SSaurabh Misra macreg->m_src_addr = atgep->atge_ether_addr; 1289015a6ef6SSaurabh Misra macreg->m_callbacks = &atge_m_callbacks; 1290015a6ef6SSaurabh Misra macreg->m_min_sdu = 0; 1291015a6ef6SSaurabh Misra macreg->m_max_sdu = atgep->atge_mtu; 1292015a6ef6SSaurabh Misra macreg->m_margin = VLAN_TAGSZ; 1293015a6ef6SSaurabh Misra 1294015a6ef6SSaurabh Misra if ((err = mac_register(macreg, &atgep->atge_mh)) != 0) { 1295015a6ef6SSaurabh Misra atge_error(devinfo, "mac_register() failed with :%d", err); 1296015a6ef6SSaurabh Misra mac_free(macreg); 1297015a6ef6SSaurabh Misra goto fail4; 1298015a6ef6SSaurabh Misra } 1299015a6ef6SSaurabh Misra 1300015a6ef6SSaurabh Misra mac_free(macreg); 1301015a6ef6SSaurabh Misra 1302015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() driver attached successfully", 1303015a6ef6SSaurabh Misra atgep->atge_name, __func__)); 1304015a6ef6SSaurabh Misra 1305015a6ef6SSaurabh Misra atge_device_reset(atgep); 1306015a6ef6SSaurabh Misra 1307015a6ef6SSaurabh Misra atgep->atge_chip_state = ATGE_CHIP_INITIALIZED; 1308015a6ef6SSaurabh Misra 1309015a6ef6SSaurabh Misra /* 1310015a6ef6SSaurabh Misra * At last - enable interrupts. 1311015a6ef6SSaurabh Misra */ 1312015a6ef6SSaurabh Misra err = atge_enable_intrs(atgep); 13130eb090a7SSaurabh Misra if (err == DDI_FAILURE) { 1314015a6ef6SSaurabh Misra goto fail5; 1315015a6ef6SSaurabh Misra } 1316015a6ef6SSaurabh Misra 1317015a6ef6SSaurabh Misra /* 1318015a6ef6SSaurabh Misra * Reset the PHY before starting. 1319015a6ef6SSaurabh Misra */ 1320*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 1321*5e8715b9SGary Mills case ATGE_CHIP_L1E: 1322015a6ef6SSaurabh Misra atge_l1e_mii_reset(atgep); 1323*5e8715b9SGary Mills break; 1324*5e8715b9SGary Mills case ATGE_CHIP_L1: 13250eb090a7SSaurabh Misra atge_l1_mii_reset(atgep); 1326*5e8715b9SGary Mills break; 1327*5e8715b9SGary Mills case ATGE_CHIP_L1C: 1328*5e8715b9SGary Mills atge_l1c_mii_reset(atgep); 1329*5e8715b9SGary Mills break; 1330015a6ef6SSaurabh Misra } 1331015a6ef6SSaurabh Misra 1332015a6ef6SSaurabh Misra /* 1333015a6ef6SSaurabh Misra * Let the PHY run. 1334015a6ef6SSaurabh Misra */ 1335015a6ef6SSaurabh Misra mii_start(atgep->atge_mii); 1336015a6ef6SSaurabh Misra 1337015a6ef6SSaurabh Misra return (DDI_SUCCESS); 1338015a6ef6SSaurabh Misra 1339015a6ef6SSaurabh Misra fail5: 1340015a6ef6SSaurabh Misra (void) mac_unregister(atgep->atge_mh); 1341015a6ef6SSaurabh Misra atge_device_stop(atgep); 1342015a6ef6SSaurabh Misra mii_stop(atgep->atge_mii); 1343015a6ef6SSaurabh Misra mii_free(atgep->atge_mii); 1344015a6ef6SSaurabh Misra fail4: 1345015a6ef6SSaurabh Misra atge_free_dma(atgep); 1346015a6ef6SSaurabh Misra mutex_destroy(&atgep->atge_intr_lock); 1347015a6ef6SSaurabh Misra mutex_destroy(&atgep->atge_tx_lock); 1348015a6ef6SSaurabh Misra mutex_destroy(&atgep->atge_rx_lock); 1349015a6ef6SSaurabh Misra atge_remove_intr(atgep); 1350015a6ef6SSaurabh Misra fail3: 1351015a6ef6SSaurabh Misra ddi_regs_map_free(&atgep->atge_io_handle); 1352015a6ef6SSaurabh Misra fail2: 1353015a6ef6SSaurabh Misra pci_config_teardown(&atgep->atge_conf_handle); 1354015a6ef6SSaurabh Misra fail1: 1355015a6ef6SSaurabh Misra if (atgep) 1356015a6ef6SSaurabh Misra kmem_free(atgep, sizeof (atge_t)); 1357015a6ef6SSaurabh Misra 1358015a6ef6SSaurabh Misra return (DDI_FAILURE); 1359015a6ef6SSaurabh Misra } 1360015a6ef6SSaurabh Misra 1361015a6ef6SSaurabh Misra static int 1362015a6ef6SSaurabh Misra atge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 1363015a6ef6SSaurabh Misra { 1364015a6ef6SSaurabh Misra atge_t *atgep; 1365015a6ef6SSaurabh Misra 1366015a6ef6SSaurabh Misra atgep = ddi_get_driver_private(dip); 1367015a6ef6SSaurabh Misra if (atgep == NULL) { 1368015a6ef6SSaurabh Misra atge_error(dip, "No soft state in detach"); 1369015a6ef6SSaurabh Misra return (DDI_FAILURE); 1370015a6ef6SSaurabh Misra } 1371015a6ef6SSaurabh Misra 1372015a6ef6SSaurabh Misra switch (cmd) { 1373015a6ef6SSaurabh Misra case DDI_DETACH: 1374015a6ef6SSaurabh Misra 1375015a6ef6SSaurabh Misra /* 1376015a6ef6SSaurabh Misra * First unregister with MAC layer before stopping DMA 1377015a6ef6SSaurabh Misra */ 13789d8d9e11SGarrett D'Amore if (mac_disable(atgep->atge_mh) != DDI_SUCCESS) 1379015a6ef6SSaurabh Misra return (DDI_FAILURE); 1380015a6ef6SSaurabh Misra 13819d8d9e11SGarrett D'Amore mii_stop(atgep->atge_mii); 1382015a6ef6SSaurabh Misra 1383015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_intr_lock); 1384015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock); 1385015a6ef6SSaurabh Misra atge_device_stop(atgep); 1386015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock); 1387015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_intr_lock); 1388015a6ef6SSaurabh Misra 1389015a6ef6SSaurabh Misra mii_free(atgep->atge_mii); 1390015a6ef6SSaurabh Misra atge_free_dma(atgep); 1391015a6ef6SSaurabh Misra 1392015a6ef6SSaurabh Misra ddi_regs_map_free(&atgep->atge_io_handle); 1393015a6ef6SSaurabh Misra atge_remove_intr(atgep); 1394015a6ef6SSaurabh Misra pci_config_teardown(&atgep->atge_conf_handle); 1395015a6ef6SSaurabh Misra 13969d8d9e11SGarrett D'Amore (void) mac_unregister(atgep->atge_mh); 1397015a6ef6SSaurabh Misra mutex_destroy(&atgep->atge_intr_lock); 1398015a6ef6SSaurabh Misra mutex_destroy(&atgep->atge_tx_lock); 1399015a6ef6SSaurabh Misra mutex_destroy(&atgep->atge_rx_lock); 1400015a6ef6SSaurabh Misra kmem_free(atgep, sizeof (atge_t)); 1401015a6ef6SSaurabh Misra ddi_set_driver_private(dip, NULL); 1402015a6ef6SSaurabh Misra 1403015a6ef6SSaurabh Misra return (DDI_SUCCESS); 1404015a6ef6SSaurabh Misra 1405015a6ef6SSaurabh Misra case DDI_SUSPEND: 1406015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() is being suspended", 1407015a6ef6SSaurabh Misra atgep->atge_name, __func__)); 1408015a6ef6SSaurabh Misra 1409015a6ef6SSaurabh Misra /* 1410015a6ef6SSaurabh Misra * Suspend monitoring MII. 1411015a6ef6SSaurabh Misra */ 1412015a6ef6SSaurabh Misra mii_suspend(atgep->atge_mii); 1413015a6ef6SSaurabh Misra 1414015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_intr_lock); 1415015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock); 1416015a6ef6SSaurabh Misra atgep->atge_chip_state |= ATGE_CHIP_SUSPENDED; 1417015a6ef6SSaurabh Misra atge_device_stop(atgep); 1418015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock); 1419015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_intr_lock); 1420015a6ef6SSaurabh Misra 1421015a6ef6SSaurabh Misra return (DDI_SUCCESS); 1422015a6ef6SSaurabh Misra 1423015a6ef6SSaurabh Misra default: 1424015a6ef6SSaurabh Misra return (DDI_FAILURE); 1425015a6ef6SSaurabh Misra } 1426015a6ef6SSaurabh Misra } 1427015a6ef6SSaurabh Misra 1428015a6ef6SSaurabh Misra int 1429015a6ef6SSaurabh Misra atge_alloc_buffers(atge_ring_t *r, size_t rcnt, size_t buflen, int f) 1430015a6ef6SSaurabh Misra { 1431015a6ef6SSaurabh Misra atge_dma_t *dma; 1432015a6ef6SSaurabh Misra atge_dma_t **tbl; 14330eb090a7SSaurabh Misra int err = DDI_SUCCESS; 1434015a6ef6SSaurabh Misra int i; 1435015a6ef6SSaurabh Misra 1436015a6ef6SSaurabh Misra tbl = kmem_zalloc(rcnt * sizeof (atge_dma_t *), KM_SLEEP); 1437015a6ef6SSaurabh Misra r->r_buf_tbl = tbl; 1438015a6ef6SSaurabh Misra 1439015a6ef6SSaurabh Misra for (i = 0; i < rcnt; i++) { 1440015a6ef6SSaurabh Misra dma = atge_buf_alloc(r->r_atge, buflen, f); 1441015a6ef6SSaurabh Misra if (dma == NULL) { 14420eb090a7SSaurabh Misra err = DDI_FAILURE; 1443015a6ef6SSaurabh Misra break; 1444015a6ef6SSaurabh Misra } 1445015a6ef6SSaurabh Misra 1446015a6ef6SSaurabh Misra tbl[i] = dma; 1447015a6ef6SSaurabh Misra } 1448015a6ef6SSaurabh Misra 1449015a6ef6SSaurabh Misra return (err); 1450015a6ef6SSaurabh Misra } 1451015a6ef6SSaurabh Misra 1452015a6ef6SSaurabh Misra void 1453015a6ef6SSaurabh Misra atge_free_buffers(atge_ring_t *r, size_t rcnt) 1454015a6ef6SSaurabh Misra { 1455015a6ef6SSaurabh Misra atge_dma_t **tbl; 1456015a6ef6SSaurabh Misra int i; 1457015a6ef6SSaurabh Misra 1458015a6ef6SSaurabh Misra if (r == NULL || r->r_buf_tbl == NULL) 1459015a6ef6SSaurabh Misra return; 1460015a6ef6SSaurabh Misra 1461015a6ef6SSaurabh Misra tbl = r->r_buf_tbl; 1462015a6ef6SSaurabh Misra for (i = 0; i < rcnt; i++) { 1463015a6ef6SSaurabh Misra if (tbl[i] != NULL) { 1464015a6ef6SSaurabh Misra atge_buf_free(tbl[i]); 1465015a6ef6SSaurabh Misra } 1466015a6ef6SSaurabh Misra } 1467015a6ef6SSaurabh Misra 1468015a6ef6SSaurabh Misra kmem_free(tbl, rcnt * sizeof (atge_dma_t *)); 1469015a6ef6SSaurabh Misra } 1470015a6ef6SSaurabh Misra 1471015a6ef6SSaurabh Misra atge_dma_t * 1472015a6ef6SSaurabh Misra atge_alloc_a_dma_blk(atge_t *atgep, ddi_dma_attr_t *attr, int size, int d) 1473015a6ef6SSaurabh Misra { 1474015a6ef6SSaurabh Misra int err; 1475015a6ef6SSaurabh Misra atge_dma_t *dma; 1476015a6ef6SSaurabh Misra 1477015a6ef6SSaurabh Misra dma = kmem_zalloc(sizeof (atge_dma_t), KM_SLEEP); 1478015a6ef6SSaurabh Misra 1479015a6ef6SSaurabh Misra err = ddi_dma_alloc_handle(atgep->atge_dip, attr, 1480015a6ef6SSaurabh Misra DDI_DMA_SLEEP, NULL, &dma->hdl); 1481015a6ef6SSaurabh Misra 1482015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 1483015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "%s() : failed" 1484015a6ef6SSaurabh Misra " in ddi_dma_alloc_handle() : %d", __func__, err); 1485015a6ef6SSaurabh Misra goto fail; 1486015a6ef6SSaurabh Misra } 1487015a6ef6SSaurabh Misra 1488015a6ef6SSaurabh Misra err = ddi_dma_mem_alloc(dma->hdl, 1489015a6ef6SSaurabh Misra size, &atge_buf_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, 1490015a6ef6SSaurabh Misra &dma->addr, &dma->len, &dma->acchdl); 1491015a6ef6SSaurabh Misra 1492015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 1493015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "%s() : failed" 1494015a6ef6SSaurabh Misra " in ddi_dma_mem_alloc() : %d", __func__, err); 1495015a6ef6SSaurabh Misra ddi_dma_free_handle(&dma->hdl); 1496015a6ef6SSaurabh Misra goto fail; 1497015a6ef6SSaurabh Misra } 1498015a6ef6SSaurabh Misra 1499015a6ef6SSaurabh Misra err = ddi_dma_addr_bind_handle(dma->hdl, NULL, dma->addr, 1500015a6ef6SSaurabh Misra dma->len, d | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 1501015a6ef6SSaurabh Misra NULL, &dma->cookie, &dma->count); 1502015a6ef6SSaurabh Misra 1503015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 1504015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "%s() : failed" 1505015a6ef6SSaurabh Misra " in ddi_dma_addr_bind_handle() : %d", __func__, err); 1506015a6ef6SSaurabh Misra ddi_dma_mem_free(&dma->acchdl); 1507015a6ef6SSaurabh Misra ddi_dma_free_handle(&dma->hdl); 1508015a6ef6SSaurabh Misra goto fail; 1509015a6ef6SSaurabh Misra } 1510015a6ef6SSaurabh Misra 1511015a6ef6SSaurabh Misra return (dma); 1512015a6ef6SSaurabh Misra fail: 1513015a6ef6SSaurabh Misra kmem_free(dma, sizeof (atge_dma_t)); 1514015a6ef6SSaurabh Misra return (NULL); 1515015a6ef6SSaurabh Misra } 1516015a6ef6SSaurabh Misra 1517015a6ef6SSaurabh Misra void 1518015a6ef6SSaurabh Misra atge_free_a_dma_blk(atge_dma_t *dma) 1519015a6ef6SSaurabh Misra { 1520015a6ef6SSaurabh Misra if (dma != NULL) { 1521015a6ef6SSaurabh Misra (void) ddi_dma_unbind_handle(dma->hdl); 1522015a6ef6SSaurabh Misra ddi_dma_mem_free(&dma->acchdl); 1523015a6ef6SSaurabh Misra ddi_dma_free_handle(&dma->hdl); 1524015a6ef6SSaurabh Misra kmem_free(dma, sizeof (atge_dma_t)); 1525015a6ef6SSaurabh Misra } 1526015a6ef6SSaurabh Misra } 1527015a6ef6SSaurabh Misra 1528015a6ef6SSaurabh Misra atge_dma_t * 1529015a6ef6SSaurabh Misra atge_buf_alloc(atge_t *atgep, size_t len, int f) 1530015a6ef6SSaurabh Misra { 1531015a6ef6SSaurabh Misra atge_dma_t *dma = NULL; 1532015a6ef6SSaurabh Misra int err; 1533015a6ef6SSaurabh Misra 1534015a6ef6SSaurabh Misra dma = kmem_zalloc(sizeof (atge_dma_t), KM_SLEEP); 1535015a6ef6SSaurabh Misra 1536015a6ef6SSaurabh Misra err = ddi_dma_alloc_handle(atgep->atge_dip, &atge_dma_attr_buf, 1537015a6ef6SSaurabh Misra DDI_DMA_SLEEP, NULL, &dma->hdl); 1538015a6ef6SSaurabh Misra 1539015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 1540015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "%s() : failed" 1541015a6ef6SSaurabh Misra " in %s() : %d", __func__, err); 1542015a6ef6SSaurabh Misra goto fail; 1543015a6ef6SSaurabh Misra } 1544015a6ef6SSaurabh Misra 1545015a6ef6SSaurabh Misra err = ddi_dma_mem_alloc(dma->hdl, len, &atge_buf_attr, 1546015a6ef6SSaurabh Misra DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, &dma->addr, 1547015a6ef6SSaurabh Misra &dma->len, &dma->acchdl); 1548015a6ef6SSaurabh Misra 1549015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 1550015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "%s() : failed" 1551015a6ef6SSaurabh Misra " in %s() : %d", __func__, err); 1552015a6ef6SSaurabh Misra ddi_dma_free_handle(&dma->hdl); 1553015a6ef6SSaurabh Misra goto fail; 1554015a6ef6SSaurabh Misra } 1555015a6ef6SSaurabh Misra 1556015a6ef6SSaurabh Misra err = ddi_dma_addr_bind_handle(dma->hdl, NULL, dma->addr, dma->len, 1557015a6ef6SSaurabh Misra (f | DDI_DMA_CONSISTENT), DDI_DMA_SLEEP, NULL, &dma->cookie, 1558015a6ef6SSaurabh Misra &dma->count); 1559015a6ef6SSaurabh Misra 1560015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 1561015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "%s() : failed" 1562015a6ef6SSaurabh Misra " in %s() : %d", __func__, err); 1563015a6ef6SSaurabh Misra ddi_dma_mem_free(&dma->acchdl); 1564015a6ef6SSaurabh Misra ddi_dma_free_handle(&dma->hdl); 1565015a6ef6SSaurabh Misra goto fail; 1566015a6ef6SSaurabh Misra } 1567015a6ef6SSaurabh Misra 1568015a6ef6SSaurabh Misra /* 1569015a6ef6SSaurabh Misra * Number of return'ed cookie should be one. 1570015a6ef6SSaurabh Misra */ 1571015a6ef6SSaurabh Misra ASSERT(dma->count == 1); 1572015a6ef6SSaurabh Misra 1573015a6ef6SSaurabh Misra return (dma); 1574015a6ef6SSaurabh Misra fail: 1575015a6ef6SSaurabh Misra kmem_free(dma, sizeof (atge_dma_t)); 1576015a6ef6SSaurabh Misra return (NULL); 1577015a6ef6SSaurabh Misra } 1578015a6ef6SSaurabh Misra 1579015a6ef6SSaurabh Misra void 1580015a6ef6SSaurabh Misra atge_buf_free(atge_dma_t *dma) 1581015a6ef6SSaurabh Misra { 1582015a6ef6SSaurabh Misra ASSERT(dma != NULL); 1583015a6ef6SSaurabh Misra 1584015a6ef6SSaurabh Misra (void) ddi_dma_unbind_handle(dma->hdl); 1585015a6ef6SSaurabh Misra ddi_dma_mem_free(&dma->acchdl); 1586015a6ef6SSaurabh Misra ddi_dma_free_handle(&dma->hdl); 1587015a6ef6SSaurabh Misra kmem_free(dma, sizeof (atge_dma_t)); 1588015a6ef6SSaurabh Misra } 1589015a6ef6SSaurabh Misra 1590015a6ef6SSaurabh Misra static int 1591015a6ef6SSaurabh Misra atge_resume(dev_info_t *dip) 1592015a6ef6SSaurabh Misra { 1593015a6ef6SSaurabh Misra atge_t *atgep; 1594015a6ef6SSaurabh Misra 1595015a6ef6SSaurabh Misra if ((atgep = ddi_get_driver_private(dip)) == NULL) { 1596015a6ef6SSaurabh Misra return (DDI_FAILURE); 1597015a6ef6SSaurabh Misra } 1598015a6ef6SSaurabh Misra 1599015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_intr_lock); 1600015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock); 1601015a6ef6SSaurabh Misra 1602015a6ef6SSaurabh Misra atgep->atge_chip_state &= ~ATGE_CHIP_SUSPENDED; 1603015a6ef6SSaurabh Misra 1604015a6ef6SSaurabh Misra if (atgep->atge_chip_state & ATGE_CHIP_RUNNING) { 1605015a6ef6SSaurabh Misra atge_device_restart(atgep); 1606015a6ef6SSaurabh Misra } else { 1607015a6ef6SSaurabh Misra atge_device_reset(atgep); 1608015a6ef6SSaurabh Misra } 1609015a6ef6SSaurabh Misra 1610015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock); 1611015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_intr_lock); 1612015a6ef6SSaurabh Misra 1613015a6ef6SSaurabh Misra /* 1614015a6ef6SSaurabh Misra * Reset the PHY before resuming MII. 1615015a6ef6SSaurabh Misra */ 1616*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 1617*5e8715b9SGary Mills case ATGE_CHIP_L1E: 1618015a6ef6SSaurabh Misra atge_l1e_mii_reset(atgep); 1619*5e8715b9SGary Mills break; 1620*5e8715b9SGary Mills case ATGE_CHIP_L1: 1621*5e8715b9SGary Mills break; 1622*5e8715b9SGary Mills case ATGE_CHIP_L1C: 1623*5e8715b9SGary Mills break; 1624015a6ef6SSaurabh Misra } 1625015a6ef6SSaurabh Misra 1626015a6ef6SSaurabh Misra mii_resume(atgep->atge_mii); 1627015a6ef6SSaurabh Misra 1628015a6ef6SSaurabh Misra /* kick-off downstream */ 1629015a6ef6SSaurabh Misra mac_tx_update(atgep->atge_mh); 1630015a6ef6SSaurabh Misra 1631015a6ef6SSaurabh Misra return (DDI_SUCCESS); 1632015a6ef6SSaurabh Misra } 1633015a6ef6SSaurabh Misra 1634015a6ef6SSaurabh Misra static int 1635015a6ef6SSaurabh Misra atge_quiesce(dev_info_t *dip) 1636015a6ef6SSaurabh Misra { 1637015a6ef6SSaurabh Misra atge_t *atgep; 1638015a6ef6SSaurabh Misra 1639015a6ef6SSaurabh Misra if ((atgep = ddi_get_driver_private(dip)) == NULL) { 1640015a6ef6SSaurabh Misra return (DDI_FAILURE); 1641015a6ef6SSaurabh Misra } 1642015a6ef6SSaurabh Misra 1643015a6ef6SSaurabh Misra atge_device_stop(atgep); 1644015a6ef6SSaurabh Misra 1645015a6ef6SSaurabh Misra return (DDI_SUCCESS); 1646015a6ef6SSaurabh Misra } 1647015a6ef6SSaurabh Misra 1648015a6ef6SSaurabh Misra void 1649015a6ef6SSaurabh Misra atge_add_multicst(atge_t *atgep, uint8_t *macaddr) 1650015a6ef6SSaurabh Misra { 1651015a6ef6SSaurabh Misra uint32_t crc; 1652015a6ef6SSaurabh Misra int bit; 1653015a6ef6SSaurabh Misra 1654015a6ef6SSaurabh Misra ASSERT(MUTEX_HELD(&atgep->atge_intr_lock)); 1655015a6ef6SSaurabh Misra ASSERT(MUTEX_HELD(&atgep->atge_tx_lock)); 1656015a6ef6SSaurabh Misra 1657015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() %x:%x:%x:%x:%x:%x", 1658015a6ef6SSaurabh Misra atgep->atge_name, __func__, macaddr[0], macaddr[1], macaddr[2], 1659015a6ef6SSaurabh Misra macaddr[3], macaddr[4], macaddr[5])); 1660015a6ef6SSaurabh Misra 1661015a6ef6SSaurabh Misra crc = atge_ether_crc(macaddr, ETHERADDRL); 1662015a6ef6SSaurabh Misra bit = (crc >> 26); 1663015a6ef6SSaurabh Misra atgep->atge_mchash_ref_cnt[bit]++; 1664015a6ef6SSaurabh Misra atgep->atge_mchash |= (1ULL << (crc >> 26)); 1665015a6ef6SSaurabh Misra 1666015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() mchash :%llx, bit : %d," 1667015a6ef6SSaurabh Misra " atge_mchash_ref_cnt[bit] :%d", 1668015a6ef6SSaurabh Misra atgep->atge_name, __func__, atgep->atge_mchash, bit, 1669015a6ef6SSaurabh Misra atgep->atge_mchash_ref_cnt[bit])); 1670015a6ef6SSaurabh Misra } 1671015a6ef6SSaurabh Misra 1672015a6ef6SSaurabh Misra void 1673015a6ef6SSaurabh Misra atge_remove_multicst(atge_t *atgep, uint8_t *macaddr) 1674015a6ef6SSaurabh Misra { 1675015a6ef6SSaurabh Misra uint32_t crc; 1676015a6ef6SSaurabh Misra int bit; 1677015a6ef6SSaurabh Misra 1678015a6ef6SSaurabh Misra ASSERT(MUTEX_HELD(&atgep->atge_intr_lock)); 1679015a6ef6SSaurabh Misra ASSERT(MUTEX_HELD(&atgep->atge_tx_lock)); 1680015a6ef6SSaurabh Misra 1681015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() %x:%x:%x:%x:%x:%x", 1682015a6ef6SSaurabh Misra atgep->atge_name, __func__, macaddr[0], macaddr[1], macaddr[2], 1683015a6ef6SSaurabh Misra macaddr[3], macaddr[4], macaddr[5])); 1684015a6ef6SSaurabh Misra 1685015a6ef6SSaurabh Misra crc = atge_ether_crc(macaddr, ETHERADDRL); 1686015a6ef6SSaurabh Misra bit = (crc >> 26); 1687015a6ef6SSaurabh Misra atgep->atge_mchash_ref_cnt[bit]--; 1688015a6ef6SSaurabh Misra if (atgep->atge_mchash_ref_cnt[bit] == 0) 1689015a6ef6SSaurabh Misra atgep->atge_mchash &= ~(1ULL << (crc >> 26)); 1690015a6ef6SSaurabh Misra 1691015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() mchash :%llx, bit : %d," 1692015a6ef6SSaurabh Misra " atge_mchash_ref_cnt[bit] :%d", 1693015a6ef6SSaurabh Misra atgep->atge_name, __func__, atgep->atge_mchash, bit, 1694015a6ef6SSaurabh Misra atgep->atge_mchash_ref_cnt[bit])); 1695015a6ef6SSaurabh Misra } 1696015a6ef6SSaurabh Misra 1697015a6ef6SSaurabh Misra int 1698015a6ef6SSaurabh Misra atge_m_multicst(void *arg, boolean_t add, const uint8_t *macaddr) 1699015a6ef6SSaurabh Misra { 1700015a6ef6SSaurabh Misra atge_t *atgep = arg; 1701015a6ef6SSaurabh Misra 1702015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_intr_lock); 1703015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock); 1704015a6ef6SSaurabh Misra 1705015a6ef6SSaurabh Misra if (add) { 1706015a6ef6SSaurabh Misra atge_add_multicst(atgep, (uint8_t *)macaddr); 1707015a6ef6SSaurabh Misra } else { 1708015a6ef6SSaurabh Misra atge_remove_multicst(atgep, (uint8_t *)macaddr); 1709015a6ef6SSaurabh Misra } 1710015a6ef6SSaurabh Misra 1711015a6ef6SSaurabh Misra atge_rxfilter(atgep); 1712015a6ef6SSaurabh Misra 1713015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock); 1714015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_intr_lock); 1715015a6ef6SSaurabh Misra 1716015a6ef6SSaurabh Misra return (0); 1717015a6ef6SSaurabh Misra } 1718015a6ef6SSaurabh Misra 1719015a6ef6SSaurabh Misra int 1720015a6ef6SSaurabh Misra atge_m_promisc(void *arg, boolean_t on) 1721015a6ef6SSaurabh Misra { 1722015a6ef6SSaurabh Misra atge_t *atgep = arg; 1723015a6ef6SSaurabh Misra 1724015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_intr_lock); 1725015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock); 1726015a6ef6SSaurabh Misra 1727015a6ef6SSaurabh Misra if (on) { 1728015a6ef6SSaurabh Misra atgep->atge_filter_flags |= ATGE_PROMISC; 1729015a6ef6SSaurabh Misra } else { 1730015a6ef6SSaurabh Misra atgep->atge_filter_flags &= ~ATGE_PROMISC; 1731015a6ef6SSaurabh Misra } 1732015a6ef6SSaurabh Misra 1733015a6ef6SSaurabh Misra if (atgep->atge_chip_state & ATGE_CHIP_RUNNING) { 1734015a6ef6SSaurabh Misra atge_rxfilter(atgep); 1735015a6ef6SSaurabh Misra } 1736015a6ef6SSaurabh Misra 1737015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock); 1738015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_intr_lock); 1739015a6ef6SSaurabh Misra 1740015a6ef6SSaurabh Misra return (0); 1741015a6ef6SSaurabh Misra } 1742015a6ef6SSaurabh Misra 1743015a6ef6SSaurabh Misra int 1744015a6ef6SSaurabh Misra atge_m_unicst(void *arg, const uint8_t *macaddr) 1745015a6ef6SSaurabh Misra { 1746015a6ef6SSaurabh Misra atge_t *atgep = arg; 1747015a6ef6SSaurabh Misra 1748015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_intr_lock); 1749015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock); 1750015a6ef6SSaurabh Misra bcopy(macaddr, atgep->atge_ether_addr, ETHERADDRL); 1751015a6ef6SSaurabh Misra atge_program_ether(atgep); 1752015a6ef6SSaurabh Misra atge_rxfilter(atgep); 1753015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock); 1754015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_intr_lock); 1755015a6ef6SSaurabh Misra 1756015a6ef6SSaurabh Misra return (0); 1757015a6ef6SSaurabh Misra } 1758015a6ef6SSaurabh Misra 1759015a6ef6SSaurabh Misra mblk_t * 1760015a6ef6SSaurabh Misra atge_m_tx(void *arg, mblk_t *mp) 1761015a6ef6SSaurabh Misra { 1762015a6ef6SSaurabh Misra atge_t *atgep = arg; 1763015a6ef6SSaurabh Misra mblk_t *nmp; 1764015a6ef6SSaurabh Misra 1765015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock); 1766015a6ef6SSaurabh Misra 1767015a6ef6SSaurabh Misra /* 1768015a6ef6SSaurabh Misra * This NIC does not like us to send pkt when link is down. 1769015a6ef6SSaurabh Misra */ 1770015a6ef6SSaurabh Misra if (!(atgep->atge_link_state & LINK_STATE_UP)) { 1771015a6ef6SSaurabh Misra atgep->atge_tx_resched = 1; 17720eb090a7SSaurabh Misra 1773015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock); 1774015a6ef6SSaurabh Misra return (mp); 1775015a6ef6SSaurabh Misra } 1776015a6ef6SSaurabh Misra 1777015a6ef6SSaurabh Misra /* 1778015a6ef6SSaurabh Misra * Don't send a pkt if chip isn't running or in suspended state. 1779015a6ef6SSaurabh Misra */ 1780015a6ef6SSaurabh Misra if ((atgep->atge_chip_state & ATGE_CHIP_RUNNING) == 0 || 1781015a6ef6SSaurabh Misra atgep->atge_chip_state & ATGE_CHIP_SUSPENDED) { 1782015a6ef6SSaurabh Misra atgep->atge_carrier_errors++; 1783015a6ef6SSaurabh Misra atgep->atge_tx_resched = 1; 17840eb090a7SSaurabh Misra 1785015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock); 1786015a6ef6SSaurabh Misra return (mp); 1787015a6ef6SSaurabh Misra } 1788015a6ef6SSaurabh Misra 1789015a6ef6SSaurabh Misra while (mp != NULL) { 1790015a6ef6SSaurabh Misra nmp = mp->b_next; 1791015a6ef6SSaurabh Misra mp->b_next = NULL; 1792015a6ef6SSaurabh Misra 17930eb090a7SSaurabh Misra if (atge_send_a_packet(atgep, mp) == DDI_FAILURE) { 1794015a6ef6SSaurabh Misra mp->b_next = nmp; 1795015a6ef6SSaurabh Misra break; 1796015a6ef6SSaurabh Misra } 1797015a6ef6SSaurabh Misra 1798015a6ef6SSaurabh Misra mp = nmp; 1799015a6ef6SSaurabh Misra } 1800015a6ef6SSaurabh Misra 1801015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock); 1802015a6ef6SSaurabh Misra return (mp); 1803015a6ef6SSaurabh Misra } 1804015a6ef6SSaurabh Misra 1805015a6ef6SSaurabh Misra int 1806015a6ef6SSaurabh Misra atge_m_start(void *arg) 1807015a6ef6SSaurabh Misra { 1808015a6ef6SSaurabh Misra atge_t *atgep = arg; 1809015a6ef6SSaurabh Misra int started = 0; 1810015a6ef6SSaurabh Misra 1811015a6ef6SSaurabh Misra ASSERT(atgep != NULL); 1812015a6ef6SSaurabh Misra 1813015a6ef6SSaurabh Misra 1814015a6ef6SSaurabh Misra mii_stop(atgep->atge_mii); 1815015a6ef6SSaurabh Misra 1816015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_intr_lock); 1817015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock); 1818015a6ef6SSaurabh Misra 1819015a6ef6SSaurabh Misra if (!(atgep->atge_chip_state & ATGE_CHIP_SUSPENDED)) { 1820015a6ef6SSaurabh Misra atge_device_restart(atgep); 1821015a6ef6SSaurabh Misra started = 1; 1822015a6ef6SSaurabh Misra } 1823015a6ef6SSaurabh Misra 1824015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock); 1825015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_intr_lock); 1826015a6ef6SSaurabh Misra 1827015a6ef6SSaurabh Misra mii_start(atgep->atge_mii); 1828015a6ef6SSaurabh Misra 1829015a6ef6SSaurabh Misra /* kick-off downstream */ 1830015a6ef6SSaurabh Misra if (started) 1831015a6ef6SSaurabh Misra mac_tx_update(atgep->atge_mh); 1832015a6ef6SSaurabh Misra 1833015a6ef6SSaurabh Misra return (0); 1834015a6ef6SSaurabh Misra } 1835015a6ef6SSaurabh Misra 1836015a6ef6SSaurabh Misra void 1837015a6ef6SSaurabh Misra atge_m_stop(void *arg) 1838015a6ef6SSaurabh Misra { 1839015a6ef6SSaurabh Misra atge_t *atgep = arg; 1840015a6ef6SSaurabh Misra 1841015a6ef6SSaurabh Misra mii_stop(atgep->atge_mii); 1842015a6ef6SSaurabh Misra 1843015a6ef6SSaurabh Misra /* 1844015a6ef6SSaurabh Misra * Cancel any pending I/O. 1845015a6ef6SSaurabh Misra */ 1846015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_intr_lock); 1847015a6ef6SSaurabh Misra atgep->atge_chip_state &= ~ATGE_CHIP_RUNNING; 1848015a6ef6SSaurabh Misra if (!(atgep->atge_chip_state & ATGE_CHIP_SUSPENDED)) 1849015a6ef6SSaurabh Misra atge_device_stop(atgep); 1850015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_intr_lock); 1851015a6ef6SSaurabh Misra } 1852015a6ef6SSaurabh Misra 1853015a6ef6SSaurabh Misra int 1854015a6ef6SSaurabh Misra atge_m_stat(void *arg, uint_t stat, uint64_t *val) 1855015a6ef6SSaurabh Misra { 1856015a6ef6SSaurabh Misra atge_t *atgep = arg; 1857015a6ef6SSaurabh Misra 1858015a6ef6SSaurabh Misra if (mii_m_getstat(atgep->atge_mii, stat, val) == 0) { 1859015a6ef6SSaurabh Misra return (0); 1860015a6ef6SSaurabh Misra } 1861015a6ef6SSaurabh Misra 1862015a6ef6SSaurabh Misra switch (stat) { 1863015a6ef6SSaurabh Misra case MAC_STAT_MULTIRCV: 1864015a6ef6SSaurabh Misra *val = atgep->atge_multircv; 1865015a6ef6SSaurabh Misra break; 1866015a6ef6SSaurabh Misra 1867015a6ef6SSaurabh Misra case MAC_STAT_BRDCSTRCV: 1868015a6ef6SSaurabh Misra *val = atgep->atge_brdcstrcv; 1869015a6ef6SSaurabh Misra break; 1870015a6ef6SSaurabh Misra 1871015a6ef6SSaurabh Misra case MAC_STAT_MULTIXMT: 1872015a6ef6SSaurabh Misra *val = atgep->atge_multixmt; 1873015a6ef6SSaurabh Misra break; 1874015a6ef6SSaurabh Misra 1875015a6ef6SSaurabh Misra case MAC_STAT_BRDCSTXMT: 1876015a6ef6SSaurabh Misra *val = atgep->atge_brdcstxmt; 1877015a6ef6SSaurabh Misra break; 1878015a6ef6SSaurabh Misra 1879015a6ef6SSaurabh Misra case MAC_STAT_IPACKETS: 1880015a6ef6SSaurabh Misra *val = atgep->atge_ipackets; 1881015a6ef6SSaurabh Misra break; 1882015a6ef6SSaurabh Misra 1883015a6ef6SSaurabh Misra case MAC_STAT_RBYTES: 1884015a6ef6SSaurabh Misra *val = atgep->atge_rbytes; 1885015a6ef6SSaurabh Misra break; 1886015a6ef6SSaurabh Misra 1887015a6ef6SSaurabh Misra case MAC_STAT_OPACKETS: 1888015a6ef6SSaurabh Misra *val = atgep->atge_opackets; 1889015a6ef6SSaurabh Misra break; 1890015a6ef6SSaurabh Misra 1891015a6ef6SSaurabh Misra case MAC_STAT_OBYTES: 1892015a6ef6SSaurabh Misra *val = atgep->atge_obytes; 1893015a6ef6SSaurabh Misra break; 1894015a6ef6SSaurabh Misra 1895015a6ef6SSaurabh Misra case MAC_STAT_NORCVBUF: 1896015a6ef6SSaurabh Misra *val = atgep->atge_norcvbuf; 1897015a6ef6SSaurabh Misra break; 1898015a6ef6SSaurabh Misra 1899015a6ef6SSaurabh Misra case MAC_STAT_NOXMTBUF: 1900015a6ef6SSaurabh Misra *val = 0; 1901015a6ef6SSaurabh Misra break; 1902015a6ef6SSaurabh Misra 1903015a6ef6SSaurabh Misra case MAC_STAT_COLLISIONS: 1904015a6ef6SSaurabh Misra *val = atgep->atge_collisions; 1905015a6ef6SSaurabh Misra break; 1906015a6ef6SSaurabh Misra 1907015a6ef6SSaurabh Misra case MAC_STAT_IERRORS: 1908015a6ef6SSaurabh Misra *val = atgep->atge_errrcv; 1909015a6ef6SSaurabh Misra break; 1910015a6ef6SSaurabh Misra 1911015a6ef6SSaurabh Misra case MAC_STAT_OERRORS: 1912015a6ef6SSaurabh Misra *val = atgep->atge_errxmt; 1913015a6ef6SSaurabh Misra break; 1914015a6ef6SSaurabh Misra 1915015a6ef6SSaurabh Misra case ETHER_STAT_ALIGN_ERRORS: 1916015a6ef6SSaurabh Misra *val = atgep->atge_align_errors; 1917015a6ef6SSaurabh Misra break; 1918015a6ef6SSaurabh Misra 1919015a6ef6SSaurabh Misra case ETHER_STAT_FCS_ERRORS: 1920015a6ef6SSaurabh Misra *val = atgep->atge_fcs_errors; 1921015a6ef6SSaurabh Misra break; 1922015a6ef6SSaurabh Misra 1923015a6ef6SSaurabh Misra case ETHER_STAT_SQE_ERRORS: 1924015a6ef6SSaurabh Misra *val = atgep->atge_sqe_errors; 1925015a6ef6SSaurabh Misra break; 1926015a6ef6SSaurabh Misra 1927015a6ef6SSaurabh Misra case ETHER_STAT_DEFER_XMTS: 1928015a6ef6SSaurabh Misra *val = atgep->atge_defer_xmts; 1929015a6ef6SSaurabh Misra break; 1930015a6ef6SSaurabh Misra 1931015a6ef6SSaurabh Misra case ETHER_STAT_FIRST_COLLISIONS: 1932015a6ef6SSaurabh Misra *val = atgep->atge_first_collisions; 1933015a6ef6SSaurabh Misra break; 1934015a6ef6SSaurabh Misra 1935015a6ef6SSaurabh Misra case ETHER_STAT_MULTI_COLLISIONS: 1936015a6ef6SSaurabh Misra *val = atgep->atge_multi_collisions; 1937015a6ef6SSaurabh Misra break; 1938015a6ef6SSaurabh Misra 1939015a6ef6SSaurabh Misra case ETHER_STAT_TX_LATE_COLLISIONS: 1940015a6ef6SSaurabh Misra *val = atgep->atge_tx_late_collisions; 1941015a6ef6SSaurabh Misra break; 1942015a6ef6SSaurabh Misra 1943015a6ef6SSaurabh Misra case ETHER_STAT_EX_COLLISIONS: 1944015a6ef6SSaurabh Misra *val = atgep->atge_ex_collisions; 1945015a6ef6SSaurabh Misra break; 1946015a6ef6SSaurabh Misra 1947015a6ef6SSaurabh Misra case ETHER_STAT_MACXMT_ERRORS: 1948015a6ef6SSaurabh Misra *val = atgep->atge_macxmt_errors; 1949015a6ef6SSaurabh Misra break; 1950015a6ef6SSaurabh Misra 1951015a6ef6SSaurabh Misra case ETHER_STAT_CARRIER_ERRORS: 1952015a6ef6SSaurabh Misra *val = atgep->atge_carrier_errors; 1953015a6ef6SSaurabh Misra break; 1954015a6ef6SSaurabh Misra 1955015a6ef6SSaurabh Misra case ETHER_STAT_TOOLONG_ERRORS: 1956015a6ef6SSaurabh Misra *val = atgep->atge_toolong_errors; 1957015a6ef6SSaurabh Misra break; 1958015a6ef6SSaurabh Misra 1959015a6ef6SSaurabh Misra case ETHER_STAT_MACRCV_ERRORS: 1960015a6ef6SSaurabh Misra *val = atgep->atge_macrcv_errors; 1961015a6ef6SSaurabh Misra break; 1962015a6ef6SSaurabh Misra 1963015a6ef6SSaurabh Misra case MAC_STAT_OVERFLOWS: 1964015a6ef6SSaurabh Misra *val = atgep->atge_overflow; 1965015a6ef6SSaurabh Misra break; 1966015a6ef6SSaurabh Misra 1967015a6ef6SSaurabh Misra case MAC_STAT_UNDERFLOWS: 1968015a6ef6SSaurabh Misra *val = atgep->atge_underflow; 1969015a6ef6SSaurabh Misra break; 1970015a6ef6SSaurabh Misra 1971015a6ef6SSaurabh Misra case ETHER_STAT_TOOSHORT_ERRORS: 1972015a6ef6SSaurabh Misra *val = atgep->atge_runt; 1973015a6ef6SSaurabh Misra break; 1974015a6ef6SSaurabh Misra 1975015a6ef6SSaurabh Misra case ETHER_STAT_JABBER_ERRORS: 1976015a6ef6SSaurabh Misra *val = atgep->atge_jabber; 1977015a6ef6SSaurabh Misra break; 1978015a6ef6SSaurabh Misra 1979015a6ef6SSaurabh Misra default: 1980015a6ef6SSaurabh Misra return (ENOTSUP); 1981015a6ef6SSaurabh Misra } 1982015a6ef6SSaurabh Misra 1983015a6ef6SSaurabh Misra return (0); 1984015a6ef6SSaurabh Misra } 1985015a6ef6SSaurabh Misra 1986015a6ef6SSaurabh Misra int 19870dc2366fSVenugopal Iyer atge_m_getprop(void *arg, const char *name, mac_prop_id_t num, uint_t sz, 19880dc2366fSVenugopal Iyer void *val) 1989015a6ef6SSaurabh Misra { 1990015a6ef6SSaurabh Misra atge_t *atgep = arg; 1991015a6ef6SSaurabh Misra 19920dc2366fSVenugopal Iyer return (mii_m_getprop(atgep->atge_mii, name, num, sz, val)); 1993015a6ef6SSaurabh Misra } 1994015a6ef6SSaurabh Misra 1995015a6ef6SSaurabh Misra int 1996015a6ef6SSaurabh Misra atge_m_setprop(void *arg, const char *name, mac_prop_id_t num, uint_t sz, 1997015a6ef6SSaurabh Misra const void *val) 1998015a6ef6SSaurabh Misra { 1999015a6ef6SSaurabh Misra atge_t *atgep = arg; 20000eb090a7SSaurabh Misra int r; 2001015a6ef6SSaurabh Misra 20020eb090a7SSaurabh Misra r = mii_m_setprop(atgep->atge_mii, name, num, sz, val); 20030eb090a7SSaurabh Misra 20040eb090a7SSaurabh Misra if (r == 0) { 20050eb090a7SSaurabh Misra mutex_enter(&atgep->atge_intr_lock); 20060eb090a7SSaurabh Misra mutex_enter(&atgep->atge_tx_lock); 20070eb090a7SSaurabh Misra 20080eb090a7SSaurabh Misra if (atgep->atge_chip_state & ATGE_CHIP_RUNNING) { 20090eb090a7SSaurabh Misra atge_device_restart(atgep); 20100eb090a7SSaurabh Misra } 20110eb090a7SSaurabh Misra 20120eb090a7SSaurabh Misra mutex_exit(&atgep->atge_tx_lock); 20130eb090a7SSaurabh Misra mutex_exit(&atgep->atge_intr_lock); 20140eb090a7SSaurabh Misra } 20150eb090a7SSaurabh Misra 20160eb090a7SSaurabh Misra return (r); 2017015a6ef6SSaurabh Misra } 2018015a6ef6SSaurabh Misra 20190dc2366fSVenugopal Iyer static void 20200dc2366fSVenugopal Iyer atge_m_propinfo(void *arg, const char *name, mac_prop_id_t num, 20210dc2366fSVenugopal Iyer mac_prop_info_handle_t prh) 20220dc2366fSVenugopal Iyer { 20230dc2366fSVenugopal Iyer atge_t *atgep = arg; 20240dc2366fSVenugopal Iyer 20250dc2366fSVenugopal Iyer mii_m_propinfo(atgep->atge_mii, name, num, prh); 20260dc2366fSVenugopal Iyer } 2027015a6ef6SSaurabh Misra 2028015a6ef6SSaurabh Misra void 2029015a6ef6SSaurabh Misra atge_program_ether(atge_t *atgep) 2030015a6ef6SSaurabh Misra { 2031015a6ef6SSaurabh Misra ether_addr_t e; 2032015a6ef6SSaurabh Misra 2033015a6ef6SSaurabh Misra /* 2034015a6ef6SSaurabh Misra * Reprogram the Station address. 2035015a6ef6SSaurabh Misra */ 2036015a6ef6SSaurabh Misra bcopy(atgep->atge_ether_addr, e, ETHERADDRL); 2037015a6ef6SSaurabh Misra OUTL(atgep, ATGE_PAR0, 2038015a6ef6SSaurabh Misra ((e[2] << 24) | (e[3] << 16) | (e[4] << 8) | e[5])); 2039015a6ef6SSaurabh Misra OUTL(atgep, ATGE_PAR1, (e[0] << 8) | e[1]); 2040015a6ef6SSaurabh Misra } 2041015a6ef6SSaurabh Misra 2042015a6ef6SSaurabh Misra /* 2043015a6ef6SSaurabh Misra * Device specific operations. 2044015a6ef6SSaurabh Misra */ 2045015a6ef6SSaurabh Misra void 2046015a6ef6SSaurabh Misra atge_device_start(atge_t *atgep) 2047015a6ef6SSaurabh Misra { 20480eb090a7SSaurabh Misra uint32_t rxf_hi, rxf_lo, rrd_hi, rrd_lo; 2049015a6ef6SSaurabh Misra uint32_t reg; 2050015a6ef6SSaurabh Misra uint32_t fsize; 2051015a6ef6SSaurabh Misra 2052015a6ef6SSaurabh Misra /* 2053015a6ef6SSaurabh Misra * Reprogram the Station address. 2054015a6ef6SSaurabh Misra */ 2055015a6ef6SSaurabh Misra atge_program_ether(atgep); 2056015a6ef6SSaurabh Misra 2057*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 2058*5e8715b9SGary Mills case ATGE_CHIP_L1E: 2059015a6ef6SSaurabh Misra atge_l1e_program_dma(atgep); 2060*5e8715b9SGary Mills break; 2061*5e8715b9SGary Mills case ATGE_CHIP_L1: 20620eb090a7SSaurabh Misra atge_l1_program_dma(atgep); 2063*5e8715b9SGary Mills break; 2064*5e8715b9SGary Mills case ATGE_CHIP_L1C: 2065*5e8715b9SGary Mills atge_l1c_program_dma(atgep); 2066*5e8715b9SGary Mills break; 2067015a6ef6SSaurabh Misra } 2068015a6ef6SSaurabh Misra 2069015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() dma, counters programmed ", atgep->atge_name, 2070015a6ef6SSaurabh Misra __func__)); 2071015a6ef6SSaurabh Misra 2072*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 2073*5e8715b9SGary Mills case ATGE_CHIP_L1E: 2074*5e8715b9SGary Mills case ATGE_CHIP_L1: 2075015a6ef6SSaurabh Misra OUTW(atgep, ATGE_INTR_CLR_TIMER, 1*1000/2); 2076*5e8715b9SGary Mills break; 2077*5e8715b9SGary Mills case ATGE_CHIP_L1C: 2078*5e8715b9SGary Mills /* 2079*5e8715b9SGary Mills * Disable interrupt re-trigger timer. We don't want automatic 2080*5e8715b9SGary Mills * re-triggering of un-ACKed interrupts. 2081*5e8715b9SGary Mills */ 2082*5e8715b9SGary Mills OUTL(atgep, ATGE_INTR_RETRIG_TIMER, ATGE_USECS(0)); 2083*5e8715b9SGary Mills /* Configure CMB. */ 2084*5e8715b9SGary Mills OUTL(atgep, ATGE_CMB_TX_TIMER, ATGE_USECS(0)); 2085*5e8715b9SGary Mills /* 2086*5e8715b9SGary Mills * Hardware can be configured to issue SMB interrupt based 2087*5e8715b9SGary Mills * on programmed interval. Since there is a callout that is 2088*5e8715b9SGary Mills * invoked for every hz in driver we use that instead of 2089*5e8715b9SGary Mills * relying on periodic SMB interrupt. 2090*5e8715b9SGary Mills */ 2091*5e8715b9SGary Mills OUTL(atgep, ATGE_SMB_STAT_TIMER, ATGE_USECS(0)); 2092*5e8715b9SGary Mills /* Clear MAC statistics. */ 2093*5e8715b9SGary Mills atge_l1c_clear_stats(atgep); 2094*5e8715b9SGary Mills break; 2095*5e8715b9SGary Mills } 2096015a6ef6SSaurabh Misra 2097015a6ef6SSaurabh Misra /* 20980eb090a7SSaurabh Misra * Set Maximum frame size but don't let MTU be less than ETHER_MTU. 2099015a6ef6SSaurabh Misra */ 2100015a6ef6SSaurabh Misra if (atgep->atge_mtu < ETHERMTU) 2101015a6ef6SSaurabh Misra atgep->atge_max_frame_size = ETHERMTU; 2102015a6ef6SSaurabh Misra else 2103015a6ef6SSaurabh Misra atgep->atge_max_frame_size = atgep->atge_mtu; 2104015a6ef6SSaurabh Misra 2105015a6ef6SSaurabh Misra atgep->atge_max_frame_size += sizeof (struct ether_header) + 2106015a6ef6SSaurabh Misra VLAN_TAGSZ + ETHERFCSL; 2107015a6ef6SSaurabh Misra OUTL(atgep, ATGE_FRAME_SIZE, atgep->atge_max_frame_size); 2108015a6ef6SSaurabh Misra 2109*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 2110*5e8715b9SGary Mills case ATGE_CHIP_L1E: 2111*5e8715b9SGary Mills break; 2112*5e8715b9SGary Mills case ATGE_CHIP_L1: 2113*5e8715b9SGary Mills break; 2114*5e8715b9SGary Mills case ATGE_CHIP_L1C: 2115*5e8715b9SGary Mills /* Disable header split(?) */ 2116*5e8715b9SGary Mills OUTL(atgep, ATGE_HDS_CFG, 0); 2117*5e8715b9SGary Mills break; 2118*5e8715b9SGary Mills } 2119015a6ef6SSaurabh Misra 2120015a6ef6SSaurabh Misra /* 2121015a6ef6SSaurabh Misra * Configure IPG/IFG parameters. 2122015a6ef6SSaurabh Misra */ 2123015a6ef6SSaurabh Misra OUTL(atgep, ATGE_IPG_IFG_CFG, 2124015a6ef6SSaurabh Misra ((IPG_IFG_IPG2_DEFAULT << IPG_IFG_IPG2_SHIFT) & IPG_IFG_IPG2_MASK) | 2125015a6ef6SSaurabh Misra ((IPG_IFG_IPG1_DEFAULT << IPG_IFG_IPG1_SHIFT) & IPG_IFG_IPG1_MASK) | 2126015a6ef6SSaurabh Misra ((IPG_IFG_MIFG_DEFAULT << IPG_IFG_MIFG_SHIFT) & IPG_IFG_MIFG_MASK) | 2127015a6ef6SSaurabh Misra ((IPG_IFG_IPGT_DEFAULT << IPG_IFG_IPGT_SHIFT) & IPG_IFG_IPGT_MASK)); 2128015a6ef6SSaurabh Misra 2129015a6ef6SSaurabh Misra /* 2130015a6ef6SSaurabh Misra * Set parameters for half-duplex media. 2131015a6ef6SSaurabh Misra */ 2132015a6ef6SSaurabh Misra OUTL(atgep, ATGE_HDPX_CFG, 2133015a6ef6SSaurabh Misra ((HDPX_CFG_LCOL_DEFAULT << HDPX_CFG_LCOL_SHIFT) & 2134015a6ef6SSaurabh Misra HDPX_CFG_LCOL_MASK) | 2135015a6ef6SSaurabh Misra ((HDPX_CFG_RETRY_DEFAULT << HDPX_CFG_RETRY_SHIFT) & 2136015a6ef6SSaurabh Misra HDPX_CFG_RETRY_MASK) | HDPX_CFG_EXC_DEF_EN | 2137015a6ef6SSaurabh Misra ((HDPX_CFG_ABEBT_DEFAULT << HDPX_CFG_ABEBT_SHIFT) & 2138015a6ef6SSaurabh Misra HDPX_CFG_ABEBT_MASK) | 2139015a6ef6SSaurabh Misra ((HDPX_CFG_JAMIPG_DEFAULT << HDPX_CFG_JAMIPG_SHIFT) & 2140015a6ef6SSaurabh Misra HDPX_CFG_JAMIPG_MASK)); 2141015a6ef6SSaurabh Misra 2142015a6ef6SSaurabh Misra /* 2143015a6ef6SSaurabh Misra * Configure jumbo frame. 2144015a6ef6SSaurabh Misra */ 2145*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 2146*5e8715b9SGary Mills case ATGE_CHIP_L1E: 2147*5e8715b9SGary Mills if (atgep->atge_flags & ATGE_FLAG_JUMBO) { 2148015a6ef6SSaurabh Misra 2149015a6ef6SSaurabh Misra if (atgep->atge_mtu < ETHERMTU) 2150015a6ef6SSaurabh Misra reg = atgep->atge_max_frame_size; 2151015a6ef6SSaurabh Misra else if (atgep->atge_mtu < 6 * 1024) 2152015a6ef6SSaurabh Misra reg = (atgep->atge_max_frame_size * 2) / 3; 2153015a6ef6SSaurabh Misra else 2154015a6ef6SSaurabh Misra reg = atgep->atge_max_frame_size / 2; 2155015a6ef6SSaurabh Misra 2156015a6ef6SSaurabh Misra OUTL(atgep, L1E_TX_JUMBO_THRESH, 2157015a6ef6SSaurabh Misra ROUNDUP(reg, TX_JUMBO_THRESH_UNIT) >> 2158015a6ef6SSaurabh Misra TX_JUMBO_THRESH_UNIT_SHIFT); 2159015a6ef6SSaurabh Misra } 2160*5e8715b9SGary Mills break; 2161*5e8715b9SGary Mills case ATGE_CHIP_L1: 2162*5e8715b9SGary Mills fsize = ROUNDUP(atgep->atge_max_frame_size, sizeof (uint64_t)); 2163*5e8715b9SGary Mills OUTL(atgep, ATGE_RXQ_JUMBO_CFG, 2164*5e8715b9SGary Mills (((fsize / sizeof (uint64_t)) << 2165*5e8715b9SGary Mills RXQ_JUMBO_CFG_SZ_THRESH_SHIFT) & 2166*5e8715b9SGary Mills RXQ_JUMBO_CFG_SZ_THRESH_MASK) | 2167*5e8715b9SGary Mills ((RXQ_JUMBO_CFG_LKAH_DEFAULT << 2168*5e8715b9SGary Mills RXQ_JUMBO_CFG_LKAH_SHIFT) & RXQ_JUMBO_CFG_LKAH_MASK) | 2169*5e8715b9SGary Mills ((ATGE_USECS(8) << RXQ_JUMBO_CFG_RRD_TIMER_SHIFT) & 2170*5e8715b9SGary Mills RXQ_JUMBO_CFG_RRD_TIMER_MASK)); 2171*5e8715b9SGary Mills break; 2172*5e8715b9SGary Mills case ATGE_CHIP_L1C: 2173*5e8715b9SGary Mills break; 2174*5e8715b9SGary Mills } 2175015a6ef6SSaurabh Misra 2176015a6ef6SSaurabh Misra /* 2177015a6ef6SSaurabh Misra * Configure flow-control parameters. 2178015a6ef6SSaurabh Misra */ 2179*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 2180*5e8715b9SGary Mills case ATGE_CHIP_L1E: 2181*5e8715b9SGary Mills case ATGE_CHIP_L1: 2182015a6ef6SSaurabh Misra if ((atgep->atge_flags & ATGE_FLAG_PCIE) != 0) { 2183015a6ef6SSaurabh Misra /* 2184015a6ef6SSaurabh Misra * Some hardware version require this magic. 2185015a6ef6SSaurabh Misra */ 2186*5e8715b9SGary Mills OUTL(atgep, ATGE_LTSSM_ID_CFG, 0x6500); 2187015a6ef6SSaurabh Misra reg = INL(atgep, 0x1008); 2188015a6ef6SSaurabh Misra OUTL(atgep, 0x1008, reg | 0x8000); 2189015a6ef6SSaurabh Misra } 2190*5e8715b9SGary Mills break; 2191*5e8715b9SGary Mills case ATGE_CHIP_L1C: 2192*5e8715b9SGary Mills break; 2193*5e8715b9SGary Mills } 2194015a6ef6SSaurabh Misra 2195015a6ef6SSaurabh Misra /* 2196015a6ef6SSaurabh Misra * These are all magic parameters which came from FreeBSD. 2197015a6ef6SSaurabh Misra */ 2198*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 2199*5e8715b9SGary Mills case ATGE_CHIP_L1E: 2200*5e8715b9SGary Mills reg = INL(atgep, L1E_SRAM_RX_FIFO_LEN); 2201*5e8715b9SGary Mills rxf_hi = (reg * 4) / 5; 2202*5e8715b9SGary Mills rxf_lo = reg/ 5; 2203*5e8715b9SGary Mills 2204*5e8715b9SGary Mills OUTL(atgep, ATGE_RXQ_FIFO_PAUSE_THRESH, 2205*5e8715b9SGary Mills ((rxf_lo << RXQ_FIFO_PAUSE_THRESH_LO_SHIFT) & 2206*5e8715b9SGary Mills RXQ_FIFO_PAUSE_THRESH_LO_MASK) | 2207*5e8715b9SGary Mills ((rxf_hi << RXQ_FIFO_PAUSE_THRESH_HI_SHIFT) & 2208*5e8715b9SGary Mills RXQ_FIFO_PAUSE_THRESH_HI_MASK)); 2209*5e8715b9SGary Mills break; 2210*5e8715b9SGary Mills case ATGE_CHIP_L1: 22110eb090a7SSaurabh Misra switch (atgep->atge_chip_rev) { 22120eb090a7SSaurabh Misra case 0x8001: 22130eb090a7SSaurabh Misra case 0x9001: 22140eb090a7SSaurabh Misra case 0x9002: 22150eb090a7SSaurabh Misra case 0x9003: 22160eb090a7SSaurabh Misra rxf_hi = L1_RX_RING_CNT / 16; 22170eb090a7SSaurabh Misra rxf_lo = (L1_RX_RING_CNT * 7) / 8; 22180eb090a7SSaurabh Misra rrd_hi = (L1_RR_RING_CNT * 7) / 8; 22190eb090a7SSaurabh Misra rrd_lo = L1_RR_RING_CNT / 16; 22200eb090a7SSaurabh Misra break; 22210eb090a7SSaurabh Misra default: 22220eb090a7SSaurabh Misra reg = INL(atgep, L1_SRAM_RX_FIFO_LEN); 22230eb090a7SSaurabh Misra rxf_lo = reg / 16; 22240eb090a7SSaurabh Misra if (rxf_lo > 192) 22250eb090a7SSaurabh Misra rxf_lo = 192; 22260eb090a7SSaurabh Misra rxf_hi = (reg * 7) / 8; 22270eb090a7SSaurabh Misra if (rxf_hi < rxf_lo) 22280eb090a7SSaurabh Misra rxf_hi = rxf_lo + 16; 22290eb090a7SSaurabh Misra reg = INL(atgep, L1_SRAM_RRD_LEN); 22300eb090a7SSaurabh Misra rrd_lo = reg / 8; 22310eb090a7SSaurabh Misra rrd_hi = (reg * 7) / 8; 22320eb090a7SSaurabh Misra if (rrd_lo > 2) 22330eb090a7SSaurabh Misra rrd_lo = 2; 22340eb090a7SSaurabh Misra if (rrd_hi < rrd_lo) 22350eb090a7SSaurabh Misra rrd_hi = rrd_lo + 3; 22360eb090a7SSaurabh Misra break; 22370eb090a7SSaurabh Misra } 22380eb090a7SSaurabh Misra 22390eb090a7SSaurabh Misra OUTL(atgep, ATGE_RXQ_FIFO_PAUSE_THRESH, 22400eb090a7SSaurabh Misra ((rxf_lo << RXQ_FIFO_PAUSE_THRESH_LO_SHIFT) & 22410eb090a7SSaurabh Misra RXQ_FIFO_PAUSE_THRESH_LO_MASK) | 22420eb090a7SSaurabh Misra ((rxf_hi << RXQ_FIFO_PAUSE_THRESH_HI_SHIFT) & 22430eb090a7SSaurabh Misra RXQ_FIFO_PAUSE_THRESH_HI_MASK)); 22440eb090a7SSaurabh Misra 22450eb090a7SSaurabh Misra OUTL(atgep, L1_RXQ_RRD_PAUSE_THRESH, 22460eb090a7SSaurabh Misra ((rrd_lo << RXQ_RRD_PAUSE_THRESH_LO_SHIFT) & 22470eb090a7SSaurabh Misra RXQ_RRD_PAUSE_THRESH_LO_MASK) | 22480eb090a7SSaurabh Misra ((rrd_hi << RXQ_RRD_PAUSE_THRESH_HI_SHIFT) & 22490eb090a7SSaurabh Misra RXQ_RRD_PAUSE_THRESH_HI_MASK)); 2250*5e8715b9SGary Mills break; 2251*5e8715b9SGary Mills case ATGE_CHIP_L1C: 2252*5e8715b9SGary Mills switch (ATGE_DID(atgep)) { 2253*5e8715b9SGary Mills case ATGE_CHIP_AR8151V2_DEV_ID: 2254*5e8715b9SGary Mills case ATGE_CHIP_AR8152V1_DEV_ID: 2255*5e8715b9SGary Mills OUTL(atgep, ATGE_SERDES_LOCK, 2256*5e8715b9SGary Mills INL(atgep, ATGE_SERDES_LOCK) | 2257*5e8715b9SGary Mills SERDES_MAC_CLK_SLOWDOWN | 2258*5e8715b9SGary Mills SERDES_PHY_CLK_SLOWDOWN); 2259*5e8715b9SGary Mills break; 2260*5e8715b9SGary Mills case ATGE_CHIP_L1CG_DEV_ID: 2261*5e8715b9SGary Mills case ATGE_CHIP_L1CF_DEV_ID: 2262*5e8715b9SGary Mills /* 2263*5e8715b9SGary Mills * Configure flow control parameters. 2264*5e8715b9SGary Mills * XON : 80% of Rx FIFO 2265*5e8715b9SGary Mills * XOFF : 30% of Rx FIFO 2266*5e8715b9SGary Mills */ 2267*5e8715b9SGary Mills reg = INL(atgep, L1C_SRAM_RX_FIFO_LEN); 2268*5e8715b9SGary Mills rxf_hi = (reg * 8) / 10; 2269*5e8715b9SGary Mills rxf_lo = (reg * 3) / 10; 2270015a6ef6SSaurabh Misra 2271015a6ef6SSaurabh Misra OUTL(atgep, ATGE_RXQ_FIFO_PAUSE_THRESH, 2272015a6ef6SSaurabh Misra ((rxf_lo << RXQ_FIFO_PAUSE_THRESH_LO_SHIFT) & 2273015a6ef6SSaurabh Misra RXQ_FIFO_PAUSE_THRESH_LO_MASK) | 2274015a6ef6SSaurabh Misra ((rxf_hi << RXQ_FIFO_PAUSE_THRESH_HI_SHIFT) & 2275015a6ef6SSaurabh Misra RXQ_FIFO_PAUSE_THRESH_HI_MASK)); 2276*5e8715b9SGary Mills break; 2277*5e8715b9SGary Mills } 2278*5e8715b9SGary Mills break; 2279015a6ef6SSaurabh Misra } 2280015a6ef6SSaurabh Misra 2281*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 2282*5e8715b9SGary Mills case ATGE_CHIP_L1E: 2283015a6ef6SSaurabh Misra /* Configure RxQ. */ 2284015a6ef6SSaurabh Misra reg = RXQ_CFG_ALIGN_32 | RXQ_CFG_CUT_THROUGH_ENB | 2285015a6ef6SSaurabh Misra RXQ_CFG_IPV6_CSUM_VERIFY | RXQ_CFG_ENB; 2286015a6ef6SSaurabh Misra OUTL(atgep, ATGE_RXQ_CFG, reg); 2287015a6ef6SSaurabh Misra /* 2288015a6ef6SSaurabh Misra * Configure TxQ. 2289015a6ef6SSaurabh Misra */ 2290015a6ef6SSaurabh Misra reg = (128 << 2291015a6ef6SSaurabh Misra (atgep->atge_dma_rd_burst >> DMA_CFG_RD_BURST_SHIFT)) << 2292015a6ef6SSaurabh Misra TXQ_CFG_TX_FIFO_BURST_SHIFT; 2293015a6ef6SSaurabh Misra 2294015a6ef6SSaurabh Misra reg |= (TXQ_CFG_TPD_BURST_DEFAULT << TXQ_CFG_TPD_BURST_SHIFT) & 2295015a6ef6SSaurabh Misra TXQ_CFG_TPD_BURST_MASK; 2296015a6ef6SSaurabh Misra 2297015a6ef6SSaurabh Misra reg |= TXQ_CFG_ENHANCED_MODE | TXQ_CFG_ENB; 2298015a6ef6SSaurabh Misra 2299015a6ef6SSaurabh Misra OUTL(atgep, ATGE_TXQ_CFG, reg); 2300015a6ef6SSaurabh Misra /* Disable RSS. */ 2301015a6ef6SSaurabh Misra OUTL(atgep, L1E_RSS_IDT_TABLE0, 0); 2302015a6ef6SSaurabh Misra OUTL(atgep, L1E_RSS_CPU, 0); 2303015a6ef6SSaurabh Misra /* 2304015a6ef6SSaurabh Misra * Configure DMA parameters. 2305015a6ef6SSaurabh Misra */ 2306015a6ef6SSaurabh Misra /* 2307015a6ef6SSaurabh Misra * Don't use Tx CMB. It is known to cause RRS update failure 2308015a6ef6SSaurabh Misra * under certain circumstances. Typical phenomenon of the 2309015a6ef6SSaurabh Misra * issue would be unexpected sequence number encountered in 2310015a6ef6SSaurabh Misra * Rx handler. Hence we don't set DMA_CFG_TXCMB_ENB. 2311015a6ef6SSaurabh Misra */ 2312015a6ef6SSaurabh Misra OUTL(atgep, ATGE_DMA_CFG, 2313015a6ef6SSaurabh Misra DMA_CFG_OUT_ORDER | DMA_CFG_RD_REQ_PRI | DMA_CFG_RCB_64 | 2314015a6ef6SSaurabh Misra atgep->atge_dma_rd_burst | atgep->atge_dma_wr_burst | 2315015a6ef6SSaurabh Misra DMA_CFG_RXCMB_ENB | 2316015a6ef6SSaurabh Misra ((DMA_CFG_RD_DELAY_CNT_DEFAULT << 2317015a6ef6SSaurabh Misra DMA_CFG_RD_DELAY_CNT_SHIFT) & DMA_CFG_RD_DELAY_CNT_MASK) | 2318015a6ef6SSaurabh Misra ((DMA_CFG_WR_DELAY_CNT_DEFAULT << 2319015a6ef6SSaurabh Misra DMA_CFG_WR_DELAY_CNT_SHIFT) & DMA_CFG_WR_DELAY_CNT_MASK)); 2320015a6ef6SSaurabh Misra /* 23210eb090a7SSaurabh Misra * Enable CMB/SMB timer. 2322015a6ef6SSaurabh Misra */ 2323*5e8715b9SGary Mills OUTL(atgep, L1E_SMB_STAT_TIMER, 100000); 2324*5e8715b9SGary Mills atge_l1e_clear_stats(atgep); 2325*5e8715b9SGary Mills break; 2326*5e8715b9SGary Mills case ATGE_CHIP_L1: 2327*5e8715b9SGary Mills /* Configure RxQ. */ 2328*5e8715b9SGary Mills reg = 2329*5e8715b9SGary Mills ((RXQ_CFG_RD_BURST_DEFAULT << RXQ_CFG_RD_BURST_SHIFT) & 2330*5e8715b9SGary Mills RXQ_CFG_RD_BURST_MASK) | 2331*5e8715b9SGary Mills ((RXQ_CFG_RRD_BURST_THRESH_DEFAULT << 2332*5e8715b9SGary Mills RXQ_CFG_RRD_BURST_THRESH_SHIFT) & 2333*5e8715b9SGary Mills RXQ_CFG_RRD_BURST_THRESH_MASK) | 2334*5e8715b9SGary Mills ((RXQ_CFG_RD_PREF_MIN_IPG_DEFAULT << 2335*5e8715b9SGary Mills RXQ_CFG_RD_PREF_MIN_IPG_SHIFT) & 2336*5e8715b9SGary Mills RXQ_CFG_RD_PREF_MIN_IPG_MASK) | 2337*5e8715b9SGary Mills RXQ_CFG_CUT_THROUGH_ENB | RXQ_CFG_ENB; 2338*5e8715b9SGary Mills OUTL(atgep, ATGE_RXQ_CFG, reg); 2339*5e8715b9SGary Mills /* 2340*5e8715b9SGary Mills * Configure TxQ. 2341*5e8715b9SGary Mills */ 2342*5e8715b9SGary Mills reg = 2343*5e8715b9SGary Mills (((TXQ_CFG_TPD_BURST_DEFAULT << TXQ_CFG_TPD_BURST_SHIFT) & 2344*5e8715b9SGary Mills TXQ_CFG_TPD_BURST_MASK) | 2345*5e8715b9SGary Mills ((TXQ_CFG_TX_FIFO_BURST_DEFAULT << 2346*5e8715b9SGary Mills TXQ_CFG_TX_FIFO_BURST_SHIFT) & 2347*5e8715b9SGary Mills TXQ_CFG_TX_FIFO_BURST_MASK) | 2348*5e8715b9SGary Mills ((TXQ_CFG_TPD_FETCH_DEFAULT << 2349*5e8715b9SGary Mills TXQ_CFG_TPD_FETCH_THRESH_SHIFT) & 2350*5e8715b9SGary Mills TXQ_CFG_TPD_FETCH_THRESH_MASK) | 2351*5e8715b9SGary Mills TXQ_CFG_ENB); 2352*5e8715b9SGary Mills OUTL(atgep, ATGE_TXQ_CFG, reg); 2353*5e8715b9SGary Mills /* Jumbo frames */ 2354*5e8715b9SGary Mills OUTL(atgep, L1_TX_JUMBO_TPD_TH_IPG, 2355*5e8715b9SGary Mills (((fsize / sizeof (uint64_t) << TX_JUMBO_TPD_TH_SHIFT)) & 2356*5e8715b9SGary Mills TX_JUMBO_TPD_TH_MASK) | 2357*5e8715b9SGary Mills ((TX_JUMBO_TPD_IPG_DEFAULT << TX_JUMBO_TPD_IPG_SHIFT) & 2358*5e8715b9SGary Mills TX_JUMBO_TPD_IPG_MASK)); 2359*5e8715b9SGary Mills /* 2360*5e8715b9SGary Mills * Configure DMA parameters. 2361*5e8715b9SGary Mills */ 2362*5e8715b9SGary Mills OUTL(atgep, ATGE_DMA_CFG, 2363*5e8715b9SGary Mills DMA_CFG_ENH_ORDER | DMA_CFG_RCB_64 | 2364*5e8715b9SGary Mills atgep->atge_dma_rd_burst | DMA_CFG_RD_ENB | 2365*5e8715b9SGary Mills atgep->atge_dma_wr_burst | DMA_CFG_WR_ENB); 2366*5e8715b9SGary Mills 2367*5e8715b9SGary Mills /* Configure CMB DMA write threshold. */ 2368*5e8715b9SGary Mills OUTL(atgep, L1_CMB_WR_THRESH, 2369*5e8715b9SGary Mills ((CMB_WR_THRESH_RRD_DEFAULT << CMB_WR_THRESH_RRD_SHIFT) & 2370*5e8715b9SGary Mills CMB_WR_THRESH_RRD_MASK) | 2371*5e8715b9SGary Mills ((CMB_WR_THRESH_TPD_DEFAULT << CMB_WR_THRESH_TPD_SHIFT) & 2372*5e8715b9SGary Mills CMB_WR_THRESH_TPD_MASK)); 2373*5e8715b9SGary Mills /* 2374*5e8715b9SGary Mills * Enable CMB/SMB timer. 2375*5e8715b9SGary Mills */ 23760eb090a7SSaurabh Misra /* Set CMB/SMB timer and enable them. */ 23770eb090a7SSaurabh Misra OUTL(atgep, L1_CMB_WR_TIMER, 23780eb090a7SSaurabh Misra ((ATGE_USECS(2) << CMB_WR_TIMER_TX_SHIFT) & 23790eb090a7SSaurabh Misra CMB_WR_TIMER_TX_MASK) | 23800eb090a7SSaurabh Misra ((ATGE_USECS(2) << CMB_WR_TIMER_RX_SHIFT) & 23810eb090a7SSaurabh Misra CMB_WR_TIMER_RX_MASK)); 23820eb090a7SSaurabh Misra 23830eb090a7SSaurabh Misra /* Request SMB updates for every seconds. */ 23840eb090a7SSaurabh Misra OUTL(atgep, L1_SMB_TIMER, ATGE_USECS(1000 * 1000)); 23850eb090a7SSaurabh Misra OUTL(atgep, L1_CSMB_CTRL, 23860eb090a7SSaurabh Misra CSMB_CTRL_SMB_ENB | CSMB_CTRL_CMB_ENB); 2387*5e8715b9SGary Mills break; 2388*5e8715b9SGary Mills case ATGE_CHIP_L1C: 2389*5e8715b9SGary Mills /* Configure RxQ. */ 2390*5e8715b9SGary Mills reg = 2391*5e8715b9SGary Mills RXQ_CFG_RD_BURST_DEFAULT << L1C_RXQ_CFG_RD_BURST_SHIFT | 2392*5e8715b9SGary Mills RXQ_CFG_IPV6_CSUM_VERIFY | RXQ_CFG_ENB; 2393*5e8715b9SGary Mills if ((atgep->atge_flags & ATGE_FLAG_ASPM_MON) != 0) 2394*5e8715b9SGary Mills reg |= RXQ_CFG_ASPM_THROUGHPUT_LIMIT_1M; 2395*5e8715b9SGary Mills OUTL(atgep, ATGE_RXQ_CFG, reg); 2396*5e8715b9SGary Mills /* 2397*5e8715b9SGary Mills * Configure TxQ. 2398*5e8715b9SGary Mills */ 2399*5e8715b9SGary Mills reg = (128 << 2400*5e8715b9SGary Mills (atgep->atge_dma_rd_burst >> DMA_CFG_RD_BURST_SHIFT)) << 2401*5e8715b9SGary Mills TXQ_CFG_TX_FIFO_BURST_SHIFT; 2402*5e8715b9SGary Mills 2403*5e8715b9SGary Mills switch (ATGE_DID(atgep)) { 2404*5e8715b9SGary Mills case ATGE_CHIP_AR8152V2_DEV_ID: 2405*5e8715b9SGary Mills case ATGE_CHIP_AR8152V1_DEV_ID: 2406*5e8715b9SGary Mills reg >>= 1; 2407*5e8715b9SGary Mills break; 2408015a6ef6SSaurabh Misra } 2409015a6ef6SSaurabh Misra 2410*5e8715b9SGary Mills reg |= (L1C_TXQ_CFG_TPD_BURST_DEFAULT << 2411*5e8715b9SGary Mills TXQ_CFG_TPD_BURST_SHIFT) & TXQ_CFG_TPD_BURST_MASK; 2412*5e8715b9SGary Mills 2413*5e8715b9SGary Mills reg |= TXQ_CFG_ENHANCED_MODE | TXQ_CFG_ENB; 2414*5e8715b9SGary Mills 2415*5e8715b9SGary Mills OUTL(atgep, L1C_TXQ_CFG, reg); 2416*5e8715b9SGary Mills /* Disable RSS until I understand L1C/L2C's RSS logic. */ 2417*5e8715b9SGary Mills OUTL(atgep, L1C_RSS_IDT_TABLE0, 0xe4e4e4e4); 2418*5e8715b9SGary Mills OUTL(atgep, L1C_RSS_CPU, 0); 2419*5e8715b9SGary Mills /* 2420*5e8715b9SGary Mills * Configure DMA parameters. 2421*5e8715b9SGary Mills */ 2422*5e8715b9SGary Mills OUTL(atgep, ATGE_DMA_CFG, 2423*5e8715b9SGary Mills DMA_CFG_SMB_DIS | 2424*5e8715b9SGary Mills DMA_CFG_OUT_ORDER | DMA_CFG_RD_REQ_PRI | DMA_CFG_RCB_64 | 2425*5e8715b9SGary Mills DMA_CFG_RD_DELAY_CNT_DEFAULT << DMA_CFG_RD_DELAY_CNT_SHIFT | 2426*5e8715b9SGary Mills DMA_CFG_WR_DELAY_CNT_DEFAULT << DMA_CFG_WR_DELAY_CNT_SHIFT | 2427*5e8715b9SGary Mills 2428*5e8715b9SGary Mills atgep->atge_dma_rd_burst | DMA_CFG_RD_ENB | 2429*5e8715b9SGary Mills atgep->atge_dma_wr_burst | DMA_CFG_WR_ENB); 2430*5e8715b9SGary Mills /* Configure CMB DMA write threshold not required. */ 2431*5e8715b9SGary Mills /* Set CMB/SMB timer and enable them not required. */ 2432*5e8715b9SGary Mills break; 2433*5e8715b9SGary Mills } 24340eb090a7SSaurabh Misra 2435015a6ef6SSaurabh Misra /* 2436015a6ef6SSaurabh Misra * Disable all WOL bits as WOL can interfere normal Rx 2437015a6ef6SSaurabh Misra * operation. 2438015a6ef6SSaurabh Misra */ 2439015a6ef6SSaurabh Misra OUTL(atgep, ATGE_WOL_CFG, 0); 2440015a6ef6SSaurabh Misra 2441015a6ef6SSaurabh Misra /* 2442015a6ef6SSaurabh Misra * Configure Tx/Rx MACs. 2443015a6ef6SSaurabh Misra * - Auto-padding for short frames. 2444015a6ef6SSaurabh Misra * - Enable CRC generation. 2445015a6ef6SSaurabh Misra * 2446015a6ef6SSaurabh Misra * Start with full-duplex/1000Mbps media. Actual reconfiguration 2447015a6ef6SSaurabh Misra * of MAC is followed after link establishment. 2448015a6ef6SSaurabh Misra */ 2449015a6ef6SSaurabh Misra reg = (ATGE_CFG_TX_CRC_ENB | ATGE_CFG_TX_AUTO_PAD | 2450015a6ef6SSaurabh Misra ATGE_CFG_FULL_DUPLEX | 2451015a6ef6SSaurabh Misra ((ATGE_CFG_PREAMBLE_DEFAULT << ATGE_CFG_PREAMBLE_SHIFT) & 2452015a6ef6SSaurabh Misra ATGE_CFG_PREAMBLE_MASK)); 2453015a6ef6SSaurabh Misra 2454*5e8715b9SGary Mills /* 2455*5e8715b9SGary Mills * AR813x/AR815x always does checksum computation regardless 2456*5e8715b9SGary Mills * of MAC_CFG_RXCSUM_ENB bit. Also the controller is known to 2457*5e8715b9SGary Mills * have bug in protocol field in Rx return structure so 2458*5e8715b9SGary Mills * these controllers can't handle fragmented frames. Disable 2459*5e8715b9SGary Mills * Rx checksum offloading until there is a newer controller 2460*5e8715b9SGary Mills * that has sane implementation. 2461*5e8715b9SGary Mills */ 2462*5e8715b9SGary Mills switch (ATGE_DID(atgep)) { 2463*5e8715b9SGary Mills case ATGE_CHIP_AR8151V2_DEV_ID: 2464*5e8715b9SGary Mills case ATGE_CHIP_AR8151V1_DEV_ID: 2465*5e8715b9SGary Mills case ATGE_CHIP_AR8152V2_DEV_ID: 2466*5e8715b9SGary Mills reg |= ATGE_CFG_HASH_ALG_CRC32 | ATGE_CFG_SPEED_MODE_SW; 2467*5e8715b9SGary Mills break; 2468*5e8715b9SGary Mills } 2469*5e8715b9SGary Mills 2470015a6ef6SSaurabh Misra if ((atgep->atge_flags & ATGE_FLAG_FASTETHER) != 0) { 2471015a6ef6SSaurabh Misra reg |= ATGE_CFG_SPEED_10_100; 2472015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() Fast Ethernet", atgep->atge_name, __func__)); 2473015a6ef6SSaurabh Misra } else { 2474015a6ef6SSaurabh Misra reg |= ATGE_CFG_SPEED_1000; 2475015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() 1G speed", atgep->atge_name, __func__)); 2476015a6ef6SSaurabh Misra } 2477*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 2478*5e8715b9SGary Mills case ATGE_CHIP_L1C: 2479*5e8715b9SGary Mills reg |= L1C_CFG_SINGLE_PAUSE_ENB; 2480*5e8715b9SGary Mills break; 2481*5e8715b9SGary Mills } 2482015a6ef6SSaurabh Misra 2483015a6ef6SSaurabh Misra OUTL(atgep, ATGE_MAC_CFG, reg); 2484015a6ef6SSaurabh Misra 2485015a6ef6SSaurabh Misra atgep->atge_chip_state |= ATGE_CHIP_RUNNING; 2486015a6ef6SSaurabh Misra 2487015a6ef6SSaurabh Misra /* 2488015a6ef6SSaurabh Misra * Set up the receive filter. 2489015a6ef6SSaurabh Misra */ 2490015a6ef6SSaurabh Misra atge_rxfilter(atgep); 2491015a6ef6SSaurabh Misra 2492015a6ef6SSaurabh Misra /* 2493015a6ef6SSaurabh Misra * Acknowledge all pending interrupts and clear it. 2494015a6ef6SSaurabh Misra */ 2495*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 2496*5e8715b9SGary Mills case ATGE_CHIP_L1E: 2497015a6ef6SSaurabh Misra OUTL(atgep, ATGE_INTR_MASK, L1E_INTRS); 2498015a6ef6SSaurabh Misra OUTL(atgep, ATGE_INTR_STATUS, 0xFFFFFFFF); 2499015a6ef6SSaurabh Misra OUTL(atgep, ATGE_INTR_STATUS, 0); 2500*5e8715b9SGary Mills break; 2501*5e8715b9SGary Mills case ATGE_CHIP_L1: 2502*5e8715b9SGary Mills case ATGE_CHIP_L1C: 2503*5e8715b9SGary Mills OUTL(atgep, ATGE_INTR_STATUS, 0); 2504*5e8715b9SGary Mills OUTL(atgep, ATGE_INTR_MASK, atgep->atge_intrs); 2505*5e8715b9SGary Mills break; 25060eb090a7SSaurabh Misra } 2507015a6ef6SSaurabh Misra 2508015a6ef6SSaurabh Misra atge_mac_config(atgep); 2509015a6ef6SSaurabh Misra 2510015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() device started", atgep->atge_name, __func__)); 2511015a6ef6SSaurabh Misra } 2512015a6ef6SSaurabh Misra 2513015a6ef6SSaurabh Misra /* 2514015a6ef6SSaurabh Misra * Generic functions. 2515015a6ef6SSaurabh Misra */ 2516015a6ef6SSaurabh Misra 2517015a6ef6SSaurabh Misra #define CRC32_POLY_BE 0x04c11db7 2518015a6ef6SSaurabh Misra uint32_t 2519015a6ef6SSaurabh Misra atge_ether_crc(const uint8_t *addr, int len) 2520015a6ef6SSaurabh Misra { 2521015a6ef6SSaurabh Misra int idx; 2522015a6ef6SSaurabh Misra int bit; 2523015a6ef6SSaurabh Misra uint_t data; 2524015a6ef6SSaurabh Misra uint32_t crc; 2525015a6ef6SSaurabh Misra 2526015a6ef6SSaurabh Misra crc = 0xffffffff; 2527015a6ef6SSaurabh Misra for (idx = 0; idx < len; idx++) { 2528015a6ef6SSaurabh Misra for (data = *addr++, bit = 0; bit < 8; bit++, data >>= 1) { 2529015a6ef6SSaurabh Misra crc = (crc << 1) 2530015a6ef6SSaurabh Misra ^ ((((crc >> 31) ^ data) & 1) ? CRC32_POLY_BE : 0); 2531015a6ef6SSaurabh Misra } 2532015a6ef6SSaurabh Misra } 2533015a6ef6SSaurabh Misra 2534015a6ef6SSaurabh Misra return (crc); 2535015a6ef6SSaurabh Misra } 2536015a6ef6SSaurabh Misra 2537015a6ef6SSaurabh Misra 2538015a6ef6SSaurabh Misra /* 2539015a6ef6SSaurabh Misra * Programs RX filter. We use a link-list to keep track of all multicast 2540015a6ef6SSaurabh Misra * addressess. 2541015a6ef6SSaurabh Misra */ 2542015a6ef6SSaurabh Misra void 2543015a6ef6SSaurabh Misra atge_rxfilter(atge_t *atgep) 2544015a6ef6SSaurabh Misra { 2545015a6ef6SSaurabh Misra uint32_t rxcfg; 2546015a6ef6SSaurabh Misra uint64_t mchash; 2547015a6ef6SSaurabh Misra 2548015a6ef6SSaurabh Misra rxcfg = INL(atgep, ATGE_MAC_CFG); 2549015a6ef6SSaurabh Misra rxcfg &= ~(ATGE_CFG_ALLMULTI | ATGE_CFG_PROMISC); 2550015a6ef6SSaurabh Misra 2551015a6ef6SSaurabh Misra /* 2552015a6ef6SSaurabh Misra * Accept broadcast frames. 2553015a6ef6SSaurabh Misra */ 2554015a6ef6SSaurabh Misra rxcfg |= ATGE_CFG_BCAST; 2555015a6ef6SSaurabh Misra 2556015a6ef6SSaurabh Misra /* 2557015a6ef6SSaurabh Misra * We don't use Hardware VLAN tagging. 2558015a6ef6SSaurabh Misra */ 2559015a6ef6SSaurabh Misra rxcfg &= ~ATGE_CFG_VLAN_TAG_STRIP; 2560015a6ef6SSaurabh Misra 2561015a6ef6SSaurabh Misra if (atgep->atge_filter_flags & (ATGE_PROMISC | ATGE_ALL_MULTICST)) { 2562015a6ef6SSaurabh Misra mchash = ~0ULL; 2563015a6ef6SSaurabh Misra 2564015a6ef6SSaurabh Misra if (atgep->atge_filter_flags & ATGE_PROMISC) 2565015a6ef6SSaurabh Misra rxcfg |= ATGE_CFG_PROMISC; 2566015a6ef6SSaurabh Misra 2567015a6ef6SSaurabh Misra if (atgep->atge_filter_flags & ATGE_ALL_MULTICST) 2568015a6ef6SSaurabh Misra rxcfg |= ATGE_CFG_ALLMULTI; 2569015a6ef6SSaurabh Misra } else { 2570015a6ef6SSaurabh Misra mchash = atgep->atge_mchash; 2571015a6ef6SSaurabh Misra } 2572015a6ef6SSaurabh Misra 2573015a6ef6SSaurabh Misra atge_program_ether(atgep); 2574015a6ef6SSaurabh Misra 2575015a6ef6SSaurabh Misra OUTL(atgep, ATGE_MAR0, (uint32_t)mchash); 2576015a6ef6SSaurabh Misra OUTL(atgep, ATGE_MAR1, (uint32_t)(mchash >> 32)); 2577015a6ef6SSaurabh Misra OUTL(atgep, ATGE_MAC_CFG, rxcfg); 2578015a6ef6SSaurabh Misra 2579015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() mac_cfg is : %x, mchash : %llx", 2580015a6ef6SSaurabh Misra atgep->atge_name, __func__, rxcfg, mchash)); 2581015a6ef6SSaurabh Misra } 2582015a6ef6SSaurabh Misra 2583015a6ef6SSaurabh Misra void 2584015a6ef6SSaurabh Misra atge_device_stop(atge_t *atgep) 2585015a6ef6SSaurabh Misra { 2586015a6ef6SSaurabh Misra uint32_t reg; 2587015a6ef6SSaurabh Misra int t; 2588015a6ef6SSaurabh Misra 2589015a6ef6SSaurabh Misra /* 2590015a6ef6SSaurabh Misra * If the chip is being suspended, then don't touch the state. Caller 2591015a6ef6SSaurabh Misra * will take care of setting the correct state. 2592015a6ef6SSaurabh Misra */ 2593015a6ef6SSaurabh Misra if (!(atgep->atge_chip_state & ATGE_CHIP_SUSPENDED)) { 2594015a6ef6SSaurabh Misra atgep->atge_chip_state |= ATGE_CHIP_STOPPED; 2595015a6ef6SSaurabh Misra atgep->atge_chip_state &= ~ATGE_CHIP_RUNNING; 2596015a6ef6SSaurabh Misra } 2597015a6ef6SSaurabh Misra 2598015a6ef6SSaurabh Misra /* 2599015a6ef6SSaurabh Misra * Collect stats for L1E. L1 chip's stats are collected by interrupt. 2600015a6ef6SSaurabh Misra */ 2601*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 2602*5e8715b9SGary Mills case ATGE_CHIP_L1E: 2603015a6ef6SSaurabh Misra atge_l1e_gather_stats(atgep); 2604*5e8715b9SGary Mills break; 2605*5e8715b9SGary Mills case ATGE_CHIP_L1: 2606*5e8715b9SGary Mills case ATGE_CHIP_L1C: 2607*5e8715b9SGary Mills break; 2608015a6ef6SSaurabh Misra } 2609015a6ef6SSaurabh Misra 2610015a6ef6SSaurabh Misra /* 2611015a6ef6SSaurabh Misra * Disable interrupts. 2612015a6ef6SSaurabh Misra */ 2613015a6ef6SSaurabh Misra atge_disable_intrs(atgep); 2614015a6ef6SSaurabh Misra 2615*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 2616*5e8715b9SGary Mills case ATGE_CHIP_L1E: 2617*5e8715b9SGary Mills /* Clear CTRL not required. */ 2618*5e8715b9SGary Mills /* Stop DMA Engine not required. */ 2619015a6ef6SSaurabh Misra /* 2620015a6ef6SSaurabh Misra * Disable queue processing. 2621015a6ef6SSaurabh Misra */ 2622015a6ef6SSaurabh Misra /* Stop TxQ */ 2623015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_TXQ_CFG); 2624015a6ef6SSaurabh Misra reg = reg & ~TXQ_CFG_ENB; 2625015a6ef6SSaurabh Misra OUTL(atgep, ATGE_TXQ_CFG, reg); 2626015a6ef6SSaurabh Misra /* Stop RxQ */ 2627015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_RXQ_CFG); 2628015a6ef6SSaurabh Misra reg = reg & ~RXQ_CFG_ENB; 2629015a6ef6SSaurabh Misra OUTL(atgep, ATGE_RXQ_CFG, reg); 2630*5e8715b9SGary Mills /* Stop DMA */ 2631015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_DMA_CFG); 2632015a6ef6SSaurabh Misra reg = reg & ~(DMA_CFG_TXCMB_ENB | DMA_CFG_RXCMB_ENB); 2633015a6ef6SSaurabh Misra OUTL(atgep, ATGE_DMA_CFG, reg); 2634015a6ef6SSaurabh Misra drv_usecwait(1000); 2635015a6ef6SSaurabh Misra atge_l1e_stop_mac(atgep); 2636015a6ef6SSaurabh Misra OUTL(atgep, ATGE_INTR_STATUS, 0xFFFFFFFF); 2637*5e8715b9SGary Mills break; 2638*5e8715b9SGary Mills case ATGE_CHIP_L1: 2639*5e8715b9SGary Mills /* Clear CTRL. */ 2640*5e8715b9SGary Mills OUTL(atgep, L1_CSMB_CTRL, 0); 2641*5e8715b9SGary Mills /* Stop DMA Engine */ 2642*5e8715b9SGary Mills atge_l1_stop_tx_mac(atgep); 2643*5e8715b9SGary Mills atge_l1_stop_rx_mac(atgep); 2644*5e8715b9SGary Mills reg = INL(atgep, ATGE_DMA_CFG); 2645*5e8715b9SGary Mills reg &= ~(DMA_CFG_RD_ENB | DMA_CFG_WR_ENB); 2646*5e8715b9SGary Mills OUTL(atgep, ATGE_DMA_CFG, reg); 2647*5e8715b9SGary Mills /* 2648*5e8715b9SGary Mills * Disable queue processing. 2649*5e8715b9SGary Mills */ 2650*5e8715b9SGary Mills /* Stop TxQ */ 2651*5e8715b9SGary Mills reg = INL(atgep, ATGE_TXQ_CFG); 2652*5e8715b9SGary Mills reg = reg & ~TXQ_CFG_ENB; 2653*5e8715b9SGary Mills OUTL(atgep, ATGE_TXQ_CFG, reg); 2654*5e8715b9SGary Mills /* Stop RxQ */ 2655*5e8715b9SGary Mills reg = INL(atgep, ATGE_RXQ_CFG); 2656*5e8715b9SGary Mills reg = reg & ~RXQ_CFG_ENB; 2657*5e8715b9SGary Mills OUTL(atgep, ATGE_RXQ_CFG, reg); 2658*5e8715b9SGary Mills break; 2659*5e8715b9SGary Mills case ATGE_CHIP_L1C: 2660*5e8715b9SGary Mills /* Clear CTRL not required. */ 2661*5e8715b9SGary Mills /* Stop DMA Engine */ 2662*5e8715b9SGary Mills atge_l1c_stop_tx_mac(atgep); 2663*5e8715b9SGary Mills atge_l1c_stop_rx_mac(atgep); 2664*5e8715b9SGary Mills reg = INL(atgep, ATGE_DMA_CFG); 2665*5e8715b9SGary Mills reg &= ~(DMA_CFG_RD_ENB | DMA_CFG_WR_ENB); 2666*5e8715b9SGary Mills OUTL(atgep, ATGE_DMA_CFG, reg); 2667*5e8715b9SGary Mills /* 2668*5e8715b9SGary Mills * Disable queue processing. 2669*5e8715b9SGary Mills */ 2670*5e8715b9SGary Mills /* Stop TxQ */ 2671*5e8715b9SGary Mills reg = INL(atgep, L1C_TXQ_CFG); 2672*5e8715b9SGary Mills reg = reg & ~TXQ_CFG_ENB; 2673*5e8715b9SGary Mills OUTL(atgep, L1C_TXQ_CFG, reg); 2674*5e8715b9SGary Mills /* Stop RxQ */ 2675*5e8715b9SGary Mills reg = INL(atgep, ATGE_RXQ_CFG); 2676*5e8715b9SGary Mills reg = reg & ~RXQ_CFG_ENB; 2677*5e8715b9SGary Mills OUTL(atgep, ATGE_RXQ_CFG, reg); 2678*5e8715b9SGary Mills break; 2679015a6ef6SSaurabh Misra } 2680015a6ef6SSaurabh Misra 2681015a6ef6SSaurabh Misra for (t = ATGE_RESET_TIMEOUT; t > 0; t--) { 2682015a6ef6SSaurabh Misra if ((reg = INL(atgep, ATGE_IDLE_STATUS)) == 0) 2683015a6ef6SSaurabh Misra break; 2684015a6ef6SSaurabh Misra drv_usecwait(10); 2685015a6ef6SSaurabh Misra } 2686015a6ef6SSaurabh Misra 2687015a6ef6SSaurabh Misra if (t == 0) { 2688015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "%s() stopping TX/RX MAC timeout", 2689015a6ef6SSaurabh Misra __func__); 2690015a6ef6SSaurabh Misra } 2691015a6ef6SSaurabh Misra } 2692015a6ef6SSaurabh Misra 2693015a6ef6SSaurabh Misra void 2694015a6ef6SSaurabh Misra atge_disable_intrs(atge_t *atgep) 2695015a6ef6SSaurabh Misra { 2696015a6ef6SSaurabh Misra OUTL(atgep, ATGE_INTR_MASK, 0); 2697015a6ef6SSaurabh Misra OUTL(atgep, ATGE_INTR_STATUS, 0xFFFFFFFF); 2698015a6ef6SSaurabh Misra } 2699015a6ef6SSaurabh Misra 2700015a6ef6SSaurabh Misra void 2701015a6ef6SSaurabh Misra atge_device_init(atge_t *atgep) 2702015a6ef6SSaurabh Misra { 2703*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 2704*5e8715b9SGary Mills case ATGE_CHIP_L1E: 2705015a6ef6SSaurabh Misra atgep->atge_intrs = L1E_INTRS; 2706015a6ef6SSaurabh Misra atgep->atge_int_mod = ATGE_IM_TIMER_DEFAULT; 2707015a6ef6SSaurabh Misra 2708015a6ef6SSaurabh Misra atge_l1e_init_tx_ring(atgep); 2709015a6ef6SSaurabh Misra atge_l1e_init_rx_pages(atgep); 2710*5e8715b9SGary Mills break; 2711*5e8715b9SGary Mills case ATGE_CHIP_L1: 27120eb090a7SSaurabh Misra atgep->atge_intrs = L1_INTRS | INTR_GPHY | INTR_PHY_LINK_DOWN | 27130eb090a7SSaurabh Misra INTR_LINK_CHG; 27140eb090a7SSaurabh Misra atgep->atge_int_mod = ATGE_IM_TIMER_DEFAULT; 27150eb090a7SSaurabh Misra 27160eb090a7SSaurabh Misra atge_l1_init_tx_ring(atgep); 27170eb090a7SSaurabh Misra atge_l1_init_rx_ring(atgep); 27180eb090a7SSaurabh Misra atge_l1_init_rr_ring(atgep); 27190eb090a7SSaurabh Misra atge_l1_init_cmb(atgep); 27200eb090a7SSaurabh Misra atge_l1_init_smb(atgep); 2721*5e8715b9SGary Mills break; 2722*5e8715b9SGary Mills case ATGE_CHIP_L1C: 2723*5e8715b9SGary Mills atgep->atge_intrs = L1C_INTRS | L1C_INTR_GPHY | 2724*5e8715b9SGary Mills L1C_INTR_PHY_LINK_DOWN; 2725*5e8715b9SGary Mills atgep->atge_int_rx_mod = 400/2; 2726*5e8715b9SGary Mills atgep->atge_int_tx_mod = 2000/1; 2727*5e8715b9SGary Mills 2728*5e8715b9SGary Mills atge_l1c_init_tx_ring(atgep); 2729*5e8715b9SGary Mills atge_l1c_init_rx_ring(atgep); 2730*5e8715b9SGary Mills atge_l1c_init_rr_ring(atgep); 2731*5e8715b9SGary Mills atge_l1c_init_cmb(atgep); 2732*5e8715b9SGary Mills atge_l1c_init_smb(atgep); 2733*5e8715b9SGary Mills 2734*5e8715b9SGary Mills /* Enable all clocks. */ 2735*5e8715b9SGary Mills OUTL(atgep, ATGE_CLK_GATING_CFG, 0); 2736*5e8715b9SGary Mills break; 2737015a6ef6SSaurabh Misra } 2738015a6ef6SSaurabh Misra } 2739015a6ef6SSaurabh Misra 2740015a6ef6SSaurabh Misra void 2741015a6ef6SSaurabh Misra atge_device_restart(atge_t *atgep) 2742015a6ef6SSaurabh Misra { 2743015a6ef6SSaurabh Misra ASSERT(MUTEX_HELD(&atgep->atge_intr_lock)); 2744015a6ef6SSaurabh Misra ASSERT(MUTEX_HELD(&atgep->atge_tx_lock)); 2745015a6ef6SSaurabh Misra 2746015a6ef6SSaurabh Misra /* 2747015a6ef6SSaurabh Misra * Cancel any pending I/O. 2748015a6ef6SSaurabh Misra */ 2749015a6ef6SSaurabh Misra atge_device_stop(atgep); 2750015a6ef6SSaurabh Misra 2751015a6ef6SSaurabh Misra /* 2752015a6ef6SSaurabh Misra * Reset the chip to a known state. 2753015a6ef6SSaurabh Misra */ 2754015a6ef6SSaurabh Misra atge_device_reset(atgep); 2755015a6ef6SSaurabh Misra 2756015a6ef6SSaurabh Misra /* 2757015a6ef6SSaurabh Misra * Initialize the ring and other descriptor like CMB/SMB/Rx return. 2758015a6ef6SSaurabh Misra */ 2759015a6ef6SSaurabh Misra atge_device_init(atgep); 2760015a6ef6SSaurabh Misra 2761015a6ef6SSaurabh Misra /* 2762015a6ef6SSaurabh Misra * Start the chip. 2763015a6ef6SSaurabh Misra */ 2764015a6ef6SSaurabh Misra atge_device_start(atgep); 2765015a6ef6SSaurabh Misra 2766015a6ef6SSaurabh Misra } 2767015a6ef6SSaurabh Misra 2768015a6ef6SSaurabh Misra static int 2769015a6ef6SSaurabh Misra atge_send_a_packet(atge_t *atgep, mblk_t *mp) 2770015a6ef6SSaurabh Misra { 27710eb090a7SSaurabh Misra uchar_t *c; 27720eb090a7SSaurabh Misra uint32_t cflags = 0; 2773015a6ef6SSaurabh Misra atge_ring_t *r; 2774015a6ef6SSaurabh Misra size_t pktlen; 2775015a6ef6SSaurabh Misra uchar_t *buf; 2776015a6ef6SSaurabh Misra int start; 2777015a6ef6SSaurabh Misra 2778015a6ef6SSaurabh Misra ASSERT(MUTEX_HELD(&atgep->atge_tx_lock)); 2779015a6ef6SSaurabh Misra ASSERT(mp != NULL); 2780015a6ef6SSaurabh Misra 2781015a6ef6SSaurabh Misra pktlen = msgsize(mp); 2782015a6ef6SSaurabh Misra if (pktlen > atgep->atge_tx_buf_len) { 2783015a6ef6SSaurabh Misra atgep->atge_macxmt_errors++; 2784015a6ef6SSaurabh Misra 2785015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() pktlen (%d) > rx_buf_len (%d)", 2786015a6ef6SSaurabh Misra atgep->atge_name, __func__, 2787015a6ef6SSaurabh Misra pktlen, atgep->atge_rx_buf_len)); 2788015a6ef6SSaurabh Misra 2789015a6ef6SSaurabh Misra freemsg(mp); 27900eb090a7SSaurabh Misra return (DDI_SUCCESS); 2791015a6ef6SSaurabh Misra } 2792015a6ef6SSaurabh Misra 2793015a6ef6SSaurabh Misra r = atgep->atge_tx_ring; 2794015a6ef6SSaurabh Misra 2795015a6ef6SSaurabh Misra if (r->r_avail_desc <= 1) { 2796015a6ef6SSaurabh Misra atgep->atge_noxmtbuf++; 2797015a6ef6SSaurabh Misra atgep->atge_tx_resched = 1; 27980eb090a7SSaurabh Misra 27990eb090a7SSaurabh Misra ATGE_DB(("%s: %s() No transmit buf", 28000eb090a7SSaurabh Misra atgep->atge_name, __func__)); 28010eb090a7SSaurabh Misra 28020eb090a7SSaurabh Misra return (DDI_FAILURE); 2803015a6ef6SSaurabh Misra } 2804015a6ef6SSaurabh Misra 2805015a6ef6SSaurabh Misra start = r->r_producer; 2806015a6ef6SSaurabh Misra 2807015a6ef6SSaurabh Misra /* 2808015a6ef6SSaurabh Misra * Get the DMA buffer to hold a packet. 2809015a6ef6SSaurabh Misra */ 2810015a6ef6SSaurabh Misra buf = (uchar_t *)r->r_buf_tbl[start]->addr; 2811015a6ef6SSaurabh Misra 2812015a6ef6SSaurabh Misra /* 2813015a6ef6SSaurabh Misra * Copy the msg and free mp 2814015a6ef6SSaurabh Misra */ 2815015a6ef6SSaurabh Misra mcopymsg(mp, buf); 2816015a6ef6SSaurabh Misra 2817015a6ef6SSaurabh Misra r->r_avail_desc--; 2818015a6ef6SSaurabh Misra 28190eb090a7SSaurabh Misra c = (uchar_t *)r->r_desc_ring->addr; 2820*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 2821*5e8715b9SGary Mills case ATGE_CHIP_L1C: 2822*5e8715b9SGary Mills { 2823*5e8715b9SGary Mills l1c_tx_desc_t *txd; 2824*5e8715b9SGary Mills 2825*5e8715b9SGary Mills c += (sizeof (l1c_tx_desc_t) * start); 2826*5e8715b9SGary Mills txd = (l1c_tx_desc_t *)c; 2827*5e8715b9SGary Mills 2828*5e8715b9SGary Mills ATGE_PUT64(r->r_desc_ring, &txd->addr, 2829*5e8715b9SGary Mills r->r_buf_tbl[start]->cookie.dmac_laddress); 2830*5e8715b9SGary Mills 2831*5e8715b9SGary Mills ATGE_PUT32(r->r_desc_ring, &txd->len, L1C_TX_BYTES(pktlen)); 2832*5e8715b9SGary Mills 2833*5e8715b9SGary Mills cflags |= L1C_TD_EOP; 2834*5e8715b9SGary Mills ATGE_PUT32(r->r_desc_ring, &txd->flags, cflags); 2835*5e8715b9SGary Mills break; 2836*5e8715b9SGary Mills } 2837*5e8715b9SGary Mills default: 2838*5e8715b9SGary Mills { 2839*5e8715b9SGary Mills atge_tx_desc_t *txd; 2840*5e8715b9SGary Mills 28410eb090a7SSaurabh Misra c += (sizeof (atge_tx_desc_t) * start); 28420eb090a7SSaurabh Misra txd = (atge_tx_desc_t *)c; 28430eb090a7SSaurabh Misra 28440eb090a7SSaurabh Misra ATGE_PUT64(r->r_desc_ring, &txd->addr, 28450eb090a7SSaurabh Misra r->r_buf_tbl[start]->cookie.dmac_laddress); 28460eb090a7SSaurabh Misra 28470eb090a7SSaurabh Misra ATGE_PUT32(r->r_desc_ring, &txd->len, ATGE_TX_BYTES(pktlen)); 28480eb090a7SSaurabh Misra 28490eb090a7SSaurabh Misra cflags |= ATGE_TD_EOP; 28500eb090a7SSaurabh Misra ATGE_PUT32(r->r_desc_ring, &txd->flags, cflags); 2851*5e8715b9SGary Mills break; 2852*5e8715b9SGary Mills } 2853*5e8715b9SGary Mills } 28540eb090a7SSaurabh Misra /* 28550eb090a7SSaurabh Misra * Sync buffer first. 28560eb090a7SSaurabh Misra */ 28570eb090a7SSaurabh Misra DMA_SYNC(r->r_buf_tbl[start], 0, pktlen, DDI_DMA_SYNC_FORDEV); 28580eb090a7SSaurabh Misra 28590eb090a7SSaurabh Misra /* 28600eb090a7SSaurabh Misra * Increment TX producer count by one. 28610eb090a7SSaurabh Misra */ 28620eb090a7SSaurabh Misra ATGE_INC_SLOT(r->r_producer, ATGE_TX_RING_CNT); 28630eb090a7SSaurabh Misra 28640eb090a7SSaurabh Misra /* 28650eb090a7SSaurabh Misra * Sync descriptor table. 28660eb090a7SSaurabh Misra */ 28670eb090a7SSaurabh Misra DMA_SYNC(r->r_desc_ring, 0, ATGE_TX_RING_SZ, DDI_DMA_SYNC_FORDEV); 28680eb090a7SSaurabh Misra 2869015a6ef6SSaurabh Misra /* 2870015a6ef6SSaurabh Misra * Program TX descriptor to send a packet. 2871015a6ef6SSaurabh Misra */ 2872*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) { 2873*5e8715b9SGary Mills case ATGE_CHIP_L1E: 28740eb090a7SSaurabh Misra atge_l1e_send_packet(r); 2875*5e8715b9SGary Mills break; 2876*5e8715b9SGary Mills case ATGE_CHIP_L1: 28770eb090a7SSaurabh Misra atge_l1_send_packet(r); 2878*5e8715b9SGary Mills break; 2879*5e8715b9SGary Mills case ATGE_CHIP_L1C: 2880*5e8715b9SGary Mills atge_l1c_send_packet(r); 2881*5e8715b9SGary Mills break; 2882015a6ef6SSaurabh Misra } 2883015a6ef6SSaurabh Misra 28840eb090a7SSaurabh Misra r->r_atge->atge_opackets++; 28850eb090a7SSaurabh Misra r->r_atge->atge_obytes += pktlen; 28860eb090a7SSaurabh Misra 28870eb090a7SSaurabh Misra ATGE_DB(("%s: %s() pktlen : %d, avail_desc : %d, producer :%d, " 28880eb090a7SSaurabh Misra "consumer : %d", atgep->atge_name, __func__, pktlen, 28890eb090a7SSaurabh Misra r->r_avail_desc, r->r_producer, r->r_consumer)); 28900eb090a7SSaurabh Misra 28910eb090a7SSaurabh Misra return (DDI_SUCCESS); 2892015a6ef6SSaurabh Misra } 2893015a6ef6SSaurabh Misra 2894015a6ef6SSaurabh Misra /* 2895015a6ef6SSaurabh Misra * Stream Information. 2896015a6ef6SSaurabh Misra */ 2897015a6ef6SSaurabh Misra DDI_DEFINE_STREAM_OPS(atge_devops, nulldev, nulldev, atge_attach, atge_detach, 2898015a6ef6SSaurabh Misra nodev, NULL, D_MP, NULL, atge_quiesce); 2899015a6ef6SSaurabh Misra 2900015a6ef6SSaurabh Misra /* 2901015a6ef6SSaurabh Misra * Module linkage information. 2902015a6ef6SSaurabh Misra */ 2903015a6ef6SSaurabh Misra static struct modldrv atge_modldrv = { 2904015a6ef6SSaurabh Misra &mod_driverops, /* Type of Module */ 2905015a6ef6SSaurabh Misra "Atheros/Attansic Gb Ethernet", /* Description */ 2906015a6ef6SSaurabh Misra &atge_devops /* drv_dev_ops */ 2907015a6ef6SSaurabh Misra }; 2908015a6ef6SSaurabh Misra 2909015a6ef6SSaurabh Misra static struct modlinkage atge_modlinkage = { 2910015a6ef6SSaurabh Misra MODREV_1, /* ml_rev */ 2911015a6ef6SSaurabh Misra (void *)&atge_modldrv, 2912015a6ef6SSaurabh Misra NULL 2913015a6ef6SSaurabh Misra }; 2914015a6ef6SSaurabh Misra 2915015a6ef6SSaurabh Misra /* 2916015a6ef6SSaurabh Misra * DDI Entry points. 2917015a6ef6SSaurabh Misra */ 2918015a6ef6SSaurabh Misra int 2919015a6ef6SSaurabh Misra _init(void) 2920015a6ef6SSaurabh Misra { 2921015a6ef6SSaurabh Misra int r; 2922015a6ef6SSaurabh Misra mac_init_ops(&atge_devops, "atge"); 2923015a6ef6SSaurabh Misra if ((r = mod_install(&atge_modlinkage)) != DDI_SUCCESS) { 2924015a6ef6SSaurabh Misra mac_fini_ops(&atge_devops); 2925015a6ef6SSaurabh Misra } 2926015a6ef6SSaurabh Misra 2927015a6ef6SSaurabh Misra return (r); 2928015a6ef6SSaurabh Misra } 2929015a6ef6SSaurabh Misra 2930015a6ef6SSaurabh Misra int 2931015a6ef6SSaurabh Misra _fini(void) 2932015a6ef6SSaurabh Misra { 2933015a6ef6SSaurabh Misra int r; 2934015a6ef6SSaurabh Misra 2935015a6ef6SSaurabh Misra if ((r = mod_remove(&atge_modlinkage)) == DDI_SUCCESS) { 2936015a6ef6SSaurabh Misra mac_fini_ops(&atge_devops); 2937015a6ef6SSaurabh Misra } 2938015a6ef6SSaurabh Misra 2939015a6ef6SSaurabh Misra return (r); 2940015a6ef6SSaurabh Misra } 2941015a6ef6SSaurabh Misra 2942015a6ef6SSaurabh Misra int 2943015a6ef6SSaurabh Misra _info(struct modinfo *modinfop) 2944015a6ef6SSaurabh Misra { 2945015a6ef6SSaurabh Misra return (mod_info(&atge_modlinkage, modinfop)); 2946015a6ef6SSaurabh Misra } 2947