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 /* 23015a6ef6SSaurabh Misra * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24015a6ef6SSaurabh Misra * Use is subject to license terms. 25015a6ef6SSaurabh Misra */ 26015a6ef6SSaurabh Misra 27015a6ef6SSaurabh Misra #include <sys/types.h> 28015a6ef6SSaurabh Misra #include <sys/stream.h> 29015a6ef6SSaurabh Misra #include <sys/strsun.h> 30015a6ef6SSaurabh Misra #include <sys/stat.h> 31015a6ef6SSaurabh Misra #include <sys/modctl.h> 32015a6ef6SSaurabh Misra #include <sys/kstat.h> 33015a6ef6SSaurabh Misra #include <sys/ethernet.h> 34015a6ef6SSaurabh Misra #include <sys/devops.h> 35015a6ef6SSaurabh Misra #include <sys/debug.h> 36015a6ef6SSaurabh Misra #include <sys/conf.h> 37015a6ef6SSaurabh Misra #include <sys/mii.h> 38015a6ef6SSaurabh Misra #include <sys/miiregs.h> 39015a6ef6SSaurabh Misra #include <sys/mac.h> 40015a6ef6SSaurabh Misra #include <sys/mac_provider.h> 41015a6ef6SSaurabh Misra #include <sys/mac_ether.h> 42015a6ef6SSaurabh Misra #include <sys/sysmacros.h> 43015a6ef6SSaurabh Misra #include <sys/dditypes.h> 44015a6ef6SSaurabh Misra #include <sys/ddi.h> 45015a6ef6SSaurabh Misra #include <sys/sunddi.h> 46015a6ef6SSaurabh Misra #include <sys/byteorder.h> 47015a6ef6SSaurabh Misra #include <sys/note.h> 48015a6ef6SSaurabh Misra #include <sys/vlan.h> 49015a6ef6SSaurabh Misra #include <sys/strsubr.h> 50015a6ef6SSaurabh Misra #include <sys/crc32.h> 51015a6ef6SSaurabh Misra #include <sys/sdt.h> 52015a6ef6SSaurabh Misra #include <sys/pci.h> 53015a6ef6SSaurabh Misra #include <sys/pci_cap.h> 54015a6ef6SSaurabh Misra 55015a6ef6SSaurabh Misra #include "atge.h" 56015a6ef6SSaurabh Misra #include "atge_cmn_reg.h" 57015a6ef6SSaurabh Misra #include "atge_l1e_reg.h" 58*0eb090a7SSaurabh Misra #include "atge_l1_reg.h" 59015a6ef6SSaurabh Misra 60015a6ef6SSaurabh Misra 61015a6ef6SSaurabh Misra /* 62015a6ef6SSaurabh Misra * Atheros/Attansic Ethernet chips are of three types - L1, L2 and L1E. 63*0eb090a7SSaurabh Misra * This driver is for L1E/L1 but can be extended to support other chips. 64*0eb090a7SSaurabh Misra * L1E comes in 1Gigabit and Fast Ethernet flavors. L1 comes in 1Gigabit 65*0eb090a7SSaurabh Misra * flavors only. 66015a6ef6SSaurabh Misra * 67015a6ef6SSaurabh Misra * Atheros/Attansic Ethernet controllers have descriptor based TX and RX 68015a6ef6SSaurabh Misra * with an exception of L1E. L1E's RX side is not descriptor based ring. 69015a6ef6SSaurabh Misra * The L1E's RX uses pages (not to be confused with MMU pages) for 70015a6ef6SSaurabh Misra * receiving pkts. The header has four fields : 71015a6ef6SSaurabh Misra * 72015a6ef6SSaurabh Misra * uint32_t seqno; Sequence number of the frame. 73015a6ef6SSaurabh Misra * uint32_t length; Length of the frame. 74015a6ef6SSaurabh Misra * uint32_t flags; Flags 75015a6ef6SSaurabh Misra * uint32_t vtag; We don't use hardware VTAG. 76015a6ef6SSaurabh Misra * 77015a6ef6SSaurabh Misra * We use only one queue for RX (each queue can have two pages) and each 78015a6ef6SSaurabh Misra * page is L1E_RX_PAGE_SZ large in bytes. That's the reason we don't 79015a6ef6SSaurabh Misra * use zero-copy RX because we are limited to two pages and each page 80015a6ef6SSaurabh Misra * accomodates large number of pkts. 81015a6ef6SSaurabh Misra * 82015a6ef6SSaurabh Misra * The TX side on all three chips is descriptor based ring; and all the 83015a6ef6SSaurabh Misra * more reason to have one driver for these chips. 84015a6ef6SSaurabh Misra * 85015a6ef6SSaurabh Misra * We use two locks - atge_intr_lock and atge_tx_lock. Both the locks 86015a6ef6SSaurabh Misra * should be held if the operation has impact on the driver instance. 87015a6ef6SSaurabh Misra * 88015a6ef6SSaurabh Misra * All the three chips have hash-based multicast filter. 89015a6ef6SSaurabh Misra * 90015a6ef6SSaurabh Misra * We use CMB (Coalescing Message Block) for RX but not for TX as there 91015a6ef6SSaurabh Misra * are some issues with TX. RX CMB is used to get the last descriptor 92015a6ef6SSaurabh Misra * posted by the chip. Each CMB is for a RX page (one queue can have two 93015a6ef6SSaurabh Misra * pages) and are uint32_t (4 bytes) long. 94015a6ef6SSaurabh Misra * 95015a6ef6SSaurabh Misra * The descriptor table should have 32-bit physical address limit due to 96015a6ef6SSaurabh Misra * the limitation of having same high address for TX/RX/SMB/CMB. The 97015a6ef6SSaurabh Misra * TX/RX buffers can be 64-bit. 98015a6ef6SSaurabh Misra * 99015a6ef6SSaurabh Misra * Every DMA memory in atge is represented by atge_dma_t be it TX/RX Buffers 100015a6ef6SSaurabh Misra * or TX/RX descriptor table or SMB/CMB. To keep the code simple, we have 101015a6ef6SSaurabh Misra * kept sgl as 1 so that we get contingous pages from root complex. 102*0eb090a7SSaurabh Misra * 103*0eb090a7SSaurabh Misra * L1 chip (0x1048) uses descriptor based TX and RX ring. Most of registers are 104*0eb090a7SSaurabh Misra * common with L1E chip (0x1026). 105015a6ef6SSaurabh Misra */ 106015a6ef6SSaurabh Misra 107015a6ef6SSaurabh Misra /* 108015a6ef6SSaurabh Misra * Function Prototypes for debugging. 109015a6ef6SSaurabh Misra */ 110015a6ef6SSaurabh Misra void atge_error(dev_info_t *, char *, ...); 111015a6ef6SSaurabh Misra void atge_debug_func(char *, ...); 112015a6ef6SSaurabh Misra 113015a6ef6SSaurabh Misra /* 114015a6ef6SSaurabh Misra * Function Prototypes for driver operations. 115015a6ef6SSaurabh Misra */ 116015a6ef6SSaurabh Misra static int atge_resume(dev_info_t *); 117015a6ef6SSaurabh Misra static int atge_add_intr(atge_t *); 118015a6ef6SSaurabh Misra static int atge_alloc_dma(atge_t *); 119015a6ef6SSaurabh Misra static void atge_remove_intr(atge_t *); 120015a6ef6SSaurabh Misra static void atge_free_dma(atge_t *); 121015a6ef6SSaurabh Misra static void atge_device_reset(atge_t *); 122015a6ef6SSaurabh Misra static void atge_device_init(atge_t *); 123015a6ef6SSaurabh Misra static void atge_device_start(atge_t *); 124015a6ef6SSaurabh Misra static void atge_disable_intrs(atge_t *); 125015a6ef6SSaurabh Misra atge_dma_t *atge_alloc_a_dma_blk(atge_t *, ddi_dma_attr_t *, int, int); 126015a6ef6SSaurabh Misra void atge_free_a_dma_blk(atge_dma_t *); 127015a6ef6SSaurabh Misra static void atge_rxfilter(atge_t *); 128015a6ef6SSaurabh Misra static void atge_device_reset_l1_l1e(atge_t *); 129015a6ef6SSaurabh Misra void atge_program_ether(atge_t *atgep); 130015a6ef6SSaurabh Misra void atge_device_restart(atge_t *); 131*0eb090a7SSaurabh Misra void atge_device_stop(atge_t *); 132015a6ef6SSaurabh Misra static int atge_send_a_packet(atge_t *, mblk_t *); 133015a6ef6SSaurabh Misra static uint32_t atge_ether_crc(const uint8_t *, int); 134015a6ef6SSaurabh Misra 135015a6ef6SSaurabh Misra 136015a6ef6SSaurabh Misra /* 137*0eb090a7SSaurabh Misra * L1E/L2E specific functions. 138015a6ef6SSaurabh Misra */ 139015a6ef6SSaurabh Misra void atge_l1e_device_reset(atge_t *); 140015a6ef6SSaurabh Misra void atge_l1e_stop_mac(atge_t *); 141015a6ef6SSaurabh Misra int atge_l1e_alloc_dma(atge_t *); 142015a6ef6SSaurabh Misra void atge_l1e_free_dma(atge_t *); 143015a6ef6SSaurabh Misra void atge_l1e_init_tx_ring(atge_t *); 144015a6ef6SSaurabh Misra void atge_l1e_init_rx_pages(atge_t *); 145015a6ef6SSaurabh Misra void atge_l1e_program_dma(atge_t *); 146*0eb090a7SSaurabh Misra void atge_l1e_send_packet(atge_ring_t *); 147015a6ef6SSaurabh Misra mblk_t *atge_l1e_receive(atge_t *); 148*0eb090a7SSaurabh Misra uint_t atge_l1e_interrupt(caddr_t, caddr_t); 149015a6ef6SSaurabh Misra void atge_l1e_gather_stats(atge_t *); 150015a6ef6SSaurabh Misra void atge_l1e_clear_stats(atge_t *); 151015a6ef6SSaurabh Misra 152015a6ef6SSaurabh Misra /* 153*0eb090a7SSaurabh Misra * L1 specific functions. 154*0eb090a7SSaurabh Misra */ 155*0eb090a7SSaurabh Misra int atge_l1_alloc_dma(atge_t *); 156*0eb090a7SSaurabh Misra void atge_l1_init_tx_ring(atge_t *); 157*0eb090a7SSaurabh Misra void atge_l1_init_rx_ring(atge_t *); 158*0eb090a7SSaurabh Misra void atge_l1_init_rr_ring(atge_t *); 159*0eb090a7SSaurabh Misra void atge_l1_init_cmb(atge_t *); 160*0eb090a7SSaurabh Misra void atge_l1_init_smb(atge_t *); 161*0eb090a7SSaurabh Misra void atge_l1_program_dma(atge_t *); 162*0eb090a7SSaurabh Misra void atge_l1_stop_tx_mac(atge_t *); 163*0eb090a7SSaurabh Misra void atge_l1_stop_rx_mac(atge_t *); 164*0eb090a7SSaurabh Misra uint_t atge_l1_interrupt(caddr_t, caddr_t); 165*0eb090a7SSaurabh Misra void atge_l1_send_packet(atge_ring_t *); 166*0eb090a7SSaurabh Misra 167*0eb090a7SSaurabh Misra 168*0eb090a7SSaurabh Misra /* 169015a6ef6SSaurabh Misra * Function prototyps for MII operations. 170015a6ef6SSaurabh Misra */ 171015a6ef6SSaurabh Misra uint16_t atge_mii_read(void *, uint8_t, uint8_t); 172015a6ef6SSaurabh Misra void atge_mii_write(void *, uint8_t, uint8_t, uint16_t); 173015a6ef6SSaurabh Misra void atge_l1e_mii_reset(void *); 174*0eb090a7SSaurabh Misra void atge_l1_mii_reset(void *); 175015a6ef6SSaurabh Misra static void atge_mii_notify(void *, link_state_t); 176*0eb090a7SSaurabh Misra void atge_tx_reclaim(atge_t *atgep, int cons); 177015a6ef6SSaurabh Misra 178*0eb090a7SSaurabh Misra /* 179*0eb090a7SSaurabh Misra * L1E/L2E chip. 180*0eb090a7SSaurabh Misra */ 181015a6ef6SSaurabh Misra static mii_ops_t atge_l1e_mii_ops = { 182015a6ef6SSaurabh Misra MII_OPS_VERSION, 183015a6ef6SSaurabh Misra atge_mii_read, 184015a6ef6SSaurabh Misra atge_mii_write, 185015a6ef6SSaurabh Misra atge_mii_notify, 186015a6ef6SSaurabh Misra atge_l1e_mii_reset 187015a6ef6SSaurabh Misra }; 188015a6ef6SSaurabh Misra 189015a6ef6SSaurabh Misra /* 190*0eb090a7SSaurabh Misra * L1 chip. 191*0eb090a7SSaurabh Misra */ 192*0eb090a7SSaurabh Misra static mii_ops_t atge_l1_mii_ops = { 193*0eb090a7SSaurabh Misra MII_OPS_VERSION, 194*0eb090a7SSaurabh Misra atge_mii_read, 195*0eb090a7SSaurabh Misra atge_mii_write, 196*0eb090a7SSaurabh Misra atge_mii_notify, 197*0eb090a7SSaurabh Misra atge_l1_mii_reset 198*0eb090a7SSaurabh Misra }; 199*0eb090a7SSaurabh Misra 200*0eb090a7SSaurabh Misra /* 201015a6ef6SSaurabh Misra * Function Prototypes for MAC callbacks. 202015a6ef6SSaurabh Misra */ 203015a6ef6SSaurabh Misra static int atge_m_stat(void *, uint_t, uint64_t *); 204015a6ef6SSaurabh Misra static int atge_m_start(void *); 205015a6ef6SSaurabh Misra static void atge_m_stop(void *); 206015a6ef6SSaurabh Misra static int atge_m_getprop(void *, const char *, mac_prop_id_t, uint_t, 207015a6ef6SSaurabh Misra uint_t, void *, uint_t *); 208015a6ef6SSaurabh Misra static int atge_m_setprop(void *, const char *, mac_prop_id_t, uint_t, 209015a6ef6SSaurabh Misra const void *); 210015a6ef6SSaurabh Misra static int atge_m_unicst(void *, const uint8_t *); 211015a6ef6SSaurabh Misra static int atge_m_multicst(void *, boolean_t, const uint8_t *); 212015a6ef6SSaurabh Misra static int atge_m_promisc(void *, boolean_t); 213015a6ef6SSaurabh Misra static mblk_t *atge_m_tx(void *, mblk_t *); 214015a6ef6SSaurabh Misra 215015a6ef6SSaurabh Misra static mac_callbacks_t atge_m_callbacks = { 216015a6ef6SSaurabh Misra MC_SETPROP | MC_GETPROP, 217015a6ef6SSaurabh Misra atge_m_stat, 218015a6ef6SSaurabh Misra atge_m_start, 219015a6ef6SSaurabh Misra atge_m_stop, 220015a6ef6SSaurabh Misra atge_m_promisc, 221015a6ef6SSaurabh Misra atge_m_multicst, 222015a6ef6SSaurabh Misra atge_m_unicst, 223015a6ef6SSaurabh Misra atge_m_tx, 224015a6ef6SSaurabh Misra NULL, /* mc_ioctl */ 225015a6ef6SSaurabh Misra NULL, /* mc_getcapab */ 226015a6ef6SSaurabh Misra NULL, /* mc_open */ 227015a6ef6SSaurabh Misra NULL, /* mc_close */ 228015a6ef6SSaurabh Misra atge_m_setprop, 229015a6ef6SSaurabh Misra atge_m_getprop, 230015a6ef6SSaurabh Misra }; 231015a6ef6SSaurabh Misra 232015a6ef6SSaurabh Misra /* 233015a6ef6SSaurabh Misra * DMA Data access requirements. 234015a6ef6SSaurabh Misra */ 235015a6ef6SSaurabh Misra static struct ddi_device_acc_attr atge_dev_attr = { 236015a6ef6SSaurabh Misra DDI_DEVICE_ATTR_V0, 237015a6ef6SSaurabh Misra DDI_STRUCTURE_LE_ACC, 238015a6ef6SSaurabh Misra DDI_STRICTORDER_ACC 239015a6ef6SSaurabh Misra }; 240015a6ef6SSaurabh Misra 241015a6ef6SSaurabh Misra /* 242015a6ef6SSaurabh Misra * Buffers should be native endianness. 243015a6ef6SSaurabh Misra */ 244015a6ef6SSaurabh Misra static struct ddi_device_acc_attr atge_buf_attr = { 245015a6ef6SSaurabh Misra DDI_DEVICE_ATTR_V0, 246015a6ef6SSaurabh Misra DDI_NEVERSWAP_ACC, /* native endianness */ 247015a6ef6SSaurabh Misra DDI_STRICTORDER_ACC 248015a6ef6SSaurabh Misra }; 249015a6ef6SSaurabh Misra 250015a6ef6SSaurabh Misra /* 251*0eb090a7SSaurabh Misra * DMA device attributes. Buffer can be 64-bit. 252015a6ef6SSaurabh Misra */ 253015a6ef6SSaurabh Misra static ddi_dma_attr_t atge_dma_attr_buf = { 254015a6ef6SSaurabh Misra DMA_ATTR_V0, /* dma_attr_version */ 255015a6ef6SSaurabh Misra 0, /* dma_attr_addr_lo */ 256015a6ef6SSaurabh Misra 0x00ffffffffffull, /* dma_attr_addr_hi */ 257015a6ef6SSaurabh Misra 0x000000003fffull, /* dma_attr_count_max */ 258015a6ef6SSaurabh Misra 8, /* dma_attr_align */ 259015a6ef6SSaurabh Misra 0x00003ffc, /* dma_attr_burstsizes */ 260015a6ef6SSaurabh Misra 1, /* dma_attr_minxfer */ 261015a6ef6SSaurabh Misra 0x0000000027ffull, /* dma_attr_maxxfer */ 262015a6ef6SSaurabh Misra 0x0000ffffffffull, /* dma_attr_seg */ 263015a6ef6SSaurabh Misra 1, /* dma_attr_sgllen */ 264015a6ef6SSaurabh Misra 1, /* dma_attr_granular */ 265015a6ef6SSaurabh Misra 0 /* dma_attr_flags */ 266015a6ef6SSaurabh Misra }; 267015a6ef6SSaurabh Misra 268015a6ef6SSaurabh Misra /* 269015a6ef6SSaurabh Misra * Table of supported devices. 270015a6ef6SSaurabh Misra */ 271015a6ef6SSaurabh Misra #define ATGE_VENDOR_ID 0x1969 272015a6ef6SSaurabh Misra #define ATGE_L1E_STR "Atheros AR8121/8113/8114" 273015a6ef6SSaurabh Misra 274015a6ef6SSaurabh Misra static atge_cards_t atge_cards[] = { 275015a6ef6SSaurabh Misra {ATGE_VENDOR_ID, ATGE_CHIP_L1E_DEV_ID, ATGE_L1E_STR, ATGE_CHIP_L1E}, 276*0eb090a7SSaurabh Misra {ATGE_VENDOR_ID, ATGE_CHIP_L1_DEV_ID, "Attansic L1", ATGE_CHIP_L1}, 277015a6ef6SSaurabh Misra }; 278015a6ef6SSaurabh Misra 279015a6ef6SSaurabh Misra /* 280015a6ef6SSaurabh Misra * Global Debugging flag. Developer level debugging is done only in DEBUG mode. 281015a6ef6SSaurabh Misra */ 282015a6ef6SSaurabh Misra int atge_debug = 1; 283015a6ef6SSaurabh Misra 284015a6ef6SSaurabh Misra /* 285015a6ef6SSaurabh Misra * Debugging and error reporting. 286015a6ef6SSaurabh Misra */ 287015a6ef6SSaurabh Misra void 288015a6ef6SSaurabh Misra atge_debug_func(char *fmt, ...) 289015a6ef6SSaurabh Misra { 290015a6ef6SSaurabh Misra va_list ap; 291015a6ef6SSaurabh Misra char buf[256]; 292015a6ef6SSaurabh Misra 293015a6ef6SSaurabh Misra va_start(ap, fmt); 294015a6ef6SSaurabh Misra (void) vsnprintf(buf, sizeof (buf), fmt, ap); 295015a6ef6SSaurabh Misra va_end(ap); 296015a6ef6SSaurabh Misra 297015a6ef6SSaurabh Misra DTRACE_PROBE1(atge__debug, char *, buf); 298015a6ef6SSaurabh Misra } 299015a6ef6SSaurabh Misra 300015a6ef6SSaurabh Misra void 301015a6ef6SSaurabh Misra atge_error(dev_info_t *dip, char *fmt, ...) 302015a6ef6SSaurabh Misra { 303015a6ef6SSaurabh Misra va_list ap; 304015a6ef6SSaurabh Misra char buf[256]; 305015a6ef6SSaurabh Misra 306015a6ef6SSaurabh Misra va_start(ap, fmt); 307015a6ef6SSaurabh Misra (void) vsnprintf(buf, sizeof (buf), fmt, ap); 308015a6ef6SSaurabh Misra va_end(ap); 309015a6ef6SSaurabh Misra 310015a6ef6SSaurabh Misra if (dip) { 311015a6ef6SSaurabh Misra cmn_err(CE_WARN, "%s%d: %s", 312015a6ef6SSaurabh Misra ddi_driver_name(dip), ddi_get_instance(dip), buf); 313015a6ef6SSaurabh Misra } else { 314015a6ef6SSaurabh Misra cmn_err(CE_WARN, "atge: %s", buf); 315015a6ef6SSaurabh Misra } 316015a6ef6SSaurabh Misra } 317015a6ef6SSaurabh Misra 318015a6ef6SSaurabh Misra void 319015a6ef6SSaurabh Misra atge_mac_config(atge_t *atgep) 320015a6ef6SSaurabh Misra { 321015a6ef6SSaurabh Misra uint32_t reg; 322015a6ef6SSaurabh Misra int speed; 323015a6ef6SSaurabh Misra link_duplex_t ld; 324015a6ef6SSaurabh Misra 325015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_MAC_CFG); 326015a6ef6SSaurabh Misra reg &= ~(ATGE_CFG_FULL_DUPLEX | ATGE_CFG_TX_FC | ATGE_CFG_RX_FC | 327015a6ef6SSaurabh Misra ATGE_CFG_SPEED_MASK); 328015a6ef6SSaurabh Misra 329015a6ef6SSaurabh Misra speed = mii_get_speed(atgep->atge_mii); 330015a6ef6SSaurabh Misra switch (speed) { 331015a6ef6SSaurabh Misra case 10: 332015a6ef6SSaurabh Misra case 100: 333015a6ef6SSaurabh Misra reg |= ATGE_CFG_SPEED_10_100; 334015a6ef6SSaurabh Misra break; 335015a6ef6SSaurabh Misra case 1000: 336015a6ef6SSaurabh Misra reg |= ATGE_CFG_SPEED_1000; 337015a6ef6SSaurabh Misra break; 338015a6ef6SSaurabh Misra } 339015a6ef6SSaurabh Misra 340015a6ef6SSaurabh Misra ld = mii_get_duplex(atgep->atge_mii); 341015a6ef6SSaurabh Misra if (ld == LINK_DUPLEX_FULL) 342015a6ef6SSaurabh Misra reg |= ATGE_CFG_FULL_DUPLEX; 343015a6ef6SSaurabh Misra 344015a6ef6SSaurabh Misra /* Re-enable TX/RX MACs */ 345*0eb090a7SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) { 346015a6ef6SSaurabh Misra reg |= ATGE_CFG_TX_ENB | ATGE_CFG_RX_ENB | ATGE_CFG_RX_FC; 347*0eb090a7SSaurabh Misra } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) { 348*0eb090a7SSaurabh Misra reg |= ATGE_CFG_TX_ENB | ATGE_CFG_RX_ENB; 349*0eb090a7SSaurabh Misra } 350*0eb090a7SSaurabh Misra 351015a6ef6SSaurabh Misra OUTL(atgep, ATGE_MAC_CFG, reg); 352015a6ef6SSaurabh Misra 353015a6ef6SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) { 354015a6ef6SSaurabh Misra reg = ATGE_USECS(ATGE_IM_RX_TIMER_DEFAULT) << IM_TIMER_RX_SHIFT; 355015a6ef6SSaurabh Misra reg |= ATGE_USECS(ATGE_IM_TX_TIMER_DEFAULT) << 356015a6ef6SSaurabh Misra IM_TIMER_TX_SHIFT; 357015a6ef6SSaurabh Misra OUTL(atgep, ATGE_IM_TIMER, reg); 358015a6ef6SSaurabh Misra } 359015a6ef6SSaurabh Misra 360015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() mac_cfg is : %x", 361015a6ef6SSaurabh Misra atgep->atge_name, __func__, INL(atgep, ATGE_MAC_CFG))); 362015a6ef6SSaurabh Misra } 363015a6ef6SSaurabh Misra 364015a6ef6SSaurabh Misra static void 365015a6ef6SSaurabh Misra atge_mii_notify(void *arg, link_state_t link) 366015a6ef6SSaurabh Misra { 367015a6ef6SSaurabh Misra atge_t *atgep = arg; 368015a6ef6SSaurabh Misra 369015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() LINK STATUS CHANGED from %x -> %x", 370015a6ef6SSaurabh Misra atgep->atge_name, __func__, atgep->atge_link_state, link)); 371015a6ef6SSaurabh Misra 372015a6ef6SSaurabh Misra mac_link_update(atgep->atge_mh, link); 373015a6ef6SSaurabh Misra 374015a6ef6SSaurabh Misra /* 375015a6ef6SSaurabh Misra * Reconfigure MAC if link status is UP now. 376015a6ef6SSaurabh Misra */ 377015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock); 378015a6ef6SSaurabh Misra if (link == LINK_STATE_UP) { 379015a6ef6SSaurabh Misra atgep->atge_link_state = LINK_STATE_UP; 380*0eb090a7SSaurabh Misra atge_mac_config(atgep); 381015a6ef6SSaurabh Misra atgep->atge_tx_resched = 0; 382015a6ef6SSaurabh Misra } else { 383015a6ef6SSaurabh Misra atgep->atge_link_state = LINK_STATE_DOWN; 384*0eb090a7SSaurabh Misra atgep->atge_flags |= ATGE_MII_CHECK; 385015a6ef6SSaurabh Misra } 386015a6ef6SSaurabh Misra 387015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock); 388015a6ef6SSaurabh Misra 389015a6ef6SSaurabh Misra if (link == LINK_STATE_UP) 390015a6ef6SSaurabh Misra mac_tx_update(atgep->atge_mh); 391015a6ef6SSaurabh Misra } 392015a6ef6SSaurabh Misra 393*0eb090a7SSaurabh Misra void 394*0eb090a7SSaurabh Misra atge_tx_reclaim(atge_t *atgep, int end) 395015a6ef6SSaurabh Misra { 396*0eb090a7SSaurabh Misra atge_tx_desc_t *txd; 397*0eb090a7SSaurabh Misra atge_ring_t *r = atgep->atge_tx_ring; 398*0eb090a7SSaurabh Misra uchar_t *c; 399*0eb090a7SSaurabh Misra int start; 400015a6ef6SSaurabh Misra 401*0eb090a7SSaurabh Misra ASSERT(MUTEX_HELD(&atgep->atge_tx_lock)); 402*0eb090a7SSaurabh Misra ASSERT(r != NULL); 403015a6ef6SSaurabh Misra 404*0eb090a7SSaurabh Misra start = r->r_consumer; 405015a6ef6SSaurabh Misra 406*0eb090a7SSaurabh Misra if (start == end) 407*0eb090a7SSaurabh Misra return; 408015a6ef6SSaurabh Misra 409*0eb090a7SSaurabh Misra while (start != end) { 410*0eb090a7SSaurabh Misra r->r_avail_desc++; 411*0eb090a7SSaurabh Misra if (r->r_avail_desc > ATGE_TX_RING_CNT) { 412015a6ef6SSaurabh Misra 413015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, 414*0eb090a7SSaurabh Misra "Reclaim : TX descriptor error"); 415015a6ef6SSaurabh Misra 416*0eb090a7SSaurabh Misra if (r->r_avail_desc > (ATGE_TX_RING_CNT + 5)) { 417015a6ef6SSaurabh Misra atge_device_stop(atgep); 418*0eb090a7SSaurabh Misra break; 419015a6ef6SSaurabh Misra } 420015a6ef6SSaurabh Misra } 421015a6ef6SSaurabh Misra 422*0eb090a7SSaurabh Misra c = (uchar_t *)r->r_desc_ring->addr; 423*0eb090a7SSaurabh Misra c += (sizeof (atge_tx_desc_t) * start); 424*0eb090a7SSaurabh Misra txd = (atge_tx_desc_t *)c; 425015a6ef6SSaurabh Misra 426015a6ef6SSaurabh Misra /* 427*0eb090a7SSaurabh Misra * Clearing TX descriptor helps in debugging some strange 428*0eb090a7SSaurabh Misra * problems. 429015a6ef6SSaurabh Misra */ 430*0eb090a7SSaurabh Misra txd->addr = 0; 431*0eb090a7SSaurabh Misra txd->len = 0; 432*0eb090a7SSaurabh Misra txd->flags = 0; 433015a6ef6SSaurabh Misra 434*0eb090a7SSaurabh Misra ATGE_INC_SLOT(start, ATGE_TX_RING_CNT); 435015a6ef6SSaurabh Misra } 436015a6ef6SSaurabh Misra 437*0eb090a7SSaurabh Misra atgep->atge_tx_ring->r_consumer = start; 438015a6ef6SSaurabh Misra 439*0eb090a7SSaurabh Misra DMA_SYNC(r->r_desc_ring, 0, ATGE_TX_RING_SZ, DDI_DMA_SYNC_FORDEV); 440015a6ef6SSaurabh Misra } 441015a6ef6SSaurabh Misra 442015a6ef6SSaurabh Misra /* 443015a6ef6SSaurabh Misra * Adds interrupt handler depending upon the type of interrupt supported by 444015a6ef6SSaurabh Misra * the chip. 445015a6ef6SSaurabh Misra */ 446015a6ef6SSaurabh Misra static int 447015a6ef6SSaurabh Misra atge_add_intr_handler(atge_t *atgep, int intr_type) 448015a6ef6SSaurabh Misra { 449015a6ef6SSaurabh Misra int err; 450015a6ef6SSaurabh Misra int count = 0; 451015a6ef6SSaurabh Misra int avail = 0; 452015a6ef6SSaurabh Misra int i; 453015a6ef6SSaurabh Misra int flag; 454015a6ef6SSaurabh Misra 455015a6ef6SSaurabh Misra if (intr_type != DDI_INTR_TYPE_FIXED) { 456015a6ef6SSaurabh Misra err = ddi_intr_get_nintrs(atgep->atge_dip, intr_type, &count); 457015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 458015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, 459015a6ef6SSaurabh Misra "ddi_intr_get_nintrs failed : %d", err); 460*0eb090a7SSaurabh Misra return (DDI_FAILURE); 461015a6ef6SSaurabh Misra } 462015a6ef6SSaurabh Misra 463015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() count : %d", 464015a6ef6SSaurabh Misra atgep->atge_name, __func__, count)); 465015a6ef6SSaurabh Misra 466015a6ef6SSaurabh Misra err = ddi_intr_get_navail(atgep->atge_dip, intr_type, &avail); 467015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 468015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, 469015a6ef6SSaurabh Misra "ddi_intr_get_navail failed : %d", err); 470*0eb090a7SSaurabh Misra return (DDI_FAILURE); 471015a6ef6SSaurabh Misra } 472015a6ef6SSaurabh Misra 473015a6ef6SSaurabh Misra if (avail < count) { 474015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "count :%d," 475015a6ef6SSaurabh Misra " avail : %d", count, avail); 476015a6ef6SSaurabh Misra } 477015a6ef6SSaurabh Misra 478015a6ef6SSaurabh Misra flag = DDI_INTR_ALLOC_STRICT; 479015a6ef6SSaurabh Misra } else { 480015a6ef6SSaurabh Misra /* 481015a6ef6SSaurabh Misra * DDI_INTR_TYPE_FIXED case. 482015a6ef6SSaurabh Misra */ 483015a6ef6SSaurabh Misra count = 1; 484015a6ef6SSaurabh Misra avail = 1; 485015a6ef6SSaurabh Misra flag = DDI_INTR_ALLOC_NORMAL; 486015a6ef6SSaurabh Misra } 487015a6ef6SSaurabh Misra 488015a6ef6SSaurabh Misra atgep->atge_intr_size = avail * sizeof (ddi_intr_handle_t); 489015a6ef6SSaurabh Misra atgep->atge_intr_handle = kmem_zalloc(atgep->atge_intr_size, KM_SLEEP); 490015a6ef6SSaurabh Misra 491015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() avail:%d, count : %d, type : %d", 492015a6ef6SSaurabh Misra atgep->atge_name, __func__, avail, count, 493015a6ef6SSaurabh Misra intr_type)); 494015a6ef6SSaurabh Misra 495015a6ef6SSaurabh Misra err = ddi_intr_alloc(atgep->atge_dip, atgep->atge_intr_handle, 496015a6ef6SSaurabh Misra intr_type, 0, avail, &atgep->atge_intr_cnt, flag); 497015a6ef6SSaurabh Misra 498015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 499015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "ddi_intr_alloc failed : %d", err); 500015a6ef6SSaurabh Misra kmem_free(atgep->atge_intr_handle, atgep->atge_intr_size); 501*0eb090a7SSaurabh Misra return (DDI_FAILURE); 502015a6ef6SSaurabh Misra } 503015a6ef6SSaurabh Misra 504015a6ef6SSaurabh Misra ATGE_DB(("%s: atge_add_intr_handler() after alloc count" 505015a6ef6SSaurabh Misra " :%d, avail : %d", atgep->atge_name, count, avail)); 506015a6ef6SSaurabh Misra 507015a6ef6SSaurabh Misra err = ddi_intr_get_pri(atgep->atge_intr_handle[0], 508015a6ef6SSaurabh Misra &atgep->atge_intr_pri); 509015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 510015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "ddi_intr_get_pri failed:%d", err); 511015a6ef6SSaurabh Misra for (i = 0; i < atgep->atge_intr_cnt; i++) { 512015a6ef6SSaurabh Misra (void) ddi_intr_free(atgep->atge_intr_handle[i]); 513015a6ef6SSaurabh Misra } 514015a6ef6SSaurabh Misra kmem_free(atgep->atge_intr_handle, atgep->atge_intr_size); 515015a6ef6SSaurabh Misra 516*0eb090a7SSaurabh Misra return (DDI_FAILURE); 517015a6ef6SSaurabh Misra } 518015a6ef6SSaurabh Misra 519015a6ef6SSaurabh Misra /* 520015a6ef6SSaurabh Misra * Add interrupt handler now. 521015a6ef6SSaurabh Misra */ 522015a6ef6SSaurabh Misra for (i = 0; i < atgep->atge_intr_cnt; i++) { 523*0eb090a7SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) { 524015a6ef6SSaurabh Misra err = ddi_intr_add_handler(atgep->atge_intr_handle[i], 525015a6ef6SSaurabh Misra atge_l1e_interrupt, atgep, (caddr_t)(uintptr_t)i); 526*0eb090a7SSaurabh Misra } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) { 527*0eb090a7SSaurabh Misra err = ddi_intr_add_handler(atgep->atge_intr_handle[i], 528*0eb090a7SSaurabh Misra atge_l1_interrupt, atgep, (caddr_t)(uintptr_t)i); 529*0eb090a7SSaurabh Misra } 530015a6ef6SSaurabh Misra 531015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 532015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, 533015a6ef6SSaurabh Misra "ddi_intr_add_handler failed : %d", err); 534015a6ef6SSaurabh Misra 535015a6ef6SSaurabh Misra (void) ddi_intr_free(atgep->atge_intr_handle[i]); 536015a6ef6SSaurabh Misra while (--i >= 0) { 537015a6ef6SSaurabh Misra (void) ddi_intr_remove_handler( 538015a6ef6SSaurabh Misra atgep->atge_intr_handle[i]); 539015a6ef6SSaurabh Misra (void) ddi_intr_free( 540015a6ef6SSaurabh Misra atgep->atge_intr_handle[i]); 541015a6ef6SSaurabh Misra } 542015a6ef6SSaurabh Misra 543015a6ef6SSaurabh Misra kmem_free(atgep->atge_intr_handle, 544015a6ef6SSaurabh Misra atgep->atge_intr_size); 545015a6ef6SSaurabh Misra 546*0eb090a7SSaurabh Misra return (DDI_FAILURE); 547015a6ef6SSaurabh Misra } 548015a6ef6SSaurabh Misra } 549015a6ef6SSaurabh Misra 550015a6ef6SSaurabh Misra err = ddi_intr_get_cap(atgep->atge_intr_handle[0], 551015a6ef6SSaurabh Misra &atgep->atge_intr_cap); 552015a6ef6SSaurabh Misra 553015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 554015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, 555015a6ef6SSaurabh Misra "ddi_intr_get_cap failed : %d", err); 556015a6ef6SSaurabh Misra atge_remove_intr(atgep); 557*0eb090a7SSaurabh Misra return (DDI_FAILURE); 558015a6ef6SSaurabh Misra } 559015a6ef6SSaurabh Misra 560015a6ef6SSaurabh Misra if (intr_type == DDI_INTR_TYPE_FIXED) 561015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_FIXED_TYPE; 562015a6ef6SSaurabh Misra else if (intr_type == DDI_INTR_TYPE_MSI) 563015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_MSI_TYPE; 564015a6ef6SSaurabh Misra else if (intr_type == DDI_INTR_TYPE_MSIX) 565015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_MSIX_TYPE; 566015a6ef6SSaurabh Misra 567*0eb090a7SSaurabh Misra return (DDI_SUCCESS); 568015a6ef6SSaurabh Misra } 569015a6ef6SSaurabh Misra 570015a6ef6SSaurabh Misra void 571015a6ef6SSaurabh Misra atge_remove_intr(atge_t *atgep) 572015a6ef6SSaurabh Misra { 573015a6ef6SSaurabh Misra int i; 574015a6ef6SSaurabh Misra int cap = 0; 575015a6ef6SSaurabh Misra 576015a6ef6SSaurabh Misra if (atgep->atge_intr_handle == NULL) 577015a6ef6SSaurabh Misra return; 578015a6ef6SSaurabh Misra 579015a6ef6SSaurabh Misra if (atgep->atge_intr_cap & DDI_INTR_FLAG_BLOCK) { 580015a6ef6SSaurabh Misra (void) ddi_intr_block_disable(atgep->atge_intr_handle, 581015a6ef6SSaurabh Misra atgep->atge_intr_cnt); 582015a6ef6SSaurabh Misra 583015a6ef6SSaurabh Misra cap = 1; 584015a6ef6SSaurabh Misra } 585015a6ef6SSaurabh Misra 586015a6ef6SSaurabh Misra for (i = 0; i < atgep->atge_intr_cnt; i++) { 587015a6ef6SSaurabh Misra if (cap == 0) 588015a6ef6SSaurabh Misra (void) ddi_intr_disable(atgep->atge_intr_handle[i]); 589015a6ef6SSaurabh Misra 590015a6ef6SSaurabh Misra (void) ddi_intr_remove_handler(atgep->atge_intr_handle[i]); 591015a6ef6SSaurabh Misra (void) ddi_intr_free(atgep->atge_intr_handle[i]); 592015a6ef6SSaurabh Misra } 593015a6ef6SSaurabh Misra 594015a6ef6SSaurabh Misra kmem_free(atgep->atge_intr_handle, atgep->atge_intr_size); 595015a6ef6SSaurabh Misra } 596015a6ef6SSaurabh Misra 597015a6ef6SSaurabh Misra int 598015a6ef6SSaurabh Misra atge_enable_intrs(atge_t *atgep) 599015a6ef6SSaurabh Misra { 600015a6ef6SSaurabh Misra int err; 601015a6ef6SSaurabh Misra int i; 602015a6ef6SSaurabh Misra 603015a6ef6SSaurabh Misra if (atgep->atge_intr_cap & DDI_INTR_FLAG_BLOCK) { 604015a6ef6SSaurabh Misra /* 605015a6ef6SSaurabh Misra * Do block enable. 606015a6ef6SSaurabh Misra */ 607015a6ef6SSaurabh Misra err = ddi_intr_block_enable(atgep->atge_intr_handle, 608015a6ef6SSaurabh Misra atgep->atge_intr_cnt); 609015a6ef6SSaurabh Misra 610015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 611015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, 612015a6ef6SSaurabh Misra "Failed to block enable intrs %d", err); 613*0eb090a7SSaurabh Misra err = DDI_FAILURE; 614015a6ef6SSaurabh Misra } else { 615*0eb090a7SSaurabh Misra err = DDI_SUCCESS; 616015a6ef6SSaurabh Misra } 617015a6ef6SSaurabh Misra } else { 618015a6ef6SSaurabh Misra /* 619015a6ef6SSaurabh Misra * Call ddi_intr_enable() for MSI non-block enable. 620015a6ef6SSaurabh Misra */ 621015a6ef6SSaurabh Misra for (i = 0; i < atgep->atge_intr_cnt; i++) { 622015a6ef6SSaurabh Misra err = ddi_intr_enable(atgep->atge_intr_handle[i]); 623015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 624015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, 625015a6ef6SSaurabh Misra "Failed to enable intrs on %d with : %d", 626015a6ef6SSaurabh Misra i, err); 627015a6ef6SSaurabh Misra break; 628015a6ef6SSaurabh Misra } 629015a6ef6SSaurabh Misra } 630015a6ef6SSaurabh Misra 631015a6ef6SSaurabh Misra if (err == DDI_SUCCESS) 632*0eb090a7SSaurabh Misra err = DDI_SUCCESS; 633015a6ef6SSaurabh Misra else 634*0eb090a7SSaurabh Misra err = DDI_FAILURE; 635015a6ef6SSaurabh Misra } 636015a6ef6SSaurabh Misra 637015a6ef6SSaurabh Misra return (err); 638015a6ef6SSaurabh Misra } 639015a6ef6SSaurabh Misra 640015a6ef6SSaurabh Misra /* 641015a6ef6SSaurabh Misra * Adds interrupt handler depending on the supported interrupt type by the 642015a6ef6SSaurabh Misra * chip. 643015a6ef6SSaurabh Misra */ 644015a6ef6SSaurabh Misra static int 645015a6ef6SSaurabh Misra atge_add_intr(atge_t *atgep) 646015a6ef6SSaurabh Misra { 647015a6ef6SSaurabh Misra int err; 648015a6ef6SSaurabh Misra 649015a6ef6SSaurabh Misra /* 650015a6ef6SSaurabh Misra * Get the supported interrupt types. 651015a6ef6SSaurabh Misra */ 652015a6ef6SSaurabh Misra err = ddi_intr_get_supported_types(atgep->atge_dip, 653015a6ef6SSaurabh Misra &atgep->atge_intr_types); 654015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 655015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, 656015a6ef6SSaurabh Misra "ddi_intr_get_supported_types failed : %d", err); 657*0eb090a7SSaurabh Misra return (DDI_FAILURE); 658015a6ef6SSaurabh Misra } 659015a6ef6SSaurabh Misra 660015a6ef6SSaurabh Misra ATGE_DB(("%s: ddi_intr_get_supported_types() returned : %d", 661015a6ef6SSaurabh Misra atgep->atge_name, atgep->atge_intr_types)); 662015a6ef6SSaurabh Misra 663015a6ef6SSaurabh Misra 664015a6ef6SSaurabh Misra if (atgep->atge_intr_types & DDI_INTR_TYPE_MSIX) { 665015a6ef6SSaurabh Misra err = atge_add_intr_handler(atgep, DDI_INTR_TYPE_MSIX); 666*0eb090a7SSaurabh Misra if (err == DDI_SUCCESS) { 667015a6ef6SSaurabh Misra ATGE_DB(("%s: Using MSIx for interrupt", 668015a6ef6SSaurabh Misra atgep->atge_name)); 669015a6ef6SSaurabh Misra return (err); 670015a6ef6SSaurabh Misra } 671015a6ef6SSaurabh Misra } 672015a6ef6SSaurabh Misra 673015a6ef6SSaurabh Misra if (atgep->atge_intr_types & DDI_INTR_TYPE_MSI) { 674015a6ef6SSaurabh Misra err = atge_add_intr_handler(atgep, DDI_INTR_TYPE_MSI); 675*0eb090a7SSaurabh Misra if (err == DDI_SUCCESS) { 676015a6ef6SSaurabh Misra ATGE_DB(("%s: Using MSI for interrupt", 677015a6ef6SSaurabh Misra atgep->atge_name)); 678015a6ef6SSaurabh Misra return (err); 679015a6ef6SSaurabh Misra } 680015a6ef6SSaurabh Misra } 681015a6ef6SSaurabh Misra 682*0eb090a7SSaurabh Misra err = DDI_FAILURE; 683015a6ef6SSaurabh Misra if (atgep->atge_intr_types & DDI_INTR_TYPE_FIXED) { 684015a6ef6SSaurabh Misra err = atge_add_intr_handler(atgep, DDI_INTR_TYPE_FIXED); 685*0eb090a7SSaurabh Misra if (err == DDI_SUCCESS) { 686015a6ef6SSaurabh Misra ATGE_DB(("%s: Using FIXED type for interrupt", 687015a6ef6SSaurabh Misra atgep->atge_name)); 688015a6ef6SSaurabh Misra return (err); 689015a6ef6SSaurabh Misra } 690015a6ef6SSaurabh Misra } 691015a6ef6SSaurabh Misra 692015a6ef6SSaurabh Misra return (err); 693015a6ef6SSaurabh Misra } 694015a6ef6SSaurabh Misra 695015a6ef6SSaurabh Misra int 696015a6ef6SSaurabh Misra atge_identify_hardware(atge_t *atgep) 697015a6ef6SSaurabh Misra { 698015a6ef6SSaurabh Misra uint16_t vid, did; 699015a6ef6SSaurabh Misra int i; 700015a6ef6SSaurabh Misra 701015a6ef6SSaurabh Misra vid = pci_config_get16(atgep->atge_conf_handle, PCI_CONF_VENID); 702015a6ef6SSaurabh Misra did = pci_config_get16(atgep->atge_conf_handle, PCI_CONF_DEVID); 703015a6ef6SSaurabh Misra 704015a6ef6SSaurabh Misra atgep->atge_model = 0; 705015a6ef6SSaurabh Misra for (i = 0; i < (sizeof (atge_cards) / sizeof (atge_cards_t)); i++) { 706015a6ef6SSaurabh Misra if (atge_cards[i].vendor_id == vid && 707015a6ef6SSaurabh Misra atge_cards[i].device_id == did) { 708015a6ef6SSaurabh Misra atgep->atge_model = atge_cards[i].model; 709015a6ef6SSaurabh Misra atgep->atge_revid = 710015a6ef6SSaurabh Misra pci_config_get8(atgep->atge_conf_handle, 711015a6ef6SSaurabh Misra PCI_CONF_REVID); 712015a6ef6SSaurabh Misra ATGE_DB(("%s: %s : PCI-ID pci%x,%x and model : %d", 713015a6ef6SSaurabh Misra atgep->atge_name, __func__, vid, did, 714015a6ef6SSaurabh Misra atgep->atge_model)); 715015a6ef6SSaurabh Misra 716*0eb090a7SSaurabh Misra return (DDI_SUCCESS); 717015a6ef6SSaurabh Misra } 718015a6ef6SSaurabh Misra } 719015a6ef6SSaurabh Misra 720015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "atge driver is attaching to unknown" 721015a6ef6SSaurabh Misra " pci%d,%d vendor/device-id card", vid, did); 722015a6ef6SSaurabh Misra 723015a6ef6SSaurabh Misra /* 724*0eb090a7SSaurabh Misra * Assume it's L1 chip. 725015a6ef6SSaurabh Misra */ 726*0eb090a7SSaurabh Misra atgep->atge_model = ATGE_CHIP_L1; 727015a6ef6SSaurabh Misra atgep->atge_revid = pci_config_get8(atgep->atge_conf_handle, 728015a6ef6SSaurabh Misra PCI_CONF_REVID); 729015a6ef6SSaurabh Misra 730015a6ef6SSaurabh Misra /* 731015a6ef6SSaurabh Misra * We will leave the decision to caller. 732015a6ef6SSaurabh Misra */ 733*0eb090a7SSaurabh Misra return (DDI_FAILURE); 734015a6ef6SSaurabh Misra } 735015a6ef6SSaurabh Misra 736015a6ef6SSaurabh Misra int 737015a6ef6SSaurabh Misra atge_get_macaddr(atge_t *atgep) 738015a6ef6SSaurabh Misra { 739015a6ef6SSaurabh Misra uint32_t reg; 740015a6ef6SSaurabh Misra 741015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_SPI_CTRL); 742015a6ef6SSaurabh Misra if ((reg & SPI_VPD_ENB) != 0) { 743015a6ef6SSaurabh Misra /* 744015a6ef6SSaurabh Misra * Get VPD stored in TWSI EEPROM. 745015a6ef6SSaurabh Misra */ 746015a6ef6SSaurabh Misra reg &= ~SPI_VPD_ENB; 747015a6ef6SSaurabh Misra OUTL(atgep, ATGE_SPI_CTRL, reg); 748015a6ef6SSaurabh Misra 749015a6ef6SSaurabh Misra ATGE_DB(("%s: %s called Get VPD", atgep->atge_name, __func__)); 750015a6ef6SSaurabh Misra } 751015a6ef6SSaurabh Misra 752015a6ef6SSaurabh Misra atgep->atge_ether_addr[5] = INB(atgep, ATGE_PAR0 + 0); 753015a6ef6SSaurabh Misra atgep->atge_ether_addr[4] = INB(atgep, ATGE_PAR0 + 1); 754015a6ef6SSaurabh Misra atgep->atge_ether_addr[3] = INB(atgep, ATGE_PAR0 + 2); 755015a6ef6SSaurabh Misra atgep->atge_ether_addr[2] = INB(atgep, ATGE_PAR0 + 3); 756015a6ef6SSaurabh Misra atgep->atge_ether_addr[1] = INB(atgep, ATGE_PAR1 + 0); 757015a6ef6SSaurabh Misra atgep->atge_ether_addr[0] = INB(atgep, ATGE_PAR1 + 1); 758015a6ef6SSaurabh Misra 759015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() Station Address - %x:%x:%x:%x:%x:%x", 760015a6ef6SSaurabh Misra atgep->atge_name, __func__, 761015a6ef6SSaurabh Misra atgep->atge_ether_addr[0], 762015a6ef6SSaurabh Misra atgep->atge_ether_addr[1], 763015a6ef6SSaurabh Misra atgep->atge_ether_addr[2], 764015a6ef6SSaurabh Misra atgep->atge_ether_addr[3], 765015a6ef6SSaurabh Misra atgep->atge_ether_addr[4], 766015a6ef6SSaurabh Misra atgep->atge_ether_addr[5])); 767015a6ef6SSaurabh Misra 768015a6ef6SSaurabh Misra bcopy(atgep->atge_ether_addr, atgep->atge_dev_addr, ETHERADDRL); 769015a6ef6SSaurabh Misra 770*0eb090a7SSaurabh Misra return (DDI_SUCCESS); 771015a6ef6SSaurabh Misra } 772015a6ef6SSaurabh Misra 773015a6ef6SSaurabh Misra /* 774015a6ef6SSaurabh Misra * Reset functionality for L1 and L1E. It's same. 775015a6ef6SSaurabh Misra */ 776015a6ef6SSaurabh Misra static void 777015a6ef6SSaurabh Misra atge_device_reset(atge_t *atgep) 778015a6ef6SSaurabh Misra { 779015a6ef6SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E || 780015a6ef6SSaurabh Misra ATGE_MODEL(atgep) == ATGE_CHIP_L1) 781015a6ef6SSaurabh Misra atge_device_reset_l1_l1e(atgep); 782015a6ef6SSaurabh Misra } 783015a6ef6SSaurabh Misra 784015a6ef6SSaurabh Misra void 785015a6ef6SSaurabh Misra atge_device_reset_l1_l1e(atge_t *atgep) 786015a6ef6SSaurabh Misra { 787015a6ef6SSaurabh Misra uint32_t reg; 788015a6ef6SSaurabh Misra int t; 789015a6ef6SSaurabh Misra 790015a6ef6SSaurabh Misra OUTL(atgep, ATGE_MASTER_CFG, MASTER_RESET); 791015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_MASTER_CFG); 792015a6ef6SSaurabh Misra for (t = ATGE_RESET_TIMEOUT; t > 0; t--) { 793015a6ef6SSaurabh Misra drv_usecwait(10); 794015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_MASTER_CFG); 795015a6ef6SSaurabh Misra if ((reg & MASTER_RESET) == 0) 796015a6ef6SSaurabh Misra break; 797015a6ef6SSaurabh Misra } 798015a6ef6SSaurabh Misra 799015a6ef6SSaurabh Misra if (t == 0) { 800015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, " master reset timeout reg : %x", 801015a6ef6SSaurabh Misra reg); 802015a6ef6SSaurabh Misra } 803015a6ef6SSaurabh Misra 804015a6ef6SSaurabh Misra for (t = ATGE_RESET_TIMEOUT; t > 0; t--) { 805015a6ef6SSaurabh Misra if ((reg = INL(atgep, ATGE_IDLE_STATUS)) == 0) 806015a6ef6SSaurabh Misra break; 807015a6ef6SSaurabh Misra 808015a6ef6SSaurabh Misra drv_usecwait(10); 809015a6ef6SSaurabh Misra } 810015a6ef6SSaurabh Misra 811015a6ef6SSaurabh Misra if (t == 0) { 812015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "device reset timeout reg : %x", 813015a6ef6SSaurabh Misra reg); 814015a6ef6SSaurabh Misra } 815015a6ef6SSaurabh Misra 816015a6ef6SSaurabh Misra /* 817015a6ef6SSaurabh Misra * Initialize PCIe module. These values came from FreeBSD and 818015a6ef6SSaurabh Misra * we don't know the meaning of it. 819015a6ef6SSaurabh Misra */ 820015a6ef6SSaurabh Misra OUTL(atgep, 0x12FC, 0x6500); 821015a6ef6SSaurabh Misra reg = INL(atgep, 0x1008) | 0x8000; 822015a6ef6SSaurabh Misra OUTL(atgep, 0x1008, reg); 823015a6ef6SSaurabh Misra 824015a6ef6SSaurabh Misra /* 825015a6ef6SSaurabh Misra * Get chip revision. 826015a6ef6SSaurabh Misra */ 827015a6ef6SSaurabh Misra atgep->atge_chip_rev = INL(atgep, ATGE_MASTER_CFG) >> 828015a6ef6SSaurabh Misra MASTER_CHIP_REV_SHIFT; 829015a6ef6SSaurabh Misra 830015a6ef6SSaurabh Misra ATGE_DB(("%s: %s reset successfully rev : %x", atgep->atge_name, 831015a6ef6SSaurabh Misra __func__, atgep->atge_chip_rev)); 832015a6ef6SSaurabh Misra } 833015a6ef6SSaurabh Misra 834015a6ef6SSaurabh Misra /* 835015a6ef6SSaurabh Misra * DMA allocation for L1 and L1E is bit different since L1E uses RX pages 836015a6ef6SSaurabh Misra * instead of descriptor based RX model. 837015a6ef6SSaurabh Misra */ 838015a6ef6SSaurabh Misra static int 839015a6ef6SSaurabh Misra atge_alloc_dma(atge_t *atgep) 840015a6ef6SSaurabh Misra { 841*0eb090a7SSaurabh Misra int err = DDI_FAILURE; 842015a6ef6SSaurabh Misra 843015a6ef6SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) { 844015a6ef6SSaurabh Misra err = atge_l1e_alloc_dma(atgep); 845*0eb090a7SSaurabh Misra } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) { 846*0eb090a7SSaurabh Misra err = atge_l1_alloc_dma(atgep); 847015a6ef6SSaurabh Misra } 848015a6ef6SSaurabh Misra 849015a6ef6SSaurabh Misra return (err); 850015a6ef6SSaurabh Misra } 851015a6ef6SSaurabh Misra 852015a6ef6SSaurabh Misra static void 853015a6ef6SSaurabh Misra atge_free_dma(atge_t *atgep) 854015a6ef6SSaurabh Misra { 855015a6ef6SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) { 856015a6ef6SSaurabh Misra atge_l1e_free_dma(atgep); 857015a6ef6SSaurabh Misra } 858015a6ef6SSaurabh Misra } 859015a6ef6SSaurabh Misra 860015a6ef6SSaurabh Misra /* 861015a6ef6SSaurabh Misra * Attach entry point in the driver. 862015a6ef6SSaurabh Misra */ 863015a6ef6SSaurabh Misra static int 864015a6ef6SSaurabh Misra atge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) 865015a6ef6SSaurabh Misra { 866015a6ef6SSaurabh Misra atge_t *atgep; 867015a6ef6SSaurabh Misra mac_register_t *macreg; 868015a6ef6SSaurabh Misra int instance; 869015a6ef6SSaurabh Misra uint16_t cap_ptr; 870015a6ef6SSaurabh Misra uint16_t burst; 871015a6ef6SSaurabh Misra int err; 872015a6ef6SSaurabh Misra mii_ops_t *mii_ops; 873015a6ef6SSaurabh Misra 874015a6ef6SSaurabh Misra instance = ddi_get_instance(devinfo); 875015a6ef6SSaurabh Misra 876015a6ef6SSaurabh Misra switch (cmd) { 877015a6ef6SSaurabh Misra default: 878015a6ef6SSaurabh Misra return (DDI_FAILURE); 879015a6ef6SSaurabh Misra 880015a6ef6SSaurabh Misra case DDI_RESUME: 881015a6ef6SSaurabh Misra return (atge_resume(devinfo)); 882015a6ef6SSaurabh Misra 883015a6ef6SSaurabh Misra case DDI_ATTACH: 884015a6ef6SSaurabh Misra ddi_set_driver_private(devinfo, NULL); 885015a6ef6SSaurabh Misra break; 886015a6ef6SSaurabh Misra } 887015a6ef6SSaurabh Misra 888015a6ef6SSaurabh Misra atgep = kmem_zalloc(sizeof (atge_t), KM_SLEEP); 889015a6ef6SSaurabh Misra ddi_set_driver_private(devinfo, atgep); 890015a6ef6SSaurabh Misra atgep->atge_dip = devinfo; 891015a6ef6SSaurabh Misra 892015a6ef6SSaurabh Misra /* 893015a6ef6SSaurabh Misra * Setup name and instance number to be used for debugging and 894015a6ef6SSaurabh Misra * error reporting. 895015a6ef6SSaurabh Misra */ 896015a6ef6SSaurabh Misra (void) snprintf(atgep->atge_name, sizeof (atgep->atge_name), "%s%d", 897015a6ef6SSaurabh Misra "atge", instance); 898015a6ef6SSaurabh Misra 899015a6ef6SSaurabh Misra 900015a6ef6SSaurabh Misra /* 901015a6ef6SSaurabh Misra * Map PCI config space. 902015a6ef6SSaurabh Misra */ 903015a6ef6SSaurabh Misra err = pci_config_setup(devinfo, &atgep->atge_conf_handle); 904015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 905015a6ef6SSaurabh Misra atge_error(devinfo, "pci_config_setup() failed"); 906015a6ef6SSaurabh Misra goto fail1; 907015a6ef6SSaurabh Misra } 908015a6ef6SSaurabh Misra 909015a6ef6SSaurabh Misra (void) atge_identify_hardware(atgep); 910015a6ef6SSaurabh Misra 911015a6ef6SSaurabh Misra /* 912015a6ef6SSaurabh Misra * Map Device registers. 913015a6ef6SSaurabh Misra */ 914015a6ef6SSaurabh Misra err = ddi_regs_map_setup(devinfo, ATGE_PCI_REG_NUMBER, 915015a6ef6SSaurabh Misra &atgep->atge_io_regs, 0, 0, &atge_dev_attr, &atgep->atge_io_handle); 916015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 917015a6ef6SSaurabh Misra atge_error(devinfo, "ddi_regs_map_setup() failed"); 918015a6ef6SSaurabh Misra goto fail2; 919015a6ef6SSaurabh Misra } 920015a6ef6SSaurabh Misra 921015a6ef6SSaurabh Misra /* 922015a6ef6SSaurabh Misra * Add interrupt and its associated handler. 923015a6ef6SSaurabh Misra */ 924015a6ef6SSaurabh Misra err = atge_add_intr(atgep); 925*0eb090a7SSaurabh Misra if (err != DDI_SUCCESS) { 926015a6ef6SSaurabh Misra atge_error(devinfo, "Failed to add interrupt handler"); 927015a6ef6SSaurabh Misra goto fail3; 928015a6ef6SSaurabh Misra } 929015a6ef6SSaurabh Misra 930015a6ef6SSaurabh Misra mutex_init(&atgep->atge_intr_lock, NULL, MUTEX_DRIVER, 931015a6ef6SSaurabh Misra DDI_INTR_PRI(atgep->atge_intr_pri)); 932015a6ef6SSaurabh Misra 933015a6ef6SSaurabh Misra mutex_init(&atgep->atge_tx_lock, NULL, MUTEX_DRIVER, 934015a6ef6SSaurabh Misra DDI_INTR_PRI(atgep->atge_intr_pri)); 935015a6ef6SSaurabh Misra 936015a6ef6SSaurabh Misra mutex_init(&atgep->atge_rx_lock, NULL, MUTEX_DRIVER, 937015a6ef6SSaurabh Misra DDI_INTR_PRI(atgep->atge_intr_pri)); 938015a6ef6SSaurabh Misra 939015a6ef6SSaurabh Misra mutex_init(&atgep->atge_mii_lock, NULL, MUTEX_DRIVER, NULL); 940015a6ef6SSaurabh Misra 941*0eb090a7SSaurabh Misra /* 942*0eb090a7SSaurabh Misra * Used to lock down MBOX register on L1 chip since RX consumer, 943*0eb090a7SSaurabh Misra * TX producer and RX return ring consumer are shared. 944*0eb090a7SSaurabh Misra */ 945*0eb090a7SSaurabh Misra mutex_init(&atgep->atge_mbox_lock, NULL, MUTEX_DRIVER, 946*0eb090a7SSaurabh Misra DDI_INTR_PRI(atgep->atge_intr_pri)); 947*0eb090a7SSaurabh Misra 948015a6ef6SSaurabh Misra atgep->atge_link_state = LINK_STATE_DOWN; 949015a6ef6SSaurabh Misra atgep->atge_mtu = ETHERMTU; 950015a6ef6SSaurabh Misra 951*0eb090a7SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) { 952015a6ef6SSaurabh Misra if (atgep->atge_revid > 0xF0) { 953015a6ef6SSaurabh Misra /* L2E Rev. B. AR8114 */ 954015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_FLAG_FASTETHER; 955015a6ef6SSaurabh Misra } else { 956*0eb090a7SSaurabh Misra if ((INL(atgep, L1E_PHY_STATUS) & 957*0eb090a7SSaurabh Misra PHY_STATUS_100M) != 0) { 958015a6ef6SSaurabh Misra /* L1E AR8121 */ 959015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_FLAG_JUMBO; 960015a6ef6SSaurabh Misra } else { 961015a6ef6SSaurabh Misra /* L2E Rev. A. AR8113 */ 962015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_FLAG_FASTETHER; 963015a6ef6SSaurabh Misra } 964015a6ef6SSaurabh Misra } 965*0eb090a7SSaurabh Misra } 966015a6ef6SSaurabh Misra 967015a6ef6SSaurabh Misra /* 968015a6ef6SSaurabh Misra * Get DMA parameters from PCIe device control register. 969015a6ef6SSaurabh Misra */ 970015a6ef6SSaurabh Misra err = PCI_CAP_LOCATE(atgep->atge_conf_handle, PCI_CAP_ID_PCI_E, 971015a6ef6SSaurabh Misra &cap_ptr); 972015a6ef6SSaurabh Misra 973015a6ef6SSaurabh Misra if (err == DDI_FAILURE) { 974015a6ef6SSaurabh Misra atgep->atge_dma_rd_burst = DMA_CFG_RD_BURST_128; 975015a6ef6SSaurabh Misra atgep->atge_dma_wr_burst = DMA_CFG_WR_BURST_128; 976015a6ef6SSaurabh Misra } else { 977015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_FLAG_PCIE; 978015a6ef6SSaurabh Misra burst = pci_config_get16(atgep->atge_conf_handle, 979015a6ef6SSaurabh Misra cap_ptr + 0x08); 980015a6ef6SSaurabh Misra 981015a6ef6SSaurabh Misra /* 982015a6ef6SSaurabh Misra * Max read request size. 983015a6ef6SSaurabh Misra */ 984015a6ef6SSaurabh Misra atgep->atge_dma_rd_burst = ((burst >> 12) & 0x07) << 985015a6ef6SSaurabh Misra DMA_CFG_RD_BURST_SHIFT; 986015a6ef6SSaurabh Misra 987015a6ef6SSaurabh Misra /* 988015a6ef6SSaurabh Misra * Max Payload Size. 989015a6ef6SSaurabh Misra */ 990015a6ef6SSaurabh Misra atgep->atge_dma_wr_burst = ((burst >> 5) & 0x07) << 991015a6ef6SSaurabh Misra DMA_CFG_WR_BURST_SHIFT; 992015a6ef6SSaurabh Misra 993015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() MRR : %d, MPS : %d", 994015a6ef6SSaurabh Misra atgep->atge_name, __func__, 995015a6ef6SSaurabh Misra (128 << ((burst >> 12) & 0x07)), 996015a6ef6SSaurabh Misra (128 << ((burst >> 5) & 0x07)))); 997015a6ef6SSaurabh Misra } 998015a6ef6SSaurabh Misra 999015a6ef6SSaurabh Misra /* 1000015a6ef6SSaurabh Misra * Allocate DMA resources. 1001015a6ef6SSaurabh Misra */ 1002015a6ef6SSaurabh Misra err = atge_alloc_dma(atgep); 1003*0eb090a7SSaurabh Misra if (err != DDI_SUCCESS) { 1004015a6ef6SSaurabh Misra atge_error(devinfo, "Failed to allocate DMA resources"); 1005015a6ef6SSaurabh Misra goto fail4; 1006015a6ef6SSaurabh Misra } 1007015a6ef6SSaurabh Misra 1008015a6ef6SSaurabh Misra /* 1009015a6ef6SSaurabh Misra * Get station address. 1010015a6ef6SSaurabh Misra */ 1011015a6ef6SSaurabh Misra (void) atge_get_macaddr(atgep); 1012015a6ef6SSaurabh Misra 1013015a6ef6SSaurabh Misra /* 1014015a6ef6SSaurabh Misra * Setup MII. 1015015a6ef6SSaurabh Misra */ 1016015a6ef6SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) { 1017015a6ef6SSaurabh Misra mii_ops = &atge_l1e_mii_ops; 1018*0eb090a7SSaurabh Misra } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) { 1019*0eb090a7SSaurabh Misra mii_ops = &atge_l1_mii_ops; 1020015a6ef6SSaurabh Misra } 1021015a6ef6SSaurabh Misra 1022015a6ef6SSaurabh Misra if ((atgep->atge_mii = mii_alloc(atgep, devinfo, 1023015a6ef6SSaurabh Misra mii_ops)) == NULL) { 1024015a6ef6SSaurabh Misra atge_error(devinfo, "mii_alloc() failed"); 1025015a6ef6SSaurabh Misra goto fail4; 1026015a6ef6SSaurabh Misra } 1027015a6ef6SSaurabh Misra 1028015a6ef6SSaurabh Misra /* 1029015a6ef6SSaurabh Misra * Register with MAC layer. 1030015a6ef6SSaurabh Misra */ 1031015a6ef6SSaurabh Misra if ((macreg = mac_alloc(MAC_VERSION)) == NULL) { 1032015a6ef6SSaurabh Misra atge_error(devinfo, "mac_alloc() failed due to version"); 1033015a6ef6SSaurabh Misra goto fail4; 1034015a6ef6SSaurabh Misra } 1035015a6ef6SSaurabh Misra 1036015a6ef6SSaurabh Misra macreg->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 1037015a6ef6SSaurabh Misra macreg->m_driver = atgep; 1038015a6ef6SSaurabh Misra macreg->m_dip = devinfo; 1039015a6ef6SSaurabh Misra macreg->m_instance = instance; 1040015a6ef6SSaurabh Misra macreg->m_src_addr = atgep->atge_ether_addr; 1041015a6ef6SSaurabh Misra macreg->m_callbacks = &atge_m_callbacks; 1042015a6ef6SSaurabh Misra macreg->m_min_sdu = 0; 1043015a6ef6SSaurabh Misra macreg->m_max_sdu = atgep->atge_mtu; 1044015a6ef6SSaurabh Misra macreg->m_margin = VLAN_TAGSZ; 1045015a6ef6SSaurabh Misra 1046015a6ef6SSaurabh Misra if ((err = mac_register(macreg, &atgep->atge_mh)) != 0) { 1047015a6ef6SSaurabh Misra atge_error(devinfo, "mac_register() failed with :%d", err); 1048015a6ef6SSaurabh Misra mac_free(macreg); 1049015a6ef6SSaurabh Misra goto fail4; 1050015a6ef6SSaurabh Misra } 1051015a6ef6SSaurabh Misra 1052015a6ef6SSaurabh Misra mac_free(macreg); 1053015a6ef6SSaurabh Misra 1054015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() driver attached successfully", 1055015a6ef6SSaurabh Misra atgep->atge_name, __func__)); 1056015a6ef6SSaurabh Misra 1057015a6ef6SSaurabh Misra atge_device_reset(atgep); 1058015a6ef6SSaurabh Misra 1059015a6ef6SSaurabh Misra atgep->atge_chip_state = ATGE_CHIP_INITIALIZED; 1060015a6ef6SSaurabh Misra 1061015a6ef6SSaurabh Misra /* 1062015a6ef6SSaurabh Misra * At last - enable interrupts. 1063015a6ef6SSaurabh Misra */ 1064015a6ef6SSaurabh Misra err = atge_enable_intrs(atgep); 1065*0eb090a7SSaurabh Misra if (err == DDI_FAILURE) { 1066015a6ef6SSaurabh Misra goto fail5; 1067015a6ef6SSaurabh Misra } 1068015a6ef6SSaurabh Misra 1069015a6ef6SSaurabh Misra /* 1070015a6ef6SSaurabh Misra * Reset the PHY before starting. 1071015a6ef6SSaurabh Misra */ 1072015a6ef6SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) { 1073015a6ef6SSaurabh Misra atge_l1e_mii_reset(atgep); 1074*0eb090a7SSaurabh Misra } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) { 1075*0eb090a7SSaurabh Misra atge_l1_mii_reset(atgep); 1076015a6ef6SSaurabh Misra } 1077015a6ef6SSaurabh Misra 1078015a6ef6SSaurabh Misra /* 1079015a6ef6SSaurabh Misra * Let the PHY run. 1080015a6ef6SSaurabh Misra */ 1081015a6ef6SSaurabh Misra mii_start(atgep->atge_mii); 1082015a6ef6SSaurabh Misra 1083015a6ef6SSaurabh Misra return (DDI_SUCCESS); 1084015a6ef6SSaurabh Misra 1085015a6ef6SSaurabh Misra fail5: 1086015a6ef6SSaurabh Misra (void) mac_unregister(atgep->atge_mh); 1087015a6ef6SSaurabh Misra atge_device_stop(atgep); 1088015a6ef6SSaurabh Misra mii_stop(atgep->atge_mii); 1089015a6ef6SSaurabh Misra mii_free(atgep->atge_mii); 1090015a6ef6SSaurabh Misra fail4: 1091015a6ef6SSaurabh Misra atge_free_dma(atgep); 1092015a6ef6SSaurabh Misra mutex_destroy(&atgep->atge_intr_lock); 1093015a6ef6SSaurabh Misra mutex_destroy(&atgep->atge_tx_lock); 1094015a6ef6SSaurabh Misra mutex_destroy(&atgep->atge_rx_lock); 1095015a6ef6SSaurabh Misra atge_remove_intr(atgep); 1096015a6ef6SSaurabh Misra fail3: 1097015a6ef6SSaurabh Misra ddi_regs_map_free(&atgep->atge_io_handle); 1098015a6ef6SSaurabh Misra fail2: 1099015a6ef6SSaurabh Misra pci_config_teardown(&atgep->atge_conf_handle); 1100015a6ef6SSaurabh Misra fail1: 1101015a6ef6SSaurabh Misra if (atgep) 1102015a6ef6SSaurabh Misra kmem_free(atgep, sizeof (atge_t)); 1103015a6ef6SSaurabh Misra 1104015a6ef6SSaurabh Misra return (DDI_FAILURE); 1105015a6ef6SSaurabh Misra } 1106015a6ef6SSaurabh Misra 1107015a6ef6SSaurabh Misra static int 1108015a6ef6SSaurabh Misra atge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 1109015a6ef6SSaurabh Misra { 1110015a6ef6SSaurabh Misra atge_t *atgep; 1111015a6ef6SSaurabh Misra 1112015a6ef6SSaurabh Misra atgep = ddi_get_driver_private(dip); 1113015a6ef6SSaurabh Misra if (atgep == NULL) { 1114015a6ef6SSaurabh Misra atge_error(dip, "No soft state in detach"); 1115015a6ef6SSaurabh Misra return (DDI_FAILURE); 1116015a6ef6SSaurabh Misra } 1117015a6ef6SSaurabh Misra 1118015a6ef6SSaurabh Misra switch (cmd) { 1119015a6ef6SSaurabh Misra case DDI_DETACH: 1120015a6ef6SSaurabh Misra mii_stop(atgep->atge_mii); 1121015a6ef6SSaurabh Misra 1122015a6ef6SSaurabh Misra /* 1123015a6ef6SSaurabh Misra * First unregister with MAC layer before stopping DMA 1124015a6ef6SSaurabh Misra */ 1125015a6ef6SSaurabh Misra if (mac_unregister(atgep->atge_mh) != DDI_SUCCESS) 1126015a6ef6SSaurabh Misra return (DDI_FAILURE); 1127015a6ef6SSaurabh Misra 1128015a6ef6SSaurabh Misra atgep->atge_mh = NULL; 1129015a6ef6SSaurabh Misra 1130015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_intr_lock); 1131015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock); 1132015a6ef6SSaurabh Misra atge_device_stop(atgep); 1133015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock); 1134015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_intr_lock); 1135015a6ef6SSaurabh Misra 1136015a6ef6SSaurabh Misra mii_free(atgep->atge_mii); 1137015a6ef6SSaurabh Misra atge_free_dma(atgep); 1138015a6ef6SSaurabh Misra 1139015a6ef6SSaurabh Misra ddi_regs_map_free(&atgep->atge_io_handle); 1140015a6ef6SSaurabh Misra atge_remove_intr(atgep); 1141015a6ef6SSaurabh Misra pci_config_teardown(&atgep->atge_conf_handle); 1142015a6ef6SSaurabh Misra 1143015a6ef6SSaurabh Misra mutex_destroy(&atgep->atge_intr_lock); 1144015a6ef6SSaurabh Misra mutex_destroy(&atgep->atge_tx_lock); 1145015a6ef6SSaurabh Misra mutex_destroy(&atgep->atge_rx_lock); 1146015a6ef6SSaurabh Misra kmem_free(atgep, sizeof (atge_t)); 1147015a6ef6SSaurabh Misra ddi_set_driver_private(dip, NULL); 1148015a6ef6SSaurabh Misra 1149015a6ef6SSaurabh Misra return (DDI_SUCCESS); 1150015a6ef6SSaurabh Misra 1151015a6ef6SSaurabh Misra case DDI_SUSPEND: 1152015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() is being suspended", 1153015a6ef6SSaurabh Misra atgep->atge_name, __func__)); 1154015a6ef6SSaurabh Misra 1155015a6ef6SSaurabh Misra /* 1156015a6ef6SSaurabh Misra * Suspend monitoring MII. 1157015a6ef6SSaurabh Misra */ 1158015a6ef6SSaurabh Misra mii_suspend(atgep->atge_mii); 1159015a6ef6SSaurabh Misra 1160015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_intr_lock); 1161015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock); 1162015a6ef6SSaurabh Misra atgep->atge_chip_state |= ATGE_CHIP_SUSPENDED; 1163015a6ef6SSaurabh Misra atge_device_stop(atgep); 1164015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock); 1165015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_intr_lock); 1166015a6ef6SSaurabh Misra 1167015a6ef6SSaurabh Misra return (DDI_SUCCESS); 1168015a6ef6SSaurabh Misra 1169015a6ef6SSaurabh Misra default: 1170015a6ef6SSaurabh Misra return (DDI_FAILURE); 1171015a6ef6SSaurabh Misra } 1172015a6ef6SSaurabh Misra } 1173015a6ef6SSaurabh Misra 1174015a6ef6SSaurabh Misra int 1175015a6ef6SSaurabh Misra atge_alloc_buffers(atge_ring_t *r, size_t rcnt, size_t buflen, int f) 1176015a6ef6SSaurabh Misra { 1177015a6ef6SSaurabh Misra atge_dma_t *dma; 1178015a6ef6SSaurabh Misra atge_dma_t **tbl; 1179*0eb090a7SSaurabh Misra int err = DDI_SUCCESS; 1180015a6ef6SSaurabh Misra int i; 1181015a6ef6SSaurabh Misra 1182015a6ef6SSaurabh Misra tbl = kmem_zalloc(rcnt * sizeof (atge_dma_t *), KM_SLEEP); 1183015a6ef6SSaurabh Misra r->r_buf_tbl = tbl; 1184015a6ef6SSaurabh Misra 1185015a6ef6SSaurabh Misra for (i = 0; i < rcnt; i++) { 1186015a6ef6SSaurabh Misra dma = atge_buf_alloc(r->r_atge, buflen, f); 1187015a6ef6SSaurabh Misra if (dma == NULL) { 1188*0eb090a7SSaurabh Misra err = DDI_FAILURE; 1189015a6ef6SSaurabh Misra break; 1190015a6ef6SSaurabh Misra } 1191015a6ef6SSaurabh Misra 1192015a6ef6SSaurabh Misra tbl[i] = dma; 1193015a6ef6SSaurabh Misra } 1194015a6ef6SSaurabh Misra 1195015a6ef6SSaurabh Misra return (err); 1196015a6ef6SSaurabh Misra } 1197015a6ef6SSaurabh Misra 1198015a6ef6SSaurabh Misra void 1199015a6ef6SSaurabh Misra atge_free_buffers(atge_ring_t *r, size_t rcnt) 1200015a6ef6SSaurabh Misra { 1201015a6ef6SSaurabh Misra atge_dma_t **tbl; 1202015a6ef6SSaurabh Misra int i; 1203015a6ef6SSaurabh Misra 1204015a6ef6SSaurabh Misra if (r == NULL || r->r_buf_tbl == NULL) 1205015a6ef6SSaurabh Misra return; 1206015a6ef6SSaurabh Misra 1207015a6ef6SSaurabh Misra tbl = r->r_buf_tbl; 1208015a6ef6SSaurabh Misra for (i = 0; i < rcnt; i++) { 1209015a6ef6SSaurabh Misra if (tbl[i] != NULL) { 1210015a6ef6SSaurabh Misra atge_buf_free(tbl[i]); 1211015a6ef6SSaurabh Misra } 1212015a6ef6SSaurabh Misra } 1213015a6ef6SSaurabh Misra 1214015a6ef6SSaurabh Misra kmem_free(tbl, rcnt * sizeof (atge_dma_t *)); 1215015a6ef6SSaurabh Misra } 1216015a6ef6SSaurabh Misra 1217015a6ef6SSaurabh Misra atge_dma_t * 1218015a6ef6SSaurabh Misra atge_alloc_a_dma_blk(atge_t *atgep, ddi_dma_attr_t *attr, int size, int d) 1219015a6ef6SSaurabh Misra { 1220015a6ef6SSaurabh Misra int err; 1221015a6ef6SSaurabh Misra atge_dma_t *dma; 1222015a6ef6SSaurabh Misra 1223015a6ef6SSaurabh Misra dma = kmem_zalloc(sizeof (atge_dma_t), KM_SLEEP); 1224015a6ef6SSaurabh Misra 1225015a6ef6SSaurabh Misra err = ddi_dma_alloc_handle(atgep->atge_dip, attr, 1226015a6ef6SSaurabh Misra DDI_DMA_SLEEP, NULL, &dma->hdl); 1227015a6ef6SSaurabh Misra 1228015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 1229015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "%s() : failed" 1230015a6ef6SSaurabh Misra " in ddi_dma_alloc_handle() : %d", __func__, err); 1231015a6ef6SSaurabh Misra goto fail; 1232015a6ef6SSaurabh Misra } 1233015a6ef6SSaurabh Misra 1234015a6ef6SSaurabh Misra err = ddi_dma_mem_alloc(dma->hdl, 1235015a6ef6SSaurabh Misra size, &atge_buf_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, 1236015a6ef6SSaurabh Misra &dma->addr, &dma->len, &dma->acchdl); 1237015a6ef6SSaurabh Misra 1238015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 1239015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "%s() : failed" 1240015a6ef6SSaurabh Misra " in ddi_dma_mem_alloc() : %d", __func__, err); 1241015a6ef6SSaurabh Misra ddi_dma_free_handle(&dma->hdl); 1242015a6ef6SSaurabh Misra goto fail; 1243015a6ef6SSaurabh Misra } 1244015a6ef6SSaurabh Misra 1245015a6ef6SSaurabh Misra err = ddi_dma_addr_bind_handle(dma->hdl, NULL, dma->addr, 1246015a6ef6SSaurabh Misra dma->len, d | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 1247015a6ef6SSaurabh Misra NULL, &dma->cookie, &dma->count); 1248015a6ef6SSaurabh Misra 1249015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 1250015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "%s() : failed" 1251015a6ef6SSaurabh Misra " in ddi_dma_addr_bind_handle() : %d", __func__, err); 1252015a6ef6SSaurabh Misra ddi_dma_mem_free(&dma->acchdl); 1253015a6ef6SSaurabh Misra ddi_dma_free_handle(&dma->hdl); 1254015a6ef6SSaurabh Misra goto fail; 1255015a6ef6SSaurabh Misra } 1256015a6ef6SSaurabh Misra 1257015a6ef6SSaurabh Misra return (dma); 1258015a6ef6SSaurabh Misra fail: 1259015a6ef6SSaurabh Misra kmem_free(dma, sizeof (atge_dma_t)); 1260015a6ef6SSaurabh Misra return (NULL); 1261015a6ef6SSaurabh Misra } 1262015a6ef6SSaurabh Misra 1263015a6ef6SSaurabh Misra void 1264015a6ef6SSaurabh Misra atge_free_a_dma_blk(atge_dma_t *dma) 1265015a6ef6SSaurabh Misra { 1266015a6ef6SSaurabh Misra if (dma != NULL) { 1267015a6ef6SSaurabh Misra (void) ddi_dma_unbind_handle(dma->hdl); 1268015a6ef6SSaurabh Misra ddi_dma_mem_free(&dma->acchdl); 1269015a6ef6SSaurabh Misra ddi_dma_free_handle(&dma->hdl); 1270015a6ef6SSaurabh Misra kmem_free(dma, sizeof (atge_dma_t)); 1271015a6ef6SSaurabh Misra } 1272015a6ef6SSaurabh Misra } 1273015a6ef6SSaurabh Misra 1274015a6ef6SSaurabh Misra atge_dma_t * 1275015a6ef6SSaurabh Misra atge_buf_alloc(atge_t *atgep, size_t len, int f) 1276015a6ef6SSaurabh Misra { 1277015a6ef6SSaurabh Misra atge_dma_t *dma = NULL; 1278015a6ef6SSaurabh Misra int err; 1279015a6ef6SSaurabh Misra 1280015a6ef6SSaurabh Misra dma = kmem_zalloc(sizeof (atge_dma_t), KM_SLEEP); 1281015a6ef6SSaurabh Misra 1282015a6ef6SSaurabh Misra err = ddi_dma_alloc_handle(atgep->atge_dip, &atge_dma_attr_buf, 1283015a6ef6SSaurabh Misra DDI_DMA_SLEEP, NULL, &dma->hdl); 1284015a6ef6SSaurabh Misra 1285015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 1286015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "%s() : failed" 1287015a6ef6SSaurabh Misra " in %s() : %d", __func__, err); 1288015a6ef6SSaurabh Misra goto fail; 1289015a6ef6SSaurabh Misra } 1290015a6ef6SSaurabh Misra 1291015a6ef6SSaurabh Misra err = ddi_dma_mem_alloc(dma->hdl, len, &atge_buf_attr, 1292015a6ef6SSaurabh Misra DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, &dma->addr, 1293015a6ef6SSaurabh Misra &dma->len, &dma->acchdl); 1294015a6ef6SSaurabh Misra 1295015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 1296015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "%s() : failed" 1297015a6ef6SSaurabh Misra " in %s() : %d", __func__, err); 1298015a6ef6SSaurabh Misra ddi_dma_free_handle(&dma->hdl); 1299015a6ef6SSaurabh Misra goto fail; 1300015a6ef6SSaurabh Misra } 1301015a6ef6SSaurabh Misra 1302015a6ef6SSaurabh Misra err = ddi_dma_addr_bind_handle(dma->hdl, NULL, dma->addr, dma->len, 1303015a6ef6SSaurabh Misra (f | DDI_DMA_CONSISTENT), DDI_DMA_SLEEP, NULL, &dma->cookie, 1304015a6ef6SSaurabh Misra &dma->count); 1305015a6ef6SSaurabh Misra 1306015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) { 1307015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "%s() : failed" 1308015a6ef6SSaurabh Misra " in %s() : %d", __func__, err); 1309015a6ef6SSaurabh Misra ddi_dma_mem_free(&dma->acchdl); 1310015a6ef6SSaurabh Misra ddi_dma_free_handle(&dma->hdl); 1311015a6ef6SSaurabh Misra goto fail; 1312015a6ef6SSaurabh Misra } 1313015a6ef6SSaurabh Misra 1314015a6ef6SSaurabh Misra /* 1315015a6ef6SSaurabh Misra * Number of return'ed cookie should be one. 1316015a6ef6SSaurabh Misra */ 1317015a6ef6SSaurabh Misra ASSERT(dma->count == 1); 1318015a6ef6SSaurabh Misra 1319015a6ef6SSaurabh Misra return (dma); 1320015a6ef6SSaurabh Misra fail: 1321015a6ef6SSaurabh Misra kmem_free(dma, sizeof (atge_dma_t)); 1322015a6ef6SSaurabh Misra return (NULL); 1323015a6ef6SSaurabh Misra } 1324015a6ef6SSaurabh Misra 1325015a6ef6SSaurabh Misra void 1326015a6ef6SSaurabh Misra atge_buf_free(atge_dma_t *dma) 1327015a6ef6SSaurabh Misra { 1328015a6ef6SSaurabh Misra ASSERT(dma != NULL); 1329015a6ef6SSaurabh Misra 1330015a6ef6SSaurabh Misra (void) ddi_dma_unbind_handle(dma->hdl); 1331015a6ef6SSaurabh Misra ddi_dma_mem_free(&dma->acchdl); 1332015a6ef6SSaurabh Misra ddi_dma_free_handle(&dma->hdl); 1333015a6ef6SSaurabh Misra kmem_free(dma, sizeof (atge_dma_t)); 1334015a6ef6SSaurabh Misra } 1335015a6ef6SSaurabh Misra 1336015a6ef6SSaurabh Misra static int 1337015a6ef6SSaurabh Misra atge_resume(dev_info_t *dip) 1338015a6ef6SSaurabh Misra { 1339015a6ef6SSaurabh Misra atge_t *atgep; 1340015a6ef6SSaurabh Misra 1341015a6ef6SSaurabh Misra if ((atgep = ddi_get_driver_private(dip)) == NULL) { 1342015a6ef6SSaurabh Misra return (DDI_FAILURE); 1343015a6ef6SSaurabh Misra } 1344015a6ef6SSaurabh Misra 1345015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_intr_lock); 1346015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock); 1347015a6ef6SSaurabh Misra 1348015a6ef6SSaurabh Misra atgep->atge_chip_state &= ~ATGE_CHIP_SUSPENDED; 1349015a6ef6SSaurabh Misra 1350015a6ef6SSaurabh Misra if (atgep->atge_chip_state & ATGE_CHIP_RUNNING) { 1351015a6ef6SSaurabh Misra atge_device_restart(atgep); 1352015a6ef6SSaurabh Misra } else { 1353015a6ef6SSaurabh Misra atge_device_reset(atgep); 1354015a6ef6SSaurabh Misra } 1355015a6ef6SSaurabh Misra 1356015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock); 1357015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_intr_lock); 1358015a6ef6SSaurabh Misra 1359015a6ef6SSaurabh Misra /* 1360015a6ef6SSaurabh Misra * Reset the PHY before resuming MII. 1361015a6ef6SSaurabh Misra */ 1362015a6ef6SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) { 1363015a6ef6SSaurabh Misra atge_l1e_mii_reset(atgep); 1364015a6ef6SSaurabh Misra } 1365015a6ef6SSaurabh Misra 1366015a6ef6SSaurabh Misra mii_resume(atgep->atge_mii); 1367015a6ef6SSaurabh Misra 1368015a6ef6SSaurabh Misra /* kick-off downstream */ 1369015a6ef6SSaurabh Misra mac_tx_update(atgep->atge_mh); 1370015a6ef6SSaurabh Misra 1371015a6ef6SSaurabh Misra return (DDI_SUCCESS); 1372015a6ef6SSaurabh Misra } 1373015a6ef6SSaurabh Misra 1374015a6ef6SSaurabh Misra static int 1375015a6ef6SSaurabh Misra atge_quiesce(dev_info_t *dip) 1376015a6ef6SSaurabh Misra { 1377015a6ef6SSaurabh Misra atge_t *atgep; 1378015a6ef6SSaurabh Misra 1379015a6ef6SSaurabh Misra if ((atgep = ddi_get_driver_private(dip)) == NULL) { 1380015a6ef6SSaurabh Misra return (DDI_FAILURE); 1381015a6ef6SSaurabh Misra } 1382015a6ef6SSaurabh Misra 1383015a6ef6SSaurabh Misra atge_device_stop(atgep); 1384015a6ef6SSaurabh Misra 1385015a6ef6SSaurabh Misra return (DDI_SUCCESS); 1386015a6ef6SSaurabh Misra } 1387015a6ef6SSaurabh Misra 1388015a6ef6SSaurabh Misra void 1389015a6ef6SSaurabh Misra atge_add_multicst(atge_t *atgep, uint8_t *macaddr) 1390015a6ef6SSaurabh Misra { 1391015a6ef6SSaurabh Misra uint32_t crc; 1392015a6ef6SSaurabh Misra int bit; 1393015a6ef6SSaurabh Misra 1394015a6ef6SSaurabh Misra ASSERT(MUTEX_HELD(&atgep->atge_intr_lock)); 1395015a6ef6SSaurabh Misra ASSERT(MUTEX_HELD(&atgep->atge_tx_lock)); 1396015a6ef6SSaurabh Misra 1397015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() %x:%x:%x:%x:%x:%x", 1398015a6ef6SSaurabh Misra atgep->atge_name, __func__, macaddr[0], macaddr[1], macaddr[2], 1399015a6ef6SSaurabh Misra macaddr[3], macaddr[4], macaddr[5])); 1400015a6ef6SSaurabh Misra 1401015a6ef6SSaurabh Misra crc = atge_ether_crc(macaddr, ETHERADDRL); 1402015a6ef6SSaurabh Misra bit = (crc >> 26); 1403015a6ef6SSaurabh Misra atgep->atge_mchash_ref_cnt[bit]++; 1404015a6ef6SSaurabh Misra atgep->atge_mchash |= (1ULL << (crc >> 26)); 1405015a6ef6SSaurabh Misra 1406015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() mchash :%llx, bit : %d," 1407015a6ef6SSaurabh Misra " atge_mchash_ref_cnt[bit] :%d", 1408015a6ef6SSaurabh Misra atgep->atge_name, __func__, atgep->atge_mchash, bit, 1409015a6ef6SSaurabh Misra atgep->atge_mchash_ref_cnt[bit])); 1410015a6ef6SSaurabh Misra } 1411015a6ef6SSaurabh Misra 1412015a6ef6SSaurabh Misra void 1413015a6ef6SSaurabh Misra atge_remove_multicst(atge_t *atgep, uint8_t *macaddr) 1414015a6ef6SSaurabh Misra { 1415015a6ef6SSaurabh Misra uint32_t crc; 1416015a6ef6SSaurabh Misra int bit; 1417015a6ef6SSaurabh Misra 1418015a6ef6SSaurabh Misra ASSERT(MUTEX_HELD(&atgep->atge_intr_lock)); 1419015a6ef6SSaurabh Misra ASSERT(MUTEX_HELD(&atgep->atge_tx_lock)); 1420015a6ef6SSaurabh Misra 1421015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() %x:%x:%x:%x:%x:%x", 1422015a6ef6SSaurabh Misra atgep->atge_name, __func__, macaddr[0], macaddr[1], macaddr[2], 1423015a6ef6SSaurabh Misra macaddr[3], macaddr[4], macaddr[5])); 1424015a6ef6SSaurabh Misra 1425015a6ef6SSaurabh Misra crc = atge_ether_crc(macaddr, ETHERADDRL); 1426015a6ef6SSaurabh Misra bit = (crc >> 26); 1427015a6ef6SSaurabh Misra atgep->atge_mchash_ref_cnt[bit]--; 1428015a6ef6SSaurabh Misra if (atgep->atge_mchash_ref_cnt[bit] == 0) 1429015a6ef6SSaurabh Misra atgep->atge_mchash &= ~(1ULL << (crc >> 26)); 1430015a6ef6SSaurabh Misra 1431015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() mchash :%llx, bit : %d," 1432015a6ef6SSaurabh Misra " atge_mchash_ref_cnt[bit] :%d", 1433015a6ef6SSaurabh Misra atgep->atge_name, __func__, atgep->atge_mchash, bit, 1434015a6ef6SSaurabh Misra atgep->atge_mchash_ref_cnt[bit])); 1435015a6ef6SSaurabh Misra } 1436015a6ef6SSaurabh Misra 1437015a6ef6SSaurabh Misra int 1438015a6ef6SSaurabh Misra atge_m_multicst(void *arg, boolean_t add, const uint8_t *macaddr) 1439015a6ef6SSaurabh Misra { 1440015a6ef6SSaurabh Misra atge_t *atgep = arg; 1441015a6ef6SSaurabh Misra 1442015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_intr_lock); 1443015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock); 1444015a6ef6SSaurabh Misra 1445015a6ef6SSaurabh Misra if (add) { 1446015a6ef6SSaurabh Misra atge_add_multicst(atgep, (uint8_t *)macaddr); 1447015a6ef6SSaurabh Misra } else { 1448015a6ef6SSaurabh Misra atge_remove_multicst(atgep, (uint8_t *)macaddr); 1449015a6ef6SSaurabh Misra } 1450015a6ef6SSaurabh Misra 1451015a6ef6SSaurabh Misra atge_rxfilter(atgep); 1452015a6ef6SSaurabh Misra 1453015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock); 1454015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_intr_lock); 1455015a6ef6SSaurabh Misra 1456015a6ef6SSaurabh Misra return (0); 1457015a6ef6SSaurabh Misra } 1458015a6ef6SSaurabh Misra 1459015a6ef6SSaurabh Misra int 1460015a6ef6SSaurabh Misra atge_m_promisc(void *arg, boolean_t on) 1461015a6ef6SSaurabh Misra { 1462015a6ef6SSaurabh Misra atge_t *atgep = arg; 1463015a6ef6SSaurabh Misra 1464015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_intr_lock); 1465015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock); 1466015a6ef6SSaurabh Misra 1467015a6ef6SSaurabh Misra if (on) { 1468015a6ef6SSaurabh Misra atgep->atge_filter_flags |= ATGE_PROMISC; 1469015a6ef6SSaurabh Misra } else { 1470015a6ef6SSaurabh Misra atgep->atge_filter_flags &= ~ATGE_PROMISC; 1471015a6ef6SSaurabh Misra } 1472015a6ef6SSaurabh Misra 1473015a6ef6SSaurabh Misra if (atgep->atge_chip_state & ATGE_CHIP_RUNNING) { 1474015a6ef6SSaurabh Misra atge_rxfilter(atgep); 1475015a6ef6SSaurabh Misra } 1476015a6ef6SSaurabh Misra 1477015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock); 1478015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_intr_lock); 1479015a6ef6SSaurabh Misra 1480015a6ef6SSaurabh Misra return (0); 1481015a6ef6SSaurabh Misra } 1482015a6ef6SSaurabh Misra 1483015a6ef6SSaurabh Misra int 1484015a6ef6SSaurabh Misra atge_m_unicst(void *arg, const uint8_t *macaddr) 1485015a6ef6SSaurabh Misra { 1486015a6ef6SSaurabh Misra atge_t *atgep = arg; 1487015a6ef6SSaurabh Misra 1488015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_intr_lock); 1489015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock); 1490015a6ef6SSaurabh Misra bcopy(macaddr, atgep->atge_ether_addr, ETHERADDRL); 1491015a6ef6SSaurabh Misra atge_program_ether(atgep); 1492015a6ef6SSaurabh Misra atge_rxfilter(atgep); 1493015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock); 1494015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_intr_lock); 1495015a6ef6SSaurabh Misra 1496015a6ef6SSaurabh Misra return (0); 1497015a6ef6SSaurabh Misra } 1498015a6ef6SSaurabh Misra 1499015a6ef6SSaurabh Misra mblk_t * 1500015a6ef6SSaurabh Misra atge_m_tx(void *arg, mblk_t *mp) 1501015a6ef6SSaurabh Misra { 1502015a6ef6SSaurabh Misra atge_t *atgep = arg; 1503015a6ef6SSaurabh Misra mblk_t *nmp; 1504015a6ef6SSaurabh Misra 1505015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock); 1506015a6ef6SSaurabh Misra 1507015a6ef6SSaurabh Misra /* 1508015a6ef6SSaurabh Misra * This NIC does not like us to send pkt when link is down. 1509015a6ef6SSaurabh Misra */ 1510015a6ef6SSaurabh Misra if (!(atgep->atge_link_state & LINK_STATE_UP)) { 1511015a6ef6SSaurabh Misra atgep->atge_tx_resched = 1; 1512*0eb090a7SSaurabh Misra 1513015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock); 1514015a6ef6SSaurabh Misra return (mp); 1515015a6ef6SSaurabh Misra } 1516015a6ef6SSaurabh Misra 1517015a6ef6SSaurabh Misra /* 1518015a6ef6SSaurabh Misra * Don't send a pkt if chip isn't running or in suspended state. 1519015a6ef6SSaurabh Misra */ 1520015a6ef6SSaurabh Misra if ((atgep->atge_chip_state & ATGE_CHIP_RUNNING) == 0 || 1521015a6ef6SSaurabh Misra atgep->atge_chip_state & ATGE_CHIP_SUSPENDED) { 1522015a6ef6SSaurabh Misra atgep->atge_carrier_errors++; 1523015a6ef6SSaurabh Misra atgep->atge_tx_resched = 1; 1524*0eb090a7SSaurabh Misra 1525015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock); 1526015a6ef6SSaurabh Misra return (mp); 1527015a6ef6SSaurabh Misra } 1528015a6ef6SSaurabh Misra 1529015a6ef6SSaurabh Misra while (mp != NULL) { 1530015a6ef6SSaurabh Misra nmp = mp->b_next; 1531015a6ef6SSaurabh Misra mp->b_next = NULL; 1532015a6ef6SSaurabh Misra 1533*0eb090a7SSaurabh Misra if (atge_send_a_packet(atgep, mp) == DDI_FAILURE) { 1534015a6ef6SSaurabh Misra mp->b_next = nmp; 1535015a6ef6SSaurabh Misra break; 1536015a6ef6SSaurabh Misra } 1537015a6ef6SSaurabh Misra 1538015a6ef6SSaurabh Misra mp = nmp; 1539015a6ef6SSaurabh Misra } 1540015a6ef6SSaurabh Misra 1541015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock); 1542015a6ef6SSaurabh Misra return (mp); 1543015a6ef6SSaurabh Misra } 1544015a6ef6SSaurabh Misra 1545015a6ef6SSaurabh Misra int 1546015a6ef6SSaurabh Misra atge_m_start(void *arg) 1547015a6ef6SSaurabh Misra { 1548015a6ef6SSaurabh Misra atge_t *atgep = arg; 1549015a6ef6SSaurabh Misra int started = 0; 1550015a6ef6SSaurabh Misra 1551015a6ef6SSaurabh Misra ASSERT(atgep != NULL); 1552015a6ef6SSaurabh Misra 1553015a6ef6SSaurabh Misra 1554015a6ef6SSaurabh Misra mii_stop(atgep->atge_mii); 1555015a6ef6SSaurabh Misra 1556015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_intr_lock); 1557015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock); 1558015a6ef6SSaurabh Misra 1559015a6ef6SSaurabh Misra if (!(atgep->atge_chip_state & ATGE_CHIP_SUSPENDED)) { 1560015a6ef6SSaurabh Misra atge_device_restart(atgep); 1561015a6ef6SSaurabh Misra started = 1; 1562015a6ef6SSaurabh Misra } 1563015a6ef6SSaurabh Misra 1564015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock); 1565015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_intr_lock); 1566015a6ef6SSaurabh Misra 1567015a6ef6SSaurabh Misra mii_start(atgep->atge_mii); 1568015a6ef6SSaurabh Misra 1569015a6ef6SSaurabh Misra /* kick-off downstream */ 1570015a6ef6SSaurabh Misra if (started) 1571015a6ef6SSaurabh Misra mac_tx_update(atgep->atge_mh); 1572015a6ef6SSaurabh Misra 1573015a6ef6SSaurabh Misra return (0); 1574015a6ef6SSaurabh Misra } 1575015a6ef6SSaurabh Misra 1576015a6ef6SSaurabh Misra void 1577015a6ef6SSaurabh Misra atge_m_stop(void *arg) 1578015a6ef6SSaurabh Misra { 1579015a6ef6SSaurabh Misra atge_t *atgep = arg; 1580015a6ef6SSaurabh Misra 1581015a6ef6SSaurabh Misra mii_stop(atgep->atge_mii); 1582015a6ef6SSaurabh Misra 1583015a6ef6SSaurabh Misra /* 1584015a6ef6SSaurabh Misra * Cancel any pending I/O. 1585015a6ef6SSaurabh Misra */ 1586015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_intr_lock); 1587015a6ef6SSaurabh Misra atgep->atge_chip_state &= ~ATGE_CHIP_RUNNING; 1588015a6ef6SSaurabh Misra if (!(atgep->atge_chip_state & ATGE_CHIP_SUSPENDED)) 1589015a6ef6SSaurabh Misra atge_device_stop(atgep); 1590015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_intr_lock); 1591015a6ef6SSaurabh Misra } 1592015a6ef6SSaurabh Misra 1593015a6ef6SSaurabh Misra int 1594015a6ef6SSaurabh Misra atge_m_stat(void *arg, uint_t stat, uint64_t *val) 1595015a6ef6SSaurabh Misra { 1596015a6ef6SSaurabh Misra atge_t *atgep = arg; 1597015a6ef6SSaurabh Misra 1598015a6ef6SSaurabh Misra if (mii_m_getstat(atgep->atge_mii, stat, val) == 0) { 1599015a6ef6SSaurabh Misra return (0); 1600015a6ef6SSaurabh Misra } 1601015a6ef6SSaurabh Misra 1602015a6ef6SSaurabh Misra switch (stat) { 1603015a6ef6SSaurabh Misra case MAC_STAT_MULTIRCV: 1604015a6ef6SSaurabh Misra *val = atgep->atge_multircv; 1605015a6ef6SSaurabh Misra break; 1606015a6ef6SSaurabh Misra 1607015a6ef6SSaurabh Misra case MAC_STAT_BRDCSTRCV: 1608015a6ef6SSaurabh Misra *val = atgep->atge_brdcstrcv; 1609015a6ef6SSaurabh Misra break; 1610015a6ef6SSaurabh Misra 1611015a6ef6SSaurabh Misra case MAC_STAT_MULTIXMT: 1612015a6ef6SSaurabh Misra *val = atgep->atge_multixmt; 1613015a6ef6SSaurabh Misra break; 1614015a6ef6SSaurabh Misra 1615015a6ef6SSaurabh Misra case MAC_STAT_BRDCSTXMT: 1616015a6ef6SSaurabh Misra *val = atgep->atge_brdcstxmt; 1617015a6ef6SSaurabh Misra break; 1618015a6ef6SSaurabh Misra 1619015a6ef6SSaurabh Misra case MAC_STAT_IPACKETS: 1620015a6ef6SSaurabh Misra *val = atgep->atge_ipackets; 1621015a6ef6SSaurabh Misra break; 1622015a6ef6SSaurabh Misra 1623015a6ef6SSaurabh Misra case MAC_STAT_RBYTES: 1624015a6ef6SSaurabh Misra *val = atgep->atge_rbytes; 1625015a6ef6SSaurabh Misra break; 1626015a6ef6SSaurabh Misra 1627015a6ef6SSaurabh Misra case MAC_STAT_OPACKETS: 1628015a6ef6SSaurabh Misra *val = atgep->atge_opackets; 1629015a6ef6SSaurabh Misra break; 1630015a6ef6SSaurabh Misra 1631015a6ef6SSaurabh Misra case MAC_STAT_OBYTES: 1632015a6ef6SSaurabh Misra *val = atgep->atge_obytes; 1633015a6ef6SSaurabh Misra break; 1634015a6ef6SSaurabh Misra 1635015a6ef6SSaurabh Misra case MAC_STAT_NORCVBUF: 1636015a6ef6SSaurabh Misra *val = atgep->atge_norcvbuf; 1637015a6ef6SSaurabh Misra break; 1638015a6ef6SSaurabh Misra 1639015a6ef6SSaurabh Misra case MAC_STAT_NOXMTBUF: 1640015a6ef6SSaurabh Misra *val = 0; 1641015a6ef6SSaurabh Misra break; 1642015a6ef6SSaurabh Misra 1643015a6ef6SSaurabh Misra case MAC_STAT_COLLISIONS: 1644015a6ef6SSaurabh Misra *val = atgep->atge_collisions; 1645015a6ef6SSaurabh Misra break; 1646015a6ef6SSaurabh Misra 1647015a6ef6SSaurabh Misra case MAC_STAT_IERRORS: 1648015a6ef6SSaurabh Misra *val = atgep->atge_errrcv; 1649015a6ef6SSaurabh Misra break; 1650015a6ef6SSaurabh Misra 1651015a6ef6SSaurabh Misra case MAC_STAT_OERRORS: 1652015a6ef6SSaurabh Misra *val = atgep->atge_errxmt; 1653015a6ef6SSaurabh Misra break; 1654015a6ef6SSaurabh Misra 1655015a6ef6SSaurabh Misra case ETHER_STAT_ALIGN_ERRORS: 1656015a6ef6SSaurabh Misra *val = atgep->atge_align_errors; 1657015a6ef6SSaurabh Misra break; 1658015a6ef6SSaurabh Misra 1659015a6ef6SSaurabh Misra case ETHER_STAT_FCS_ERRORS: 1660015a6ef6SSaurabh Misra *val = atgep->atge_fcs_errors; 1661015a6ef6SSaurabh Misra break; 1662015a6ef6SSaurabh Misra 1663015a6ef6SSaurabh Misra case ETHER_STAT_SQE_ERRORS: 1664015a6ef6SSaurabh Misra *val = atgep->atge_sqe_errors; 1665015a6ef6SSaurabh Misra break; 1666015a6ef6SSaurabh Misra 1667015a6ef6SSaurabh Misra case ETHER_STAT_DEFER_XMTS: 1668015a6ef6SSaurabh Misra *val = atgep->atge_defer_xmts; 1669015a6ef6SSaurabh Misra break; 1670015a6ef6SSaurabh Misra 1671015a6ef6SSaurabh Misra case ETHER_STAT_FIRST_COLLISIONS: 1672015a6ef6SSaurabh Misra *val = atgep->atge_first_collisions; 1673015a6ef6SSaurabh Misra break; 1674015a6ef6SSaurabh Misra 1675015a6ef6SSaurabh Misra case ETHER_STAT_MULTI_COLLISIONS: 1676015a6ef6SSaurabh Misra *val = atgep->atge_multi_collisions; 1677015a6ef6SSaurabh Misra break; 1678015a6ef6SSaurabh Misra 1679015a6ef6SSaurabh Misra case ETHER_STAT_TX_LATE_COLLISIONS: 1680015a6ef6SSaurabh Misra *val = atgep->atge_tx_late_collisions; 1681015a6ef6SSaurabh Misra break; 1682015a6ef6SSaurabh Misra 1683015a6ef6SSaurabh Misra case ETHER_STAT_EX_COLLISIONS: 1684015a6ef6SSaurabh Misra *val = atgep->atge_ex_collisions; 1685015a6ef6SSaurabh Misra break; 1686015a6ef6SSaurabh Misra 1687015a6ef6SSaurabh Misra case ETHER_STAT_MACXMT_ERRORS: 1688015a6ef6SSaurabh Misra *val = atgep->atge_macxmt_errors; 1689015a6ef6SSaurabh Misra break; 1690015a6ef6SSaurabh Misra 1691015a6ef6SSaurabh Misra case ETHER_STAT_CARRIER_ERRORS: 1692015a6ef6SSaurabh Misra *val = atgep->atge_carrier_errors; 1693015a6ef6SSaurabh Misra break; 1694015a6ef6SSaurabh Misra 1695015a6ef6SSaurabh Misra case ETHER_STAT_TOOLONG_ERRORS: 1696015a6ef6SSaurabh Misra *val = atgep->atge_toolong_errors; 1697015a6ef6SSaurabh Misra break; 1698015a6ef6SSaurabh Misra 1699015a6ef6SSaurabh Misra case ETHER_STAT_MACRCV_ERRORS: 1700015a6ef6SSaurabh Misra *val = atgep->atge_macrcv_errors; 1701015a6ef6SSaurabh Misra break; 1702015a6ef6SSaurabh Misra 1703015a6ef6SSaurabh Misra case MAC_STAT_OVERFLOWS: 1704015a6ef6SSaurabh Misra *val = atgep->atge_overflow; 1705015a6ef6SSaurabh Misra break; 1706015a6ef6SSaurabh Misra 1707015a6ef6SSaurabh Misra case MAC_STAT_UNDERFLOWS: 1708015a6ef6SSaurabh Misra *val = atgep->atge_underflow; 1709015a6ef6SSaurabh Misra break; 1710015a6ef6SSaurabh Misra 1711015a6ef6SSaurabh Misra case ETHER_STAT_TOOSHORT_ERRORS: 1712015a6ef6SSaurabh Misra *val = atgep->atge_runt; 1713015a6ef6SSaurabh Misra break; 1714015a6ef6SSaurabh Misra 1715015a6ef6SSaurabh Misra case ETHER_STAT_JABBER_ERRORS: 1716015a6ef6SSaurabh Misra *val = atgep->atge_jabber; 1717015a6ef6SSaurabh Misra break; 1718015a6ef6SSaurabh Misra 1719015a6ef6SSaurabh Misra default: 1720015a6ef6SSaurabh Misra return (ENOTSUP); 1721015a6ef6SSaurabh Misra } 1722015a6ef6SSaurabh Misra 1723015a6ef6SSaurabh Misra return (0); 1724015a6ef6SSaurabh Misra } 1725015a6ef6SSaurabh Misra 1726015a6ef6SSaurabh Misra int 1727015a6ef6SSaurabh Misra atge_m_getprop(void *arg, const char *name, mac_prop_id_t num, uint_t flags, 1728015a6ef6SSaurabh Misra uint_t sz, void *val, uint_t *perm) 1729015a6ef6SSaurabh Misra { 1730015a6ef6SSaurabh Misra atge_t *atgep = arg; 1731015a6ef6SSaurabh Misra 1732015a6ef6SSaurabh Misra return (mii_m_getprop(atgep->atge_mii, name, num, flags, sz, val, 1733015a6ef6SSaurabh Misra perm)); 1734015a6ef6SSaurabh Misra } 1735015a6ef6SSaurabh Misra 1736015a6ef6SSaurabh Misra int 1737015a6ef6SSaurabh Misra atge_m_setprop(void *arg, const char *name, mac_prop_id_t num, uint_t sz, 1738015a6ef6SSaurabh Misra const void *val) 1739015a6ef6SSaurabh Misra { 1740015a6ef6SSaurabh Misra atge_t *atgep = arg; 1741*0eb090a7SSaurabh Misra int r; 1742015a6ef6SSaurabh Misra 1743*0eb090a7SSaurabh Misra r = mii_m_setprop(atgep->atge_mii, name, num, sz, val); 1744*0eb090a7SSaurabh Misra 1745*0eb090a7SSaurabh Misra if (r == 0) { 1746*0eb090a7SSaurabh Misra mutex_enter(&atgep->atge_intr_lock); 1747*0eb090a7SSaurabh Misra mutex_enter(&atgep->atge_tx_lock); 1748*0eb090a7SSaurabh Misra 1749*0eb090a7SSaurabh Misra if (atgep->atge_chip_state & ATGE_CHIP_RUNNING) { 1750*0eb090a7SSaurabh Misra atge_device_restart(atgep); 1751*0eb090a7SSaurabh Misra } 1752*0eb090a7SSaurabh Misra 1753*0eb090a7SSaurabh Misra mutex_exit(&atgep->atge_tx_lock); 1754*0eb090a7SSaurabh Misra mutex_exit(&atgep->atge_intr_lock); 1755*0eb090a7SSaurabh Misra } 1756*0eb090a7SSaurabh Misra 1757*0eb090a7SSaurabh Misra return (r); 1758015a6ef6SSaurabh Misra } 1759015a6ef6SSaurabh Misra 1760015a6ef6SSaurabh Misra 1761015a6ef6SSaurabh Misra void 1762015a6ef6SSaurabh Misra atge_program_ether(atge_t *atgep) 1763015a6ef6SSaurabh Misra { 1764015a6ef6SSaurabh Misra ether_addr_t e; 1765015a6ef6SSaurabh Misra 1766015a6ef6SSaurabh Misra /* 1767015a6ef6SSaurabh Misra * Reprogram the Station address. 1768015a6ef6SSaurabh Misra */ 1769015a6ef6SSaurabh Misra bcopy(atgep->atge_ether_addr, e, ETHERADDRL); 1770015a6ef6SSaurabh Misra OUTL(atgep, ATGE_PAR0, 1771015a6ef6SSaurabh Misra ((e[2] << 24) | (e[3] << 16) | (e[4] << 8) | e[5])); 1772015a6ef6SSaurabh Misra OUTL(atgep, ATGE_PAR1, (e[0] << 8) | e[1]); 1773015a6ef6SSaurabh Misra } 1774015a6ef6SSaurabh Misra 1775015a6ef6SSaurabh Misra /* 1776015a6ef6SSaurabh Misra * Device specific operations. 1777015a6ef6SSaurabh Misra */ 1778015a6ef6SSaurabh Misra void 1779015a6ef6SSaurabh Misra atge_device_start(atge_t *atgep) 1780015a6ef6SSaurabh Misra { 1781*0eb090a7SSaurabh Misra uint32_t rxf_hi, rxf_lo, rrd_hi, rrd_lo; 1782015a6ef6SSaurabh Misra uint32_t reg; 1783015a6ef6SSaurabh Misra uint32_t fsize; 1784015a6ef6SSaurabh Misra 1785015a6ef6SSaurabh Misra /* 1786015a6ef6SSaurabh Misra * Reprogram the Station address. 1787015a6ef6SSaurabh Misra */ 1788015a6ef6SSaurabh Misra atge_program_ether(atgep); 1789015a6ef6SSaurabh Misra 1790015a6ef6SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) { 1791015a6ef6SSaurabh Misra atge_l1e_program_dma(atgep); 1792*0eb090a7SSaurabh Misra } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) { 1793*0eb090a7SSaurabh Misra atge_l1_program_dma(atgep); 1794015a6ef6SSaurabh Misra } 1795015a6ef6SSaurabh Misra 1796015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() dma, counters programmed ", atgep->atge_name, 1797015a6ef6SSaurabh Misra __func__)); 1798015a6ef6SSaurabh Misra 1799015a6ef6SSaurabh Misra OUTW(atgep, ATGE_INTR_CLR_TIMER, 1*1000/2); 1800015a6ef6SSaurabh Misra 1801015a6ef6SSaurabh Misra /* 1802*0eb090a7SSaurabh Misra * Set Maximum frame size but don't let MTU be less than ETHER_MTU. 1803015a6ef6SSaurabh Misra */ 1804015a6ef6SSaurabh Misra if (atgep->atge_mtu < ETHERMTU) 1805015a6ef6SSaurabh Misra atgep->atge_max_frame_size = ETHERMTU; 1806015a6ef6SSaurabh Misra else 1807015a6ef6SSaurabh Misra atgep->atge_max_frame_size = atgep->atge_mtu; 1808015a6ef6SSaurabh Misra 1809015a6ef6SSaurabh Misra atgep->atge_max_frame_size += sizeof (struct ether_header) + 1810015a6ef6SSaurabh Misra VLAN_TAGSZ + ETHERFCSL; 1811015a6ef6SSaurabh Misra OUTL(atgep, ATGE_FRAME_SIZE, atgep->atge_max_frame_size); 1812015a6ef6SSaurabh Misra 1813015a6ef6SSaurabh Misra 1814015a6ef6SSaurabh Misra /* 1815015a6ef6SSaurabh Misra * Configure IPG/IFG parameters. 1816015a6ef6SSaurabh Misra */ 1817015a6ef6SSaurabh Misra OUTL(atgep, ATGE_IPG_IFG_CFG, 1818015a6ef6SSaurabh Misra ((IPG_IFG_IPG2_DEFAULT << IPG_IFG_IPG2_SHIFT) & IPG_IFG_IPG2_MASK) | 1819015a6ef6SSaurabh Misra ((IPG_IFG_IPG1_DEFAULT << IPG_IFG_IPG1_SHIFT) & IPG_IFG_IPG1_MASK) | 1820015a6ef6SSaurabh Misra ((IPG_IFG_MIFG_DEFAULT << IPG_IFG_MIFG_SHIFT) & IPG_IFG_MIFG_MASK) | 1821015a6ef6SSaurabh Misra ((IPG_IFG_IPGT_DEFAULT << IPG_IFG_IPGT_SHIFT) & IPG_IFG_IPGT_MASK)); 1822015a6ef6SSaurabh Misra 1823015a6ef6SSaurabh Misra /* 1824015a6ef6SSaurabh Misra * Set parameters for half-duplex media. 1825015a6ef6SSaurabh Misra */ 1826015a6ef6SSaurabh Misra OUTL(atgep, ATGE_HDPX_CFG, 1827015a6ef6SSaurabh Misra ((HDPX_CFG_LCOL_DEFAULT << HDPX_CFG_LCOL_SHIFT) & 1828015a6ef6SSaurabh Misra HDPX_CFG_LCOL_MASK) | 1829015a6ef6SSaurabh Misra ((HDPX_CFG_RETRY_DEFAULT << HDPX_CFG_RETRY_SHIFT) & 1830015a6ef6SSaurabh Misra HDPX_CFG_RETRY_MASK) | HDPX_CFG_EXC_DEF_EN | 1831015a6ef6SSaurabh Misra ((HDPX_CFG_ABEBT_DEFAULT << HDPX_CFG_ABEBT_SHIFT) & 1832015a6ef6SSaurabh Misra HDPX_CFG_ABEBT_MASK) | 1833015a6ef6SSaurabh Misra ((HDPX_CFG_JAMIPG_DEFAULT << HDPX_CFG_JAMIPG_SHIFT) & 1834015a6ef6SSaurabh Misra HDPX_CFG_JAMIPG_MASK)); 1835015a6ef6SSaurabh Misra 1836015a6ef6SSaurabh Misra /* 1837015a6ef6SSaurabh Misra * Configure jumbo frame. 1838015a6ef6SSaurabh Misra */ 1839015a6ef6SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) { 1840015a6ef6SSaurabh Misra fsize = ROUNDUP(atgep->atge_max_frame_size, sizeof (uint64_t)); 1841015a6ef6SSaurabh Misra OUTL(atgep, ATGE_RXQ_JUMBO_CFG, 1842015a6ef6SSaurabh Misra (((fsize / sizeof (uint64_t)) << 1843015a6ef6SSaurabh Misra RXQ_JUMBO_CFG_SZ_THRESH_SHIFT) & 1844015a6ef6SSaurabh Misra RXQ_JUMBO_CFG_SZ_THRESH_MASK) | 1845015a6ef6SSaurabh Misra ((RXQ_JUMBO_CFG_LKAH_DEFAULT << 1846015a6ef6SSaurabh Misra RXQ_JUMBO_CFG_LKAH_SHIFT) & RXQ_JUMBO_CFG_LKAH_MASK) | 1847015a6ef6SSaurabh Misra ((ATGE_USECS(8) << RXQ_JUMBO_CFG_RRD_TIMER_SHIFT) & 1848015a6ef6SSaurabh Misra RXQ_JUMBO_CFG_RRD_TIMER_MASK)); 1849015a6ef6SSaurabh Misra } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E && 1850015a6ef6SSaurabh Misra atgep->atge_flags & ATGE_FLAG_JUMBO) { 1851015a6ef6SSaurabh Misra 1852015a6ef6SSaurabh Misra if (atgep->atge_mtu < ETHERMTU) 1853015a6ef6SSaurabh Misra reg = atgep->atge_max_frame_size; 1854015a6ef6SSaurabh Misra else if (atgep->atge_mtu < 6 * 1024) 1855015a6ef6SSaurabh Misra reg = (atgep->atge_max_frame_size * 2) / 3; 1856015a6ef6SSaurabh Misra else 1857015a6ef6SSaurabh Misra reg = atgep->atge_max_frame_size / 2; 1858015a6ef6SSaurabh Misra 1859015a6ef6SSaurabh Misra OUTL(atgep, L1E_TX_JUMBO_THRESH, 1860015a6ef6SSaurabh Misra ROUNDUP(reg, TX_JUMBO_THRESH_UNIT) >> 1861015a6ef6SSaurabh Misra TX_JUMBO_THRESH_UNIT_SHIFT); 1862015a6ef6SSaurabh Misra } 1863015a6ef6SSaurabh Misra 1864015a6ef6SSaurabh Misra /* 1865015a6ef6SSaurabh Misra * Configure flow-control parameters. 1866015a6ef6SSaurabh Misra */ 1867015a6ef6SSaurabh Misra if ((atgep->atge_flags & ATGE_FLAG_PCIE) != 0) { 1868015a6ef6SSaurabh Misra /* 1869015a6ef6SSaurabh Misra * Some hardware version require this magic. 1870015a6ef6SSaurabh Misra */ 1871015a6ef6SSaurabh Misra OUTL(atgep, 0x12FC, 0x6500); 1872015a6ef6SSaurabh Misra reg = INL(atgep, 0x1008); 1873015a6ef6SSaurabh Misra OUTL(atgep, 0x1008, reg | 0x8000); 1874015a6ef6SSaurabh Misra } 1875015a6ef6SSaurabh Misra 1876015a6ef6SSaurabh Misra /* 1877015a6ef6SSaurabh Misra * These are all magic parameters which came from FreeBSD. 1878015a6ef6SSaurabh Misra */ 1879*0eb090a7SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) { 1880*0eb090a7SSaurabh Misra switch (atgep->atge_chip_rev) { 1881*0eb090a7SSaurabh Misra case 0x8001: 1882*0eb090a7SSaurabh Misra case 0x9001: 1883*0eb090a7SSaurabh Misra case 0x9002: 1884*0eb090a7SSaurabh Misra case 0x9003: 1885*0eb090a7SSaurabh Misra rxf_hi = L1_RX_RING_CNT / 16; 1886*0eb090a7SSaurabh Misra rxf_lo = (L1_RX_RING_CNT * 7) / 8; 1887*0eb090a7SSaurabh Misra rrd_hi = (L1_RR_RING_CNT * 7) / 8; 1888*0eb090a7SSaurabh Misra rrd_lo = L1_RR_RING_CNT / 16; 1889*0eb090a7SSaurabh Misra break; 1890*0eb090a7SSaurabh Misra default: 1891*0eb090a7SSaurabh Misra reg = INL(atgep, L1_SRAM_RX_FIFO_LEN); 1892*0eb090a7SSaurabh Misra rxf_lo = reg / 16; 1893*0eb090a7SSaurabh Misra if (rxf_lo > 192) 1894*0eb090a7SSaurabh Misra rxf_lo = 192; 1895*0eb090a7SSaurabh Misra rxf_hi = (reg * 7) / 8; 1896*0eb090a7SSaurabh Misra if (rxf_hi < rxf_lo) 1897*0eb090a7SSaurabh Misra rxf_hi = rxf_lo + 16; 1898*0eb090a7SSaurabh Misra reg = INL(atgep, L1_SRAM_RRD_LEN); 1899*0eb090a7SSaurabh Misra rrd_lo = reg / 8; 1900*0eb090a7SSaurabh Misra rrd_hi = (reg * 7) / 8; 1901*0eb090a7SSaurabh Misra if (rrd_lo > 2) 1902*0eb090a7SSaurabh Misra rrd_lo = 2; 1903*0eb090a7SSaurabh Misra if (rrd_hi < rrd_lo) 1904*0eb090a7SSaurabh Misra rrd_hi = rrd_lo + 3; 1905*0eb090a7SSaurabh Misra break; 1906*0eb090a7SSaurabh Misra } 1907*0eb090a7SSaurabh Misra 1908*0eb090a7SSaurabh Misra OUTL(atgep, ATGE_RXQ_FIFO_PAUSE_THRESH, 1909*0eb090a7SSaurabh Misra ((rxf_lo << RXQ_FIFO_PAUSE_THRESH_LO_SHIFT) & 1910*0eb090a7SSaurabh Misra RXQ_FIFO_PAUSE_THRESH_LO_MASK) | 1911*0eb090a7SSaurabh Misra ((rxf_hi << RXQ_FIFO_PAUSE_THRESH_HI_SHIFT) & 1912*0eb090a7SSaurabh Misra RXQ_FIFO_PAUSE_THRESH_HI_MASK)); 1913*0eb090a7SSaurabh Misra 1914*0eb090a7SSaurabh Misra OUTL(atgep, L1_RXQ_RRD_PAUSE_THRESH, 1915*0eb090a7SSaurabh Misra ((rrd_lo << RXQ_RRD_PAUSE_THRESH_LO_SHIFT) & 1916*0eb090a7SSaurabh Misra RXQ_RRD_PAUSE_THRESH_LO_MASK) | 1917*0eb090a7SSaurabh Misra ((rrd_hi << RXQ_RRD_PAUSE_THRESH_HI_SHIFT) & 1918*0eb090a7SSaurabh Misra RXQ_RRD_PAUSE_THRESH_HI_MASK)); 1919*0eb090a7SSaurabh Misra } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) { 1920015a6ef6SSaurabh Misra reg = INL(atgep, L1E_SRAM_RX_FIFO_LEN); 1921015a6ef6SSaurabh Misra rxf_hi = (reg * 4) / 5; 1922015a6ef6SSaurabh Misra rxf_lo = reg/ 5; 1923015a6ef6SSaurabh Misra 1924015a6ef6SSaurabh Misra OUTL(atgep, ATGE_RXQ_FIFO_PAUSE_THRESH, 1925015a6ef6SSaurabh Misra ((rxf_lo << RXQ_FIFO_PAUSE_THRESH_LO_SHIFT) & 1926015a6ef6SSaurabh Misra RXQ_FIFO_PAUSE_THRESH_LO_MASK) | 1927015a6ef6SSaurabh Misra ((rxf_hi << RXQ_FIFO_PAUSE_THRESH_HI_SHIFT) & 1928015a6ef6SSaurabh Misra RXQ_FIFO_PAUSE_THRESH_HI_MASK)); 1929015a6ef6SSaurabh Misra } 1930015a6ef6SSaurabh Misra 1931015a6ef6SSaurabh Misra /* Configure RxQ. */ 1932015a6ef6SSaurabh Misra reg = 0; 1933*0eb090a7SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) { 1934*0eb090a7SSaurabh Misra reg = 1935*0eb090a7SSaurabh Misra ((RXQ_CFG_RD_BURST_DEFAULT << RXQ_CFG_RD_BURST_SHIFT) & 1936*0eb090a7SSaurabh Misra RXQ_CFG_RD_BURST_MASK) | 1937*0eb090a7SSaurabh Misra ((RXQ_CFG_RRD_BURST_THRESH_DEFAULT << 1938*0eb090a7SSaurabh Misra RXQ_CFG_RRD_BURST_THRESH_SHIFT) & 1939*0eb090a7SSaurabh Misra RXQ_CFG_RRD_BURST_THRESH_MASK) | 1940*0eb090a7SSaurabh Misra ((RXQ_CFG_RD_PREF_MIN_IPG_DEFAULT << 1941*0eb090a7SSaurabh Misra RXQ_CFG_RD_PREF_MIN_IPG_SHIFT) & 1942*0eb090a7SSaurabh Misra RXQ_CFG_RD_PREF_MIN_IPG_MASK) | 1943*0eb090a7SSaurabh Misra RXQ_CFG_CUT_THROUGH_ENB | RXQ_CFG_ENB; 1944*0eb090a7SSaurabh Misra OUTL(atgep, ATGE_RXQ_CFG, reg); 1945*0eb090a7SSaurabh Misra } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) { 1946015a6ef6SSaurabh Misra reg = RXQ_CFG_ALIGN_32 | RXQ_CFG_CUT_THROUGH_ENB | 1947015a6ef6SSaurabh Misra RXQ_CFG_IPV6_CSUM_VERIFY | RXQ_CFG_ENB; 1948015a6ef6SSaurabh Misra OUTL(atgep, ATGE_RXQ_CFG, reg); 1949015a6ef6SSaurabh Misra } 1950015a6ef6SSaurabh Misra 1951015a6ef6SSaurabh Misra /* 1952015a6ef6SSaurabh Misra * Configure TxQ. 1953015a6ef6SSaurabh Misra */ 1954*0eb090a7SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) { 1955*0eb090a7SSaurabh Misra reg = 1956*0eb090a7SSaurabh Misra (((TXQ_CFG_TPD_BURST_DEFAULT << TXQ_CFG_TPD_BURST_SHIFT) & 1957*0eb090a7SSaurabh Misra TXQ_CFG_TPD_BURST_MASK) | 1958*0eb090a7SSaurabh Misra ((TXQ_CFG_TX_FIFO_BURST_DEFAULT << 1959*0eb090a7SSaurabh Misra TXQ_CFG_TX_FIFO_BURST_SHIFT) & 1960*0eb090a7SSaurabh Misra TXQ_CFG_TX_FIFO_BURST_MASK) | 1961*0eb090a7SSaurabh Misra ((TXQ_CFG_TPD_FETCH_DEFAULT << 1962*0eb090a7SSaurabh Misra TXQ_CFG_TPD_FETCH_THRESH_SHIFT) & 1963*0eb090a7SSaurabh Misra TXQ_CFG_TPD_FETCH_THRESH_MASK) | 1964*0eb090a7SSaurabh Misra TXQ_CFG_ENB); 1965*0eb090a7SSaurabh Misra OUTL(atgep, ATGE_TXQ_CFG, reg); 1966*0eb090a7SSaurabh Misra } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) { 1967015a6ef6SSaurabh Misra reg = (128 << 1968015a6ef6SSaurabh Misra (atgep->atge_dma_rd_burst >> DMA_CFG_RD_BURST_SHIFT)) << 1969015a6ef6SSaurabh Misra TXQ_CFG_TX_FIFO_BURST_SHIFT; 1970015a6ef6SSaurabh Misra 1971015a6ef6SSaurabh Misra reg |= (TXQ_CFG_TPD_BURST_DEFAULT << TXQ_CFG_TPD_BURST_SHIFT) & 1972015a6ef6SSaurabh Misra TXQ_CFG_TPD_BURST_MASK; 1973015a6ef6SSaurabh Misra 1974015a6ef6SSaurabh Misra reg |= TXQ_CFG_ENHANCED_MODE | TXQ_CFG_ENB; 1975015a6ef6SSaurabh Misra 1976015a6ef6SSaurabh Misra OUTL(atgep, ATGE_TXQ_CFG, reg); 1977015a6ef6SSaurabh Misra } 1978015a6ef6SSaurabh Misra 1979*0eb090a7SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) { 1980*0eb090a7SSaurabh Misra OUTL(atgep, L1_TX_JUMBO_TPD_TH_IPG, 1981*0eb090a7SSaurabh Misra (((fsize / sizeof (uint64_t) << TX_JUMBO_TPD_TH_SHIFT)) & 1982*0eb090a7SSaurabh Misra TX_JUMBO_TPD_TH_MASK) | 1983*0eb090a7SSaurabh Misra ((TX_JUMBO_TPD_IPG_DEFAULT << TX_JUMBO_TPD_IPG_SHIFT) & 1984*0eb090a7SSaurabh Misra TX_JUMBO_TPD_IPG_MASK)); 1985*0eb090a7SSaurabh Misra } 1986*0eb090a7SSaurabh Misra 1987015a6ef6SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) { 1988015a6ef6SSaurabh Misra /* Disable RSS. */ 1989015a6ef6SSaurabh Misra OUTL(atgep, L1E_RSS_IDT_TABLE0, 0); 1990015a6ef6SSaurabh Misra OUTL(atgep, L1E_RSS_CPU, 0); 1991015a6ef6SSaurabh Misra } 1992015a6ef6SSaurabh Misra 1993015a6ef6SSaurabh Misra /* 1994015a6ef6SSaurabh Misra * Configure DMA parameters. 1995015a6ef6SSaurabh Misra */ 1996*0eb090a7SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) { 1997*0eb090a7SSaurabh Misra OUTL(atgep, ATGE_DMA_CFG, 1998*0eb090a7SSaurabh Misra DMA_CFG_ENH_ORDER | DMA_CFG_RCB_64 | 1999*0eb090a7SSaurabh Misra atgep->atge_dma_rd_burst | DMA_CFG_RD_ENB | 2000*0eb090a7SSaurabh Misra atgep->atge_dma_wr_burst | DMA_CFG_WR_ENB); 2001*0eb090a7SSaurabh Misra 2002*0eb090a7SSaurabh Misra /* Configure CMB DMA write threshold. */ 2003*0eb090a7SSaurabh Misra OUTL(atgep, L1_CMB_WR_THRESH, 2004*0eb090a7SSaurabh Misra ((CMB_WR_THRESH_RRD_DEFAULT << CMB_WR_THRESH_RRD_SHIFT) & 2005*0eb090a7SSaurabh Misra CMB_WR_THRESH_RRD_MASK) | 2006*0eb090a7SSaurabh Misra ((CMB_WR_THRESH_TPD_DEFAULT << CMB_WR_THRESH_TPD_SHIFT) & 2007*0eb090a7SSaurabh Misra CMB_WR_THRESH_TPD_MASK)); 2008*0eb090a7SSaurabh Misra } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) { 2009015a6ef6SSaurabh Misra /* 2010015a6ef6SSaurabh Misra * Don't use Tx CMB. It is known to cause RRS update failure 2011015a6ef6SSaurabh Misra * under certain circumstances. Typical phenomenon of the 2012015a6ef6SSaurabh Misra * issue would be unexpected sequence number encountered in 2013015a6ef6SSaurabh Misra * Rx handler. Hence we don't set DMA_CFG_TXCMB_ENB. 2014015a6ef6SSaurabh Misra */ 2015015a6ef6SSaurabh Misra OUTL(atgep, ATGE_DMA_CFG, 2016015a6ef6SSaurabh Misra DMA_CFG_OUT_ORDER | DMA_CFG_RD_REQ_PRI | DMA_CFG_RCB_64 | 2017015a6ef6SSaurabh Misra atgep->atge_dma_rd_burst | atgep->atge_dma_wr_burst | 2018015a6ef6SSaurabh Misra DMA_CFG_RXCMB_ENB | 2019015a6ef6SSaurabh Misra ((DMA_CFG_RD_DELAY_CNT_DEFAULT << 2020015a6ef6SSaurabh Misra DMA_CFG_RD_DELAY_CNT_SHIFT) & DMA_CFG_RD_DELAY_CNT_MASK) | 2021015a6ef6SSaurabh Misra ((DMA_CFG_WR_DELAY_CNT_DEFAULT << 2022015a6ef6SSaurabh Misra DMA_CFG_WR_DELAY_CNT_SHIFT) & DMA_CFG_WR_DELAY_CNT_MASK)); 2023015a6ef6SSaurabh Misra } 2024015a6ef6SSaurabh Misra 2025015a6ef6SSaurabh Misra /* 2026*0eb090a7SSaurabh Misra * Enable CMB/SMB timer. 2027015a6ef6SSaurabh Misra */ 2028*0eb090a7SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) { 2029*0eb090a7SSaurabh Misra /* Set CMB/SMB timer and enable them. */ 2030*0eb090a7SSaurabh Misra OUTL(atgep, L1_CMB_WR_TIMER, 2031*0eb090a7SSaurabh Misra ((ATGE_USECS(2) << CMB_WR_TIMER_TX_SHIFT) & 2032*0eb090a7SSaurabh Misra CMB_WR_TIMER_TX_MASK) | 2033*0eb090a7SSaurabh Misra ((ATGE_USECS(2) << CMB_WR_TIMER_RX_SHIFT) & 2034*0eb090a7SSaurabh Misra CMB_WR_TIMER_RX_MASK)); 2035*0eb090a7SSaurabh Misra 2036*0eb090a7SSaurabh Misra /* Request SMB updates for every seconds. */ 2037*0eb090a7SSaurabh Misra OUTL(atgep, L1_SMB_TIMER, ATGE_USECS(1000 * 1000)); 2038*0eb090a7SSaurabh Misra OUTL(atgep, L1_CSMB_CTRL, 2039*0eb090a7SSaurabh Misra CSMB_CTRL_SMB_ENB | CSMB_CTRL_CMB_ENB); 2040*0eb090a7SSaurabh Misra } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) { 2041015a6ef6SSaurabh Misra OUTL(atgep, L1E_SMB_STAT_TIMER, 100000); 2042015a6ef6SSaurabh Misra atge_l1e_clear_stats(atgep); 2043015a6ef6SSaurabh Misra } 2044015a6ef6SSaurabh Misra 2045*0eb090a7SSaurabh Misra 2046015a6ef6SSaurabh Misra /* 2047015a6ef6SSaurabh Misra * Disable all WOL bits as WOL can interfere normal Rx 2048015a6ef6SSaurabh Misra * operation. 2049015a6ef6SSaurabh Misra */ 2050015a6ef6SSaurabh Misra OUTL(atgep, ATGE_WOL_CFG, 0); 2051015a6ef6SSaurabh Misra 2052015a6ef6SSaurabh Misra /* 2053015a6ef6SSaurabh Misra * Configure Tx/Rx MACs. 2054015a6ef6SSaurabh Misra * - Auto-padding for short frames. 2055015a6ef6SSaurabh Misra * - Enable CRC generation. 2056015a6ef6SSaurabh Misra * 2057015a6ef6SSaurabh Misra * Start with full-duplex/1000Mbps media. Actual reconfiguration 2058015a6ef6SSaurabh Misra * of MAC is followed after link establishment. 2059015a6ef6SSaurabh Misra */ 2060015a6ef6SSaurabh Misra reg = (ATGE_CFG_TX_CRC_ENB | ATGE_CFG_TX_AUTO_PAD | 2061015a6ef6SSaurabh Misra ATGE_CFG_FULL_DUPLEX | 2062015a6ef6SSaurabh Misra ((ATGE_CFG_PREAMBLE_DEFAULT << ATGE_CFG_PREAMBLE_SHIFT) & 2063015a6ef6SSaurabh Misra ATGE_CFG_PREAMBLE_MASK)); 2064015a6ef6SSaurabh Misra 2065015a6ef6SSaurabh Misra if ((atgep->atge_flags & ATGE_FLAG_FASTETHER) != 0) { 2066015a6ef6SSaurabh Misra reg |= ATGE_CFG_SPEED_10_100; 2067015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() Fast Ethernet", atgep->atge_name, __func__)); 2068015a6ef6SSaurabh Misra } else { 2069015a6ef6SSaurabh Misra reg |= ATGE_CFG_SPEED_1000; 2070015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() 1G speed", atgep->atge_name, __func__)); 2071015a6ef6SSaurabh Misra } 2072015a6ef6SSaurabh Misra 2073015a6ef6SSaurabh Misra OUTL(atgep, ATGE_MAC_CFG, reg); 2074015a6ef6SSaurabh Misra 2075015a6ef6SSaurabh Misra atgep->atge_chip_state |= ATGE_CHIP_RUNNING; 2076015a6ef6SSaurabh Misra 2077015a6ef6SSaurabh Misra /* 2078015a6ef6SSaurabh Misra * Set up the receive filter. 2079015a6ef6SSaurabh Misra */ 2080015a6ef6SSaurabh Misra atge_rxfilter(atgep); 2081015a6ef6SSaurabh Misra 2082015a6ef6SSaurabh Misra /* 2083015a6ef6SSaurabh Misra * Acknowledge all pending interrupts and clear it. 2084015a6ef6SSaurabh Misra */ 2085*0eb090a7SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) { 2086*0eb090a7SSaurabh Misra OUTL(atgep, ATGE_INTR_STATUS, 0); 2087*0eb090a7SSaurabh Misra OUTL(atgep, ATGE_INTR_MASK, atgep->atge_intrs); 2088*0eb090a7SSaurabh Misra } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) { 2089015a6ef6SSaurabh Misra OUTL(atgep, ATGE_INTR_MASK, L1E_INTRS); 2090015a6ef6SSaurabh Misra OUTL(atgep, ATGE_INTR_STATUS, 0xFFFFFFFF); 2091015a6ef6SSaurabh Misra OUTL(atgep, ATGE_INTR_STATUS, 0); 2092*0eb090a7SSaurabh Misra } 2093015a6ef6SSaurabh Misra 2094015a6ef6SSaurabh Misra atge_mac_config(atgep); 2095015a6ef6SSaurabh Misra 2096015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() device started", atgep->atge_name, __func__)); 2097015a6ef6SSaurabh Misra } 2098015a6ef6SSaurabh Misra 2099015a6ef6SSaurabh Misra /* 2100015a6ef6SSaurabh Misra * Generic functions. 2101015a6ef6SSaurabh Misra */ 2102015a6ef6SSaurabh Misra 2103015a6ef6SSaurabh Misra #define CRC32_POLY_BE 0x04c11db7 2104015a6ef6SSaurabh Misra uint32_t 2105015a6ef6SSaurabh Misra atge_ether_crc(const uint8_t *addr, int len) 2106015a6ef6SSaurabh Misra { 2107015a6ef6SSaurabh Misra int idx; 2108015a6ef6SSaurabh Misra int bit; 2109015a6ef6SSaurabh Misra uint_t data; 2110015a6ef6SSaurabh Misra uint32_t crc; 2111015a6ef6SSaurabh Misra 2112015a6ef6SSaurabh Misra crc = 0xffffffff; 2113015a6ef6SSaurabh Misra for (idx = 0; idx < len; idx++) { 2114015a6ef6SSaurabh Misra for (data = *addr++, bit = 0; bit < 8; bit++, data >>= 1) { 2115015a6ef6SSaurabh Misra crc = (crc << 1) 2116015a6ef6SSaurabh Misra ^ ((((crc >> 31) ^ data) & 1) ? CRC32_POLY_BE : 0); 2117015a6ef6SSaurabh Misra } 2118015a6ef6SSaurabh Misra } 2119015a6ef6SSaurabh Misra 2120015a6ef6SSaurabh Misra return (crc); 2121015a6ef6SSaurabh Misra } 2122015a6ef6SSaurabh Misra 2123015a6ef6SSaurabh Misra 2124015a6ef6SSaurabh Misra /* 2125015a6ef6SSaurabh Misra * Programs RX filter. We use a link-list to keep track of all multicast 2126015a6ef6SSaurabh Misra * addressess. 2127015a6ef6SSaurabh Misra */ 2128015a6ef6SSaurabh Misra void 2129015a6ef6SSaurabh Misra atge_rxfilter(atge_t *atgep) 2130015a6ef6SSaurabh Misra { 2131015a6ef6SSaurabh Misra uint32_t rxcfg; 2132015a6ef6SSaurabh Misra uint64_t mchash; 2133015a6ef6SSaurabh Misra 2134015a6ef6SSaurabh Misra rxcfg = INL(atgep, ATGE_MAC_CFG); 2135015a6ef6SSaurabh Misra rxcfg &= ~(ATGE_CFG_ALLMULTI | ATGE_CFG_PROMISC); 2136015a6ef6SSaurabh Misra 2137015a6ef6SSaurabh Misra /* 2138015a6ef6SSaurabh Misra * Accept broadcast frames. 2139015a6ef6SSaurabh Misra */ 2140015a6ef6SSaurabh Misra rxcfg |= ATGE_CFG_BCAST; 2141015a6ef6SSaurabh Misra 2142015a6ef6SSaurabh Misra /* 2143015a6ef6SSaurabh Misra * We don't use Hardware VLAN tagging. 2144015a6ef6SSaurabh Misra */ 2145015a6ef6SSaurabh Misra rxcfg &= ~ATGE_CFG_VLAN_TAG_STRIP; 2146015a6ef6SSaurabh Misra 2147015a6ef6SSaurabh Misra if (atgep->atge_filter_flags & (ATGE_PROMISC | ATGE_ALL_MULTICST)) { 2148015a6ef6SSaurabh Misra mchash = ~0ULL; 2149015a6ef6SSaurabh Misra 2150015a6ef6SSaurabh Misra if (atgep->atge_filter_flags & ATGE_PROMISC) 2151015a6ef6SSaurabh Misra rxcfg |= ATGE_CFG_PROMISC; 2152015a6ef6SSaurabh Misra 2153015a6ef6SSaurabh Misra if (atgep->atge_filter_flags & ATGE_ALL_MULTICST) 2154015a6ef6SSaurabh Misra rxcfg |= ATGE_CFG_ALLMULTI; 2155015a6ef6SSaurabh Misra } else { 2156015a6ef6SSaurabh Misra mchash = atgep->atge_mchash; 2157015a6ef6SSaurabh Misra } 2158015a6ef6SSaurabh Misra 2159015a6ef6SSaurabh Misra atge_program_ether(atgep); 2160015a6ef6SSaurabh Misra 2161015a6ef6SSaurabh Misra OUTL(atgep, ATGE_MAR0, (uint32_t)mchash); 2162015a6ef6SSaurabh Misra OUTL(atgep, ATGE_MAR1, (uint32_t)(mchash >> 32)); 2163015a6ef6SSaurabh Misra OUTL(atgep, ATGE_MAC_CFG, rxcfg); 2164015a6ef6SSaurabh Misra 2165015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() mac_cfg is : %x, mchash : %llx", 2166015a6ef6SSaurabh Misra atgep->atge_name, __func__, rxcfg, mchash)); 2167015a6ef6SSaurabh Misra } 2168015a6ef6SSaurabh Misra 2169015a6ef6SSaurabh Misra void 2170015a6ef6SSaurabh Misra atge_device_stop(atge_t *atgep) 2171015a6ef6SSaurabh Misra { 2172015a6ef6SSaurabh Misra uint32_t reg; 2173015a6ef6SSaurabh Misra int t; 2174015a6ef6SSaurabh Misra 2175015a6ef6SSaurabh Misra /* 2176015a6ef6SSaurabh Misra * If the chip is being suspended, then don't touch the state. Caller 2177015a6ef6SSaurabh Misra * will take care of setting the correct state. 2178015a6ef6SSaurabh Misra */ 2179015a6ef6SSaurabh Misra if (!(atgep->atge_chip_state & ATGE_CHIP_SUSPENDED)) { 2180015a6ef6SSaurabh Misra atgep->atge_chip_state |= ATGE_CHIP_STOPPED; 2181015a6ef6SSaurabh Misra atgep->atge_chip_state &= ~ATGE_CHIP_RUNNING; 2182015a6ef6SSaurabh Misra } 2183015a6ef6SSaurabh Misra 2184015a6ef6SSaurabh Misra /* 2185015a6ef6SSaurabh Misra * Collect stats for L1E. L1 chip's stats are collected by interrupt. 2186015a6ef6SSaurabh Misra */ 2187015a6ef6SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) { 2188015a6ef6SSaurabh Misra atge_l1e_gather_stats(atgep); 2189015a6ef6SSaurabh Misra } 2190015a6ef6SSaurabh Misra 2191015a6ef6SSaurabh Misra /* 2192015a6ef6SSaurabh Misra * Disable interrupts. 2193015a6ef6SSaurabh Misra */ 2194015a6ef6SSaurabh Misra atge_disable_intrs(atgep); 2195015a6ef6SSaurabh Misra 2196*0eb090a7SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) 2197*0eb090a7SSaurabh Misra OUTL(atgep, L1_CSMB_CTRL, 0); 2198*0eb090a7SSaurabh Misra 2199*0eb090a7SSaurabh Misra /* Stop DMA Engine */ 2200*0eb090a7SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) { 2201*0eb090a7SSaurabh Misra atge_l1_stop_tx_mac(atgep); 2202*0eb090a7SSaurabh Misra atge_l1_stop_rx_mac(atgep); 2203*0eb090a7SSaurabh Misra 2204*0eb090a7SSaurabh Misra reg = INL(atgep, ATGE_DMA_CFG); 2205*0eb090a7SSaurabh Misra reg &= ~(DMA_CFG_RD_ENB | DMA_CFG_WR_ENB); 2206*0eb090a7SSaurabh Misra OUTL(atgep, ATGE_DMA_CFG, reg); 2207*0eb090a7SSaurabh Misra 2208*0eb090a7SSaurabh Misra } 2209*0eb090a7SSaurabh Misra 2210015a6ef6SSaurabh Misra /* 2211015a6ef6SSaurabh Misra * Disable queue processing. 2212015a6ef6SSaurabh Misra */ 2213015a6ef6SSaurabh Misra /* Stop TxQ */ 2214015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_TXQ_CFG); 2215015a6ef6SSaurabh Misra reg = reg & ~TXQ_CFG_ENB; 2216015a6ef6SSaurabh Misra OUTL(atgep, ATGE_TXQ_CFG, reg); 2217015a6ef6SSaurabh Misra 2218015a6ef6SSaurabh Misra /* Stop RxQ */ 2219015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_RXQ_CFG); 2220015a6ef6SSaurabh Misra reg = reg & ~RXQ_CFG_ENB; 2221015a6ef6SSaurabh Misra OUTL(atgep, ATGE_RXQ_CFG, reg); 2222015a6ef6SSaurabh Misra 2223015a6ef6SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) { 2224015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_DMA_CFG); 2225015a6ef6SSaurabh Misra reg = reg & ~(DMA_CFG_TXCMB_ENB | DMA_CFG_RXCMB_ENB); 2226015a6ef6SSaurabh Misra OUTL(atgep, ATGE_DMA_CFG, reg); 2227015a6ef6SSaurabh Misra drv_usecwait(1000); 2228015a6ef6SSaurabh Misra atge_l1e_stop_mac(atgep); 2229015a6ef6SSaurabh Misra OUTL(atgep, ATGE_INTR_STATUS, 0xFFFFFFFF); 2230015a6ef6SSaurabh Misra } 2231015a6ef6SSaurabh Misra 2232015a6ef6SSaurabh Misra for (t = ATGE_RESET_TIMEOUT; t > 0; t--) { 2233015a6ef6SSaurabh Misra if ((reg = INL(atgep, ATGE_IDLE_STATUS)) == 0) 2234015a6ef6SSaurabh Misra break; 2235015a6ef6SSaurabh Misra drv_usecwait(10); 2236015a6ef6SSaurabh Misra } 2237015a6ef6SSaurabh Misra 2238015a6ef6SSaurabh Misra if (t == 0) { 2239015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "%s() stopping TX/RX MAC timeout", 2240015a6ef6SSaurabh Misra __func__); 2241015a6ef6SSaurabh Misra } 2242015a6ef6SSaurabh Misra } 2243015a6ef6SSaurabh Misra 2244015a6ef6SSaurabh Misra void 2245015a6ef6SSaurabh Misra atge_disable_intrs(atge_t *atgep) 2246015a6ef6SSaurabh Misra { 2247015a6ef6SSaurabh Misra OUTL(atgep, ATGE_INTR_MASK, 0); 2248015a6ef6SSaurabh Misra OUTL(atgep, ATGE_INTR_STATUS, 0xFFFFFFFF); 2249015a6ef6SSaurabh Misra } 2250015a6ef6SSaurabh Misra 2251015a6ef6SSaurabh Misra void 2252015a6ef6SSaurabh Misra atge_device_init(atge_t *atgep) 2253015a6ef6SSaurabh Misra { 2254015a6ef6SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) { 2255015a6ef6SSaurabh Misra atgep->atge_intrs = L1E_INTRS; 2256015a6ef6SSaurabh Misra atgep->atge_int_mod = ATGE_IM_TIMER_DEFAULT; 2257015a6ef6SSaurabh Misra 2258015a6ef6SSaurabh Misra atge_l1e_init_tx_ring(atgep); 2259015a6ef6SSaurabh Misra atge_l1e_init_rx_pages(atgep); 2260*0eb090a7SSaurabh Misra } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) { 2261*0eb090a7SSaurabh Misra atgep->atge_intrs = L1_INTRS | INTR_GPHY | INTR_PHY_LINK_DOWN | 2262*0eb090a7SSaurabh Misra INTR_LINK_CHG; 2263*0eb090a7SSaurabh Misra atgep->atge_int_mod = ATGE_IM_TIMER_DEFAULT; 2264*0eb090a7SSaurabh Misra 2265*0eb090a7SSaurabh Misra atge_l1_init_tx_ring(atgep); 2266*0eb090a7SSaurabh Misra atge_l1_init_rx_ring(atgep); 2267*0eb090a7SSaurabh Misra atge_l1_init_rr_ring(atgep); 2268*0eb090a7SSaurabh Misra atge_l1_init_cmb(atgep); 2269*0eb090a7SSaurabh Misra atge_l1_init_smb(atgep); 2270015a6ef6SSaurabh Misra } 2271015a6ef6SSaurabh Misra } 2272015a6ef6SSaurabh Misra 2273015a6ef6SSaurabh Misra void 2274015a6ef6SSaurabh Misra atge_device_restart(atge_t *atgep) 2275015a6ef6SSaurabh Misra { 2276015a6ef6SSaurabh Misra ASSERT(MUTEX_HELD(&atgep->atge_intr_lock)); 2277015a6ef6SSaurabh Misra ASSERT(MUTEX_HELD(&atgep->atge_tx_lock)); 2278015a6ef6SSaurabh Misra 2279015a6ef6SSaurabh Misra /* 2280015a6ef6SSaurabh Misra * Cancel any pending I/O. 2281015a6ef6SSaurabh Misra */ 2282015a6ef6SSaurabh Misra atge_device_stop(atgep); 2283015a6ef6SSaurabh Misra 2284015a6ef6SSaurabh Misra /* 2285015a6ef6SSaurabh Misra * Reset the chip to a known state. 2286015a6ef6SSaurabh Misra */ 2287015a6ef6SSaurabh Misra atge_device_reset(atgep); 2288015a6ef6SSaurabh Misra 2289015a6ef6SSaurabh Misra /* 2290015a6ef6SSaurabh Misra * Initialize the ring and other descriptor like CMB/SMB/Rx return. 2291015a6ef6SSaurabh Misra */ 2292015a6ef6SSaurabh Misra atge_device_init(atgep); 2293015a6ef6SSaurabh Misra 2294015a6ef6SSaurabh Misra /* 2295015a6ef6SSaurabh Misra * Start the chip. 2296015a6ef6SSaurabh Misra */ 2297015a6ef6SSaurabh Misra atge_device_start(atgep); 2298015a6ef6SSaurabh Misra 2299015a6ef6SSaurabh Misra } 2300015a6ef6SSaurabh Misra 2301015a6ef6SSaurabh Misra static int 2302015a6ef6SSaurabh Misra atge_send_a_packet(atge_t *atgep, mblk_t *mp) 2303015a6ef6SSaurabh Misra { 2304*0eb090a7SSaurabh Misra atge_tx_desc_t *txd; 2305*0eb090a7SSaurabh Misra uchar_t *c; 2306*0eb090a7SSaurabh Misra uint32_t cflags = 0; 2307015a6ef6SSaurabh Misra atge_ring_t *r; 2308015a6ef6SSaurabh Misra size_t pktlen; 2309015a6ef6SSaurabh Misra uchar_t *buf; 2310015a6ef6SSaurabh Misra int start; 2311015a6ef6SSaurabh Misra 2312015a6ef6SSaurabh Misra ASSERT(MUTEX_HELD(&atgep->atge_tx_lock)); 2313015a6ef6SSaurabh Misra ASSERT(mp != NULL); 2314015a6ef6SSaurabh Misra 2315015a6ef6SSaurabh Misra pktlen = msgsize(mp); 2316015a6ef6SSaurabh Misra if (pktlen > atgep->atge_tx_buf_len) { 2317015a6ef6SSaurabh Misra atgep->atge_macxmt_errors++; 2318015a6ef6SSaurabh Misra 2319015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() pktlen (%d) > rx_buf_len (%d)", 2320015a6ef6SSaurabh Misra atgep->atge_name, __func__, 2321015a6ef6SSaurabh Misra pktlen, atgep->atge_rx_buf_len)); 2322015a6ef6SSaurabh Misra 2323015a6ef6SSaurabh Misra freemsg(mp); 2324*0eb090a7SSaurabh Misra return (DDI_SUCCESS); 2325015a6ef6SSaurabh Misra } 2326015a6ef6SSaurabh Misra 2327015a6ef6SSaurabh Misra r = atgep->atge_tx_ring; 2328015a6ef6SSaurabh Misra 2329015a6ef6SSaurabh Misra if (r->r_avail_desc <= 1) { 2330015a6ef6SSaurabh Misra atgep->atge_noxmtbuf++; 2331015a6ef6SSaurabh Misra atgep->atge_tx_resched = 1; 2332*0eb090a7SSaurabh Misra 2333*0eb090a7SSaurabh Misra ATGE_DB(("%s: %s() No transmit buf", 2334*0eb090a7SSaurabh Misra atgep->atge_name, __func__)); 2335*0eb090a7SSaurabh Misra 2336*0eb090a7SSaurabh Misra return (DDI_FAILURE); 2337015a6ef6SSaurabh Misra } 2338015a6ef6SSaurabh Misra 2339015a6ef6SSaurabh Misra start = r->r_producer; 2340015a6ef6SSaurabh Misra 2341015a6ef6SSaurabh Misra /* 2342015a6ef6SSaurabh Misra * Get the DMA buffer to hold a packet. 2343015a6ef6SSaurabh Misra */ 2344015a6ef6SSaurabh Misra buf = (uchar_t *)r->r_buf_tbl[start]->addr; 2345015a6ef6SSaurabh Misra 2346015a6ef6SSaurabh Misra /* 2347015a6ef6SSaurabh Misra * Copy the msg and free mp 2348015a6ef6SSaurabh Misra */ 2349015a6ef6SSaurabh Misra mcopymsg(mp, buf); 2350015a6ef6SSaurabh Misra 2351015a6ef6SSaurabh Misra r->r_avail_desc--; 2352015a6ef6SSaurabh Misra 2353*0eb090a7SSaurabh Misra c = (uchar_t *)r->r_desc_ring->addr; 2354*0eb090a7SSaurabh Misra c += (sizeof (atge_tx_desc_t) * start); 2355*0eb090a7SSaurabh Misra txd = (atge_tx_desc_t *)c; 2356*0eb090a7SSaurabh Misra 2357*0eb090a7SSaurabh Misra ATGE_PUT64(r->r_desc_ring, &txd->addr, 2358*0eb090a7SSaurabh Misra r->r_buf_tbl[start]->cookie.dmac_laddress); 2359*0eb090a7SSaurabh Misra 2360*0eb090a7SSaurabh Misra ATGE_PUT32(r->r_desc_ring, &txd->len, ATGE_TX_BYTES(pktlen)); 2361*0eb090a7SSaurabh Misra 2362*0eb090a7SSaurabh Misra cflags |= ATGE_TD_EOP; 2363*0eb090a7SSaurabh Misra ATGE_PUT32(r->r_desc_ring, &txd->flags, cflags); 2364*0eb090a7SSaurabh Misra 2365*0eb090a7SSaurabh Misra /* 2366*0eb090a7SSaurabh Misra * Sync buffer first. 2367*0eb090a7SSaurabh Misra */ 2368*0eb090a7SSaurabh Misra DMA_SYNC(r->r_buf_tbl[start], 0, pktlen, DDI_DMA_SYNC_FORDEV); 2369*0eb090a7SSaurabh Misra 2370*0eb090a7SSaurabh Misra /* 2371*0eb090a7SSaurabh Misra * Increment TX producer count by one. 2372*0eb090a7SSaurabh Misra */ 2373*0eb090a7SSaurabh Misra ATGE_INC_SLOT(r->r_producer, ATGE_TX_RING_CNT); 2374*0eb090a7SSaurabh Misra 2375*0eb090a7SSaurabh Misra /* 2376*0eb090a7SSaurabh Misra * Sync descriptor table. 2377*0eb090a7SSaurabh Misra */ 2378*0eb090a7SSaurabh Misra DMA_SYNC(r->r_desc_ring, 0, ATGE_TX_RING_SZ, DDI_DMA_SYNC_FORDEV); 2379*0eb090a7SSaurabh Misra 2380015a6ef6SSaurabh Misra /* 2381015a6ef6SSaurabh Misra * Program TX descriptor to send a packet. 2382015a6ef6SSaurabh Misra */ 2383015a6ef6SSaurabh Misra if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) { 2384*0eb090a7SSaurabh Misra atge_l1e_send_packet(r); 2385*0eb090a7SSaurabh Misra } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) { 2386*0eb090a7SSaurabh Misra atge_l1_send_packet(r); 2387015a6ef6SSaurabh Misra } 2388015a6ef6SSaurabh Misra 2389*0eb090a7SSaurabh Misra r->r_atge->atge_opackets++; 2390*0eb090a7SSaurabh Misra r->r_atge->atge_obytes += pktlen; 2391*0eb090a7SSaurabh Misra 2392*0eb090a7SSaurabh Misra ATGE_DB(("%s: %s() pktlen : %d, avail_desc : %d, producer :%d, " 2393*0eb090a7SSaurabh Misra "consumer : %d", atgep->atge_name, __func__, pktlen, 2394*0eb090a7SSaurabh Misra r->r_avail_desc, r->r_producer, r->r_consumer)); 2395*0eb090a7SSaurabh Misra 2396*0eb090a7SSaurabh Misra return (DDI_SUCCESS); 2397015a6ef6SSaurabh Misra } 2398015a6ef6SSaurabh Misra 2399015a6ef6SSaurabh Misra /* 2400015a6ef6SSaurabh Misra * Stream Information. 2401015a6ef6SSaurabh Misra */ 2402015a6ef6SSaurabh Misra DDI_DEFINE_STREAM_OPS(atge_devops, nulldev, nulldev, atge_attach, atge_detach, 2403015a6ef6SSaurabh Misra nodev, NULL, D_MP, NULL, atge_quiesce); 2404015a6ef6SSaurabh Misra 2405015a6ef6SSaurabh Misra /* 2406015a6ef6SSaurabh Misra * Module linkage information. 2407015a6ef6SSaurabh Misra */ 2408015a6ef6SSaurabh Misra static struct modldrv atge_modldrv = { 2409015a6ef6SSaurabh Misra &mod_driverops, /* Type of Module */ 2410015a6ef6SSaurabh Misra "Atheros/Attansic Gb Ethernet", /* Description */ 2411015a6ef6SSaurabh Misra &atge_devops /* drv_dev_ops */ 2412015a6ef6SSaurabh Misra }; 2413015a6ef6SSaurabh Misra 2414015a6ef6SSaurabh Misra static struct modlinkage atge_modlinkage = { 2415015a6ef6SSaurabh Misra MODREV_1, /* ml_rev */ 2416015a6ef6SSaurabh Misra (void *)&atge_modldrv, 2417015a6ef6SSaurabh Misra NULL 2418015a6ef6SSaurabh Misra }; 2419015a6ef6SSaurabh Misra 2420015a6ef6SSaurabh Misra /* 2421015a6ef6SSaurabh Misra * DDI Entry points. 2422015a6ef6SSaurabh Misra */ 2423015a6ef6SSaurabh Misra int 2424015a6ef6SSaurabh Misra _init(void) 2425015a6ef6SSaurabh Misra { 2426015a6ef6SSaurabh Misra int r; 2427015a6ef6SSaurabh Misra mac_init_ops(&atge_devops, "atge"); 2428015a6ef6SSaurabh Misra if ((r = mod_install(&atge_modlinkage)) != DDI_SUCCESS) { 2429015a6ef6SSaurabh Misra mac_fini_ops(&atge_devops); 2430015a6ef6SSaurabh Misra } 2431015a6ef6SSaurabh Misra 2432015a6ef6SSaurabh Misra return (r); 2433015a6ef6SSaurabh Misra } 2434015a6ef6SSaurabh Misra 2435015a6ef6SSaurabh Misra int 2436015a6ef6SSaurabh Misra _fini(void) 2437015a6ef6SSaurabh Misra { 2438015a6ef6SSaurabh Misra int r; 2439015a6ef6SSaurabh Misra 2440015a6ef6SSaurabh Misra if ((r = mod_remove(&atge_modlinkage)) == DDI_SUCCESS) { 2441015a6ef6SSaurabh Misra mac_fini_ops(&atge_devops); 2442015a6ef6SSaurabh Misra } 2443015a6ef6SSaurabh Misra 2444015a6ef6SSaurabh Misra return (r); 2445015a6ef6SSaurabh Misra } 2446015a6ef6SSaurabh Misra 2447015a6ef6SSaurabh Misra int 2448015a6ef6SSaurabh Misra _info(struct modinfo *modinfop) 2449015a6ef6SSaurabh Misra { 2450015a6ef6SSaurabh Misra return (mod_info(&atge_modlinkage, modinfop)); 2451015a6ef6SSaurabh Misra } 2452