015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * CDDL HEADER START
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * The contents of this file are subject to the terms of the
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Common Development and Distribution License (the "License").
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * You may not use this file except in compliance with the License.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * See the License for the specific language governing permissions
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * and limitations under the License.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * When distributing Covered Code, include this CDDL HEADER in each
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * If applicable, add the following below this CDDL HEADER, with the
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * fields enclosed by brackets "[]" replaced with your own identifying
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * information: Portions Copyright [yyyy] [name of copyright owner]
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * CDDL HEADER END
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Copyright (c) 2012 Gary Mills
9d8d9e1151895fac86a2e3216647dd2a020ecf71Garrett D'Amore * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Copyright (c) 2009, Pyun YongHyeon <yongari@FreeBSD.org>
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * All rights reserved.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Redistribution and use in source and binary forms, with or without
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * modification, are permitted provided that the following conditions
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * 1. Redistributions of source code must retain the above copyright
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * notice unmodified, this list of conditions, and the following
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * disclaimer.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * 2. Redistributions in binary form must reproduce the above copyright
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * notice, this list of conditions and the following disclaimer in the
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * documentation and/or other materials provided with the distribution.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * SUCH DAMAGE.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Atheros/Attansic Ethernet chips are of four types - L1, L2, L1E and L1C.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * This driver is for L1E/L1/L1C but can be extended to support other chips.
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra * L1E comes in 1Gigabit and Fast Ethernet flavors. L1 comes in 1Gigabit
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * flavors only. L1C comes in both flavours.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Atheros/Attansic Ethernet controllers have descriptor based TX and RX
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * with an exception of L1E. L1E's RX side is not descriptor based ring.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * The L1E's RX uses pages (not to be confused with MMU pages) for
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * receiving pkts. The header has four fields :
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * uint32_t seqno; Sequence number of the frame.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * uint32_t length; Length of the frame.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * uint32_t flags; Flags
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * uint32_t vtag; We don't use hardware VTAG.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * We use only one queue for RX (each queue can have two pages) and each
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * page is L1E_RX_PAGE_SZ large in bytes. That's the reason we don't
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * use zero-copy RX because we are limited to two pages and each page
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * accomodates large number of pkts.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * The TX side on all three chips is descriptor based ring; and all the
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * more reason to have one driver for these chips.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * We use two locks - atge_intr_lock and atge_tx_lock. Both the locks
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * should be held if the operation has impact on the driver instance.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * All the three chips have hash-based multicast filter.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * We use CMB (Coalescing Message Block) for RX but not for TX as there
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * are some issues with TX. RX CMB is used to get the last descriptor
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * posted by the chip. Each CMB is for a RX page (one queue can have two
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * pages) and are uint32_t (4 bytes) long.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * The descriptor table should have 32-bit physical address limit due to
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * the limitation of having same high address for TX/RX/SMB/CMB. The
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * TX/RX buffers can be 64-bit.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Every DMA memory in atge is represented by atge_dma_t be it TX/RX Buffers
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * or TX/RX descriptor table or SMB/CMB. To keep the code simple, we have
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * kept sgl as 1 so that we get contingous pages from root complex.
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra * L1 chip (0x1048) uses descriptor based TX and RX ring. Most of registers are
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra * common with L1E chip (0x1026).
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Function Prototypes for debugging.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misravoid atge_debug_func(char *, ...);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Function Prototypes for driver operations.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misraatge_dma_t *atge_alloc_a_dma_blk(atge_t *, ddi_dma_attr_t *, int, int);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misrastatic void atge_device_reset_l1_l1e(atge_t *);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misrastatic int atge_send_a_packet(atge_t *, mblk_t *);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misrastatic uint32_t atge_ether_crc(const uint8_t *, int);
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra * L1E/L2E specific functions.
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra * L1 specific functions.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * L1C specific functions.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Function prototyps for MII operations.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misrauint16_t atge_mii_read(void *, uint8_t, uint8_t);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misravoid atge_mii_write(void *, uint8_t, uint8_t, uint16_t);
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Millsuint16_t atge_l1c_mii_read(void *, uint8_t, uint8_t);
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Millsvoid atge_l1c_mii_write(void *, uint8_t, uint8_t, uint16_t);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misrastatic void atge_mii_notify(void *, link_state_t);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Function Prototypes for MAC callbacks.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misrastatic int atge_m_stat(void *, uint_t, uint64_t *);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misrastatic int atge_m_start(void *);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misrastatic void atge_m_stop(void *);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misrastatic int atge_m_getprop(void *, const char *, mac_prop_id_t, uint_t,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misrastatic int atge_m_setprop(void *, const char *, mac_prop_id_t, uint_t,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra const void *);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic void atge_m_propinfo(void *, const char *, mac_prop_id_t,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misrastatic int atge_m_unicst(void *, const uint8_t *);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misrastatic int atge_m_multicst(void *, boolean_t, const uint8_t *);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * DMA Data access requirements.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misrastatic struct ddi_device_acc_attr atge_dev_attr = {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Buffers should be native endianness.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misrastatic struct ddi_device_acc_attr atge_buf_attr = {
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra * DMA device attributes. Buffer can be 64-bit.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra 0, /* dma_attr_addr_lo */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra 0 /* dma_attr_flags */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Table of supported devices.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills#define ATGE_L1CG_STR "Atheros AR8131 Gigabit Ethernet"
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills#define ATGE_L1CF_STR "Atheros AR8132 Fast Ethernet"
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra#define ATGE_L1E_STR "Atheros AR8121/8113/8114"
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills#define ATGE_AR8151V1_STR "Atheros AR8151 v1.0 Gigabit Ethernet"
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills#define ATGE_AR8151V2_STR "Atheros AR8151 v2.0 Gigabit Ethernet"
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills#define ATGE_AR8152V1_STR "Atheros AR8152 v1.1 Fast Ethernet"
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills#define ATGE_AR8152V2_STR "Atheros AR8152 v2.0 Fast Ethernet"
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_AR8151V2_DEV_ID, ATGE_AR8151V2_STR,
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_AR8151V1_DEV_ID, ATGE_AR8151V1_STR,
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_AR8152V2_DEV_ID, ATGE_AR8152V2_STR,
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_AR8152V1_DEV_ID, ATGE_AR8152V1_STR,
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_L1CG_DEV_ID, ATGE_L1CG_STR, ATGE_CHIP_L1C},
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_L1CF_DEV_ID, ATGE_L1CF_STR, ATGE_CHIP_L1C},
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra {ATGE_VENDOR_ID, ATGE_CHIP_L1E_DEV_ID, ATGE_L1E_STR, ATGE_CHIP_L1E},
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_L1_DEV_ID, ATGE_L1_STR, ATGE_CHIP_L1},
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Global Debugging flag. Developer level debugging is done only in DEBUG mode.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Debugging and error reporting.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Millsatge_message(dev_info_t *dip, int level, char *fmt, va_list ap)
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills char *p = "!%s%d: %s";
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills char *q = "!atge: %s";
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ddi_driver_name(dip), ddi_get_instance(dip), buf);
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Re-enable TX/RX MACs */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra reg &= ~(ATGE_CFG_FULL_DUPLEX | ATGE_CFG_TX_FC | ATGE_CFG_RX_FC |
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills reg |= ATGE_CFG_HASH_ALG_CRC32 | ATGE_CFG_SPEED_MODE_SW;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra /* Re-enable TX/RX MACs */
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra reg |= ATGE_CFG_TX_ENB | ATGE_CFG_RX_ENB | ATGE_CFG_RX_FC;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra reg = ATGE_USECS(ATGE_IM_RX_TIMER_DEFAULT) << IM_TIMER_RX_SHIFT;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra reg |= ATGE_USECS(ATGE_IM_TX_TIMER_DEFAULT) <<
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Configure interrupt moderation timer. */
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills reg = ATGE_USECS(atgep->atge_int_rx_mod) << IM_TIMER_RX_SHIFT;
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills reg |= ATGE_USECS(atgep->atge_int_tx_mod) << IM_TIMER_TX_SHIFT;
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * We don't want to automatic interrupt clear as task queue
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * for the interrupt should know interrupt status.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_name, __func__, INL(atgep, ATGE_MAC_CFG)));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_DB(("%s: %s() LINK STATUS CHANGED from %x -> %x",
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_name, __func__, atgep->atge_link_state, link));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Reconfigure MAC if link status is UP now.
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra "Reclaim : TX descriptor error");
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra if (r->r_avail_desc > (ATGE_TX_RING_CNT + 5)) {
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra * Clearing TX descriptor helps in debugging some strange
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra DMA_SYNC(r->r_desc_ring, 0, ATGE_TX_RING_SZ, DDI_DMA_SYNC_FORDEV);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Adds interrupt handler depending upon the type of interrupt supported by
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misraatge_add_intr_handler(atge_t *atgep, int intr_type)
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra err = ddi_intr_get_nintrs(atgep->atge_dip, intr_type, &count);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra err = ddi_intr_get_navail(atgep->atge_dip, intr_type, &avail);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * DDI_INTR_TYPE_FIXED case.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_intr_size = avail * sizeof (ddi_intr_handle_t);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_intr_handle = kmem_zalloc(atgep->atge_intr_size, KM_SLEEP);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_DB(("%s: %s() avail:%d, count : %d, type : %d",
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra err = ddi_intr_alloc(atgep->atge_dip, atgep->atge_intr_handle,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra intr_type, 0, avail, &atgep->atge_intr_cnt, flag);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atge_error(atgep->atge_dip, "ddi_intr_alloc failed : %d", err);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra kmem_free(atgep->atge_intr_handle, atgep->atge_intr_size);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_DB(("%s: atge_add_intr_handler() after alloc count"
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra " :%d, avail : %d", atgep->atge_name, count, avail));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra err = ddi_intr_get_pri(atgep->atge_intr_handle[0],
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atge_error(atgep->atge_dip, "ddi_intr_get_pri failed:%d", err);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra (void) ddi_intr_free(atgep->atge_intr_handle[i]);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra kmem_free(atgep->atge_intr_handle, atgep->atge_intr_size);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Add interrupt handler now.
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra err = ddi_intr_add_handler(atgep->atge_intr_handle[i],
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra atge_l1e_interrupt, atgep, (caddr_t)(uintptr_t)i);
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra err = ddi_intr_add_handler(atgep->atge_intr_handle[i],
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra atge_l1_interrupt, atgep, (caddr_t)(uintptr_t)i);
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills err = ddi_intr_add_handler(atgep->atge_intr_handle[i],
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills atge_l1c_interrupt, atgep, (caddr_t)(uintptr_t)i);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra (void) ddi_intr_free(atgep->atge_intr_handle[i]);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra while (--i >= 0) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra err = ddi_intr_get_cap(atgep->atge_intr_handle[0],
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if (atgep->atge_intr_cap & DDI_INTR_FLAG_BLOCK) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra (void) ddi_intr_block_disable(atgep->atge_intr_handle,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra (void) ddi_intr_disable(atgep->atge_intr_handle[i]);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra (void) ddi_intr_remove_handler(atgep->atge_intr_handle[i]);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra (void) ddi_intr_free(atgep->atge_intr_handle[i]);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra kmem_free(atgep->atge_intr_handle, atgep->atge_intr_size);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if (atgep->atge_intr_cap & DDI_INTR_FLAG_BLOCK) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Do block enable.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra err = ddi_intr_block_enable(atgep->atge_intr_handle,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Call ddi_intr_enable() for MSI non-block enable.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra err = ddi_intr_enable(atgep->atge_intr_handle[i]);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra "Failed to enable intrs on %d with : %d",
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Adds interrupt handler depending on the supported interrupt type by the
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Get the supported interrupt types.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra err = ddi_intr_get_supported_types(atgep->atge_dip,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra "ddi_intr_get_supported_types failed : %d", err);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_DB(("%s: ddi_intr_get_supported_types() returned : %d",
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if (atgep->atge_intr_types & DDI_INTR_TYPE_MSIX) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra err = atge_add_intr_handler(atgep, DDI_INTR_TYPE_MSIX);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if (atgep->atge_intr_types & DDI_INTR_TYPE_MSI) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra err = atge_add_intr_handler(atgep, DDI_INTR_TYPE_MSI);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if (atgep->atge_intr_types & DDI_INTR_TYPE_FIXED) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra err = atge_add_intr_handler(atgep, DDI_INTR_TYPE_FIXED);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_DB(("%s: Using FIXED type for interrupt",
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra vid = pci_config_get16(atgep->atge_conf_handle, PCI_CONF_VENID);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra did = pci_config_get16(atgep->atge_conf_handle, PCI_CONF_DEVID);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra for (i = 0; i < (sizeof (atge_cards) / sizeof (atge_cards_t)); i++) {
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills atge_notice(atgep->atge_dip, "PCI-ID pci%x,%x,%x: %s",
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_DB(("%s: %s : PCI-ID pci%x,%x and model : %d",
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atge_error(atgep->atge_dip, "atge driver is attaching to unknown"
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Assume it's L1C chip.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_revid = pci_config_get8(atgep->atge_conf_handle,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * We will leave the decision to caller.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Get VPD stored in TWSI EEPROM.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_DB(("%s: %s called Get VPD", atgep->atge_name, __func__));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_ether_addr[5] = INB(atgep, ATGE_PAR0 + 0);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_ether_addr[4] = INB(atgep, ATGE_PAR0 + 1);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_ether_addr[3] = INB(atgep, ATGE_PAR0 + 2);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_ether_addr[2] = INB(atgep, ATGE_PAR0 + 3);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_ether_addr[1] = INB(atgep, ATGE_PAR1 + 0);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_ether_addr[0] = INB(atgep, ATGE_PAR1 + 1);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_DB(("%s: %s() Station Address - %x:%x:%x:%x:%x:%x",
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra bcopy(atgep->atge_ether_addr, atgep->atge_dev_addr, ETHERADDRL);
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Reset functionality for L1, L1E, and L1C. It's same.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills OUTL(atgep, ATGE_MASTER_CFG, MASTER_RESET | 0x40);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra for (t = ATGE_RESET_TIMEOUT; t > 0; t--) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if (t == 0) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atge_error(atgep->atge_dip, " master reset timeout reg : %x",
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra for (t = ATGE_RESET_TIMEOUT; t > 0; t--) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if ((reg = INL(atgep, ATGE_IDLE_STATUS)) == 0)
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if (t == 0) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atge_error(atgep->atge_dip, "device reset timeout reg : %x",
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Initialize PCIe module. These values came from FreeBSD and
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * we don't know the meaning of it.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Get chip revision.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_chip_rev = INL(atgep, ATGE_MASTER_CFG) >>
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_DB(("%s: %s reset successfully rev : %x", atgep->atge_name,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * DMA allocation for L1 and L1E is bit different since L1E uses RX pages
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * instead of descriptor based RX model.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Attach entry point in the driver.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misraatge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep = kmem_zalloc(sizeof (atge_t), KM_SLEEP);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Setup name and instance number to be used for debugging and
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * error reporting.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra (void) snprintf(atgep->atge_name, sizeof (atgep->atge_name), "%s%d",
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Map PCI config space.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra err = pci_config_setup(devinfo, &atgep->atge_conf_handle);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atge_error(devinfo, "pci_config_setup() failed");
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Map Device registers.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra err = ddi_regs_map_setup(devinfo, ATGE_PCI_REG_NUMBER,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra &atgep->atge_io_regs, 0, 0, &atge_dev_attr, &atgep->atge_io_handle);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atge_error(devinfo, "ddi_regs_map_setup() failed");
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Add interrupt and its associated handler.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atge_error(devinfo, "Failed to add interrupt handler");
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra mutex_init(&atgep->atge_intr_lock, NULL, MUTEX_DRIVER,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra mutex_init(&atgep->atge_tx_lock, NULL, MUTEX_DRIVER,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra mutex_init(&atgep->atge_rx_lock, NULL, MUTEX_DRIVER,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra mutex_init(&atgep->atge_mii_lock, NULL, MUTEX_DRIVER, NULL);
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra * Used to lock down MBOX register on L1 chip since RX consumer,
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra * TX producer and RX return ring consumer are shared.
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra mutex_init(&atgep->atge_mbox_lock, NULL, MUTEX_DRIVER,
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra /* L2E Rev. B. AR8114 */
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra /* L1E AR8121 */
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra /* L2E Rev. A. AR8113 */
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * One odd thing is AR8132 uses the same PHY hardware(F1
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * gigabit PHY) of AR8131. So atphy(4) of AR8132 reports
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * the PHY supports 1000Mbps but that's not true. The PHY
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * used in AR8132 can't establish gigabit link even if it
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * shows the same PHY model/revision number of AR8131.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * It seems that AR813x/AR815x has silicon bug for SMB. In
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * addition, Atheros said that enabling SMB wouldn't improve
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * performance. However I think it's bad to access lots of
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * registers to extract MAC statistics.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Don't use Tx CMB. It is known to have silicon bug.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Get DMA parameters from PCIe device control register.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra err = PCI_CAP_LOCATE(atgep->atge_conf_handle, PCI_CAP_ID_PCI_E,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_dma_rd_burst = DMA_CFG_RD_BURST_128;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_dma_wr_burst = DMA_CFG_WR_BURST_128;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra burst = pci_config_get16(atgep->atge_conf_handle,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Max read request size.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_dma_rd_burst = ((burst >> 12) & 0x07) <<
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Max Payload Size.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_dma_wr_burst = ((burst >> 5) & 0x07) <<
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Clear data link and flow-control protocol error. */
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills OUTL_AND(atgep, ATGE_LTSSM_ID_CFG, ~LTSSM_ID_WRO_ENB);
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills OUTL_OR(atgep, ATGE_PCIE_PHYMISC, PCIE_PHYMISC_FORCE_RCV_DET);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Allocate DMA resources.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atge_error(devinfo, "Failed to allocate DMA resources");
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Get station address.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if ((atgep->atge_mii = mii_alloc(atgep, devinfo,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Register with MAC layer.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if ((macreg = mac_alloc(MAC_VERSION)) == NULL) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atge_error(devinfo, "mac_alloc() failed due to version");
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra macreg->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if ((err = mac_register(macreg, &atgep->atge_mh)) != 0) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atge_error(devinfo, "mac_register() failed with :%d", err);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_DB(("%s: %s() driver attached successfully",
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_chip_state = ATGE_CHIP_INITIALIZED;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * At last - enable interrupts.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Reset the PHY before starting.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Let the PHY run.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra pci_config_teardown(&atgep->atge_conf_handle);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misraatge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * First unregister with MAC layer before stopping DMA
9d8d9e1151895fac86a2e3216647dd2a020ecf71Garrett D'Amore if (mac_disable(atgep->atge_mh) != DDI_SUCCESS)
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra pci_config_teardown(&atgep->atge_conf_handle);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Suspend monitoring MII.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_chip_state |= ATGE_CHIP_SUSPENDED;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misraatge_alloc_buffers(atge_ring_t *r, size_t rcnt, size_t buflen, int f)
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra tbl = kmem_zalloc(rcnt * sizeof (atge_dma_t *), KM_SLEEP);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra for (i = 0; i < rcnt; i++) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra for (i = 0; i < rcnt; i++) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misraatge_alloc_a_dma_blk(atge_t *atgep, ddi_dma_attr_t *attr, int size, int d)
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra dma = kmem_zalloc(sizeof (atge_dma_t), KM_SLEEP);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra err = ddi_dma_alloc_handle(atgep->atge_dip, attr,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra " in ddi_dma_alloc_handle() : %d", __func__, err);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra size, &atge_buf_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra " in ddi_dma_mem_alloc() : %d", __func__, err);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra err = ddi_dma_addr_bind_handle(dma->hdl, NULL, dma->addr,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra dma->len, d | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra " in ddi_dma_addr_bind_handle() : %d", __func__, err);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misraatge_buf_alloc(atge_t *atgep, size_t len, int f)
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra dma = kmem_zalloc(sizeof (atge_dma_t), KM_SLEEP);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra err = ddi_dma_alloc_handle(atgep->atge_dip, &atge_dma_attr_buf,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra err = ddi_dma_mem_alloc(dma->hdl, len, &atge_buf_attr,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, &dma->addr,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra err = ddi_dma_addr_bind_handle(dma->hdl, NULL, dma->addr, dma->len,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra (f | DDI_DMA_CONSISTENT), DDI_DMA_SLEEP, NULL, &dma->cookie,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Number of return'ed cookie should be one.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if ((atgep = ddi_get_driver_private(dip)) == NULL) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_chip_state &= ~ATGE_CHIP_SUSPENDED;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if (atgep->atge_chip_state & ATGE_CHIP_RUNNING) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Reset the PHY before resuming MII.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra /* kick-off downstream */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if ((atgep = ddi_get_driver_private(dip)) == NULL) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misraatge_add_multicst(atge_t *atgep, uint8_t *macaddr)
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_name, __func__, macaddr[0], macaddr[1], macaddr[2],
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra " atge_mchash_ref_cnt[bit] :%d",
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_name, __func__, atgep->atge_mchash, bit,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misraatge_remove_multicst(atge_t *atgep, uint8_t *macaddr)
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_name, __func__, macaddr[0], macaddr[1], macaddr[2],
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra " atge_mchash_ref_cnt[bit] :%d",
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_name, __func__, atgep->atge_mchash, bit,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misraatge_m_multicst(void *arg, boolean_t add, const uint8_t *macaddr)
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atge_remove_multicst(atgep, (uint8_t *)macaddr);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if (atgep->atge_chip_state & ATGE_CHIP_RUNNING) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misraatge_m_unicst(void *arg, const uint8_t *macaddr)
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra bcopy(macaddr, atgep->atge_ether_addr, ETHERADDRL);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * This NIC does not like us to send pkt when link is down.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if (!(atgep->atge_link_state & LINK_STATE_UP)) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Don't send a pkt if chip isn't running or in suspended state.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if ((atgep->atge_chip_state & ATGE_CHIP_RUNNING) == 0 ||
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_chip_state & ATGE_CHIP_SUSPENDED) {
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra if (atge_send_a_packet(atgep, mp) == DDI_FAILURE) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if (!(atgep->atge_chip_state & ATGE_CHIP_SUSPENDED)) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra /* kick-off downstream */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Cancel any pending I/O.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if (!(atgep->atge_chip_state & ATGE_CHIP_SUSPENDED))
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misraatge_m_stat(void *arg, uint_t stat, uint64_t *val)
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if (mii_m_getstat(atgep->atge_mii, stat, val) == 0) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyeratge_m_getprop(void *arg, const char *name, mac_prop_id_t num, uint_t sz,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return (mii_m_getprop(atgep->atge_mii, name, num, sz, val));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misraatge_m_setprop(void *arg, const char *name, mac_prop_id_t num, uint_t sz,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra const void *val)
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra r = mii_m_setprop(atgep->atge_mii, name, num, sz, val);
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra if (r == 0) {
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra if (atgep->atge_chip_state & ATGE_CHIP_RUNNING) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyeratge_m_propinfo(void *arg, const char *name, mac_prop_id_t num,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mii_m_propinfo(atgep->atge_mii, name, num, prh);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Reprogram the Station address.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ((e[2] << 24) | (e[3] << 16) | (e[4] << 8) | e[5]));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Device specific operations.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Reprogram the Station address.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_DB(("%s: %s() dma, counters programmed ", atgep->atge_name,
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Disable interrupt re-trigger timer. We don't want automatic
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * re-triggering of un-ACKed interrupts.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills OUTL(atgep, ATGE_INTR_RETRIG_TIMER, ATGE_USECS(0));
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Configure CMB. */
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Hardware can be configured to issue SMB interrupt based
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * on programmed interval. Since there is a callout that is
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * invoked for every hz in driver we use that instead of
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * relying on periodic SMB interrupt.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Clear MAC statistics. */
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra * Set Maximum frame size but don't let MTU be less than ETHER_MTU.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_max_frame_size += sizeof (struct ether_header) +
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra OUTL(atgep, ATGE_FRAME_SIZE, atgep->atge_max_frame_size);
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Disable header split(?) */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Configure IPG/IFG parameters.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ((IPG_IFG_IPG2_DEFAULT << IPG_IFG_IPG2_SHIFT) & IPG_IFG_IPG2_MASK) |
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ((IPG_IFG_IPG1_DEFAULT << IPG_IFG_IPG1_SHIFT) & IPG_IFG_IPG1_MASK) |
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ((IPG_IFG_MIFG_DEFAULT << IPG_IFG_MIFG_SHIFT) & IPG_IFG_MIFG_MASK) |
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ((IPG_IFG_IPGT_DEFAULT << IPG_IFG_IPGT_SHIFT) & IPG_IFG_IPGT_MASK));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Set parameters for half-duplex media.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ((HDPX_CFG_LCOL_DEFAULT << HDPX_CFG_LCOL_SHIFT) &
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ((HDPX_CFG_RETRY_DEFAULT << HDPX_CFG_RETRY_SHIFT) &
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ((HDPX_CFG_ABEBT_DEFAULT << HDPX_CFG_ABEBT_SHIFT) &
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ((HDPX_CFG_JAMIPG_DEFAULT << HDPX_CFG_JAMIPG_SHIFT) &
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Configure jumbo frame.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra fsize = ROUNDUP(atgep->atge_max_frame_size, sizeof (uint64_t));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra RXQ_JUMBO_CFG_LKAH_SHIFT) & RXQ_JUMBO_CFG_LKAH_MASK) |
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ((ATGE_USECS(8) << RXQ_JUMBO_CFG_RRD_TIMER_SHIFT) &
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Configure flow-control parameters.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Some hardware version require this magic.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * These are all magic parameters which came from FreeBSD.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Configure flow control parameters.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * XON : 80% of Rx FIFO
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * XOFF : 30% of Rx FIFO
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Configure RxQ. */
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills reg = RXQ_CFG_ALIGN_32 | RXQ_CFG_CUT_THROUGH_ENB |
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Configure TxQ.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills (atgep->atge_dma_rd_burst >> DMA_CFG_RD_BURST_SHIFT)) <<
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills reg |= (TXQ_CFG_TPD_BURST_DEFAULT << TXQ_CFG_TPD_BURST_SHIFT) &
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Disable RSS. */
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Configure DMA parameters.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Don't use Tx CMB. It is known to cause RRS update failure
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * under certain circumstances. Typical phenomenon of the
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * issue would be unexpected sequence number encountered in
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Rx handler. Hence we don't set DMA_CFG_TXCMB_ENB.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills DMA_CFG_OUT_ORDER | DMA_CFG_RD_REQ_PRI | DMA_CFG_RCB_64 |
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills atgep->atge_dma_rd_burst | atgep->atge_dma_wr_burst |
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills DMA_CFG_RD_DELAY_CNT_SHIFT) & DMA_CFG_RD_DELAY_CNT_MASK) |
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills DMA_CFG_WR_DELAY_CNT_SHIFT) & DMA_CFG_WR_DELAY_CNT_MASK));
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Enable CMB/SMB timer.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Configure RxQ. */
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra ((RXQ_CFG_RD_BURST_DEFAULT << RXQ_CFG_RD_BURST_SHIFT) &
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Configure TxQ.
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra (((TXQ_CFG_TPD_BURST_DEFAULT << TXQ_CFG_TPD_BURST_SHIFT) &
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Jumbo frames */
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra (((fsize / sizeof (uint64_t) << TX_JUMBO_TPD_TH_SHIFT)) &
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra ((TX_JUMBO_TPD_IPG_DEFAULT << TX_JUMBO_TPD_IPG_SHIFT) &
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Configure DMA parameters.
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra /* Configure CMB DMA write threshold. */
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra ((CMB_WR_THRESH_RRD_DEFAULT << CMB_WR_THRESH_RRD_SHIFT) &
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra ((CMB_WR_THRESH_TPD_DEFAULT << CMB_WR_THRESH_TPD_SHIFT) &
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Enable CMB/SMB timer.
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra /* Set CMB/SMB timer and enable them. */
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra /* Request SMB updates for every seconds. */
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra OUTL(atgep, L1_SMB_TIMER, ATGE_USECS(1000 * 1000));
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Configure RxQ. */
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills RXQ_CFG_RD_BURST_DEFAULT << L1C_RXQ_CFG_RD_BURST_SHIFT |
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills if ((atgep->atge_flags & ATGE_FLAG_ASPM_MON) != 0)
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Configure TxQ.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills (atgep->atge_dma_rd_burst >> DMA_CFG_RD_BURST_SHIFT)) <<
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills TXQ_CFG_TPD_BURST_SHIFT) & TXQ_CFG_TPD_BURST_MASK;
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Disable RSS until I understand L1C/L2C's RSS logic. */
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Configure DMA parameters.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills DMA_CFG_OUT_ORDER | DMA_CFG_RD_REQ_PRI | DMA_CFG_RCB_64 |
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills DMA_CFG_RD_DELAY_CNT_DEFAULT << DMA_CFG_RD_DELAY_CNT_SHIFT |
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills DMA_CFG_WR_DELAY_CNT_DEFAULT << DMA_CFG_WR_DELAY_CNT_SHIFT |
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Configure CMB DMA write threshold not required. */
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Set CMB/SMB timer and enable them not required. */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Disable all WOL bits as WOL can interfere normal Rx
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Configure Tx/Rx MACs.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * - Auto-padding for short frames.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * - Enable CRC generation.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Start with full-duplex/1000Mbps media. Actual reconfiguration
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * of MAC is followed after link establishment.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra reg = (ATGE_CFG_TX_CRC_ENB | ATGE_CFG_TX_AUTO_PAD |
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ((ATGE_CFG_PREAMBLE_DEFAULT << ATGE_CFG_PREAMBLE_SHIFT) &
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * AR813x/AR815x always does checksum computation regardless
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * of MAC_CFG_RXCSUM_ENB bit. Also the controller is known to
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * have bug in protocol field in Rx return structure so
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * these controllers can't handle fragmented frames. Disable
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Rx checksum offloading until there is a newer controller
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * that has sane implementation.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills reg |= ATGE_CFG_HASH_ALG_CRC32 | ATGE_CFG_SPEED_MODE_SW;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if ((atgep->atge_flags & ATGE_FLAG_FASTETHER) != 0) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_DB(("%s: %s() Fast Ethernet", atgep->atge_name, __func__));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_DB(("%s: %s() 1G speed", atgep->atge_name, __func__));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Set up the receive filter.
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra * Acknowledge all pending interrupts and clear it.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_DB(("%s: %s() device started", atgep->atge_name, __func__));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Generic functions.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra for (data = *addr++, bit = 0; bit < 8; bit++, data >>= 1) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ^ ((((crc >> 31) ^ data) & 1) ? CRC32_POLY_BE : 0);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Programs RX filter. We use a link-list to keep track of all multicast
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * addressess.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra rxcfg &= ~(ATGE_CFG_ALLMULTI | ATGE_CFG_PROMISC);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Accept broadcast frames.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * We don't use Hardware VLAN tagging.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if (atgep->atge_filter_flags & (ATGE_PROMISC | ATGE_ALL_MULTICST)) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if (atgep->atge_filter_flags & ATGE_ALL_MULTICST)
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra OUTL(atgep, ATGE_MAR1, (uint32_t)(mchash >> 32));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_DB(("%s: %s() mac_cfg is : %x, mchash : %llx",
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * If the chip is being suspended, then don't touch the state. Caller
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * will take care of setting the correct state.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if (!(atgep->atge_chip_state & ATGE_CHIP_SUSPENDED)) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Collect stats for L1E. L1 chip's stats are collected by interrupt.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Disable interrupts.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Clear CTRL not required. */
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Stop DMA Engine not required. */
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Disable queue processing.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Stop TxQ */
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Stop RxQ */
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Stop DMA */
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills reg = reg & ~(DMA_CFG_TXCMB_ENB | DMA_CFG_RXCMB_ENB);
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Clear CTRL. */
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Stop DMA Engine */
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Disable queue processing.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Stop TxQ */
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Stop RxQ */
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Clear CTRL not required. */
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Stop DMA Engine */
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Disable queue processing.
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Stop TxQ */
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Stop RxQ */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra for (t = ATGE_RESET_TIMEOUT; t > 0; t--) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if ((reg = INL(atgep, ATGE_IDLE_STATUS)) == 0)
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if (t == 0) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atge_error(atgep->atge_dip, "%s() stopping TX/RX MAC timeout",
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra atgep->atge_intrs = L1_INTRS | INTR_GPHY | INTR_PHY_LINK_DOWN |
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills /* Enable all clocks. */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Cancel any pending I/O.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Reset the chip to a known state.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Initialize the ring and other descriptor like CMB/SMB/Rx return.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Start the chip.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_DB(("%s: %s() pktlen (%d) > rx_buf_len (%d)",
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Get the DMA buffer to hold a packet.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Copy the msg and free mp
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills ATGE_PUT32(r->r_desc_ring, &txd->len, L1C_TX_BYTES(pktlen));
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills ATGE_PUT32(r->r_desc_ring, &txd->len, ATGE_TX_BYTES(pktlen));
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra * Sync buffer first.
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra DMA_SYNC(r->r_buf_tbl[start], 0, pktlen, DDI_DMA_SYNC_FORDEV);
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra * Increment TX producer count by one.
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra ATGE_INC_SLOT(r->r_producer, ATGE_TX_RING_CNT);
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra * Sync descriptor table.
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra DMA_SYNC(r->r_desc_ring, 0, ATGE_TX_RING_SZ, DDI_DMA_SYNC_FORDEV);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Program TX descriptor to send a packet.
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra ATGE_DB(("%s: %s() pktlen : %d, avail_desc : %d, producer :%d, "
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra "consumer : %d", atgep->atge_name, __func__, pktlen,
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra r->r_avail_desc, r->r_producer, r->r_consumer));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Stream Information.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh MisraDDI_DEFINE_STREAM_OPS(atge_devops, nulldev, nulldev, atge_attach, atge_detach,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Module linkage information.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra "Atheros/Attansic Gb Ethernet", /* Description */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * DDI Entry points.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if ((r = mod_install(&atge_modlinkage)) != DDI_SUCCESS) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if ((r = mod_remove(&atge_modlinkage)) == DDI_SUCCESS) {