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 /*
235e8715b9SGary Mills * Copyright (c) 2012 Gary Mills
245e8715b9SGary Mills *
259d8d9e11SGarrett D'Amore * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
26*80e3e236SJohn Levon *
27*80e3e236SJohn Levon * Copyright (c) 2018, Joyent, Inc.
28015a6ef6SSaurabh Misra */
295e8715b9SGary Mills /*
305e8715b9SGary Mills * Copyright (c) 2009, Pyun YongHyeon <yongari@FreeBSD.org>
315e8715b9SGary Mills * All rights reserved.
325e8715b9SGary Mills *
335e8715b9SGary Mills * Redistribution and use in source and binary forms, with or without
345e8715b9SGary Mills * modification, are permitted provided that the following conditions
355e8715b9SGary Mills * are met:
365e8715b9SGary Mills * 1. Redistributions of source code must retain the above copyright
375e8715b9SGary Mills * notice unmodified, this list of conditions, and the following
385e8715b9SGary Mills * disclaimer.
395e8715b9SGary Mills * 2. Redistributions in binary form must reproduce the above copyright
405e8715b9SGary Mills * notice, this list of conditions and the following disclaimer in the
415e8715b9SGary Mills * documentation and/or other materials provided with the distribution.
425e8715b9SGary Mills *
435e8715b9SGary Mills * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
445e8715b9SGary Mills * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
455e8715b9SGary Mills * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
465e8715b9SGary Mills * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
475e8715b9SGary Mills * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
485e8715b9SGary Mills * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
495e8715b9SGary Mills * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
505e8715b9SGary Mills * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
515e8715b9SGary Mills * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
525e8715b9SGary Mills * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
535e8715b9SGary Mills * SUCH DAMAGE.
545e8715b9SGary Mills */
55015a6ef6SSaurabh Misra
56015a6ef6SSaurabh Misra #include <sys/types.h>
57015a6ef6SSaurabh Misra #include <sys/stream.h>
58015a6ef6SSaurabh Misra #include <sys/strsun.h>
59015a6ef6SSaurabh Misra #include <sys/stat.h>
60015a6ef6SSaurabh Misra #include <sys/modctl.h>
61015a6ef6SSaurabh Misra #include <sys/kstat.h>
62015a6ef6SSaurabh Misra #include <sys/ethernet.h>
63015a6ef6SSaurabh Misra #include <sys/devops.h>
64015a6ef6SSaurabh Misra #include <sys/debug.h>
65015a6ef6SSaurabh Misra #include <sys/conf.h>
66015a6ef6SSaurabh Misra #include <sys/mii.h>
67015a6ef6SSaurabh Misra #include <sys/miiregs.h>
68015a6ef6SSaurabh Misra #include <sys/mac.h>
69015a6ef6SSaurabh Misra #include <sys/mac_provider.h>
70015a6ef6SSaurabh Misra #include <sys/mac_ether.h>
71015a6ef6SSaurabh Misra #include <sys/sysmacros.h>
72015a6ef6SSaurabh Misra #include <sys/dditypes.h>
73015a6ef6SSaurabh Misra #include <sys/ddi.h>
74015a6ef6SSaurabh Misra #include <sys/sunddi.h>
75015a6ef6SSaurabh Misra #include <sys/byteorder.h>
76015a6ef6SSaurabh Misra #include <sys/note.h>
77015a6ef6SSaurabh Misra #include <sys/vlan.h>
78015a6ef6SSaurabh Misra #include <sys/strsubr.h>
79015a6ef6SSaurabh Misra #include <sys/crc32.h>
80015a6ef6SSaurabh Misra #include <sys/sdt.h>
81015a6ef6SSaurabh Misra #include <sys/pci.h>
82015a6ef6SSaurabh Misra #include <sys/pci_cap.h>
83015a6ef6SSaurabh Misra
84015a6ef6SSaurabh Misra #include "atge.h"
85015a6ef6SSaurabh Misra #include "atge_cmn_reg.h"
865e8715b9SGary Mills #include "atge_l1c_reg.h"
87015a6ef6SSaurabh Misra #include "atge_l1e_reg.h"
880eb090a7SSaurabh Misra #include "atge_l1_reg.h"
89015a6ef6SSaurabh Misra
90015a6ef6SSaurabh Misra
91015a6ef6SSaurabh Misra /*
925e8715b9SGary Mills * Atheros/Attansic Ethernet chips are of four types - L1, L2, L1E and L1C.
935e8715b9SGary Mills * This driver is for L1E/L1/L1C but can be extended to support other chips.
940eb090a7SSaurabh Misra * L1E comes in 1Gigabit and Fast Ethernet flavors. L1 comes in 1Gigabit
955e8715b9SGary Mills * flavors only. L1C comes in both flavours.
96015a6ef6SSaurabh Misra *
97015a6ef6SSaurabh Misra * Atheros/Attansic Ethernet controllers have descriptor based TX and RX
98015a6ef6SSaurabh Misra * with an exception of L1E. L1E's RX side is not descriptor based ring.
99015a6ef6SSaurabh Misra * The L1E's RX uses pages (not to be confused with MMU pages) for
100015a6ef6SSaurabh Misra * receiving pkts. The header has four fields :
101015a6ef6SSaurabh Misra *
102015a6ef6SSaurabh Misra * uint32_t seqno; Sequence number of the frame.
103015a6ef6SSaurabh Misra * uint32_t length; Length of the frame.
104015a6ef6SSaurabh Misra * uint32_t flags; Flags
105015a6ef6SSaurabh Misra * uint32_t vtag; We don't use hardware VTAG.
106015a6ef6SSaurabh Misra *
107015a6ef6SSaurabh Misra * We use only one queue for RX (each queue can have two pages) and each
108015a6ef6SSaurabh Misra * page is L1E_RX_PAGE_SZ large in bytes. That's the reason we don't
109015a6ef6SSaurabh Misra * use zero-copy RX because we are limited to two pages and each page
110015a6ef6SSaurabh Misra * accomodates large number of pkts.
111015a6ef6SSaurabh Misra *
112015a6ef6SSaurabh Misra * The TX side on all three chips is descriptor based ring; and all the
113015a6ef6SSaurabh Misra * more reason to have one driver for these chips.
114015a6ef6SSaurabh Misra *
115015a6ef6SSaurabh Misra * We use two locks - atge_intr_lock and atge_tx_lock. Both the locks
116015a6ef6SSaurabh Misra * should be held if the operation has impact on the driver instance.
117015a6ef6SSaurabh Misra *
118015a6ef6SSaurabh Misra * All the three chips have hash-based multicast filter.
119015a6ef6SSaurabh Misra *
120015a6ef6SSaurabh Misra * We use CMB (Coalescing Message Block) for RX but not for TX as there
121015a6ef6SSaurabh Misra * are some issues with TX. RX CMB is used to get the last descriptor
122015a6ef6SSaurabh Misra * posted by the chip. Each CMB is for a RX page (one queue can have two
123015a6ef6SSaurabh Misra * pages) and are uint32_t (4 bytes) long.
124015a6ef6SSaurabh Misra *
125015a6ef6SSaurabh Misra * The descriptor table should have 32-bit physical address limit due to
126015a6ef6SSaurabh Misra * the limitation of having same high address for TX/RX/SMB/CMB. The
127015a6ef6SSaurabh Misra * TX/RX buffers can be 64-bit.
128015a6ef6SSaurabh Misra *
129015a6ef6SSaurabh Misra * Every DMA memory in atge is represented by atge_dma_t be it TX/RX Buffers
130015a6ef6SSaurabh Misra * or TX/RX descriptor table or SMB/CMB. To keep the code simple, we have
131015a6ef6SSaurabh Misra * kept sgl as 1 so that we get contingous pages from root complex.
1320eb090a7SSaurabh Misra *
1330eb090a7SSaurabh Misra * L1 chip (0x1048) uses descriptor based TX and RX ring. Most of registers are
1340eb090a7SSaurabh Misra * common with L1E chip (0x1026).
135015a6ef6SSaurabh Misra */
136015a6ef6SSaurabh Misra
137015a6ef6SSaurabh Misra /*
138015a6ef6SSaurabh Misra * Function Prototypes for debugging.
139015a6ef6SSaurabh Misra */
140015a6ef6SSaurabh Misra void atge_error(dev_info_t *, char *, ...);
141015a6ef6SSaurabh Misra void atge_debug_func(char *, ...);
142015a6ef6SSaurabh Misra
143015a6ef6SSaurabh Misra /*
144015a6ef6SSaurabh Misra * Function Prototypes for driver operations.
145015a6ef6SSaurabh Misra */
146015a6ef6SSaurabh Misra static int atge_resume(dev_info_t *);
147015a6ef6SSaurabh Misra static int atge_add_intr(atge_t *);
148015a6ef6SSaurabh Misra static int atge_alloc_dma(atge_t *);
149015a6ef6SSaurabh Misra static void atge_remove_intr(atge_t *);
150015a6ef6SSaurabh Misra static void atge_free_dma(atge_t *);
151015a6ef6SSaurabh Misra static void atge_device_reset(atge_t *);
152015a6ef6SSaurabh Misra static void atge_device_init(atge_t *);
153015a6ef6SSaurabh Misra static void atge_device_start(atge_t *);
154015a6ef6SSaurabh Misra static void atge_disable_intrs(atge_t *);
155015a6ef6SSaurabh Misra atge_dma_t *atge_alloc_a_dma_blk(atge_t *, ddi_dma_attr_t *, int, int);
156015a6ef6SSaurabh Misra void atge_free_a_dma_blk(atge_dma_t *);
157015a6ef6SSaurabh Misra static void atge_rxfilter(atge_t *);
158015a6ef6SSaurabh Misra static void atge_device_reset_l1_l1e(atge_t *);
159015a6ef6SSaurabh Misra void atge_program_ether(atge_t *atgep);
160015a6ef6SSaurabh Misra void atge_device_restart(atge_t *);
1610eb090a7SSaurabh Misra void atge_device_stop(atge_t *);
162015a6ef6SSaurabh Misra static int atge_send_a_packet(atge_t *, mblk_t *);
163015a6ef6SSaurabh Misra static uint32_t atge_ether_crc(const uint8_t *, int);
164015a6ef6SSaurabh Misra
165015a6ef6SSaurabh Misra
166015a6ef6SSaurabh Misra /*
1670eb090a7SSaurabh Misra * L1E/L2E specific functions.
168015a6ef6SSaurabh Misra */
169015a6ef6SSaurabh Misra void atge_l1e_device_reset(atge_t *);
170015a6ef6SSaurabh Misra void atge_l1e_stop_mac(atge_t *);
171015a6ef6SSaurabh Misra int atge_l1e_alloc_dma(atge_t *);
172015a6ef6SSaurabh Misra void atge_l1e_free_dma(atge_t *);
173015a6ef6SSaurabh Misra void atge_l1e_init_tx_ring(atge_t *);
174015a6ef6SSaurabh Misra void atge_l1e_init_rx_pages(atge_t *);
175015a6ef6SSaurabh Misra void atge_l1e_program_dma(atge_t *);
1760eb090a7SSaurabh Misra void atge_l1e_send_packet(atge_ring_t *);
177015a6ef6SSaurabh Misra mblk_t *atge_l1e_receive(atge_t *);
1780eb090a7SSaurabh Misra uint_t atge_l1e_interrupt(caddr_t, caddr_t);
179015a6ef6SSaurabh Misra void atge_l1e_gather_stats(atge_t *);
180015a6ef6SSaurabh Misra void atge_l1e_clear_stats(atge_t *);
181015a6ef6SSaurabh Misra
1820eb090a7SSaurabh Misra /*
1830eb090a7SSaurabh Misra * L1 specific functions.
1840eb090a7SSaurabh Misra */
1850eb090a7SSaurabh Misra int atge_l1_alloc_dma(atge_t *);
1865e8715b9SGary Mills void atge_l1_free_dma(atge_t *);
1870eb090a7SSaurabh Misra void atge_l1_init_tx_ring(atge_t *);
1880eb090a7SSaurabh Misra void atge_l1_init_rx_ring(atge_t *);
1890eb090a7SSaurabh Misra void atge_l1_init_rr_ring(atge_t *);
1900eb090a7SSaurabh Misra void atge_l1_init_cmb(atge_t *);
1910eb090a7SSaurabh Misra void atge_l1_init_smb(atge_t *);
1920eb090a7SSaurabh Misra void atge_l1_program_dma(atge_t *);
1930eb090a7SSaurabh Misra void atge_l1_stop_tx_mac(atge_t *);
1940eb090a7SSaurabh Misra void atge_l1_stop_rx_mac(atge_t *);
1950eb090a7SSaurabh Misra uint_t atge_l1_interrupt(caddr_t, caddr_t);
1960eb090a7SSaurabh Misra void atge_l1_send_packet(atge_ring_t *);
1970eb090a7SSaurabh Misra
1985e8715b9SGary Mills /*
1995e8715b9SGary Mills * L1C specific functions.
2005e8715b9SGary Mills */
2015e8715b9SGary Mills int atge_l1c_alloc_dma(atge_t *);
2025e8715b9SGary Mills void atge_l1c_free_dma(atge_t *);
2035e8715b9SGary Mills void atge_l1c_init_tx_ring(atge_t *);
2045e8715b9SGary Mills void atge_l1c_init_rx_ring(atge_t *);
2055e8715b9SGary Mills void atge_l1c_init_rr_ring(atge_t *);
2065e8715b9SGary Mills void atge_l1c_init_cmb(atge_t *);
2075e8715b9SGary Mills void atge_l1c_init_smb(atge_t *);
2085e8715b9SGary Mills void atge_l1c_program_dma(atge_t *);
2095e8715b9SGary Mills void atge_l1c_stop_tx_mac(atge_t *);
2105e8715b9SGary Mills void atge_l1c_stop_rx_mac(atge_t *);
2115e8715b9SGary Mills uint_t atge_l1c_interrupt(caddr_t, caddr_t);
2125e8715b9SGary Mills void atge_l1c_send_packet(atge_ring_t *);
2135e8715b9SGary Mills void atge_l1c_gather_stats(atge_t *);
2145e8715b9SGary Mills void atge_l1c_clear_stats(atge_t *);
2150eb090a7SSaurabh Misra
216015a6ef6SSaurabh Misra /*
217015a6ef6SSaurabh Misra * Function prototyps for MII operations.
218015a6ef6SSaurabh Misra */
219015a6ef6SSaurabh Misra uint16_t atge_mii_read(void *, uint8_t, uint8_t);
220015a6ef6SSaurabh Misra void atge_mii_write(void *, uint8_t, uint8_t, uint16_t);
2215e8715b9SGary Mills uint16_t atge_l1c_mii_read(void *, uint8_t, uint8_t);
2225e8715b9SGary Mills void atge_l1c_mii_write(void *, uint8_t, uint8_t, uint16_t);
223015a6ef6SSaurabh Misra void atge_l1e_mii_reset(void *);
2240eb090a7SSaurabh Misra void atge_l1_mii_reset(void *);
2255e8715b9SGary Mills void atge_l1c_mii_reset(void *);
226015a6ef6SSaurabh Misra static void atge_mii_notify(void *, link_state_t);
2270eb090a7SSaurabh Misra void atge_tx_reclaim(atge_t *atgep, int cons);
228015a6ef6SSaurabh Misra
2290eb090a7SSaurabh Misra /*
2300eb090a7SSaurabh Misra * L1E/L2E chip.
2310eb090a7SSaurabh Misra */
232015a6ef6SSaurabh Misra static mii_ops_t atge_l1e_mii_ops = {
233015a6ef6SSaurabh Misra MII_OPS_VERSION,
234015a6ef6SSaurabh Misra atge_mii_read,
235015a6ef6SSaurabh Misra atge_mii_write,
236015a6ef6SSaurabh Misra atge_mii_notify,
237015a6ef6SSaurabh Misra atge_l1e_mii_reset
238015a6ef6SSaurabh Misra };
239015a6ef6SSaurabh Misra
2400eb090a7SSaurabh Misra /*
2410eb090a7SSaurabh Misra * L1 chip.
2420eb090a7SSaurabh Misra */
2430eb090a7SSaurabh Misra static mii_ops_t atge_l1_mii_ops = {
2440eb090a7SSaurabh Misra MII_OPS_VERSION,
2450eb090a7SSaurabh Misra atge_mii_read,
2460eb090a7SSaurabh Misra atge_mii_write,
2470eb090a7SSaurabh Misra atge_mii_notify,
2480eb090a7SSaurabh Misra atge_l1_mii_reset
2490eb090a7SSaurabh Misra };
2500eb090a7SSaurabh Misra
2515e8715b9SGary Mills /*
2525e8715b9SGary Mills * L1C chip.
2535e8715b9SGary Mills */
2545e8715b9SGary Mills static mii_ops_t atge_l1c_mii_ops = {
2555e8715b9SGary Mills MII_OPS_VERSION,
2565e8715b9SGary Mills atge_l1c_mii_read,
2575e8715b9SGary Mills atge_l1c_mii_write,
2585e8715b9SGary Mills atge_mii_notify,
2595e8715b9SGary Mills NULL
2605e8715b9SGary Mills };
2615e8715b9SGary Mills
262015a6ef6SSaurabh Misra /*
263015a6ef6SSaurabh Misra * Function Prototypes for MAC callbacks.
264015a6ef6SSaurabh Misra */
265015a6ef6SSaurabh Misra static int atge_m_stat(void *, uint_t, uint64_t *);
266015a6ef6SSaurabh Misra static int atge_m_start(void *);
267015a6ef6SSaurabh Misra static void atge_m_stop(void *);
268015a6ef6SSaurabh Misra static int atge_m_getprop(void *, const char *, mac_prop_id_t, uint_t,
2690dc2366fSVenugopal Iyer void *);
270015a6ef6SSaurabh Misra static int atge_m_setprop(void *, const char *, mac_prop_id_t, uint_t,
271015a6ef6SSaurabh Misra const void *);
2720dc2366fSVenugopal Iyer static void atge_m_propinfo(void *, const char *, mac_prop_id_t,
2730dc2366fSVenugopal Iyer mac_prop_info_handle_t);
274015a6ef6SSaurabh Misra static int atge_m_unicst(void *, const uint8_t *);
275015a6ef6SSaurabh Misra static int atge_m_multicst(void *, boolean_t, const uint8_t *);
276015a6ef6SSaurabh Misra static int atge_m_promisc(void *, boolean_t);
277015a6ef6SSaurabh Misra static mblk_t *atge_m_tx(void *, mblk_t *);
278015a6ef6SSaurabh Misra
279015a6ef6SSaurabh Misra static mac_callbacks_t atge_m_callbacks = {
2800dc2366fSVenugopal Iyer MC_SETPROP | MC_GETPROP | MC_PROPINFO,
281015a6ef6SSaurabh Misra atge_m_stat,
282015a6ef6SSaurabh Misra atge_m_start,
283015a6ef6SSaurabh Misra atge_m_stop,
284015a6ef6SSaurabh Misra atge_m_promisc,
285015a6ef6SSaurabh Misra atge_m_multicst,
286015a6ef6SSaurabh Misra atge_m_unicst,
287015a6ef6SSaurabh Misra atge_m_tx,
2880dc2366fSVenugopal Iyer NULL, /* mc_reserved */
289015a6ef6SSaurabh Misra NULL, /* mc_ioctl */
290015a6ef6SSaurabh Misra NULL, /* mc_getcapab */
291015a6ef6SSaurabh Misra NULL, /* mc_open */
292015a6ef6SSaurabh Misra NULL, /* mc_close */
293015a6ef6SSaurabh Misra atge_m_setprop,
294015a6ef6SSaurabh Misra atge_m_getprop,
2950dc2366fSVenugopal Iyer atge_m_propinfo
296015a6ef6SSaurabh Misra };
297015a6ef6SSaurabh Misra
298015a6ef6SSaurabh Misra /*
299015a6ef6SSaurabh Misra * DMA Data access requirements.
300015a6ef6SSaurabh Misra */
301015a6ef6SSaurabh Misra static struct ddi_device_acc_attr atge_dev_attr = {
302015a6ef6SSaurabh Misra DDI_DEVICE_ATTR_V0,
303015a6ef6SSaurabh Misra DDI_STRUCTURE_LE_ACC,
304015a6ef6SSaurabh Misra DDI_STRICTORDER_ACC
305015a6ef6SSaurabh Misra };
306015a6ef6SSaurabh Misra
307015a6ef6SSaurabh Misra /*
308015a6ef6SSaurabh Misra * Buffers should be native endianness.
309015a6ef6SSaurabh Misra */
310015a6ef6SSaurabh Misra static struct ddi_device_acc_attr atge_buf_attr = {
311015a6ef6SSaurabh Misra DDI_DEVICE_ATTR_V0,
312015a6ef6SSaurabh Misra DDI_NEVERSWAP_ACC, /* native endianness */
313015a6ef6SSaurabh Misra DDI_STRICTORDER_ACC
314015a6ef6SSaurabh Misra };
315015a6ef6SSaurabh Misra
316015a6ef6SSaurabh Misra /*
3170eb090a7SSaurabh Misra * DMA device attributes. Buffer can be 64-bit.
318015a6ef6SSaurabh Misra */
319015a6ef6SSaurabh Misra static ddi_dma_attr_t atge_dma_attr_buf = {
320015a6ef6SSaurabh Misra DMA_ATTR_V0, /* dma_attr_version */
321015a6ef6SSaurabh Misra 0, /* dma_attr_addr_lo */
322015a6ef6SSaurabh Misra 0x00ffffffffffull, /* dma_attr_addr_hi */
323015a6ef6SSaurabh Misra 0x000000003fffull, /* dma_attr_count_max */
324015a6ef6SSaurabh Misra 8, /* dma_attr_align */
325015a6ef6SSaurabh Misra 0x00003ffc, /* dma_attr_burstsizes */
326015a6ef6SSaurabh Misra 1, /* dma_attr_minxfer */
327015a6ef6SSaurabh Misra 0x0000000027ffull, /* dma_attr_maxxfer */
328015a6ef6SSaurabh Misra 0x0000ffffffffull, /* dma_attr_seg */
329015a6ef6SSaurabh Misra 1, /* dma_attr_sgllen */
330015a6ef6SSaurabh Misra 1, /* dma_attr_granular */
331015a6ef6SSaurabh Misra 0 /* dma_attr_flags */
332015a6ef6SSaurabh Misra };
333015a6ef6SSaurabh Misra
334015a6ef6SSaurabh Misra /*
335015a6ef6SSaurabh Misra * Table of supported devices.
336015a6ef6SSaurabh Misra */
337015a6ef6SSaurabh Misra #define ATGE_VENDOR_ID 0x1969
3385e8715b9SGary Mills #define ATGE_L1_STR "Attansic L1"
3395e8715b9SGary Mills #define ATGE_L1CG_STR "Atheros AR8131 Gigabit Ethernet"
3405e8715b9SGary Mills #define ATGE_L1CF_STR "Atheros AR8132 Fast Ethernet"
341015a6ef6SSaurabh Misra #define ATGE_L1E_STR "Atheros AR8121/8113/8114"
3425e8715b9SGary Mills #define ATGE_AR8151V1_STR "Atheros AR8151 v1.0 Gigabit Ethernet"
3435e8715b9SGary Mills #define ATGE_AR8151V2_STR "Atheros AR8151 v2.0 Gigabit Ethernet"
3445e8715b9SGary Mills #define ATGE_AR8152V1_STR "Atheros AR8152 v1.1 Fast Ethernet"
3455e8715b9SGary Mills #define ATGE_AR8152V2_STR "Atheros AR8152 v2.0 Fast Ethernet"
346015a6ef6SSaurabh Misra
347015a6ef6SSaurabh Misra static atge_cards_t atge_cards[] = {
3485e8715b9SGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_AR8151V2_DEV_ID, ATGE_AR8151V2_STR,
3495e8715b9SGary Mills ATGE_CHIP_L1C},
3505e8715b9SGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_AR8151V1_DEV_ID, ATGE_AR8151V1_STR,
3515e8715b9SGary Mills ATGE_CHIP_L1C},
3525e8715b9SGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_AR8152V2_DEV_ID, ATGE_AR8152V2_STR,
3535e8715b9SGary Mills ATGE_CHIP_L1C},
3545e8715b9SGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_AR8152V1_DEV_ID, ATGE_AR8152V1_STR,
3555e8715b9SGary Mills ATGE_CHIP_L1C},
3565e8715b9SGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_L1CG_DEV_ID, ATGE_L1CG_STR, ATGE_CHIP_L1C},
3575e8715b9SGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_L1CF_DEV_ID, ATGE_L1CF_STR, ATGE_CHIP_L1C},
358015a6ef6SSaurabh Misra {ATGE_VENDOR_ID, ATGE_CHIP_L1E_DEV_ID, ATGE_L1E_STR, ATGE_CHIP_L1E},
3595e8715b9SGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_L1_DEV_ID, ATGE_L1_STR, ATGE_CHIP_L1},
360015a6ef6SSaurabh Misra };
361015a6ef6SSaurabh Misra
362015a6ef6SSaurabh Misra /*
363015a6ef6SSaurabh Misra * Global Debugging flag. Developer level debugging is done only in DEBUG mode.
364015a6ef6SSaurabh Misra */
365015a6ef6SSaurabh Misra int atge_debug = 1;
366015a6ef6SSaurabh Misra
367015a6ef6SSaurabh Misra /*
368015a6ef6SSaurabh Misra * Debugging and error reporting.
369015a6ef6SSaurabh Misra */
370015a6ef6SSaurabh Misra void
atge_debug_func(char * fmt,...)371015a6ef6SSaurabh Misra atge_debug_func(char *fmt, ...)
372015a6ef6SSaurabh Misra {
373015a6ef6SSaurabh Misra va_list ap;
374015a6ef6SSaurabh Misra char buf[256];
375015a6ef6SSaurabh Misra
376015a6ef6SSaurabh Misra va_start(ap, fmt);
377015a6ef6SSaurabh Misra (void) vsnprintf(buf, sizeof (buf), fmt, ap);
378015a6ef6SSaurabh Misra va_end(ap);
379015a6ef6SSaurabh Misra
380015a6ef6SSaurabh Misra DTRACE_PROBE1(atge__debug, char *, buf);
381015a6ef6SSaurabh Misra }
382015a6ef6SSaurabh Misra
3835e8715b9SGary Mills static
384015a6ef6SSaurabh Misra void
atge_message(dev_info_t * dip,int level,char * fmt,va_list ap)3855e8715b9SGary Mills atge_message(dev_info_t *dip, int level, char *fmt, va_list ap)
386015a6ef6SSaurabh Misra {
387015a6ef6SSaurabh Misra char buf[256];
3885e8715b9SGary Mills char *p = "!%s%d: %s";
3895e8715b9SGary Mills char *q = "!atge: %s";
390015a6ef6SSaurabh Misra
391015a6ef6SSaurabh Misra (void) vsnprintf(buf, sizeof (buf), fmt, ap);
3925e8715b9SGary Mills
3935e8715b9SGary Mills if (level != CE_NOTE) {
3945e8715b9SGary Mills p++;
3955e8715b9SGary Mills q++;
3965e8715b9SGary Mills }
397015a6ef6SSaurabh Misra
398015a6ef6SSaurabh Misra if (dip) {
3995e8715b9SGary Mills cmn_err(level, p,
400015a6ef6SSaurabh Misra ddi_driver_name(dip), ddi_get_instance(dip), buf);
401015a6ef6SSaurabh Misra } else {
4025e8715b9SGary Mills cmn_err(level, q, buf);
403015a6ef6SSaurabh Misra }
404015a6ef6SSaurabh Misra }
405015a6ef6SSaurabh Misra
4065e8715b9SGary Mills void
atge_notice(dev_info_t * dip,char * fmt,...)4075e8715b9SGary Mills atge_notice(dev_info_t *dip, char *fmt, ...)
4085e8715b9SGary Mills {
4095e8715b9SGary Mills va_list ap;
4105e8715b9SGary Mills
4115e8715b9SGary Mills va_start(ap, fmt);
4125e8715b9SGary Mills (void) atge_message(dip, CE_NOTE, fmt, ap);
4135e8715b9SGary Mills va_end(ap);
4145e8715b9SGary Mills }
4155e8715b9SGary Mills
4165e8715b9SGary Mills void
atge_error(dev_info_t * dip,char * fmt,...)4175e8715b9SGary Mills atge_error(dev_info_t *dip, char *fmt, ...)
4185e8715b9SGary Mills {
4195e8715b9SGary Mills va_list ap;
4205e8715b9SGary Mills
4215e8715b9SGary Mills va_start(ap, fmt);
4225e8715b9SGary Mills (void) atge_message(dip, CE_WARN, fmt, ap);
4235e8715b9SGary Mills va_end(ap);
4245e8715b9SGary Mills }
4255e8715b9SGary Mills
426015a6ef6SSaurabh Misra void
atge_mac_config(atge_t * atgep)427015a6ef6SSaurabh Misra atge_mac_config(atge_t *atgep)
428015a6ef6SSaurabh Misra {
429015a6ef6SSaurabh Misra uint32_t reg;
430015a6ef6SSaurabh Misra int speed;
431015a6ef6SSaurabh Misra link_duplex_t ld;
432015a6ef6SSaurabh Misra
4335e8715b9SGary Mills /* Re-enable TX/RX MACs */
434015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_MAC_CFG);
435015a6ef6SSaurabh Misra reg &= ~(ATGE_CFG_FULL_DUPLEX | ATGE_CFG_TX_FC | ATGE_CFG_RX_FC |
436015a6ef6SSaurabh Misra ATGE_CFG_SPEED_MASK);
437015a6ef6SSaurabh Misra
4385e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
4395e8715b9SGary Mills case ATGE_CHIP_L1C:
4405e8715b9SGary Mills switch (ATGE_DID(atgep)) {
4415e8715b9SGary Mills case ATGE_CHIP_AR8151V2_DEV_ID:
4425e8715b9SGary Mills case ATGE_CHIP_AR8151V1_DEV_ID:
4435e8715b9SGary Mills case ATGE_CHIP_AR8152V2_DEV_ID:
4445e8715b9SGary Mills reg |= ATGE_CFG_HASH_ALG_CRC32 | ATGE_CFG_SPEED_MODE_SW;
4455e8715b9SGary Mills break;
4465e8715b9SGary Mills }
4475e8715b9SGary Mills break;
4485e8715b9SGary Mills }
4495e8715b9SGary Mills
450015a6ef6SSaurabh Misra speed = mii_get_speed(atgep->atge_mii);
451015a6ef6SSaurabh Misra switch (speed) {
452015a6ef6SSaurabh Misra case 10:
453015a6ef6SSaurabh Misra case 100:
454015a6ef6SSaurabh Misra reg |= ATGE_CFG_SPEED_10_100;
455015a6ef6SSaurabh Misra break;
456015a6ef6SSaurabh Misra case 1000:
457015a6ef6SSaurabh Misra reg |= ATGE_CFG_SPEED_1000;
458015a6ef6SSaurabh Misra break;
459015a6ef6SSaurabh Misra }
460015a6ef6SSaurabh Misra
461015a6ef6SSaurabh Misra ld = mii_get_duplex(atgep->atge_mii);
462015a6ef6SSaurabh Misra if (ld == LINK_DUPLEX_FULL)
463015a6ef6SSaurabh Misra reg |= ATGE_CFG_FULL_DUPLEX;
464015a6ef6SSaurabh Misra
465015a6ef6SSaurabh Misra /* Re-enable TX/RX MACs */
4665e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
4675e8715b9SGary Mills case ATGE_CHIP_L1E:
4680eb090a7SSaurabh Misra reg |= ATGE_CFG_TX_ENB | ATGE_CFG_RX_ENB | ATGE_CFG_RX_FC;
4695e8715b9SGary Mills break;
4705e8715b9SGary Mills case ATGE_CHIP_L1:
4715e8715b9SGary Mills case ATGE_CHIP_L1C:
4720eb090a7SSaurabh Misra reg |= ATGE_CFG_TX_ENB | ATGE_CFG_RX_ENB;
4735e8715b9SGary Mills break;
4740eb090a7SSaurabh Misra }
4750eb090a7SSaurabh Misra
476015a6ef6SSaurabh Misra OUTL(atgep, ATGE_MAC_CFG, reg);
477015a6ef6SSaurabh Misra
4785e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
4795e8715b9SGary Mills case ATGE_CHIP_L1E:
480015a6ef6SSaurabh Misra reg = ATGE_USECS(ATGE_IM_RX_TIMER_DEFAULT) << IM_TIMER_RX_SHIFT;
481015a6ef6SSaurabh Misra reg |= ATGE_USECS(ATGE_IM_TX_TIMER_DEFAULT) <<
482015a6ef6SSaurabh Misra IM_TIMER_TX_SHIFT;
483015a6ef6SSaurabh Misra OUTL(atgep, ATGE_IM_TIMER, reg);
4845e8715b9SGary Mills break;
4855e8715b9SGary Mills case ATGE_CHIP_L1:
4865e8715b9SGary Mills break;
4875e8715b9SGary Mills case ATGE_CHIP_L1C:
4885e8715b9SGary Mills /* Configure interrupt moderation timer. */
4895e8715b9SGary Mills reg = ATGE_USECS(atgep->atge_int_rx_mod) << IM_TIMER_RX_SHIFT;
4905e8715b9SGary Mills reg |= ATGE_USECS(atgep->atge_int_tx_mod) << IM_TIMER_TX_SHIFT;
4915e8715b9SGary Mills OUTL(atgep, ATGE_IM_TIMER, reg);
4925e8715b9SGary Mills /*
4935e8715b9SGary Mills * We don't want to automatic interrupt clear as task queue
4945e8715b9SGary Mills * for the interrupt should know interrupt status.
4955e8715b9SGary Mills */
4965e8715b9SGary Mills reg = 0;
4975e8715b9SGary Mills if (ATGE_USECS(atgep->atge_int_rx_mod) != 0)
4985e8715b9SGary Mills reg |= MASTER_IM_RX_TIMER_ENB;
4995e8715b9SGary Mills if (ATGE_USECS(atgep->atge_int_tx_mod) != 0)
5005e8715b9SGary Mills reg |= MASTER_IM_TX_TIMER_ENB;
5015e8715b9SGary Mills OUTL(atgep, ATGE_MASTER_CFG, reg);
5025e8715b9SGary Mills break;
503015a6ef6SSaurabh Misra }
504015a6ef6SSaurabh Misra
505015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() mac_cfg is : %x",
506015a6ef6SSaurabh Misra atgep->atge_name, __func__, INL(atgep, ATGE_MAC_CFG)));
507015a6ef6SSaurabh Misra }
508015a6ef6SSaurabh Misra
509015a6ef6SSaurabh Misra static void
atge_mii_notify(void * arg,link_state_t link)510015a6ef6SSaurabh Misra atge_mii_notify(void *arg, link_state_t link)
511015a6ef6SSaurabh Misra {
512015a6ef6SSaurabh Misra atge_t *atgep = arg;
513015a6ef6SSaurabh Misra
514015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() LINK STATUS CHANGED from %x -> %x",
515015a6ef6SSaurabh Misra atgep->atge_name, __func__, atgep->atge_link_state, link));
516015a6ef6SSaurabh Misra
517015a6ef6SSaurabh Misra mac_link_update(atgep->atge_mh, link);
518015a6ef6SSaurabh Misra
519015a6ef6SSaurabh Misra /*
520015a6ef6SSaurabh Misra * Reconfigure MAC if link status is UP now.
521015a6ef6SSaurabh Misra */
522015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock);
523015a6ef6SSaurabh Misra if (link == LINK_STATE_UP) {
524015a6ef6SSaurabh Misra atgep->atge_link_state = LINK_STATE_UP;
5250eb090a7SSaurabh Misra atge_mac_config(atgep);
526015a6ef6SSaurabh Misra atgep->atge_tx_resched = 0;
527015a6ef6SSaurabh Misra } else {
528015a6ef6SSaurabh Misra atgep->atge_link_state = LINK_STATE_DOWN;
5290eb090a7SSaurabh Misra atgep->atge_flags |= ATGE_MII_CHECK;
530015a6ef6SSaurabh Misra }
531015a6ef6SSaurabh Misra
532015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock);
533015a6ef6SSaurabh Misra
534015a6ef6SSaurabh Misra if (link == LINK_STATE_UP)
535015a6ef6SSaurabh Misra mac_tx_update(atgep->atge_mh);
536015a6ef6SSaurabh Misra }
537015a6ef6SSaurabh Misra
5380eb090a7SSaurabh Misra void
atge_tx_reclaim(atge_t * atgep,int end)5390eb090a7SSaurabh Misra atge_tx_reclaim(atge_t *atgep, int end)
540015a6ef6SSaurabh Misra {
5410eb090a7SSaurabh Misra atge_tx_desc_t *txd;
5420eb090a7SSaurabh Misra atge_ring_t *r = atgep->atge_tx_ring;
5430eb090a7SSaurabh Misra uchar_t *c;
5440eb090a7SSaurabh Misra int start;
545015a6ef6SSaurabh Misra
5460eb090a7SSaurabh Misra ASSERT(MUTEX_HELD(&atgep->atge_tx_lock));
5470eb090a7SSaurabh Misra ASSERT(r != NULL);
548015a6ef6SSaurabh Misra
5490eb090a7SSaurabh Misra start = r->r_consumer;
550015a6ef6SSaurabh Misra
5510eb090a7SSaurabh Misra if (start == end)
5520eb090a7SSaurabh Misra return;
553015a6ef6SSaurabh Misra
5540eb090a7SSaurabh Misra while (start != end) {
5550eb090a7SSaurabh Misra r->r_avail_desc++;
5560eb090a7SSaurabh Misra if (r->r_avail_desc > ATGE_TX_RING_CNT) {
557015a6ef6SSaurabh Misra
558015a6ef6SSaurabh Misra atge_error(atgep->atge_dip,
5590eb090a7SSaurabh Misra "Reclaim : TX descriptor error");
560015a6ef6SSaurabh Misra
5610eb090a7SSaurabh Misra if (r->r_avail_desc > (ATGE_TX_RING_CNT + 5)) {
562015a6ef6SSaurabh Misra atge_device_stop(atgep);
5630eb090a7SSaurabh Misra break;
564015a6ef6SSaurabh Misra }
565015a6ef6SSaurabh Misra }
566015a6ef6SSaurabh Misra
5670eb090a7SSaurabh Misra c = (uchar_t *)r->r_desc_ring->addr;
5680eb090a7SSaurabh Misra c += (sizeof (atge_tx_desc_t) * start);
5690eb090a7SSaurabh Misra txd = (atge_tx_desc_t *)c;
570015a6ef6SSaurabh Misra
5710eb090a7SSaurabh Misra /*
5720eb090a7SSaurabh Misra * Clearing TX descriptor helps in debugging some strange
5730eb090a7SSaurabh Misra * problems.
5740eb090a7SSaurabh Misra */
5750eb090a7SSaurabh Misra txd->addr = 0;
5760eb090a7SSaurabh Misra txd->len = 0;
5770eb090a7SSaurabh Misra txd->flags = 0;
578015a6ef6SSaurabh Misra
5790eb090a7SSaurabh Misra ATGE_INC_SLOT(start, ATGE_TX_RING_CNT);
580015a6ef6SSaurabh Misra }
581015a6ef6SSaurabh Misra
5820eb090a7SSaurabh Misra atgep->atge_tx_ring->r_consumer = start;
583015a6ef6SSaurabh Misra
5840eb090a7SSaurabh Misra DMA_SYNC(r->r_desc_ring, 0, ATGE_TX_RING_SZ, DDI_DMA_SYNC_FORDEV);
585015a6ef6SSaurabh Misra }
586015a6ef6SSaurabh Misra
587015a6ef6SSaurabh Misra /*
588015a6ef6SSaurabh Misra * Adds interrupt handler depending upon the type of interrupt supported by
589015a6ef6SSaurabh Misra * the chip.
590015a6ef6SSaurabh Misra */
591015a6ef6SSaurabh Misra static int
atge_add_intr_handler(atge_t * atgep,int intr_type)592015a6ef6SSaurabh Misra atge_add_intr_handler(atge_t *atgep, int intr_type)
593015a6ef6SSaurabh Misra {
594015a6ef6SSaurabh Misra int err;
595015a6ef6SSaurabh Misra int count = 0;
596015a6ef6SSaurabh Misra int avail = 0;
597015a6ef6SSaurabh Misra int i;
598015a6ef6SSaurabh Misra int flag;
599015a6ef6SSaurabh Misra
600015a6ef6SSaurabh Misra if (intr_type != DDI_INTR_TYPE_FIXED) {
601015a6ef6SSaurabh Misra err = ddi_intr_get_nintrs(atgep->atge_dip, intr_type, &count);
602015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
603015a6ef6SSaurabh Misra atge_error(atgep->atge_dip,
604015a6ef6SSaurabh Misra "ddi_intr_get_nintrs failed : %d", err);
6050eb090a7SSaurabh Misra return (DDI_FAILURE);
606015a6ef6SSaurabh Misra }
607015a6ef6SSaurabh Misra
608015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() count : %d",
609015a6ef6SSaurabh Misra atgep->atge_name, __func__, count));
610015a6ef6SSaurabh Misra
611015a6ef6SSaurabh Misra err = ddi_intr_get_navail(atgep->atge_dip, intr_type, &avail);
612015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
613015a6ef6SSaurabh Misra atge_error(atgep->atge_dip,
614015a6ef6SSaurabh Misra "ddi_intr_get_navail failed : %d", err);
6150eb090a7SSaurabh Misra return (DDI_FAILURE);
616015a6ef6SSaurabh Misra }
617015a6ef6SSaurabh Misra
618015a6ef6SSaurabh Misra if (avail < count) {
619015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "count :%d,"
620015a6ef6SSaurabh Misra " avail : %d", count, avail);
621015a6ef6SSaurabh Misra }
622015a6ef6SSaurabh Misra
623015a6ef6SSaurabh Misra flag = DDI_INTR_ALLOC_STRICT;
624015a6ef6SSaurabh Misra } else {
625015a6ef6SSaurabh Misra /*
626015a6ef6SSaurabh Misra * DDI_INTR_TYPE_FIXED case.
627015a6ef6SSaurabh Misra */
628015a6ef6SSaurabh Misra count = 1;
629015a6ef6SSaurabh Misra avail = 1;
630015a6ef6SSaurabh Misra flag = DDI_INTR_ALLOC_NORMAL;
631015a6ef6SSaurabh Misra }
632015a6ef6SSaurabh Misra
633015a6ef6SSaurabh Misra atgep->atge_intr_size = avail * sizeof (ddi_intr_handle_t);
634015a6ef6SSaurabh Misra atgep->atge_intr_handle = kmem_zalloc(atgep->atge_intr_size, KM_SLEEP);
635015a6ef6SSaurabh Misra
636015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() avail:%d, count : %d, type : %d",
637015a6ef6SSaurabh Misra atgep->atge_name, __func__, avail, count,
638015a6ef6SSaurabh Misra intr_type));
639015a6ef6SSaurabh Misra
640015a6ef6SSaurabh Misra err = ddi_intr_alloc(atgep->atge_dip, atgep->atge_intr_handle,
641015a6ef6SSaurabh Misra intr_type, 0, avail, &atgep->atge_intr_cnt, flag);
642015a6ef6SSaurabh Misra
643015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
644015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "ddi_intr_alloc failed : %d", err);
645015a6ef6SSaurabh Misra kmem_free(atgep->atge_intr_handle, atgep->atge_intr_size);
6460eb090a7SSaurabh Misra return (DDI_FAILURE);
647015a6ef6SSaurabh Misra }
648015a6ef6SSaurabh Misra
649015a6ef6SSaurabh Misra ATGE_DB(("%s: atge_add_intr_handler() after alloc count"
650015a6ef6SSaurabh Misra " :%d, avail : %d", atgep->atge_name, count, avail));
651015a6ef6SSaurabh Misra
652015a6ef6SSaurabh Misra err = ddi_intr_get_pri(atgep->atge_intr_handle[0],
653015a6ef6SSaurabh Misra &atgep->atge_intr_pri);
654015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
655015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "ddi_intr_get_pri failed:%d", err);
656015a6ef6SSaurabh Misra for (i = 0; i < atgep->atge_intr_cnt; i++) {
657015a6ef6SSaurabh Misra (void) ddi_intr_free(atgep->atge_intr_handle[i]);
658015a6ef6SSaurabh Misra }
659015a6ef6SSaurabh Misra kmem_free(atgep->atge_intr_handle, atgep->atge_intr_size);
660015a6ef6SSaurabh Misra
6610eb090a7SSaurabh Misra return (DDI_FAILURE);
662015a6ef6SSaurabh Misra }
663015a6ef6SSaurabh Misra
664015a6ef6SSaurabh Misra /*
665015a6ef6SSaurabh Misra * Add interrupt handler now.
666015a6ef6SSaurabh Misra */
667015a6ef6SSaurabh Misra for (i = 0; i < atgep->atge_intr_cnt; i++) {
6685e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
6695e8715b9SGary Mills case ATGE_CHIP_L1E:
6700eb090a7SSaurabh Misra err = ddi_intr_add_handler(atgep->atge_intr_handle[i],
6710eb090a7SSaurabh Misra atge_l1e_interrupt, atgep, (caddr_t)(uintptr_t)i);
6725e8715b9SGary Mills break;
6735e8715b9SGary Mills case ATGE_CHIP_L1:
6740eb090a7SSaurabh Misra err = ddi_intr_add_handler(atgep->atge_intr_handle[i],
6750eb090a7SSaurabh Misra atge_l1_interrupt, atgep, (caddr_t)(uintptr_t)i);
6765e8715b9SGary Mills break;
6775e8715b9SGary Mills case ATGE_CHIP_L1C:
6785e8715b9SGary Mills err = ddi_intr_add_handler(atgep->atge_intr_handle[i],
6795e8715b9SGary Mills atge_l1c_interrupt, atgep, (caddr_t)(uintptr_t)i);
6805e8715b9SGary Mills break;
6810eb090a7SSaurabh Misra }
682015a6ef6SSaurabh Misra
683015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
684015a6ef6SSaurabh Misra atge_error(atgep->atge_dip,
685015a6ef6SSaurabh Misra "ddi_intr_add_handler failed : %d", err);
686015a6ef6SSaurabh Misra
687015a6ef6SSaurabh Misra (void) ddi_intr_free(atgep->atge_intr_handle[i]);
688015a6ef6SSaurabh Misra while (--i >= 0) {
689015a6ef6SSaurabh Misra (void) ddi_intr_remove_handler(
690015a6ef6SSaurabh Misra atgep->atge_intr_handle[i]);
691015a6ef6SSaurabh Misra (void) ddi_intr_free(
692015a6ef6SSaurabh Misra atgep->atge_intr_handle[i]);
693015a6ef6SSaurabh Misra }
694015a6ef6SSaurabh Misra
695015a6ef6SSaurabh Misra kmem_free(atgep->atge_intr_handle,
696015a6ef6SSaurabh Misra atgep->atge_intr_size);
697015a6ef6SSaurabh Misra
6980eb090a7SSaurabh Misra return (DDI_FAILURE);
699015a6ef6SSaurabh Misra }
700015a6ef6SSaurabh Misra }
701015a6ef6SSaurabh Misra
702015a6ef6SSaurabh Misra err = ddi_intr_get_cap(atgep->atge_intr_handle[0],
703015a6ef6SSaurabh Misra &atgep->atge_intr_cap);
704015a6ef6SSaurabh Misra
705015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
706015a6ef6SSaurabh Misra atge_error(atgep->atge_dip,
707015a6ef6SSaurabh Misra "ddi_intr_get_cap failed : %d", err);
708015a6ef6SSaurabh Misra atge_remove_intr(atgep);
7090eb090a7SSaurabh Misra return (DDI_FAILURE);
710015a6ef6SSaurabh Misra }
711015a6ef6SSaurabh Misra
712015a6ef6SSaurabh Misra if (intr_type == DDI_INTR_TYPE_FIXED)
713015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_FIXED_TYPE;
714015a6ef6SSaurabh Misra else if (intr_type == DDI_INTR_TYPE_MSI)
715015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_MSI_TYPE;
716015a6ef6SSaurabh Misra else if (intr_type == DDI_INTR_TYPE_MSIX)
717015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_MSIX_TYPE;
718015a6ef6SSaurabh Misra
7190eb090a7SSaurabh Misra return (DDI_SUCCESS);
720015a6ef6SSaurabh Misra }
721015a6ef6SSaurabh Misra
722015a6ef6SSaurabh Misra void
atge_remove_intr(atge_t * atgep)723015a6ef6SSaurabh Misra atge_remove_intr(atge_t *atgep)
724015a6ef6SSaurabh Misra {
725015a6ef6SSaurabh Misra int i;
726015a6ef6SSaurabh Misra int cap = 0;
727015a6ef6SSaurabh Misra
728015a6ef6SSaurabh Misra if (atgep->atge_intr_handle == NULL)
729015a6ef6SSaurabh Misra return;
730015a6ef6SSaurabh Misra
731015a6ef6SSaurabh Misra if (atgep->atge_intr_cap & DDI_INTR_FLAG_BLOCK) {
732015a6ef6SSaurabh Misra (void) ddi_intr_block_disable(atgep->atge_intr_handle,
733015a6ef6SSaurabh Misra atgep->atge_intr_cnt);
734015a6ef6SSaurabh Misra
735015a6ef6SSaurabh Misra cap = 1;
736015a6ef6SSaurabh Misra }
737015a6ef6SSaurabh Misra
738015a6ef6SSaurabh Misra for (i = 0; i < atgep->atge_intr_cnt; i++) {
739015a6ef6SSaurabh Misra if (cap == 0)
740015a6ef6SSaurabh Misra (void) ddi_intr_disable(atgep->atge_intr_handle[i]);
741015a6ef6SSaurabh Misra
742015a6ef6SSaurabh Misra (void) ddi_intr_remove_handler(atgep->atge_intr_handle[i]);
743015a6ef6SSaurabh Misra (void) ddi_intr_free(atgep->atge_intr_handle[i]);
744015a6ef6SSaurabh Misra }
745015a6ef6SSaurabh Misra
746015a6ef6SSaurabh Misra kmem_free(atgep->atge_intr_handle, atgep->atge_intr_size);
747015a6ef6SSaurabh Misra }
748015a6ef6SSaurabh Misra
749015a6ef6SSaurabh Misra int
atge_enable_intrs(atge_t * atgep)750015a6ef6SSaurabh Misra atge_enable_intrs(atge_t *atgep)
751015a6ef6SSaurabh Misra {
752015a6ef6SSaurabh Misra int err;
753015a6ef6SSaurabh Misra int i;
754015a6ef6SSaurabh Misra
755015a6ef6SSaurabh Misra if (atgep->atge_intr_cap & DDI_INTR_FLAG_BLOCK) {
756015a6ef6SSaurabh Misra /*
757015a6ef6SSaurabh Misra * Do block enable.
758015a6ef6SSaurabh Misra */
759015a6ef6SSaurabh Misra err = ddi_intr_block_enable(atgep->atge_intr_handle,
760015a6ef6SSaurabh Misra atgep->atge_intr_cnt);
761015a6ef6SSaurabh Misra
762015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
763015a6ef6SSaurabh Misra atge_error(atgep->atge_dip,
764015a6ef6SSaurabh Misra "Failed to block enable intrs %d", err);
7650eb090a7SSaurabh Misra err = DDI_FAILURE;
766015a6ef6SSaurabh Misra } else {
7670eb090a7SSaurabh Misra err = DDI_SUCCESS;
768015a6ef6SSaurabh Misra }
769015a6ef6SSaurabh Misra } else {
770015a6ef6SSaurabh Misra /*
771015a6ef6SSaurabh Misra * Call ddi_intr_enable() for MSI non-block enable.
772015a6ef6SSaurabh Misra */
773015a6ef6SSaurabh Misra for (i = 0; i < atgep->atge_intr_cnt; i++) {
774015a6ef6SSaurabh Misra err = ddi_intr_enable(atgep->atge_intr_handle[i]);
775015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
776015a6ef6SSaurabh Misra atge_error(atgep->atge_dip,
777015a6ef6SSaurabh Misra "Failed to enable intrs on %d with : %d",
778015a6ef6SSaurabh Misra i, err);
779015a6ef6SSaurabh Misra break;
780015a6ef6SSaurabh Misra }
781015a6ef6SSaurabh Misra }
782015a6ef6SSaurabh Misra
783015a6ef6SSaurabh Misra if (err == DDI_SUCCESS)
7840eb090a7SSaurabh Misra err = DDI_SUCCESS;
785015a6ef6SSaurabh Misra else
7860eb090a7SSaurabh Misra err = DDI_FAILURE;
787015a6ef6SSaurabh Misra }
788015a6ef6SSaurabh Misra
789015a6ef6SSaurabh Misra return (err);
790015a6ef6SSaurabh Misra }
791015a6ef6SSaurabh Misra
792015a6ef6SSaurabh Misra /*
793015a6ef6SSaurabh Misra * Adds interrupt handler depending on the supported interrupt type by the
794015a6ef6SSaurabh Misra * chip.
795015a6ef6SSaurabh Misra */
796015a6ef6SSaurabh Misra static int
atge_add_intr(atge_t * atgep)797015a6ef6SSaurabh Misra atge_add_intr(atge_t *atgep)
798015a6ef6SSaurabh Misra {
799015a6ef6SSaurabh Misra int err;
800015a6ef6SSaurabh Misra
801015a6ef6SSaurabh Misra /*
802015a6ef6SSaurabh Misra * Get the supported interrupt types.
803015a6ef6SSaurabh Misra */
804015a6ef6SSaurabh Misra err = ddi_intr_get_supported_types(atgep->atge_dip,
805015a6ef6SSaurabh Misra &atgep->atge_intr_types);
806015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
807015a6ef6SSaurabh Misra atge_error(atgep->atge_dip,
808015a6ef6SSaurabh Misra "ddi_intr_get_supported_types failed : %d", err);
8090eb090a7SSaurabh Misra return (DDI_FAILURE);
810015a6ef6SSaurabh Misra }
811015a6ef6SSaurabh Misra
812015a6ef6SSaurabh Misra ATGE_DB(("%s: ddi_intr_get_supported_types() returned : %d",
813015a6ef6SSaurabh Misra atgep->atge_name, atgep->atge_intr_types));
814015a6ef6SSaurabh Misra
815015a6ef6SSaurabh Misra
816015a6ef6SSaurabh Misra if (atgep->atge_intr_types & DDI_INTR_TYPE_MSIX) {
817015a6ef6SSaurabh Misra err = atge_add_intr_handler(atgep, DDI_INTR_TYPE_MSIX);
8180eb090a7SSaurabh Misra if (err == DDI_SUCCESS) {
819015a6ef6SSaurabh Misra ATGE_DB(("%s: Using MSIx for interrupt",
820015a6ef6SSaurabh Misra atgep->atge_name));
821015a6ef6SSaurabh Misra return (err);
822015a6ef6SSaurabh Misra }
823015a6ef6SSaurabh Misra }
824015a6ef6SSaurabh Misra
825015a6ef6SSaurabh Misra if (atgep->atge_intr_types & DDI_INTR_TYPE_MSI) {
826015a6ef6SSaurabh Misra err = atge_add_intr_handler(atgep, DDI_INTR_TYPE_MSI);
8270eb090a7SSaurabh Misra if (err == DDI_SUCCESS) {
828015a6ef6SSaurabh Misra ATGE_DB(("%s: Using MSI for interrupt",
829015a6ef6SSaurabh Misra atgep->atge_name));
830015a6ef6SSaurabh Misra return (err);
831015a6ef6SSaurabh Misra }
832015a6ef6SSaurabh Misra }
833015a6ef6SSaurabh Misra
8340eb090a7SSaurabh Misra err = DDI_FAILURE;
835015a6ef6SSaurabh Misra if (atgep->atge_intr_types & DDI_INTR_TYPE_FIXED) {
836015a6ef6SSaurabh Misra err = atge_add_intr_handler(atgep, DDI_INTR_TYPE_FIXED);
8370eb090a7SSaurabh Misra if (err == DDI_SUCCESS) {
838015a6ef6SSaurabh Misra ATGE_DB(("%s: Using FIXED type for interrupt",
839015a6ef6SSaurabh Misra atgep->atge_name));
840015a6ef6SSaurabh Misra return (err);
841015a6ef6SSaurabh Misra }
842015a6ef6SSaurabh Misra }
843015a6ef6SSaurabh Misra
844015a6ef6SSaurabh Misra return (err);
845015a6ef6SSaurabh Misra }
846015a6ef6SSaurabh Misra
847015a6ef6SSaurabh Misra int
atge_identify_hardware(atge_t * atgep)848015a6ef6SSaurabh Misra atge_identify_hardware(atge_t *atgep)
849015a6ef6SSaurabh Misra {
850015a6ef6SSaurabh Misra uint16_t vid, did;
851015a6ef6SSaurabh Misra int i;
852015a6ef6SSaurabh Misra
853015a6ef6SSaurabh Misra vid = pci_config_get16(atgep->atge_conf_handle, PCI_CONF_VENID);
854015a6ef6SSaurabh Misra did = pci_config_get16(atgep->atge_conf_handle, PCI_CONF_DEVID);
855015a6ef6SSaurabh Misra
856015a6ef6SSaurabh Misra atgep->atge_model = 0;
857015a6ef6SSaurabh Misra for (i = 0; i < (sizeof (atge_cards) / sizeof (atge_cards_t)); i++) {
858015a6ef6SSaurabh Misra if (atge_cards[i].vendor_id == vid &&
859015a6ef6SSaurabh Misra atge_cards[i].device_id == did) {
860015a6ef6SSaurabh Misra atgep->atge_model = atge_cards[i].model;
8615e8715b9SGary Mills atgep->atge_vid = vid;
8625e8715b9SGary Mills atgep->atge_did = did;
863015a6ef6SSaurabh Misra atgep->atge_revid =
864015a6ef6SSaurabh Misra pci_config_get8(atgep->atge_conf_handle,
865015a6ef6SSaurabh Misra PCI_CONF_REVID);
8665e8715b9SGary Mills atge_notice(atgep->atge_dip, "PCI-ID pci%x,%x,%x: %s",
8675e8715b9SGary Mills vid, did, atgep->atge_revid,
8685e8715b9SGary Mills atge_cards[i].cardname);
869015a6ef6SSaurabh Misra ATGE_DB(("%s: %s : PCI-ID pci%x,%x and model : %d",
870015a6ef6SSaurabh Misra atgep->atge_name, __func__, vid, did,
871015a6ef6SSaurabh Misra atgep->atge_model));
872015a6ef6SSaurabh Misra
8730eb090a7SSaurabh Misra return (DDI_SUCCESS);
874015a6ef6SSaurabh Misra }
875015a6ef6SSaurabh Misra }
876015a6ef6SSaurabh Misra
877015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "atge driver is attaching to unknown"
8785e8715b9SGary Mills " pci%x,%x vendor/device-id card", vid, did);
879015a6ef6SSaurabh Misra
880015a6ef6SSaurabh Misra /*
8815e8715b9SGary Mills * Assume it's L1C chip.
882015a6ef6SSaurabh Misra */
8835e8715b9SGary Mills atgep->atge_model = ATGE_CHIP_L1C;
8845e8715b9SGary Mills atgep->atge_vid = vid;
8855e8715b9SGary Mills atgep->atge_did = did;
886015a6ef6SSaurabh Misra atgep->atge_revid = pci_config_get8(atgep->atge_conf_handle,
887015a6ef6SSaurabh Misra PCI_CONF_REVID);
888015a6ef6SSaurabh Misra
889015a6ef6SSaurabh Misra /*
890015a6ef6SSaurabh Misra * We will leave the decision to caller.
891015a6ef6SSaurabh Misra */
8920eb090a7SSaurabh Misra return (DDI_FAILURE);
893015a6ef6SSaurabh Misra }
894015a6ef6SSaurabh Misra
895015a6ef6SSaurabh Misra int
atge_get_macaddr(atge_t * atgep)896015a6ef6SSaurabh Misra atge_get_macaddr(atge_t *atgep)
897015a6ef6SSaurabh Misra {
898015a6ef6SSaurabh Misra uint32_t reg;
899015a6ef6SSaurabh Misra
900015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_SPI_CTRL);
901015a6ef6SSaurabh Misra if ((reg & SPI_VPD_ENB) != 0) {
902015a6ef6SSaurabh Misra /*
903015a6ef6SSaurabh Misra * Get VPD stored in TWSI EEPROM.
904015a6ef6SSaurabh Misra */
905015a6ef6SSaurabh Misra reg &= ~SPI_VPD_ENB;
906015a6ef6SSaurabh Misra OUTL(atgep, ATGE_SPI_CTRL, reg);
907015a6ef6SSaurabh Misra
908015a6ef6SSaurabh Misra ATGE_DB(("%s: %s called Get VPD", atgep->atge_name, __func__));
909015a6ef6SSaurabh Misra }
910015a6ef6SSaurabh Misra
911015a6ef6SSaurabh Misra atgep->atge_ether_addr[5] = INB(atgep, ATGE_PAR0 + 0);
912015a6ef6SSaurabh Misra atgep->atge_ether_addr[4] = INB(atgep, ATGE_PAR0 + 1);
913015a6ef6SSaurabh Misra atgep->atge_ether_addr[3] = INB(atgep, ATGE_PAR0 + 2);
914015a6ef6SSaurabh Misra atgep->atge_ether_addr[2] = INB(atgep, ATGE_PAR0 + 3);
915015a6ef6SSaurabh Misra atgep->atge_ether_addr[1] = INB(atgep, ATGE_PAR1 + 0);
916015a6ef6SSaurabh Misra atgep->atge_ether_addr[0] = INB(atgep, ATGE_PAR1 + 1);
917015a6ef6SSaurabh Misra
918015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() Station Address - %x:%x:%x:%x:%x:%x",
919015a6ef6SSaurabh Misra atgep->atge_name, __func__,
920015a6ef6SSaurabh Misra atgep->atge_ether_addr[0],
921015a6ef6SSaurabh Misra atgep->atge_ether_addr[1],
922015a6ef6SSaurabh Misra atgep->atge_ether_addr[2],
923015a6ef6SSaurabh Misra atgep->atge_ether_addr[3],
924015a6ef6SSaurabh Misra atgep->atge_ether_addr[4],
925015a6ef6SSaurabh Misra atgep->atge_ether_addr[5]));
926015a6ef6SSaurabh Misra
927015a6ef6SSaurabh Misra bcopy(atgep->atge_ether_addr, atgep->atge_dev_addr, ETHERADDRL);
928015a6ef6SSaurabh Misra
9290eb090a7SSaurabh Misra return (DDI_SUCCESS);
930015a6ef6SSaurabh Misra }
931015a6ef6SSaurabh Misra
932015a6ef6SSaurabh Misra /*
9335e8715b9SGary Mills * Reset functionality for L1, L1E, and L1C. It's same.
934015a6ef6SSaurabh Misra */
935015a6ef6SSaurabh Misra static void
atge_device_reset(atge_t * atgep)936015a6ef6SSaurabh Misra atge_device_reset(atge_t *atgep)
937015a6ef6SSaurabh Misra {
9385e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
9395e8715b9SGary Mills case ATGE_CHIP_L1E:
9405e8715b9SGary Mills case ATGE_CHIP_L1:
9415e8715b9SGary Mills case ATGE_CHIP_L1C:
942015a6ef6SSaurabh Misra atge_device_reset_l1_l1e(atgep);
9435e8715b9SGary Mills break;
9445e8715b9SGary Mills }
945015a6ef6SSaurabh Misra }
946015a6ef6SSaurabh Misra
947015a6ef6SSaurabh Misra void
atge_device_reset_l1_l1e(atge_t * atgep)948015a6ef6SSaurabh Misra atge_device_reset_l1_l1e(atge_t *atgep)
949015a6ef6SSaurabh Misra {
950015a6ef6SSaurabh Misra uint32_t reg;
951015a6ef6SSaurabh Misra int t;
9525e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
9535e8715b9SGary Mills case ATGE_CHIP_L1C:
9545e8715b9SGary Mills OUTL(atgep, ATGE_MASTER_CFG, MASTER_RESET | 0x40);
9555e8715b9SGary Mills break;
9565e8715b9SGary Mills default:
9575e8715b9SGary Mills OUTL(atgep, ATGE_MASTER_CFG, MASTER_RESET);
9585e8715b9SGary Mills break;
9595e8715b9SGary Mills }
960015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_MASTER_CFG);
961015a6ef6SSaurabh Misra for (t = ATGE_RESET_TIMEOUT; t > 0; t--) {
962015a6ef6SSaurabh Misra drv_usecwait(10);
963015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_MASTER_CFG);
964015a6ef6SSaurabh Misra if ((reg & MASTER_RESET) == 0)
965015a6ef6SSaurabh Misra break;
966015a6ef6SSaurabh Misra }
967015a6ef6SSaurabh Misra
968015a6ef6SSaurabh Misra if (t == 0) {
969015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, " master reset timeout reg : %x",
970015a6ef6SSaurabh Misra reg);
971015a6ef6SSaurabh Misra }
972015a6ef6SSaurabh Misra
973015a6ef6SSaurabh Misra for (t = ATGE_RESET_TIMEOUT; t > 0; t--) {
974015a6ef6SSaurabh Misra if ((reg = INL(atgep, ATGE_IDLE_STATUS)) == 0)
975015a6ef6SSaurabh Misra break;
976015a6ef6SSaurabh Misra
977015a6ef6SSaurabh Misra drv_usecwait(10);
978015a6ef6SSaurabh Misra }
979015a6ef6SSaurabh Misra
980015a6ef6SSaurabh Misra if (t == 0) {
981015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "device reset timeout reg : %x",
982015a6ef6SSaurabh Misra reg);
983015a6ef6SSaurabh Misra }
984015a6ef6SSaurabh Misra
9855e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
9865e8715b9SGary Mills case ATGE_CHIP_L1E:
9875e8715b9SGary Mills case ATGE_CHIP_L1:
9885e8715b9SGary Mills /*
9895e8715b9SGary Mills * Initialize PCIe module. These values came from FreeBSD and
9905e8715b9SGary Mills * we don't know the meaning of it.
9915e8715b9SGary Mills */
9925e8715b9SGary Mills OUTL(atgep, ATGE_LTSSM_ID_CFG, 0x6500);
9935e8715b9SGary Mills reg = INL(atgep, 0x1008) | 0x8000;
9945e8715b9SGary Mills OUTL(atgep, 0x1008, reg);
9955e8715b9SGary Mills break;
9965e8715b9SGary Mills case ATGE_CHIP_L1C:
9975e8715b9SGary Mills break;
9985e8715b9SGary Mills }
999015a6ef6SSaurabh Misra
1000015a6ef6SSaurabh Misra /*
1001015a6ef6SSaurabh Misra * Get chip revision.
1002015a6ef6SSaurabh Misra */
1003015a6ef6SSaurabh Misra atgep->atge_chip_rev = INL(atgep, ATGE_MASTER_CFG) >>
1004015a6ef6SSaurabh Misra MASTER_CHIP_REV_SHIFT;
1005015a6ef6SSaurabh Misra
1006015a6ef6SSaurabh Misra ATGE_DB(("%s: %s reset successfully rev : %x", atgep->atge_name,
1007015a6ef6SSaurabh Misra __func__, atgep->atge_chip_rev));
1008015a6ef6SSaurabh Misra }
1009015a6ef6SSaurabh Misra
1010015a6ef6SSaurabh Misra /*
1011015a6ef6SSaurabh Misra * DMA allocation for L1 and L1E is bit different since L1E uses RX pages
1012015a6ef6SSaurabh Misra * instead of descriptor based RX model.
1013015a6ef6SSaurabh Misra */
1014015a6ef6SSaurabh Misra static int
atge_alloc_dma(atge_t * atgep)1015015a6ef6SSaurabh Misra atge_alloc_dma(atge_t *atgep)
1016015a6ef6SSaurabh Misra {
10170eb090a7SSaurabh Misra int err = DDI_FAILURE;
1018015a6ef6SSaurabh Misra
10195e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
10205e8715b9SGary Mills case ATGE_CHIP_L1E:
1021015a6ef6SSaurabh Misra err = atge_l1e_alloc_dma(atgep);
10225e8715b9SGary Mills break;
10235e8715b9SGary Mills case ATGE_CHIP_L1:
10240eb090a7SSaurabh Misra err = atge_l1_alloc_dma(atgep);
10255e8715b9SGary Mills break;
10265e8715b9SGary Mills case ATGE_CHIP_L1C:
10275e8715b9SGary Mills err = atge_l1c_alloc_dma(atgep);
10285e8715b9SGary Mills break;
1029015a6ef6SSaurabh Misra }
1030015a6ef6SSaurabh Misra
1031015a6ef6SSaurabh Misra return (err);
1032015a6ef6SSaurabh Misra }
1033015a6ef6SSaurabh Misra
1034015a6ef6SSaurabh Misra static void
atge_free_dma(atge_t * atgep)1035015a6ef6SSaurabh Misra atge_free_dma(atge_t *atgep)
1036015a6ef6SSaurabh Misra {
10375e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
10385e8715b9SGary Mills case ATGE_CHIP_L1E:
1039015a6ef6SSaurabh Misra atge_l1e_free_dma(atgep);
10405e8715b9SGary Mills break;
10415e8715b9SGary Mills case ATGE_CHIP_L1:
10425e8715b9SGary Mills atge_l1_free_dma(atgep);
10435e8715b9SGary Mills break;
10445e8715b9SGary Mills case ATGE_CHIP_L1C:
10455e8715b9SGary Mills atge_l1c_free_dma(atgep);
10465e8715b9SGary Mills break;
1047015a6ef6SSaurabh Misra }
1048015a6ef6SSaurabh Misra }
1049015a6ef6SSaurabh Misra
1050015a6ef6SSaurabh Misra /*
1051015a6ef6SSaurabh Misra * Attach entry point in the driver.
1052015a6ef6SSaurabh Misra */
1053015a6ef6SSaurabh Misra static int
atge_attach(dev_info_t * devinfo,ddi_attach_cmd_t cmd)1054015a6ef6SSaurabh Misra atge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
1055015a6ef6SSaurabh Misra {
1056015a6ef6SSaurabh Misra atge_t *atgep;
1057015a6ef6SSaurabh Misra mac_register_t *macreg;
1058015a6ef6SSaurabh Misra int instance;
1059015a6ef6SSaurabh Misra uint16_t cap_ptr;
1060015a6ef6SSaurabh Misra uint16_t burst;
1061015a6ef6SSaurabh Misra int err;
1062015a6ef6SSaurabh Misra mii_ops_t *mii_ops;
1063015a6ef6SSaurabh Misra
1064015a6ef6SSaurabh Misra instance = ddi_get_instance(devinfo);
1065015a6ef6SSaurabh Misra
1066015a6ef6SSaurabh Misra switch (cmd) {
1067015a6ef6SSaurabh Misra case DDI_RESUME:
1068015a6ef6SSaurabh Misra return (atge_resume(devinfo));
1069015a6ef6SSaurabh Misra
1070015a6ef6SSaurabh Misra case DDI_ATTACH:
1071015a6ef6SSaurabh Misra ddi_set_driver_private(devinfo, NULL);
1072015a6ef6SSaurabh Misra break;
10735e8715b9SGary Mills default:
10745e8715b9SGary Mills return (DDI_FAILURE);
10755e8715b9SGary Mills
1076015a6ef6SSaurabh Misra }
1077015a6ef6SSaurabh Misra
1078015a6ef6SSaurabh Misra atgep = kmem_zalloc(sizeof (atge_t), KM_SLEEP);
1079015a6ef6SSaurabh Misra ddi_set_driver_private(devinfo, atgep);
1080015a6ef6SSaurabh Misra atgep->atge_dip = devinfo;
1081015a6ef6SSaurabh Misra
1082015a6ef6SSaurabh Misra /*
1083015a6ef6SSaurabh Misra * Setup name and instance number to be used for debugging and
1084015a6ef6SSaurabh Misra * error reporting.
1085015a6ef6SSaurabh Misra */
1086015a6ef6SSaurabh Misra (void) snprintf(atgep->atge_name, sizeof (atgep->atge_name), "%s%d",
1087015a6ef6SSaurabh Misra "atge", instance);
1088015a6ef6SSaurabh Misra
1089015a6ef6SSaurabh Misra
1090015a6ef6SSaurabh Misra /*
1091015a6ef6SSaurabh Misra * Map PCI config space.
1092015a6ef6SSaurabh Misra */
1093015a6ef6SSaurabh Misra err = pci_config_setup(devinfo, &atgep->atge_conf_handle);
1094015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
1095015a6ef6SSaurabh Misra atge_error(devinfo, "pci_config_setup() failed");
1096015a6ef6SSaurabh Misra goto fail1;
1097015a6ef6SSaurabh Misra }
1098015a6ef6SSaurabh Misra
1099015a6ef6SSaurabh Misra (void) atge_identify_hardware(atgep);
1100015a6ef6SSaurabh Misra
1101015a6ef6SSaurabh Misra /*
1102015a6ef6SSaurabh Misra * Map Device registers.
1103015a6ef6SSaurabh Misra */
1104015a6ef6SSaurabh Misra err = ddi_regs_map_setup(devinfo, ATGE_PCI_REG_NUMBER,
1105015a6ef6SSaurabh Misra &atgep->atge_io_regs, 0, 0, &atge_dev_attr, &atgep->atge_io_handle);
1106015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
1107015a6ef6SSaurabh Misra atge_error(devinfo, "ddi_regs_map_setup() failed");
1108015a6ef6SSaurabh Misra goto fail2;
1109015a6ef6SSaurabh Misra }
1110015a6ef6SSaurabh Misra
1111015a6ef6SSaurabh Misra /*
1112015a6ef6SSaurabh Misra * Add interrupt and its associated handler.
1113015a6ef6SSaurabh Misra */
1114015a6ef6SSaurabh Misra err = atge_add_intr(atgep);
11150eb090a7SSaurabh Misra if (err != DDI_SUCCESS) {
1116015a6ef6SSaurabh Misra atge_error(devinfo, "Failed to add interrupt handler");
1117015a6ef6SSaurabh Misra goto fail3;
1118015a6ef6SSaurabh Misra }
1119015a6ef6SSaurabh Misra
1120015a6ef6SSaurabh Misra mutex_init(&atgep->atge_intr_lock, NULL, MUTEX_DRIVER,
1121015a6ef6SSaurabh Misra DDI_INTR_PRI(atgep->atge_intr_pri));
1122015a6ef6SSaurabh Misra
1123015a6ef6SSaurabh Misra mutex_init(&atgep->atge_tx_lock, NULL, MUTEX_DRIVER,
1124015a6ef6SSaurabh Misra DDI_INTR_PRI(atgep->atge_intr_pri));
1125015a6ef6SSaurabh Misra
1126015a6ef6SSaurabh Misra mutex_init(&atgep->atge_rx_lock, NULL, MUTEX_DRIVER,
1127015a6ef6SSaurabh Misra DDI_INTR_PRI(atgep->atge_intr_pri));
1128015a6ef6SSaurabh Misra
1129015a6ef6SSaurabh Misra mutex_init(&atgep->atge_mii_lock, NULL, MUTEX_DRIVER, NULL);
1130015a6ef6SSaurabh Misra
11310eb090a7SSaurabh Misra /*
11320eb090a7SSaurabh Misra * Used to lock down MBOX register on L1 chip since RX consumer,
11330eb090a7SSaurabh Misra * TX producer and RX return ring consumer are shared.
11340eb090a7SSaurabh Misra */
11350eb090a7SSaurabh Misra mutex_init(&atgep->atge_mbox_lock, NULL, MUTEX_DRIVER,
11360eb090a7SSaurabh Misra DDI_INTR_PRI(atgep->atge_intr_pri));
11370eb090a7SSaurabh Misra
1138015a6ef6SSaurabh Misra atgep->atge_link_state = LINK_STATE_DOWN;
1139015a6ef6SSaurabh Misra atgep->atge_mtu = ETHERMTU;
1140015a6ef6SSaurabh Misra
11415e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
11425e8715b9SGary Mills case ATGE_CHIP_L1E:
11430eb090a7SSaurabh Misra if (atgep->atge_revid > 0xF0) {
11440eb090a7SSaurabh Misra /* L2E Rev. B. AR8114 */
1145015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_FLAG_FASTETHER;
11460eb090a7SSaurabh Misra } else {
11470eb090a7SSaurabh Misra if ((INL(atgep, L1E_PHY_STATUS) &
11480eb090a7SSaurabh Misra PHY_STATUS_100M) != 0) {
11490eb090a7SSaurabh Misra /* L1E AR8121 */
11500eb090a7SSaurabh Misra atgep->atge_flags |= ATGE_FLAG_JUMBO;
11510eb090a7SSaurabh Misra } else {
11520eb090a7SSaurabh Misra /* L2E Rev. A. AR8113 */
11530eb090a7SSaurabh Misra atgep->atge_flags |= ATGE_FLAG_FASTETHER;
11540eb090a7SSaurabh Misra }
1155015a6ef6SSaurabh Misra }
11565e8715b9SGary Mills break;
11575e8715b9SGary Mills case ATGE_CHIP_L1:
11585e8715b9SGary Mills break;
11595e8715b9SGary Mills case ATGE_CHIP_L1C:
11605e8715b9SGary Mills /*
11615e8715b9SGary Mills * One odd thing is AR8132 uses the same PHY hardware(F1
11625e8715b9SGary Mills * gigabit PHY) of AR8131. So atphy(4) of AR8132 reports
11635e8715b9SGary Mills * the PHY supports 1000Mbps but that's not true. The PHY
11645e8715b9SGary Mills * used in AR8132 can't establish gigabit link even if it
11655e8715b9SGary Mills * shows the same PHY model/revision number of AR8131.
11665e8715b9SGary Mills *
11675e8715b9SGary Mills * It seems that AR813x/AR815x has silicon bug for SMB. In
11685e8715b9SGary Mills * addition, Atheros said that enabling SMB wouldn't improve
11695e8715b9SGary Mills * performance. However I think it's bad to access lots of
11705e8715b9SGary Mills * registers to extract MAC statistics.
11715e8715b9SGary Mills *
11725e8715b9SGary Mills * Don't use Tx CMB. It is known to have silicon bug.
11735e8715b9SGary Mills */
11745e8715b9SGary Mills switch (ATGE_DID(atgep)) {
11755e8715b9SGary Mills case ATGE_CHIP_AR8152V2_DEV_ID:
11765e8715b9SGary Mills case ATGE_CHIP_AR8152V1_DEV_ID:
11775e8715b9SGary Mills atgep->atge_flags |= ATGE_FLAG_APS |
11785e8715b9SGary Mills ATGE_FLAG_FASTETHER |
11795e8715b9SGary Mills ATGE_FLAG_ASPM_MON | ATGE_FLAG_JUMBO |
11805e8715b9SGary Mills ATGE_FLAG_SMB_BUG | ATGE_FLAG_CMB_BUG;
11815e8715b9SGary Mills break;
11825e8715b9SGary Mills case ATGE_CHIP_AR8151V2_DEV_ID:
11835e8715b9SGary Mills case ATGE_CHIP_AR8151V1_DEV_ID:
11845e8715b9SGary Mills atgep->atge_flags |= ATGE_FLAG_APS |
11855e8715b9SGary Mills ATGE_FLAG_ASPM_MON | ATGE_FLAG_JUMBO |
11865e8715b9SGary Mills ATGE_FLAG_SMB_BUG | ATGE_FLAG_CMB_BUG;
11875e8715b9SGary Mills break;
11885e8715b9SGary Mills case ATGE_CHIP_L1CF_DEV_ID:
11895e8715b9SGary Mills atgep->atge_flags |= ATGE_FLAG_FASTETHER;
11905e8715b9SGary Mills break;
11915e8715b9SGary Mills case ATGE_CHIP_L1CG_DEV_ID:
11925e8715b9SGary Mills break;
11935e8715b9SGary Mills }
11945e8715b9SGary Mills break;
1195015a6ef6SSaurabh Misra }
1196015a6ef6SSaurabh Misra
1197015a6ef6SSaurabh Misra /*
1198015a6ef6SSaurabh Misra * Get DMA parameters from PCIe device control register.
1199015a6ef6SSaurabh Misra */
1200015a6ef6SSaurabh Misra err = PCI_CAP_LOCATE(atgep->atge_conf_handle, PCI_CAP_ID_PCI_E,
1201015a6ef6SSaurabh Misra &cap_ptr);
1202015a6ef6SSaurabh Misra
1203015a6ef6SSaurabh Misra if (err == DDI_FAILURE) {
1204015a6ef6SSaurabh Misra atgep->atge_dma_rd_burst = DMA_CFG_RD_BURST_128;
1205015a6ef6SSaurabh Misra atgep->atge_dma_wr_burst = DMA_CFG_WR_BURST_128;
1206015a6ef6SSaurabh Misra } else {
1207015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_FLAG_PCIE;
1208015a6ef6SSaurabh Misra burst = pci_config_get16(atgep->atge_conf_handle,
1209015a6ef6SSaurabh Misra cap_ptr + 0x08);
1210015a6ef6SSaurabh Misra
1211015a6ef6SSaurabh Misra /*
1212015a6ef6SSaurabh Misra * Max read request size.
1213015a6ef6SSaurabh Misra */
1214015a6ef6SSaurabh Misra atgep->atge_dma_rd_burst = ((burst >> 12) & 0x07) <<
1215015a6ef6SSaurabh Misra DMA_CFG_RD_BURST_SHIFT;
1216015a6ef6SSaurabh Misra
1217015a6ef6SSaurabh Misra /*
1218015a6ef6SSaurabh Misra * Max Payload Size.
1219015a6ef6SSaurabh Misra */
1220015a6ef6SSaurabh Misra atgep->atge_dma_wr_burst = ((burst >> 5) & 0x07) <<
1221015a6ef6SSaurabh Misra DMA_CFG_WR_BURST_SHIFT;
1222015a6ef6SSaurabh Misra
1223015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() MRR : %d, MPS : %d",
1224015a6ef6SSaurabh Misra atgep->atge_name, __func__,
1225015a6ef6SSaurabh Misra (128 << ((burst >> 12) & 0x07)),
1226015a6ef6SSaurabh Misra (128 << ((burst >> 5) & 0x07))));
1227015a6ef6SSaurabh Misra }
1228015a6ef6SSaurabh Misra
12295e8715b9SGary Mills /* Clear data link and flow-control protocol error. */
12305e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
12315e8715b9SGary Mills case ATGE_CHIP_L1E:
12325e8715b9SGary Mills break;
12335e8715b9SGary Mills case ATGE_CHIP_L1:
12345e8715b9SGary Mills break;
12355e8715b9SGary Mills case ATGE_CHIP_L1C:
12365e8715b9SGary Mills OUTL_AND(atgep, ATGE_PEX_UNC_ERR_SEV,
12375e8715b9SGary Mills ~(PEX_UNC_ERR_SEV_UC | PEX_UNC_ERR_SEV_FCP));
12385e8715b9SGary Mills OUTL_AND(atgep, ATGE_LTSSM_ID_CFG, ~LTSSM_ID_WRO_ENB);
12395e8715b9SGary Mills OUTL_OR(atgep, ATGE_PCIE_PHYMISC, PCIE_PHYMISC_FORCE_RCV_DET);
12405e8715b9SGary Mills break;
12415e8715b9SGary Mills }
12425e8715b9SGary Mills
1243015a6ef6SSaurabh Misra /*
1244015a6ef6SSaurabh Misra * Allocate DMA resources.
1245015a6ef6SSaurabh Misra */
1246015a6ef6SSaurabh Misra err = atge_alloc_dma(atgep);
12470eb090a7SSaurabh Misra if (err != DDI_SUCCESS) {
1248015a6ef6SSaurabh Misra atge_error(devinfo, "Failed to allocate DMA resources");
1249015a6ef6SSaurabh Misra goto fail4;
1250015a6ef6SSaurabh Misra }
1251015a6ef6SSaurabh Misra
1252015a6ef6SSaurabh Misra /*
1253015a6ef6SSaurabh Misra * Get station address.
1254015a6ef6SSaurabh Misra */
1255015a6ef6SSaurabh Misra (void) atge_get_macaddr(atgep);
1256015a6ef6SSaurabh Misra
1257015a6ef6SSaurabh Misra /*
1258015a6ef6SSaurabh Misra * Setup MII.
1259015a6ef6SSaurabh Misra */
12605e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
12615e8715b9SGary Mills case ATGE_CHIP_L1E:
1262015a6ef6SSaurabh Misra mii_ops = &atge_l1e_mii_ops;
12635e8715b9SGary Mills break;
12645e8715b9SGary Mills case ATGE_CHIP_L1:
12650eb090a7SSaurabh Misra mii_ops = &atge_l1_mii_ops;
12665e8715b9SGary Mills break;
12675e8715b9SGary Mills case ATGE_CHIP_L1C:
12685e8715b9SGary Mills mii_ops = &atge_l1c_mii_ops;
12695e8715b9SGary Mills break;
1270015a6ef6SSaurabh Misra }
1271015a6ef6SSaurabh Misra
1272015a6ef6SSaurabh Misra if ((atgep->atge_mii = mii_alloc(atgep, devinfo,
1273015a6ef6SSaurabh Misra mii_ops)) == NULL) {
1274015a6ef6SSaurabh Misra atge_error(devinfo, "mii_alloc() failed");
1275015a6ef6SSaurabh Misra goto fail4;
1276015a6ef6SSaurabh Misra }
1277015a6ef6SSaurabh Misra
1278015a6ef6SSaurabh Misra /*
1279015a6ef6SSaurabh Misra * Register with MAC layer.
1280015a6ef6SSaurabh Misra */
1281015a6ef6SSaurabh Misra if ((macreg = mac_alloc(MAC_VERSION)) == NULL) {
1282015a6ef6SSaurabh Misra atge_error(devinfo, "mac_alloc() failed due to version");
1283015a6ef6SSaurabh Misra goto fail4;
1284015a6ef6SSaurabh Misra }
1285015a6ef6SSaurabh Misra
1286015a6ef6SSaurabh Misra macreg->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
1287015a6ef6SSaurabh Misra macreg->m_driver = atgep;
1288015a6ef6SSaurabh Misra macreg->m_dip = devinfo;
1289015a6ef6SSaurabh Misra macreg->m_instance = instance;
1290015a6ef6SSaurabh Misra macreg->m_src_addr = atgep->atge_ether_addr;
1291015a6ef6SSaurabh Misra macreg->m_callbacks = &atge_m_callbacks;
1292015a6ef6SSaurabh Misra macreg->m_min_sdu = 0;
1293015a6ef6SSaurabh Misra macreg->m_max_sdu = atgep->atge_mtu;
1294015a6ef6SSaurabh Misra macreg->m_margin = VLAN_TAGSZ;
1295015a6ef6SSaurabh Misra
1296015a6ef6SSaurabh Misra if ((err = mac_register(macreg, &atgep->atge_mh)) != 0) {
1297015a6ef6SSaurabh Misra atge_error(devinfo, "mac_register() failed with :%d", err);
1298015a6ef6SSaurabh Misra mac_free(macreg);
1299015a6ef6SSaurabh Misra goto fail4;
1300015a6ef6SSaurabh Misra }
1301015a6ef6SSaurabh Misra
1302015a6ef6SSaurabh Misra mac_free(macreg);
1303015a6ef6SSaurabh Misra
1304015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() driver attached successfully",
1305015a6ef6SSaurabh Misra atgep->atge_name, __func__));
1306015a6ef6SSaurabh Misra
1307015a6ef6SSaurabh Misra atge_device_reset(atgep);
1308015a6ef6SSaurabh Misra
1309015a6ef6SSaurabh Misra atgep->atge_chip_state = ATGE_CHIP_INITIALIZED;
1310015a6ef6SSaurabh Misra
1311015a6ef6SSaurabh Misra /*
1312015a6ef6SSaurabh Misra * At last - enable interrupts.
1313015a6ef6SSaurabh Misra */
1314015a6ef6SSaurabh Misra err = atge_enable_intrs(atgep);
13150eb090a7SSaurabh Misra if (err == DDI_FAILURE) {
1316015a6ef6SSaurabh Misra goto fail5;
1317015a6ef6SSaurabh Misra }
1318015a6ef6SSaurabh Misra
1319015a6ef6SSaurabh Misra /*
1320015a6ef6SSaurabh Misra * Reset the PHY before starting.
1321015a6ef6SSaurabh Misra */
13225e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
13235e8715b9SGary Mills case ATGE_CHIP_L1E:
1324015a6ef6SSaurabh Misra atge_l1e_mii_reset(atgep);
13255e8715b9SGary Mills break;
13265e8715b9SGary Mills case ATGE_CHIP_L1:
13270eb090a7SSaurabh Misra atge_l1_mii_reset(atgep);
13285e8715b9SGary Mills break;
13295e8715b9SGary Mills case ATGE_CHIP_L1C:
13305e8715b9SGary Mills atge_l1c_mii_reset(atgep);
13315e8715b9SGary Mills break;
1332015a6ef6SSaurabh Misra }
1333015a6ef6SSaurabh Misra
1334015a6ef6SSaurabh Misra /*
1335015a6ef6SSaurabh Misra * Let the PHY run.
1336015a6ef6SSaurabh Misra */
1337015a6ef6SSaurabh Misra mii_start(atgep->atge_mii);
1338015a6ef6SSaurabh Misra
1339015a6ef6SSaurabh Misra return (DDI_SUCCESS);
1340015a6ef6SSaurabh Misra
1341015a6ef6SSaurabh Misra fail5:
1342015a6ef6SSaurabh Misra (void) mac_unregister(atgep->atge_mh);
1343015a6ef6SSaurabh Misra atge_device_stop(atgep);
1344015a6ef6SSaurabh Misra mii_stop(atgep->atge_mii);
1345015a6ef6SSaurabh Misra mii_free(atgep->atge_mii);
1346015a6ef6SSaurabh Misra fail4:
1347015a6ef6SSaurabh Misra atge_free_dma(atgep);
1348015a6ef6SSaurabh Misra mutex_destroy(&atgep->atge_intr_lock);
1349015a6ef6SSaurabh Misra mutex_destroy(&atgep->atge_tx_lock);
1350015a6ef6SSaurabh Misra mutex_destroy(&atgep->atge_rx_lock);
1351015a6ef6SSaurabh Misra atge_remove_intr(atgep);
1352015a6ef6SSaurabh Misra fail3:
1353015a6ef6SSaurabh Misra ddi_regs_map_free(&atgep->atge_io_handle);
1354015a6ef6SSaurabh Misra fail2:
1355015a6ef6SSaurabh Misra pci_config_teardown(&atgep->atge_conf_handle);
1356015a6ef6SSaurabh Misra fail1:
1357*80e3e236SJohn Levon kmem_free(atgep, sizeof (atge_t));
1358015a6ef6SSaurabh Misra return (DDI_FAILURE);
1359015a6ef6SSaurabh Misra }
1360015a6ef6SSaurabh Misra
1361015a6ef6SSaurabh Misra static int
atge_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)1362015a6ef6SSaurabh Misra atge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1363015a6ef6SSaurabh Misra {
1364015a6ef6SSaurabh Misra atge_t *atgep;
1365015a6ef6SSaurabh Misra
1366015a6ef6SSaurabh Misra atgep = ddi_get_driver_private(dip);
1367015a6ef6SSaurabh Misra if (atgep == NULL) {
1368015a6ef6SSaurabh Misra atge_error(dip, "No soft state in detach");
1369015a6ef6SSaurabh Misra return (DDI_FAILURE);
1370015a6ef6SSaurabh Misra }
1371015a6ef6SSaurabh Misra
1372015a6ef6SSaurabh Misra switch (cmd) {
1373015a6ef6SSaurabh Misra case DDI_DETACH:
1374015a6ef6SSaurabh Misra
1375015a6ef6SSaurabh Misra /*
1376015a6ef6SSaurabh Misra * First unregister with MAC layer before stopping DMA
1377015a6ef6SSaurabh Misra */
13789d8d9e11SGarrett D'Amore if (mac_disable(atgep->atge_mh) != DDI_SUCCESS)
1379015a6ef6SSaurabh Misra return (DDI_FAILURE);
1380015a6ef6SSaurabh Misra
13819d8d9e11SGarrett D'Amore mii_stop(atgep->atge_mii);
1382015a6ef6SSaurabh Misra
1383015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_intr_lock);
1384015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock);
1385015a6ef6SSaurabh Misra atge_device_stop(atgep);
1386015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock);
1387015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_intr_lock);
1388015a6ef6SSaurabh Misra
1389015a6ef6SSaurabh Misra mii_free(atgep->atge_mii);
1390015a6ef6SSaurabh Misra atge_free_dma(atgep);
1391015a6ef6SSaurabh Misra
1392015a6ef6SSaurabh Misra ddi_regs_map_free(&atgep->atge_io_handle);
1393015a6ef6SSaurabh Misra atge_remove_intr(atgep);
1394015a6ef6SSaurabh Misra pci_config_teardown(&atgep->atge_conf_handle);
1395015a6ef6SSaurabh Misra
13969d8d9e11SGarrett D'Amore (void) mac_unregister(atgep->atge_mh);
1397015a6ef6SSaurabh Misra mutex_destroy(&atgep->atge_intr_lock);
1398015a6ef6SSaurabh Misra mutex_destroy(&atgep->atge_tx_lock);
1399015a6ef6SSaurabh Misra mutex_destroy(&atgep->atge_rx_lock);
1400015a6ef6SSaurabh Misra kmem_free(atgep, sizeof (atge_t));
1401015a6ef6SSaurabh Misra ddi_set_driver_private(dip, NULL);
1402015a6ef6SSaurabh Misra
1403015a6ef6SSaurabh Misra return (DDI_SUCCESS);
1404015a6ef6SSaurabh Misra
1405015a6ef6SSaurabh Misra case DDI_SUSPEND:
1406015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() is being suspended",
1407015a6ef6SSaurabh Misra atgep->atge_name, __func__));
1408015a6ef6SSaurabh Misra
1409015a6ef6SSaurabh Misra /*
1410015a6ef6SSaurabh Misra * Suspend monitoring MII.
1411015a6ef6SSaurabh Misra */
1412015a6ef6SSaurabh Misra mii_suspend(atgep->atge_mii);
1413015a6ef6SSaurabh Misra
1414015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_intr_lock);
1415015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock);
1416015a6ef6SSaurabh Misra atgep->atge_chip_state |= ATGE_CHIP_SUSPENDED;
1417015a6ef6SSaurabh Misra atge_device_stop(atgep);
1418015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock);
1419015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_intr_lock);
1420015a6ef6SSaurabh Misra
1421015a6ef6SSaurabh Misra return (DDI_SUCCESS);
1422015a6ef6SSaurabh Misra
1423015a6ef6SSaurabh Misra default:
1424015a6ef6SSaurabh Misra return (DDI_FAILURE);
1425015a6ef6SSaurabh Misra }
1426015a6ef6SSaurabh Misra }
1427015a6ef6SSaurabh Misra
1428015a6ef6SSaurabh Misra int
atge_alloc_buffers(atge_ring_t * r,size_t rcnt,size_t buflen,int f)1429015a6ef6SSaurabh Misra atge_alloc_buffers(atge_ring_t *r, size_t rcnt, size_t buflen, int f)
1430015a6ef6SSaurabh Misra {
1431015a6ef6SSaurabh Misra atge_dma_t *dma;
1432015a6ef6SSaurabh Misra atge_dma_t **tbl;
14330eb090a7SSaurabh Misra int err = DDI_SUCCESS;
1434015a6ef6SSaurabh Misra int i;
1435015a6ef6SSaurabh Misra
1436015a6ef6SSaurabh Misra tbl = kmem_zalloc(rcnt * sizeof (atge_dma_t *), KM_SLEEP);
1437015a6ef6SSaurabh Misra r->r_buf_tbl = tbl;
1438015a6ef6SSaurabh Misra
1439015a6ef6SSaurabh Misra for (i = 0; i < rcnt; i++) {
1440015a6ef6SSaurabh Misra dma = atge_buf_alloc(r->r_atge, buflen, f);
1441015a6ef6SSaurabh Misra if (dma == NULL) {
14420eb090a7SSaurabh Misra err = DDI_FAILURE;
1443015a6ef6SSaurabh Misra break;
1444015a6ef6SSaurabh Misra }
1445015a6ef6SSaurabh Misra
1446015a6ef6SSaurabh Misra tbl[i] = dma;
1447015a6ef6SSaurabh Misra }
1448015a6ef6SSaurabh Misra
1449015a6ef6SSaurabh Misra return (err);
1450015a6ef6SSaurabh Misra }
1451015a6ef6SSaurabh Misra
1452015a6ef6SSaurabh Misra void
atge_free_buffers(atge_ring_t * r,size_t rcnt)1453015a6ef6SSaurabh Misra atge_free_buffers(atge_ring_t *r, size_t rcnt)
1454015a6ef6SSaurabh Misra {
1455015a6ef6SSaurabh Misra atge_dma_t **tbl;
1456015a6ef6SSaurabh Misra int i;
1457015a6ef6SSaurabh Misra
1458015a6ef6SSaurabh Misra if (r == NULL || r->r_buf_tbl == NULL)
1459015a6ef6SSaurabh Misra return;
1460015a6ef6SSaurabh Misra
1461015a6ef6SSaurabh Misra tbl = r->r_buf_tbl;
1462015a6ef6SSaurabh Misra for (i = 0; i < rcnt; i++) {
1463015a6ef6SSaurabh Misra if (tbl[i] != NULL) {
1464015a6ef6SSaurabh Misra atge_buf_free(tbl[i]);
1465015a6ef6SSaurabh Misra }
1466015a6ef6SSaurabh Misra }
1467015a6ef6SSaurabh Misra
1468015a6ef6SSaurabh Misra kmem_free(tbl, rcnt * sizeof (atge_dma_t *));
1469015a6ef6SSaurabh Misra }
1470015a6ef6SSaurabh Misra
1471015a6ef6SSaurabh Misra atge_dma_t *
atge_alloc_a_dma_blk(atge_t * atgep,ddi_dma_attr_t * attr,int size,int d)1472015a6ef6SSaurabh Misra atge_alloc_a_dma_blk(atge_t *atgep, ddi_dma_attr_t *attr, int size, int d)
1473015a6ef6SSaurabh Misra {
1474015a6ef6SSaurabh Misra int err;
1475015a6ef6SSaurabh Misra atge_dma_t *dma;
1476015a6ef6SSaurabh Misra
1477015a6ef6SSaurabh Misra dma = kmem_zalloc(sizeof (atge_dma_t), KM_SLEEP);
1478015a6ef6SSaurabh Misra
1479015a6ef6SSaurabh Misra err = ddi_dma_alloc_handle(atgep->atge_dip, attr,
1480015a6ef6SSaurabh Misra DDI_DMA_SLEEP, NULL, &dma->hdl);
1481015a6ef6SSaurabh Misra
1482015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
1483015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "%s() : failed"
1484015a6ef6SSaurabh Misra " in ddi_dma_alloc_handle() : %d", __func__, err);
1485015a6ef6SSaurabh Misra goto fail;
1486015a6ef6SSaurabh Misra }
1487015a6ef6SSaurabh Misra
1488015a6ef6SSaurabh Misra err = ddi_dma_mem_alloc(dma->hdl,
1489015a6ef6SSaurabh Misra size, &atge_buf_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
1490015a6ef6SSaurabh Misra &dma->addr, &dma->len, &dma->acchdl);
1491015a6ef6SSaurabh Misra
1492015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
1493015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "%s() : failed"
1494015a6ef6SSaurabh Misra " in ddi_dma_mem_alloc() : %d", __func__, err);
1495015a6ef6SSaurabh Misra ddi_dma_free_handle(&dma->hdl);
1496015a6ef6SSaurabh Misra goto fail;
1497015a6ef6SSaurabh Misra }
1498015a6ef6SSaurabh Misra
1499015a6ef6SSaurabh Misra err = ddi_dma_addr_bind_handle(dma->hdl, NULL, dma->addr,
1500015a6ef6SSaurabh Misra dma->len, d | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP,
1501015a6ef6SSaurabh Misra NULL, &dma->cookie, &dma->count);
1502015a6ef6SSaurabh Misra
1503015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
1504015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "%s() : failed"
1505015a6ef6SSaurabh Misra " in ddi_dma_addr_bind_handle() : %d", __func__, err);
1506015a6ef6SSaurabh Misra ddi_dma_mem_free(&dma->acchdl);
1507015a6ef6SSaurabh Misra ddi_dma_free_handle(&dma->hdl);
1508015a6ef6SSaurabh Misra goto fail;
1509015a6ef6SSaurabh Misra }
1510015a6ef6SSaurabh Misra
1511015a6ef6SSaurabh Misra return (dma);
1512015a6ef6SSaurabh Misra fail:
1513015a6ef6SSaurabh Misra kmem_free(dma, sizeof (atge_dma_t));
1514015a6ef6SSaurabh Misra return (NULL);
1515015a6ef6SSaurabh Misra }
1516015a6ef6SSaurabh Misra
1517015a6ef6SSaurabh Misra void
atge_free_a_dma_blk(atge_dma_t * dma)1518015a6ef6SSaurabh Misra atge_free_a_dma_blk(atge_dma_t *dma)
1519015a6ef6SSaurabh Misra {
1520015a6ef6SSaurabh Misra if (dma != NULL) {
1521015a6ef6SSaurabh Misra (void) ddi_dma_unbind_handle(dma->hdl);
1522015a6ef6SSaurabh Misra ddi_dma_mem_free(&dma->acchdl);
1523015a6ef6SSaurabh Misra ddi_dma_free_handle(&dma->hdl);
1524015a6ef6SSaurabh Misra kmem_free(dma, sizeof (atge_dma_t));
1525015a6ef6SSaurabh Misra }
1526015a6ef6SSaurabh Misra }
1527015a6ef6SSaurabh Misra
1528015a6ef6SSaurabh Misra atge_dma_t *
atge_buf_alloc(atge_t * atgep,size_t len,int f)1529015a6ef6SSaurabh Misra atge_buf_alloc(atge_t *atgep, size_t len, int f)
1530015a6ef6SSaurabh Misra {
1531015a6ef6SSaurabh Misra atge_dma_t *dma = NULL;
1532015a6ef6SSaurabh Misra int err;
1533015a6ef6SSaurabh Misra
1534015a6ef6SSaurabh Misra dma = kmem_zalloc(sizeof (atge_dma_t), KM_SLEEP);
1535015a6ef6SSaurabh Misra
1536015a6ef6SSaurabh Misra err = ddi_dma_alloc_handle(atgep->atge_dip, &atge_dma_attr_buf,
1537015a6ef6SSaurabh Misra DDI_DMA_SLEEP, NULL, &dma->hdl);
1538015a6ef6SSaurabh Misra
1539015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
1540015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "%s() : failed"
1541015a6ef6SSaurabh Misra " in %s() : %d", __func__, err);
1542015a6ef6SSaurabh Misra goto fail;
1543015a6ef6SSaurabh Misra }
1544015a6ef6SSaurabh Misra
1545015a6ef6SSaurabh Misra err = ddi_dma_mem_alloc(dma->hdl, len, &atge_buf_attr,
1546015a6ef6SSaurabh Misra DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, &dma->addr,
1547015a6ef6SSaurabh Misra &dma->len, &dma->acchdl);
1548015a6ef6SSaurabh Misra
1549015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
1550015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "%s() : failed"
1551015a6ef6SSaurabh Misra " in %s() : %d", __func__, err);
1552015a6ef6SSaurabh Misra ddi_dma_free_handle(&dma->hdl);
1553015a6ef6SSaurabh Misra goto fail;
1554015a6ef6SSaurabh Misra }
1555015a6ef6SSaurabh Misra
1556015a6ef6SSaurabh Misra err = ddi_dma_addr_bind_handle(dma->hdl, NULL, dma->addr, dma->len,
1557015a6ef6SSaurabh Misra (f | DDI_DMA_CONSISTENT), DDI_DMA_SLEEP, NULL, &dma->cookie,
1558015a6ef6SSaurabh Misra &dma->count);
1559015a6ef6SSaurabh Misra
1560015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
1561015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "%s() : failed"
1562015a6ef6SSaurabh Misra " in %s() : %d", __func__, err);
1563015a6ef6SSaurabh Misra ddi_dma_mem_free(&dma->acchdl);
1564015a6ef6SSaurabh Misra ddi_dma_free_handle(&dma->hdl);
1565015a6ef6SSaurabh Misra goto fail;
1566015a6ef6SSaurabh Misra }
1567015a6ef6SSaurabh Misra
1568015a6ef6SSaurabh Misra /*
1569015a6ef6SSaurabh Misra * Number of return'ed cookie should be one.
1570015a6ef6SSaurabh Misra */
1571015a6ef6SSaurabh Misra ASSERT(dma->count == 1);
1572015a6ef6SSaurabh Misra
1573015a6ef6SSaurabh Misra return (dma);
1574015a6ef6SSaurabh Misra fail:
1575015a6ef6SSaurabh Misra kmem_free(dma, sizeof (atge_dma_t));
1576015a6ef6SSaurabh Misra return (NULL);
1577015a6ef6SSaurabh Misra }
1578015a6ef6SSaurabh Misra
1579015a6ef6SSaurabh Misra void
atge_buf_free(atge_dma_t * dma)1580015a6ef6SSaurabh Misra atge_buf_free(atge_dma_t *dma)
1581015a6ef6SSaurabh Misra {
1582015a6ef6SSaurabh Misra ASSERT(dma != NULL);
1583015a6ef6SSaurabh Misra
1584015a6ef6SSaurabh Misra (void) ddi_dma_unbind_handle(dma->hdl);
1585015a6ef6SSaurabh Misra ddi_dma_mem_free(&dma->acchdl);
1586015a6ef6SSaurabh Misra ddi_dma_free_handle(&dma->hdl);
1587015a6ef6SSaurabh Misra kmem_free(dma, sizeof (atge_dma_t));
1588015a6ef6SSaurabh Misra }
1589015a6ef6SSaurabh Misra
1590015a6ef6SSaurabh Misra static int
atge_resume(dev_info_t * dip)1591015a6ef6SSaurabh Misra atge_resume(dev_info_t *dip)
1592015a6ef6SSaurabh Misra {
1593015a6ef6SSaurabh Misra atge_t *atgep;
1594015a6ef6SSaurabh Misra
1595015a6ef6SSaurabh Misra if ((atgep = ddi_get_driver_private(dip)) == NULL) {
1596015a6ef6SSaurabh Misra return (DDI_FAILURE);
1597015a6ef6SSaurabh Misra }
1598015a6ef6SSaurabh Misra
1599015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_intr_lock);
1600015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock);
1601015a6ef6SSaurabh Misra
1602015a6ef6SSaurabh Misra atgep->atge_chip_state &= ~ATGE_CHIP_SUSPENDED;
1603015a6ef6SSaurabh Misra
1604015a6ef6SSaurabh Misra if (atgep->atge_chip_state & ATGE_CHIP_RUNNING) {
1605015a6ef6SSaurabh Misra atge_device_restart(atgep);
1606015a6ef6SSaurabh Misra } else {
1607015a6ef6SSaurabh Misra atge_device_reset(atgep);
1608015a6ef6SSaurabh Misra }
1609015a6ef6SSaurabh Misra
1610015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock);
1611015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_intr_lock);
1612015a6ef6SSaurabh Misra
1613015a6ef6SSaurabh Misra /*
1614015a6ef6SSaurabh Misra * Reset the PHY before resuming MII.
1615015a6ef6SSaurabh Misra */
16165e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
16175e8715b9SGary Mills case ATGE_CHIP_L1E:
1618015a6ef6SSaurabh Misra atge_l1e_mii_reset(atgep);
16195e8715b9SGary Mills break;
16205e8715b9SGary Mills case ATGE_CHIP_L1:
16215e8715b9SGary Mills break;
16225e8715b9SGary Mills case ATGE_CHIP_L1C:
16235e8715b9SGary Mills break;
1624015a6ef6SSaurabh Misra }
1625015a6ef6SSaurabh Misra
1626015a6ef6SSaurabh Misra mii_resume(atgep->atge_mii);
1627015a6ef6SSaurabh Misra
1628015a6ef6SSaurabh Misra /* kick-off downstream */
1629015a6ef6SSaurabh Misra mac_tx_update(atgep->atge_mh);
1630015a6ef6SSaurabh Misra
1631015a6ef6SSaurabh Misra return (DDI_SUCCESS);
1632015a6ef6SSaurabh Misra }
1633015a6ef6SSaurabh Misra
1634015a6ef6SSaurabh Misra static int
atge_quiesce(dev_info_t * dip)1635015a6ef6SSaurabh Misra atge_quiesce(dev_info_t *dip)
1636015a6ef6SSaurabh Misra {
1637015a6ef6SSaurabh Misra atge_t *atgep;
1638015a6ef6SSaurabh Misra
1639015a6ef6SSaurabh Misra if ((atgep = ddi_get_driver_private(dip)) == NULL) {
1640015a6ef6SSaurabh Misra return (DDI_FAILURE);
1641015a6ef6SSaurabh Misra }
1642015a6ef6SSaurabh Misra
1643015a6ef6SSaurabh Misra atge_device_stop(atgep);
1644015a6ef6SSaurabh Misra
1645015a6ef6SSaurabh Misra return (DDI_SUCCESS);
1646015a6ef6SSaurabh Misra }
1647015a6ef6SSaurabh Misra
1648015a6ef6SSaurabh Misra void
atge_add_multicst(atge_t * atgep,uint8_t * macaddr)1649015a6ef6SSaurabh Misra atge_add_multicst(atge_t *atgep, uint8_t *macaddr)
1650015a6ef6SSaurabh Misra {
1651015a6ef6SSaurabh Misra uint32_t crc;
1652015a6ef6SSaurabh Misra int bit;
1653015a6ef6SSaurabh Misra
1654015a6ef6SSaurabh Misra ASSERT(MUTEX_HELD(&atgep->atge_intr_lock));
1655015a6ef6SSaurabh Misra ASSERT(MUTEX_HELD(&atgep->atge_tx_lock));
1656015a6ef6SSaurabh Misra
1657015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() %x:%x:%x:%x:%x:%x",
1658015a6ef6SSaurabh Misra atgep->atge_name, __func__, macaddr[0], macaddr[1], macaddr[2],
1659015a6ef6SSaurabh Misra macaddr[3], macaddr[4], macaddr[5]));
1660015a6ef6SSaurabh Misra
1661015a6ef6SSaurabh Misra crc = atge_ether_crc(macaddr, ETHERADDRL);
1662015a6ef6SSaurabh Misra bit = (crc >> 26);
1663015a6ef6SSaurabh Misra atgep->atge_mchash_ref_cnt[bit]++;
1664015a6ef6SSaurabh Misra atgep->atge_mchash |= (1ULL << (crc >> 26));
1665015a6ef6SSaurabh Misra
1666015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() mchash :%llx, bit : %d,"
1667015a6ef6SSaurabh Misra " atge_mchash_ref_cnt[bit] :%d",
1668015a6ef6SSaurabh Misra atgep->atge_name, __func__, atgep->atge_mchash, bit,
1669015a6ef6SSaurabh Misra atgep->atge_mchash_ref_cnt[bit]));
1670015a6ef6SSaurabh Misra }
1671015a6ef6SSaurabh Misra
1672015a6ef6SSaurabh Misra void
atge_remove_multicst(atge_t * atgep,uint8_t * macaddr)1673015a6ef6SSaurabh Misra atge_remove_multicst(atge_t *atgep, uint8_t *macaddr)
1674015a6ef6SSaurabh Misra {
1675015a6ef6SSaurabh Misra uint32_t crc;
1676015a6ef6SSaurabh Misra int bit;
1677015a6ef6SSaurabh Misra
1678015a6ef6SSaurabh Misra ASSERT(MUTEX_HELD(&atgep->atge_intr_lock));
1679015a6ef6SSaurabh Misra ASSERT(MUTEX_HELD(&atgep->atge_tx_lock));
1680015a6ef6SSaurabh Misra
1681015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() %x:%x:%x:%x:%x:%x",
1682015a6ef6SSaurabh Misra atgep->atge_name, __func__, macaddr[0], macaddr[1], macaddr[2],
1683015a6ef6SSaurabh Misra macaddr[3], macaddr[4], macaddr[5]));
1684015a6ef6SSaurabh Misra
1685015a6ef6SSaurabh Misra crc = atge_ether_crc(macaddr, ETHERADDRL);
1686015a6ef6SSaurabh Misra bit = (crc >> 26);
1687015a6ef6SSaurabh Misra atgep->atge_mchash_ref_cnt[bit]--;
1688015a6ef6SSaurabh Misra if (atgep->atge_mchash_ref_cnt[bit] == 0)
1689015a6ef6SSaurabh Misra atgep->atge_mchash &= ~(1ULL << (crc >> 26));
1690015a6ef6SSaurabh Misra
1691015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() mchash :%llx, bit : %d,"
1692015a6ef6SSaurabh Misra " atge_mchash_ref_cnt[bit] :%d",
1693015a6ef6SSaurabh Misra atgep->atge_name, __func__, atgep->atge_mchash, bit,
1694015a6ef6SSaurabh Misra atgep->atge_mchash_ref_cnt[bit]));
1695015a6ef6SSaurabh Misra }
1696015a6ef6SSaurabh Misra
1697015a6ef6SSaurabh Misra int
atge_m_multicst(void * arg,boolean_t add,const uint8_t * macaddr)1698015a6ef6SSaurabh Misra atge_m_multicst(void *arg, boolean_t add, const uint8_t *macaddr)
1699015a6ef6SSaurabh Misra {
1700015a6ef6SSaurabh Misra atge_t *atgep = arg;
1701015a6ef6SSaurabh Misra
1702015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_intr_lock);
1703015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock);
1704015a6ef6SSaurabh Misra
1705015a6ef6SSaurabh Misra if (add) {
1706015a6ef6SSaurabh Misra atge_add_multicst(atgep, (uint8_t *)macaddr);
1707015a6ef6SSaurabh Misra } else {
1708015a6ef6SSaurabh Misra atge_remove_multicst(atgep, (uint8_t *)macaddr);
1709015a6ef6SSaurabh Misra }
1710015a6ef6SSaurabh Misra
1711015a6ef6SSaurabh Misra atge_rxfilter(atgep);
1712015a6ef6SSaurabh Misra
1713015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock);
1714015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_intr_lock);
1715015a6ef6SSaurabh Misra
1716015a6ef6SSaurabh Misra return (0);
1717015a6ef6SSaurabh Misra }
1718015a6ef6SSaurabh Misra
1719015a6ef6SSaurabh Misra int
atge_m_promisc(void * arg,boolean_t on)1720015a6ef6SSaurabh Misra atge_m_promisc(void *arg, boolean_t on)
1721015a6ef6SSaurabh Misra {
1722015a6ef6SSaurabh Misra atge_t *atgep = arg;
1723015a6ef6SSaurabh Misra
1724015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_intr_lock);
1725015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock);
1726015a6ef6SSaurabh Misra
1727015a6ef6SSaurabh Misra if (on) {
1728015a6ef6SSaurabh Misra atgep->atge_filter_flags |= ATGE_PROMISC;
1729015a6ef6SSaurabh Misra } else {
1730015a6ef6SSaurabh Misra atgep->atge_filter_flags &= ~ATGE_PROMISC;
1731015a6ef6SSaurabh Misra }
1732015a6ef6SSaurabh Misra
1733015a6ef6SSaurabh Misra if (atgep->atge_chip_state & ATGE_CHIP_RUNNING) {
1734015a6ef6SSaurabh Misra atge_rxfilter(atgep);
1735015a6ef6SSaurabh Misra }
1736015a6ef6SSaurabh Misra
1737015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock);
1738015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_intr_lock);
1739015a6ef6SSaurabh Misra
1740015a6ef6SSaurabh Misra return (0);
1741015a6ef6SSaurabh Misra }
1742015a6ef6SSaurabh Misra
1743015a6ef6SSaurabh Misra int
atge_m_unicst(void * arg,const uint8_t * macaddr)1744015a6ef6SSaurabh Misra atge_m_unicst(void *arg, const uint8_t *macaddr)
1745015a6ef6SSaurabh Misra {
1746015a6ef6SSaurabh Misra atge_t *atgep = arg;
1747015a6ef6SSaurabh Misra
1748015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_intr_lock);
1749015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock);
1750015a6ef6SSaurabh Misra bcopy(macaddr, atgep->atge_ether_addr, ETHERADDRL);
1751015a6ef6SSaurabh Misra atge_program_ether(atgep);
1752015a6ef6SSaurabh Misra atge_rxfilter(atgep);
1753015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock);
1754015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_intr_lock);
1755015a6ef6SSaurabh Misra
1756015a6ef6SSaurabh Misra return (0);
1757015a6ef6SSaurabh Misra }
1758015a6ef6SSaurabh Misra
1759015a6ef6SSaurabh Misra mblk_t *
atge_m_tx(void * arg,mblk_t * mp)1760015a6ef6SSaurabh Misra atge_m_tx(void *arg, mblk_t *mp)
1761015a6ef6SSaurabh Misra {
1762015a6ef6SSaurabh Misra atge_t *atgep = arg;
1763015a6ef6SSaurabh Misra mblk_t *nmp;
1764015a6ef6SSaurabh Misra
1765015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock);
1766015a6ef6SSaurabh Misra
1767015a6ef6SSaurabh Misra /*
1768015a6ef6SSaurabh Misra * This NIC does not like us to send pkt when link is down.
1769015a6ef6SSaurabh Misra */
1770015a6ef6SSaurabh Misra if (!(atgep->atge_link_state & LINK_STATE_UP)) {
1771015a6ef6SSaurabh Misra atgep->atge_tx_resched = 1;
17720eb090a7SSaurabh Misra
1773015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock);
1774015a6ef6SSaurabh Misra return (mp);
1775015a6ef6SSaurabh Misra }
1776015a6ef6SSaurabh Misra
1777015a6ef6SSaurabh Misra /*
1778015a6ef6SSaurabh Misra * Don't send a pkt if chip isn't running or in suspended state.
1779015a6ef6SSaurabh Misra */
1780015a6ef6SSaurabh Misra if ((atgep->atge_chip_state & ATGE_CHIP_RUNNING) == 0 ||
1781015a6ef6SSaurabh Misra atgep->atge_chip_state & ATGE_CHIP_SUSPENDED) {
1782015a6ef6SSaurabh Misra atgep->atge_carrier_errors++;
1783015a6ef6SSaurabh Misra atgep->atge_tx_resched = 1;
17840eb090a7SSaurabh Misra
1785015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock);
1786015a6ef6SSaurabh Misra return (mp);
1787015a6ef6SSaurabh Misra }
1788015a6ef6SSaurabh Misra
1789015a6ef6SSaurabh Misra while (mp != NULL) {
1790015a6ef6SSaurabh Misra nmp = mp->b_next;
1791015a6ef6SSaurabh Misra mp->b_next = NULL;
1792015a6ef6SSaurabh Misra
17930eb090a7SSaurabh Misra if (atge_send_a_packet(atgep, mp) == DDI_FAILURE) {
1794015a6ef6SSaurabh Misra mp->b_next = nmp;
1795015a6ef6SSaurabh Misra break;
1796015a6ef6SSaurabh Misra }
1797015a6ef6SSaurabh Misra
1798015a6ef6SSaurabh Misra mp = nmp;
1799015a6ef6SSaurabh Misra }
1800015a6ef6SSaurabh Misra
1801015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock);
1802015a6ef6SSaurabh Misra return (mp);
1803015a6ef6SSaurabh Misra }
1804015a6ef6SSaurabh Misra
1805015a6ef6SSaurabh Misra int
atge_m_start(void * arg)1806015a6ef6SSaurabh Misra atge_m_start(void *arg)
1807015a6ef6SSaurabh Misra {
1808015a6ef6SSaurabh Misra atge_t *atgep = arg;
1809015a6ef6SSaurabh Misra int started = 0;
1810015a6ef6SSaurabh Misra
1811015a6ef6SSaurabh Misra ASSERT(atgep != NULL);
1812015a6ef6SSaurabh Misra
1813015a6ef6SSaurabh Misra
1814015a6ef6SSaurabh Misra mii_stop(atgep->atge_mii);
1815015a6ef6SSaurabh Misra
1816015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_intr_lock);
1817015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock);
1818015a6ef6SSaurabh Misra
1819015a6ef6SSaurabh Misra if (!(atgep->atge_chip_state & ATGE_CHIP_SUSPENDED)) {
1820015a6ef6SSaurabh Misra atge_device_restart(atgep);
1821015a6ef6SSaurabh Misra started = 1;
1822015a6ef6SSaurabh Misra }
1823015a6ef6SSaurabh Misra
1824015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock);
1825015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_intr_lock);
1826015a6ef6SSaurabh Misra
1827015a6ef6SSaurabh Misra mii_start(atgep->atge_mii);
1828015a6ef6SSaurabh Misra
1829015a6ef6SSaurabh Misra /* kick-off downstream */
1830015a6ef6SSaurabh Misra if (started)
1831015a6ef6SSaurabh Misra mac_tx_update(atgep->atge_mh);
1832015a6ef6SSaurabh Misra
1833015a6ef6SSaurabh Misra return (0);
1834015a6ef6SSaurabh Misra }
1835015a6ef6SSaurabh Misra
1836015a6ef6SSaurabh Misra void
atge_m_stop(void * arg)1837015a6ef6SSaurabh Misra atge_m_stop(void *arg)
1838015a6ef6SSaurabh Misra {
1839015a6ef6SSaurabh Misra atge_t *atgep = arg;
1840015a6ef6SSaurabh Misra
1841015a6ef6SSaurabh Misra mii_stop(atgep->atge_mii);
1842015a6ef6SSaurabh Misra
1843015a6ef6SSaurabh Misra /*
1844015a6ef6SSaurabh Misra * Cancel any pending I/O.
1845015a6ef6SSaurabh Misra */
1846015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_intr_lock);
1847015a6ef6SSaurabh Misra atgep->atge_chip_state &= ~ATGE_CHIP_RUNNING;
1848015a6ef6SSaurabh Misra if (!(atgep->atge_chip_state & ATGE_CHIP_SUSPENDED))
1849015a6ef6SSaurabh Misra atge_device_stop(atgep);
1850015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_intr_lock);
1851015a6ef6SSaurabh Misra }
1852015a6ef6SSaurabh Misra
1853015a6ef6SSaurabh Misra int
atge_m_stat(void * arg,uint_t stat,uint64_t * val)1854015a6ef6SSaurabh Misra atge_m_stat(void *arg, uint_t stat, uint64_t *val)
1855015a6ef6SSaurabh Misra {
1856015a6ef6SSaurabh Misra atge_t *atgep = arg;
1857015a6ef6SSaurabh Misra
1858015a6ef6SSaurabh Misra if (mii_m_getstat(atgep->atge_mii, stat, val) == 0) {
1859015a6ef6SSaurabh Misra return (0);
1860015a6ef6SSaurabh Misra }
1861015a6ef6SSaurabh Misra
1862015a6ef6SSaurabh Misra switch (stat) {
1863015a6ef6SSaurabh Misra case MAC_STAT_MULTIRCV:
1864015a6ef6SSaurabh Misra *val = atgep->atge_multircv;
1865015a6ef6SSaurabh Misra break;
1866015a6ef6SSaurabh Misra
1867015a6ef6SSaurabh Misra case MAC_STAT_BRDCSTRCV:
1868015a6ef6SSaurabh Misra *val = atgep->atge_brdcstrcv;
1869015a6ef6SSaurabh Misra break;
1870015a6ef6SSaurabh Misra
1871015a6ef6SSaurabh Misra case MAC_STAT_MULTIXMT:
1872015a6ef6SSaurabh Misra *val = atgep->atge_multixmt;
1873015a6ef6SSaurabh Misra break;
1874015a6ef6SSaurabh Misra
1875015a6ef6SSaurabh Misra case MAC_STAT_BRDCSTXMT:
1876015a6ef6SSaurabh Misra *val = atgep->atge_brdcstxmt;
1877015a6ef6SSaurabh Misra break;
1878015a6ef6SSaurabh Misra
1879015a6ef6SSaurabh Misra case MAC_STAT_IPACKETS:
1880015a6ef6SSaurabh Misra *val = atgep->atge_ipackets;
1881015a6ef6SSaurabh Misra break;
1882015a6ef6SSaurabh Misra
1883015a6ef6SSaurabh Misra case MAC_STAT_RBYTES:
1884015a6ef6SSaurabh Misra *val = atgep->atge_rbytes;
1885015a6ef6SSaurabh Misra break;
1886015a6ef6SSaurabh Misra
1887015a6ef6SSaurabh Misra case MAC_STAT_OPACKETS:
1888015a6ef6SSaurabh Misra *val = atgep->atge_opackets;
1889015a6ef6SSaurabh Misra break;
1890015a6ef6SSaurabh Misra
1891015a6ef6SSaurabh Misra case MAC_STAT_OBYTES:
1892015a6ef6SSaurabh Misra *val = atgep->atge_obytes;
1893015a6ef6SSaurabh Misra break;
1894015a6ef6SSaurabh Misra
1895015a6ef6SSaurabh Misra case MAC_STAT_NORCVBUF:
1896015a6ef6SSaurabh Misra *val = atgep->atge_norcvbuf;
1897015a6ef6SSaurabh Misra break;
1898015a6ef6SSaurabh Misra
1899015a6ef6SSaurabh Misra case MAC_STAT_NOXMTBUF:
1900015a6ef6SSaurabh Misra *val = 0;
1901015a6ef6SSaurabh Misra break;
1902015a6ef6SSaurabh Misra
1903015a6ef6SSaurabh Misra case MAC_STAT_COLLISIONS:
1904015a6ef6SSaurabh Misra *val = atgep->atge_collisions;
1905015a6ef6SSaurabh Misra break;
1906015a6ef6SSaurabh Misra
1907015a6ef6SSaurabh Misra case MAC_STAT_IERRORS:
1908015a6ef6SSaurabh Misra *val = atgep->atge_errrcv;
1909015a6ef6SSaurabh Misra break;
1910015a6ef6SSaurabh Misra
1911015a6ef6SSaurabh Misra case MAC_STAT_OERRORS:
1912015a6ef6SSaurabh Misra *val = atgep->atge_errxmt;
1913015a6ef6SSaurabh Misra break;
1914015a6ef6SSaurabh Misra
1915015a6ef6SSaurabh Misra case ETHER_STAT_ALIGN_ERRORS:
1916015a6ef6SSaurabh Misra *val = atgep->atge_align_errors;
1917015a6ef6SSaurabh Misra break;
1918015a6ef6SSaurabh Misra
1919015a6ef6SSaurabh Misra case ETHER_STAT_FCS_ERRORS:
1920015a6ef6SSaurabh Misra *val = atgep->atge_fcs_errors;
1921015a6ef6SSaurabh Misra break;
1922015a6ef6SSaurabh Misra
1923015a6ef6SSaurabh Misra case ETHER_STAT_SQE_ERRORS:
1924015a6ef6SSaurabh Misra *val = atgep->atge_sqe_errors;
1925015a6ef6SSaurabh Misra break;
1926015a6ef6SSaurabh Misra
1927015a6ef6SSaurabh Misra case ETHER_STAT_DEFER_XMTS:
1928015a6ef6SSaurabh Misra *val = atgep->atge_defer_xmts;
1929015a6ef6SSaurabh Misra break;
1930015a6ef6SSaurabh Misra
1931015a6ef6SSaurabh Misra case ETHER_STAT_FIRST_COLLISIONS:
1932015a6ef6SSaurabh Misra *val = atgep->atge_first_collisions;
1933015a6ef6SSaurabh Misra break;
1934015a6ef6SSaurabh Misra
1935015a6ef6SSaurabh Misra case ETHER_STAT_MULTI_COLLISIONS:
1936015a6ef6SSaurabh Misra *val = atgep->atge_multi_collisions;
1937015a6ef6SSaurabh Misra break;
1938015a6ef6SSaurabh Misra
1939015a6ef6SSaurabh Misra case ETHER_STAT_TX_LATE_COLLISIONS:
1940015a6ef6SSaurabh Misra *val = atgep->atge_tx_late_collisions;
1941015a6ef6SSaurabh Misra break;
1942015a6ef6SSaurabh Misra
1943015a6ef6SSaurabh Misra case ETHER_STAT_EX_COLLISIONS:
1944015a6ef6SSaurabh Misra *val = atgep->atge_ex_collisions;
1945015a6ef6SSaurabh Misra break;
1946015a6ef6SSaurabh Misra
1947015a6ef6SSaurabh Misra case ETHER_STAT_MACXMT_ERRORS:
1948015a6ef6SSaurabh Misra *val = atgep->atge_macxmt_errors;
1949015a6ef6SSaurabh Misra break;
1950015a6ef6SSaurabh Misra
1951015a6ef6SSaurabh Misra case ETHER_STAT_CARRIER_ERRORS:
1952015a6ef6SSaurabh Misra *val = atgep->atge_carrier_errors;
1953015a6ef6SSaurabh Misra break;
1954015a6ef6SSaurabh Misra
1955015a6ef6SSaurabh Misra case ETHER_STAT_TOOLONG_ERRORS:
1956015a6ef6SSaurabh Misra *val = atgep->atge_toolong_errors;
1957015a6ef6SSaurabh Misra break;
1958015a6ef6SSaurabh Misra
1959015a6ef6SSaurabh Misra case ETHER_STAT_MACRCV_ERRORS:
1960015a6ef6SSaurabh Misra *val = atgep->atge_macrcv_errors;
1961015a6ef6SSaurabh Misra break;
1962015a6ef6SSaurabh Misra
1963015a6ef6SSaurabh Misra case MAC_STAT_OVERFLOWS:
1964015a6ef6SSaurabh Misra *val = atgep->atge_overflow;
1965015a6ef6SSaurabh Misra break;
1966015a6ef6SSaurabh Misra
1967015a6ef6SSaurabh Misra case MAC_STAT_UNDERFLOWS:
1968015a6ef6SSaurabh Misra *val = atgep->atge_underflow;
1969015a6ef6SSaurabh Misra break;
1970015a6ef6SSaurabh Misra
1971015a6ef6SSaurabh Misra case ETHER_STAT_TOOSHORT_ERRORS:
1972015a6ef6SSaurabh Misra *val = atgep->atge_runt;
1973015a6ef6SSaurabh Misra break;
1974015a6ef6SSaurabh Misra
1975015a6ef6SSaurabh Misra case ETHER_STAT_JABBER_ERRORS:
1976015a6ef6SSaurabh Misra *val = atgep->atge_jabber;
1977015a6ef6SSaurabh Misra break;
1978015a6ef6SSaurabh Misra
1979015a6ef6SSaurabh Misra default:
1980015a6ef6SSaurabh Misra return (ENOTSUP);
1981015a6ef6SSaurabh Misra }
1982015a6ef6SSaurabh Misra
1983015a6ef6SSaurabh Misra return (0);
1984015a6ef6SSaurabh Misra }
1985015a6ef6SSaurabh Misra
1986015a6ef6SSaurabh Misra int
atge_m_getprop(void * arg,const char * name,mac_prop_id_t num,uint_t sz,void * val)19870dc2366fSVenugopal Iyer atge_m_getprop(void *arg, const char *name, mac_prop_id_t num, uint_t sz,
19880dc2366fSVenugopal Iyer void *val)
1989015a6ef6SSaurabh Misra {
1990015a6ef6SSaurabh Misra atge_t *atgep = arg;
1991015a6ef6SSaurabh Misra
19920dc2366fSVenugopal Iyer return (mii_m_getprop(atgep->atge_mii, name, num, sz, val));
1993015a6ef6SSaurabh Misra }
1994015a6ef6SSaurabh Misra
1995015a6ef6SSaurabh Misra int
atge_m_setprop(void * arg,const char * name,mac_prop_id_t num,uint_t sz,const void * val)1996015a6ef6SSaurabh Misra atge_m_setprop(void *arg, const char *name, mac_prop_id_t num, uint_t sz,
1997015a6ef6SSaurabh Misra const void *val)
1998015a6ef6SSaurabh Misra {
1999015a6ef6SSaurabh Misra atge_t *atgep = arg;
20000eb090a7SSaurabh Misra int r;
20010eb090a7SSaurabh Misra
20020eb090a7SSaurabh Misra r = mii_m_setprop(atgep->atge_mii, name, num, sz, val);
20030eb090a7SSaurabh Misra
20040eb090a7SSaurabh Misra if (r == 0) {
20050eb090a7SSaurabh Misra mutex_enter(&atgep->atge_intr_lock);
20060eb090a7SSaurabh Misra mutex_enter(&atgep->atge_tx_lock);
2007015a6ef6SSaurabh Misra
20080eb090a7SSaurabh Misra if (atgep->atge_chip_state & ATGE_CHIP_RUNNING) {
20090eb090a7SSaurabh Misra atge_device_restart(atgep);
20100eb090a7SSaurabh Misra }
20110eb090a7SSaurabh Misra
20120eb090a7SSaurabh Misra mutex_exit(&atgep->atge_tx_lock);
20130eb090a7SSaurabh Misra mutex_exit(&atgep->atge_intr_lock);
20140eb090a7SSaurabh Misra }
20150eb090a7SSaurabh Misra
20160eb090a7SSaurabh Misra return (r);
2017015a6ef6SSaurabh Misra }
2018015a6ef6SSaurabh Misra
20190dc2366fSVenugopal Iyer static void
atge_m_propinfo(void * arg,const char * name,mac_prop_id_t num,mac_prop_info_handle_t prh)20200dc2366fSVenugopal Iyer atge_m_propinfo(void *arg, const char *name, mac_prop_id_t num,
20210dc2366fSVenugopal Iyer mac_prop_info_handle_t prh)
20220dc2366fSVenugopal Iyer {
20230dc2366fSVenugopal Iyer atge_t *atgep = arg;
20240dc2366fSVenugopal Iyer
20250dc2366fSVenugopal Iyer mii_m_propinfo(atgep->atge_mii, name, num, prh);
20260dc2366fSVenugopal Iyer }
2027015a6ef6SSaurabh Misra
2028015a6ef6SSaurabh Misra void
atge_program_ether(atge_t * atgep)2029015a6ef6SSaurabh Misra atge_program_ether(atge_t *atgep)
2030015a6ef6SSaurabh Misra {
2031015a6ef6SSaurabh Misra ether_addr_t e;
2032015a6ef6SSaurabh Misra
2033015a6ef6SSaurabh Misra /*
2034015a6ef6SSaurabh Misra * Reprogram the Station address.
2035015a6ef6SSaurabh Misra */
2036015a6ef6SSaurabh Misra bcopy(atgep->atge_ether_addr, e, ETHERADDRL);
2037015a6ef6SSaurabh Misra OUTL(atgep, ATGE_PAR0,
2038015a6ef6SSaurabh Misra ((e[2] << 24) | (e[3] << 16) | (e[4] << 8) | e[5]));
2039015a6ef6SSaurabh Misra OUTL(atgep, ATGE_PAR1, (e[0] << 8) | e[1]);
2040015a6ef6SSaurabh Misra }
2041015a6ef6SSaurabh Misra
2042015a6ef6SSaurabh Misra /*
2043015a6ef6SSaurabh Misra * Device specific operations.
2044015a6ef6SSaurabh Misra */
2045015a6ef6SSaurabh Misra void
atge_device_start(atge_t * atgep)2046015a6ef6SSaurabh Misra atge_device_start(atge_t *atgep)
2047015a6ef6SSaurabh Misra {
20480eb090a7SSaurabh Misra uint32_t rxf_hi, rxf_lo, rrd_hi, rrd_lo;
2049015a6ef6SSaurabh Misra uint32_t reg;
2050015a6ef6SSaurabh Misra uint32_t fsize;
2051015a6ef6SSaurabh Misra
2052015a6ef6SSaurabh Misra /*
2053015a6ef6SSaurabh Misra * Reprogram the Station address.
2054015a6ef6SSaurabh Misra */
2055015a6ef6SSaurabh Misra atge_program_ether(atgep);
2056015a6ef6SSaurabh Misra
20575e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
20585e8715b9SGary Mills case ATGE_CHIP_L1E:
2059015a6ef6SSaurabh Misra atge_l1e_program_dma(atgep);
20605e8715b9SGary Mills break;
20615e8715b9SGary Mills case ATGE_CHIP_L1:
20620eb090a7SSaurabh Misra atge_l1_program_dma(atgep);
20635e8715b9SGary Mills break;
20645e8715b9SGary Mills case ATGE_CHIP_L1C:
20655e8715b9SGary Mills atge_l1c_program_dma(atgep);
20665e8715b9SGary Mills break;
2067015a6ef6SSaurabh Misra }
2068015a6ef6SSaurabh Misra
2069015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() dma, counters programmed ", atgep->atge_name,
2070015a6ef6SSaurabh Misra __func__));
2071015a6ef6SSaurabh Misra
20725e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
20735e8715b9SGary Mills case ATGE_CHIP_L1E:
20745e8715b9SGary Mills case ATGE_CHIP_L1:
20755e8715b9SGary Mills OUTW(atgep, ATGE_INTR_CLR_TIMER, 1*1000/2);
20765e8715b9SGary Mills break;
20775e8715b9SGary Mills case ATGE_CHIP_L1C:
20785e8715b9SGary Mills /*
20795e8715b9SGary Mills * Disable interrupt re-trigger timer. We don't want automatic
20805e8715b9SGary Mills * re-triggering of un-ACKed interrupts.
20815e8715b9SGary Mills */
20825e8715b9SGary Mills OUTL(atgep, ATGE_INTR_RETRIG_TIMER, ATGE_USECS(0));
20835e8715b9SGary Mills /* Configure CMB. */
20845e8715b9SGary Mills OUTL(atgep, ATGE_CMB_TX_TIMER, ATGE_USECS(0));
20855e8715b9SGary Mills /*
20865e8715b9SGary Mills * Hardware can be configured to issue SMB interrupt based
20875e8715b9SGary Mills * on programmed interval. Since there is a callout that is
20885e8715b9SGary Mills * invoked for every hz in driver we use that instead of
20895e8715b9SGary Mills * relying on periodic SMB interrupt.
20905e8715b9SGary Mills */
20915e8715b9SGary Mills OUTL(atgep, ATGE_SMB_STAT_TIMER, ATGE_USECS(0));
20925e8715b9SGary Mills /* Clear MAC statistics. */
20935e8715b9SGary Mills atge_l1c_clear_stats(atgep);
20945e8715b9SGary Mills break;
20955e8715b9SGary Mills }
2096015a6ef6SSaurabh Misra
2097015a6ef6SSaurabh Misra /*
20980eb090a7SSaurabh Misra * Set Maximum frame size but don't let MTU be less than ETHER_MTU.
2099015a6ef6SSaurabh Misra */
2100015a6ef6SSaurabh Misra if (atgep->atge_mtu < ETHERMTU)
2101015a6ef6SSaurabh Misra atgep->atge_max_frame_size = ETHERMTU;
2102015a6ef6SSaurabh Misra else
2103015a6ef6SSaurabh Misra atgep->atge_max_frame_size = atgep->atge_mtu;
2104015a6ef6SSaurabh Misra
2105015a6ef6SSaurabh Misra atgep->atge_max_frame_size += sizeof (struct ether_header) +
2106015a6ef6SSaurabh Misra VLAN_TAGSZ + ETHERFCSL;
2107015a6ef6SSaurabh Misra OUTL(atgep, ATGE_FRAME_SIZE, atgep->atge_max_frame_size);
2108015a6ef6SSaurabh Misra
21095e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
21105e8715b9SGary Mills case ATGE_CHIP_L1E:
21115e8715b9SGary Mills break;
21125e8715b9SGary Mills case ATGE_CHIP_L1:
21135e8715b9SGary Mills break;
21145e8715b9SGary Mills case ATGE_CHIP_L1C:
21155e8715b9SGary Mills /* Disable header split(?) */
21165e8715b9SGary Mills OUTL(atgep, ATGE_HDS_CFG, 0);
21175e8715b9SGary Mills break;
21185e8715b9SGary Mills }
2119015a6ef6SSaurabh Misra
2120015a6ef6SSaurabh Misra /*
2121015a6ef6SSaurabh Misra * Configure IPG/IFG parameters.
2122015a6ef6SSaurabh Misra */
2123015a6ef6SSaurabh Misra OUTL(atgep, ATGE_IPG_IFG_CFG,
2124015a6ef6SSaurabh Misra ((IPG_IFG_IPG2_DEFAULT << IPG_IFG_IPG2_SHIFT) & IPG_IFG_IPG2_MASK) |
2125015a6ef6SSaurabh Misra ((IPG_IFG_IPG1_DEFAULT << IPG_IFG_IPG1_SHIFT) & IPG_IFG_IPG1_MASK) |
2126015a6ef6SSaurabh Misra ((IPG_IFG_MIFG_DEFAULT << IPG_IFG_MIFG_SHIFT) & IPG_IFG_MIFG_MASK) |
2127015a6ef6SSaurabh Misra ((IPG_IFG_IPGT_DEFAULT << IPG_IFG_IPGT_SHIFT) & IPG_IFG_IPGT_MASK));
2128015a6ef6SSaurabh Misra
2129015a6ef6SSaurabh Misra /*
2130015a6ef6SSaurabh Misra * Set parameters for half-duplex media.
2131015a6ef6SSaurabh Misra */
2132015a6ef6SSaurabh Misra OUTL(atgep, ATGE_HDPX_CFG,
2133015a6ef6SSaurabh Misra ((HDPX_CFG_LCOL_DEFAULT << HDPX_CFG_LCOL_SHIFT) &
2134015a6ef6SSaurabh Misra HDPX_CFG_LCOL_MASK) |
2135015a6ef6SSaurabh Misra ((HDPX_CFG_RETRY_DEFAULT << HDPX_CFG_RETRY_SHIFT) &
2136015a6ef6SSaurabh Misra HDPX_CFG_RETRY_MASK) | HDPX_CFG_EXC_DEF_EN |
2137015a6ef6SSaurabh Misra ((HDPX_CFG_ABEBT_DEFAULT << HDPX_CFG_ABEBT_SHIFT) &
2138015a6ef6SSaurabh Misra HDPX_CFG_ABEBT_MASK) |
2139015a6ef6SSaurabh Misra ((HDPX_CFG_JAMIPG_DEFAULT << HDPX_CFG_JAMIPG_SHIFT) &
2140015a6ef6SSaurabh Misra HDPX_CFG_JAMIPG_MASK));
2141015a6ef6SSaurabh Misra
2142015a6ef6SSaurabh Misra /*
2143015a6ef6SSaurabh Misra * Configure jumbo frame.
2144015a6ef6SSaurabh Misra */
21455e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
21465e8715b9SGary Mills case ATGE_CHIP_L1E:
21475e8715b9SGary Mills if (atgep->atge_flags & ATGE_FLAG_JUMBO) {
21485e8715b9SGary Mills
21495e8715b9SGary Mills if (atgep->atge_mtu < ETHERMTU)
21505e8715b9SGary Mills reg = atgep->atge_max_frame_size;
21515e8715b9SGary Mills else if (atgep->atge_mtu < 6 * 1024)
21525e8715b9SGary Mills reg = (atgep->atge_max_frame_size * 2) / 3;
21535e8715b9SGary Mills else
21545e8715b9SGary Mills reg = atgep->atge_max_frame_size / 2;
21555e8715b9SGary Mills
21565e8715b9SGary Mills OUTL(atgep, L1E_TX_JUMBO_THRESH,
21575e8715b9SGary Mills ROUNDUP(reg, TX_JUMBO_THRESH_UNIT) >>
21585e8715b9SGary Mills TX_JUMBO_THRESH_UNIT_SHIFT);
21595e8715b9SGary Mills }
21605e8715b9SGary Mills break;
21615e8715b9SGary Mills case ATGE_CHIP_L1:
2162015a6ef6SSaurabh Misra fsize = ROUNDUP(atgep->atge_max_frame_size, sizeof (uint64_t));
2163015a6ef6SSaurabh Misra OUTL(atgep, ATGE_RXQ_JUMBO_CFG,
2164015a6ef6SSaurabh Misra (((fsize / sizeof (uint64_t)) <<
2165015a6ef6SSaurabh Misra RXQ_JUMBO_CFG_SZ_THRESH_SHIFT) &
2166015a6ef6SSaurabh Misra RXQ_JUMBO_CFG_SZ_THRESH_MASK) |
2167015a6ef6SSaurabh Misra ((RXQ_JUMBO_CFG_LKAH_DEFAULT <<
2168015a6ef6SSaurabh Misra RXQ_JUMBO_CFG_LKAH_SHIFT) & RXQ_JUMBO_CFG_LKAH_MASK) |
2169015a6ef6SSaurabh Misra ((ATGE_USECS(8) << RXQ_JUMBO_CFG_RRD_TIMER_SHIFT) &
2170015a6ef6SSaurabh Misra RXQ_JUMBO_CFG_RRD_TIMER_MASK));
21715e8715b9SGary Mills break;
21725e8715b9SGary Mills case ATGE_CHIP_L1C:
21735e8715b9SGary Mills break;
2174015a6ef6SSaurabh Misra }
2175015a6ef6SSaurabh Misra
2176015a6ef6SSaurabh Misra /*
2177015a6ef6SSaurabh Misra * Configure flow-control parameters.
2178015a6ef6SSaurabh Misra */
21795e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
21805e8715b9SGary Mills case ATGE_CHIP_L1E:
21815e8715b9SGary Mills case ATGE_CHIP_L1:
21825e8715b9SGary Mills if ((atgep->atge_flags & ATGE_FLAG_PCIE) != 0) {
2183015a6ef6SSaurabh Misra /*
2184015a6ef6SSaurabh Misra * Some hardware version require this magic.
2185015a6ef6SSaurabh Misra */
21865e8715b9SGary Mills OUTL(atgep, ATGE_LTSSM_ID_CFG, 0x6500);
2187015a6ef6SSaurabh Misra reg = INL(atgep, 0x1008);
2188015a6ef6SSaurabh Misra OUTL(atgep, 0x1008, reg | 0x8000);
21895e8715b9SGary Mills }
21905e8715b9SGary Mills break;
21915e8715b9SGary Mills case ATGE_CHIP_L1C:
21925e8715b9SGary Mills break;
2193015a6ef6SSaurabh Misra }
2194015a6ef6SSaurabh Misra
2195015a6ef6SSaurabh Misra /*
2196015a6ef6SSaurabh Misra * These are all magic parameters which came from FreeBSD.
2197015a6ef6SSaurabh Misra */
21985e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
21995e8715b9SGary Mills case ATGE_CHIP_L1E:
22005e8715b9SGary Mills reg = INL(atgep, L1E_SRAM_RX_FIFO_LEN);
22015e8715b9SGary Mills rxf_hi = (reg * 4) / 5;
22025e8715b9SGary Mills rxf_lo = reg/ 5;
22035e8715b9SGary Mills
22045e8715b9SGary Mills OUTL(atgep, ATGE_RXQ_FIFO_PAUSE_THRESH,
22055e8715b9SGary Mills ((rxf_lo << RXQ_FIFO_PAUSE_THRESH_LO_SHIFT) &
22065e8715b9SGary Mills RXQ_FIFO_PAUSE_THRESH_LO_MASK) |
22075e8715b9SGary Mills ((rxf_hi << RXQ_FIFO_PAUSE_THRESH_HI_SHIFT) &
22085e8715b9SGary Mills RXQ_FIFO_PAUSE_THRESH_HI_MASK));
22095e8715b9SGary Mills break;
22105e8715b9SGary Mills case ATGE_CHIP_L1:
22110eb090a7SSaurabh Misra switch (atgep->atge_chip_rev) {
22120eb090a7SSaurabh Misra case 0x8001:
22130eb090a7SSaurabh Misra case 0x9001:
22140eb090a7SSaurabh Misra case 0x9002:
22150eb090a7SSaurabh Misra case 0x9003:
22160eb090a7SSaurabh Misra rxf_hi = L1_RX_RING_CNT / 16;
22170eb090a7SSaurabh Misra rxf_lo = (L1_RX_RING_CNT * 7) / 8;
22180eb090a7SSaurabh Misra rrd_hi = (L1_RR_RING_CNT * 7) / 8;
22190eb090a7SSaurabh Misra rrd_lo = L1_RR_RING_CNT / 16;
22200eb090a7SSaurabh Misra break;
22210eb090a7SSaurabh Misra default:
22220eb090a7SSaurabh Misra reg = INL(atgep, L1_SRAM_RX_FIFO_LEN);
22230eb090a7SSaurabh Misra rxf_lo = reg / 16;
22240eb090a7SSaurabh Misra if (rxf_lo > 192)
22250eb090a7SSaurabh Misra rxf_lo = 192;
22260eb090a7SSaurabh Misra rxf_hi = (reg * 7) / 8;
22270eb090a7SSaurabh Misra if (rxf_hi < rxf_lo)
22280eb090a7SSaurabh Misra rxf_hi = rxf_lo + 16;
22290eb090a7SSaurabh Misra reg = INL(atgep, L1_SRAM_RRD_LEN);
22300eb090a7SSaurabh Misra rrd_lo = reg / 8;
22310eb090a7SSaurabh Misra rrd_hi = (reg * 7) / 8;
22320eb090a7SSaurabh Misra if (rrd_lo > 2)
22330eb090a7SSaurabh Misra rrd_lo = 2;
22340eb090a7SSaurabh Misra if (rrd_hi < rrd_lo)
22350eb090a7SSaurabh Misra rrd_hi = rrd_lo + 3;
22360eb090a7SSaurabh Misra break;
22370eb090a7SSaurabh Misra }
22380eb090a7SSaurabh Misra
22390eb090a7SSaurabh Misra OUTL(atgep, ATGE_RXQ_FIFO_PAUSE_THRESH,
22400eb090a7SSaurabh Misra ((rxf_lo << RXQ_FIFO_PAUSE_THRESH_LO_SHIFT) &
22410eb090a7SSaurabh Misra RXQ_FIFO_PAUSE_THRESH_LO_MASK) |
22420eb090a7SSaurabh Misra ((rxf_hi << RXQ_FIFO_PAUSE_THRESH_HI_SHIFT) &
22430eb090a7SSaurabh Misra RXQ_FIFO_PAUSE_THRESH_HI_MASK));
22440eb090a7SSaurabh Misra
22450eb090a7SSaurabh Misra OUTL(atgep, L1_RXQ_RRD_PAUSE_THRESH,
22460eb090a7SSaurabh Misra ((rrd_lo << RXQ_RRD_PAUSE_THRESH_LO_SHIFT) &
22470eb090a7SSaurabh Misra RXQ_RRD_PAUSE_THRESH_LO_MASK) |
22480eb090a7SSaurabh Misra ((rrd_hi << RXQ_RRD_PAUSE_THRESH_HI_SHIFT) &
22490eb090a7SSaurabh Misra RXQ_RRD_PAUSE_THRESH_HI_MASK));
22505e8715b9SGary Mills break;
22515e8715b9SGary Mills case ATGE_CHIP_L1C:
22525e8715b9SGary Mills switch (ATGE_DID(atgep)) {
22535e8715b9SGary Mills case ATGE_CHIP_AR8151V2_DEV_ID:
22545e8715b9SGary Mills case ATGE_CHIP_AR8152V1_DEV_ID:
22555e8715b9SGary Mills OUTL(atgep, ATGE_SERDES_LOCK,
22565e8715b9SGary Mills INL(atgep, ATGE_SERDES_LOCK) |
22575e8715b9SGary Mills SERDES_MAC_CLK_SLOWDOWN |
22585e8715b9SGary Mills SERDES_PHY_CLK_SLOWDOWN);
22595e8715b9SGary Mills break;
22605e8715b9SGary Mills case ATGE_CHIP_L1CG_DEV_ID:
22615e8715b9SGary Mills case ATGE_CHIP_L1CF_DEV_ID:
22625e8715b9SGary Mills /*
22635e8715b9SGary Mills * Configure flow control parameters.
22645e8715b9SGary Mills * XON : 80% of Rx FIFO
22655e8715b9SGary Mills * XOFF : 30% of Rx FIFO
22665e8715b9SGary Mills */
22675e8715b9SGary Mills reg = INL(atgep, L1C_SRAM_RX_FIFO_LEN);
22685e8715b9SGary Mills rxf_hi = (reg * 8) / 10;
22695e8715b9SGary Mills rxf_lo = (reg * 3) / 10;
22705e8715b9SGary Mills
22715e8715b9SGary Mills OUTL(atgep, ATGE_RXQ_FIFO_PAUSE_THRESH,
22725e8715b9SGary Mills ((rxf_lo << RXQ_FIFO_PAUSE_THRESH_LO_SHIFT) &
22735e8715b9SGary Mills RXQ_FIFO_PAUSE_THRESH_LO_MASK) |
22745e8715b9SGary Mills ((rxf_hi << RXQ_FIFO_PAUSE_THRESH_HI_SHIFT) &
22755e8715b9SGary Mills RXQ_FIFO_PAUSE_THRESH_HI_MASK));
22765e8715b9SGary Mills break;
22775e8715b9SGary Mills }
22785e8715b9SGary Mills break;
2279015a6ef6SSaurabh Misra }
2280015a6ef6SSaurabh Misra
22815e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
22825e8715b9SGary Mills case ATGE_CHIP_L1E:
22835e8715b9SGary Mills /* Configure RxQ. */
22845e8715b9SGary Mills reg = RXQ_CFG_ALIGN_32 | RXQ_CFG_CUT_THROUGH_ENB |
22855e8715b9SGary Mills RXQ_CFG_IPV6_CSUM_VERIFY | RXQ_CFG_ENB;
22865e8715b9SGary Mills OUTL(atgep, ATGE_RXQ_CFG, reg);
22875e8715b9SGary Mills /*
22885e8715b9SGary Mills * Configure TxQ.
22895e8715b9SGary Mills */
22905e8715b9SGary Mills reg = (128 <<
22915e8715b9SGary Mills (atgep->atge_dma_rd_burst >> DMA_CFG_RD_BURST_SHIFT)) <<
22925e8715b9SGary Mills TXQ_CFG_TX_FIFO_BURST_SHIFT;
22935e8715b9SGary Mills
22945e8715b9SGary Mills reg |= (TXQ_CFG_TPD_BURST_DEFAULT << TXQ_CFG_TPD_BURST_SHIFT) &
22955e8715b9SGary Mills TXQ_CFG_TPD_BURST_MASK;
22965e8715b9SGary Mills
22975e8715b9SGary Mills reg |= TXQ_CFG_ENHANCED_MODE | TXQ_CFG_ENB;
22985e8715b9SGary Mills
22995e8715b9SGary Mills OUTL(atgep, ATGE_TXQ_CFG, reg);
23005e8715b9SGary Mills /* Disable RSS. */
23015e8715b9SGary Mills OUTL(atgep, L1E_RSS_IDT_TABLE0, 0);
23025e8715b9SGary Mills OUTL(atgep, L1E_RSS_CPU, 0);
23035e8715b9SGary Mills /*
23045e8715b9SGary Mills * Configure DMA parameters.
23055e8715b9SGary Mills */
23065e8715b9SGary Mills /*
23075e8715b9SGary Mills * Don't use Tx CMB. It is known to cause RRS update failure
23085e8715b9SGary Mills * under certain circumstances. Typical phenomenon of the
23095e8715b9SGary Mills * issue would be unexpected sequence number encountered in
23105e8715b9SGary Mills * Rx handler. Hence we don't set DMA_CFG_TXCMB_ENB.
23115e8715b9SGary Mills */
23125e8715b9SGary Mills OUTL(atgep, ATGE_DMA_CFG,
23135e8715b9SGary Mills DMA_CFG_OUT_ORDER | DMA_CFG_RD_REQ_PRI | DMA_CFG_RCB_64 |
23145e8715b9SGary Mills atgep->atge_dma_rd_burst | atgep->atge_dma_wr_burst |
23155e8715b9SGary Mills DMA_CFG_RXCMB_ENB |
23165e8715b9SGary Mills ((DMA_CFG_RD_DELAY_CNT_DEFAULT <<
23175e8715b9SGary Mills DMA_CFG_RD_DELAY_CNT_SHIFT) & DMA_CFG_RD_DELAY_CNT_MASK) |
23185e8715b9SGary Mills ((DMA_CFG_WR_DELAY_CNT_DEFAULT <<
23195e8715b9SGary Mills DMA_CFG_WR_DELAY_CNT_SHIFT) & DMA_CFG_WR_DELAY_CNT_MASK));
23205e8715b9SGary Mills /*
23215e8715b9SGary Mills * Enable CMB/SMB timer.
23225e8715b9SGary Mills */
23235e8715b9SGary Mills OUTL(atgep, L1E_SMB_STAT_TIMER, 100000);
23245e8715b9SGary Mills atge_l1e_clear_stats(atgep);
23255e8715b9SGary Mills break;
23265e8715b9SGary Mills case ATGE_CHIP_L1:
23275e8715b9SGary Mills /* Configure RxQ. */
23280eb090a7SSaurabh Misra reg =
23290eb090a7SSaurabh Misra ((RXQ_CFG_RD_BURST_DEFAULT << RXQ_CFG_RD_BURST_SHIFT) &
23300eb090a7SSaurabh Misra RXQ_CFG_RD_BURST_MASK) |
23310eb090a7SSaurabh Misra ((RXQ_CFG_RRD_BURST_THRESH_DEFAULT <<
23320eb090a7SSaurabh Misra RXQ_CFG_RRD_BURST_THRESH_SHIFT) &
23330eb090a7SSaurabh Misra RXQ_CFG_RRD_BURST_THRESH_MASK) |
23340eb090a7SSaurabh Misra ((RXQ_CFG_RD_PREF_MIN_IPG_DEFAULT <<
23350eb090a7SSaurabh Misra RXQ_CFG_RD_PREF_MIN_IPG_SHIFT) &
23360eb090a7SSaurabh Misra RXQ_CFG_RD_PREF_MIN_IPG_MASK) |
23370eb090a7SSaurabh Misra RXQ_CFG_CUT_THROUGH_ENB | RXQ_CFG_ENB;
23380eb090a7SSaurabh Misra OUTL(atgep, ATGE_RXQ_CFG, reg);
23395e8715b9SGary Mills /*
23405e8715b9SGary Mills * Configure TxQ.
23415e8715b9SGary Mills */
23420eb090a7SSaurabh Misra reg =
23430eb090a7SSaurabh Misra (((TXQ_CFG_TPD_BURST_DEFAULT << TXQ_CFG_TPD_BURST_SHIFT) &
23440eb090a7SSaurabh Misra TXQ_CFG_TPD_BURST_MASK) |
23450eb090a7SSaurabh Misra ((TXQ_CFG_TX_FIFO_BURST_DEFAULT <<
23460eb090a7SSaurabh Misra TXQ_CFG_TX_FIFO_BURST_SHIFT) &
23470eb090a7SSaurabh Misra TXQ_CFG_TX_FIFO_BURST_MASK) |
23480eb090a7SSaurabh Misra ((TXQ_CFG_TPD_FETCH_DEFAULT <<
23490eb090a7SSaurabh Misra TXQ_CFG_TPD_FETCH_THRESH_SHIFT) &
23500eb090a7SSaurabh Misra TXQ_CFG_TPD_FETCH_THRESH_MASK) |
23510eb090a7SSaurabh Misra TXQ_CFG_ENB);
23520eb090a7SSaurabh Misra OUTL(atgep, ATGE_TXQ_CFG, reg);
23535e8715b9SGary Mills /* Jumbo frames */
23540eb090a7SSaurabh Misra OUTL(atgep, L1_TX_JUMBO_TPD_TH_IPG,
23550eb090a7SSaurabh Misra (((fsize / sizeof (uint64_t) << TX_JUMBO_TPD_TH_SHIFT)) &
23560eb090a7SSaurabh Misra TX_JUMBO_TPD_TH_MASK) |
23570eb090a7SSaurabh Misra ((TX_JUMBO_TPD_IPG_DEFAULT << TX_JUMBO_TPD_IPG_SHIFT) &
23580eb090a7SSaurabh Misra TX_JUMBO_TPD_IPG_MASK));
23595e8715b9SGary Mills /*
23605e8715b9SGary Mills * Configure DMA parameters.
23615e8715b9SGary Mills */
23620eb090a7SSaurabh Misra OUTL(atgep, ATGE_DMA_CFG,
23630eb090a7SSaurabh Misra DMA_CFG_ENH_ORDER | DMA_CFG_RCB_64 |
23640eb090a7SSaurabh Misra atgep->atge_dma_rd_burst | DMA_CFG_RD_ENB |
23650eb090a7SSaurabh Misra atgep->atge_dma_wr_burst | DMA_CFG_WR_ENB);
23660eb090a7SSaurabh Misra
23670eb090a7SSaurabh Misra /* Configure CMB DMA write threshold. */
23680eb090a7SSaurabh Misra OUTL(atgep, L1_CMB_WR_THRESH,
23690eb090a7SSaurabh Misra ((CMB_WR_THRESH_RRD_DEFAULT << CMB_WR_THRESH_RRD_SHIFT) &
23700eb090a7SSaurabh Misra CMB_WR_THRESH_RRD_MASK) |
23710eb090a7SSaurabh Misra ((CMB_WR_THRESH_TPD_DEFAULT << CMB_WR_THRESH_TPD_SHIFT) &
23720eb090a7SSaurabh Misra CMB_WR_THRESH_TPD_MASK));
2373015a6ef6SSaurabh Misra /*
23745e8715b9SGary Mills * Enable CMB/SMB timer.
2375015a6ef6SSaurabh Misra */
23760eb090a7SSaurabh Misra /* Set CMB/SMB timer and enable them. */
23770eb090a7SSaurabh Misra OUTL(atgep, L1_CMB_WR_TIMER,
23780eb090a7SSaurabh Misra ((ATGE_USECS(2) << CMB_WR_TIMER_TX_SHIFT) &
23790eb090a7SSaurabh Misra CMB_WR_TIMER_TX_MASK) |
23800eb090a7SSaurabh Misra ((ATGE_USECS(2) << CMB_WR_TIMER_RX_SHIFT) &
23810eb090a7SSaurabh Misra CMB_WR_TIMER_RX_MASK));
23820eb090a7SSaurabh Misra
23830eb090a7SSaurabh Misra /* Request SMB updates for every seconds. */
23840eb090a7SSaurabh Misra OUTL(atgep, L1_SMB_TIMER, ATGE_USECS(1000 * 1000));
23850eb090a7SSaurabh Misra OUTL(atgep, L1_CSMB_CTRL,
23860eb090a7SSaurabh Misra CSMB_CTRL_SMB_ENB | CSMB_CTRL_CMB_ENB);
23875e8715b9SGary Mills break;
23885e8715b9SGary Mills case ATGE_CHIP_L1C:
23895e8715b9SGary Mills /* Configure RxQ. */
23905e8715b9SGary Mills reg =
23915e8715b9SGary Mills RXQ_CFG_RD_BURST_DEFAULT << L1C_RXQ_CFG_RD_BURST_SHIFT |
23925e8715b9SGary Mills RXQ_CFG_IPV6_CSUM_VERIFY | RXQ_CFG_ENB;
23935e8715b9SGary Mills if ((atgep->atge_flags & ATGE_FLAG_ASPM_MON) != 0)
23945e8715b9SGary Mills reg |= RXQ_CFG_ASPM_THROUGHPUT_LIMIT_1M;
23955e8715b9SGary Mills OUTL(atgep, ATGE_RXQ_CFG, reg);
23965e8715b9SGary Mills /*
23975e8715b9SGary Mills * Configure TxQ.
23985e8715b9SGary Mills */
23995e8715b9SGary Mills reg = (128 <<
24005e8715b9SGary Mills (atgep->atge_dma_rd_burst >> DMA_CFG_RD_BURST_SHIFT)) <<
24015e8715b9SGary Mills TXQ_CFG_TX_FIFO_BURST_SHIFT;
24025e8715b9SGary Mills
24035e8715b9SGary Mills switch (ATGE_DID(atgep)) {
24045e8715b9SGary Mills case ATGE_CHIP_AR8152V2_DEV_ID:
24055e8715b9SGary Mills case ATGE_CHIP_AR8152V1_DEV_ID:
24065e8715b9SGary Mills reg >>= 1;
24075e8715b9SGary Mills break;
24085e8715b9SGary Mills }
24095e8715b9SGary Mills
24105e8715b9SGary Mills reg |= (L1C_TXQ_CFG_TPD_BURST_DEFAULT <<
24115e8715b9SGary Mills TXQ_CFG_TPD_BURST_SHIFT) & TXQ_CFG_TPD_BURST_MASK;
2412015a6ef6SSaurabh Misra
24135e8715b9SGary Mills reg |= TXQ_CFG_ENHANCED_MODE | TXQ_CFG_ENB;
24145e8715b9SGary Mills
24155e8715b9SGary Mills OUTL(atgep, L1C_TXQ_CFG, reg);
24165e8715b9SGary Mills /* Disable RSS until I understand L1C/L2C's RSS logic. */
24175e8715b9SGary Mills OUTL(atgep, L1C_RSS_IDT_TABLE0, 0xe4e4e4e4);
24185e8715b9SGary Mills OUTL(atgep, L1C_RSS_CPU, 0);
24195e8715b9SGary Mills /*
24205e8715b9SGary Mills * Configure DMA parameters.
24215e8715b9SGary Mills */
24225e8715b9SGary Mills OUTL(atgep, ATGE_DMA_CFG,
24235e8715b9SGary Mills DMA_CFG_SMB_DIS |
24245e8715b9SGary Mills DMA_CFG_OUT_ORDER | DMA_CFG_RD_REQ_PRI | DMA_CFG_RCB_64 |
24255e8715b9SGary Mills DMA_CFG_RD_DELAY_CNT_DEFAULT << DMA_CFG_RD_DELAY_CNT_SHIFT |
24265e8715b9SGary Mills DMA_CFG_WR_DELAY_CNT_DEFAULT << DMA_CFG_WR_DELAY_CNT_SHIFT |
24275e8715b9SGary Mills
24285e8715b9SGary Mills atgep->atge_dma_rd_burst | DMA_CFG_RD_ENB |
24295e8715b9SGary Mills atgep->atge_dma_wr_burst | DMA_CFG_WR_ENB);
24305e8715b9SGary Mills /* Configure CMB DMA write threshold not required. */
24315e8715b9SGary Mills /* Set CMB/SMB timer and enable them not required. */
24325e8715b9SGary Mills break;
24335e8715b9SGary Mills }
24340eb090a7SSaurabh Misra
2435015a6ef6SSaurabh Misra /*
2436015a6ef6SSaurabh Misra * Disable all WOL bits as WOL can interfere normal Rx
2437015a6ef6SSaurabh Misra * operation.
2438015a6ef6SSaurabh Misra */
2439015a6ef6SSaurabh Misra OUTL(atgep, ATGE_WOL_CFG, 0);
2440015a6ef6SSaurabh Misra
2441015a6ef6SSaurabh Misra /*
2442015a6ef6SSaurabh Misra * Configure Tx/Rx MACs.
2443015a6ef6SSaurabh Misra * - Auto-padding for short frames.
2444015a6ef6SSaurabh Misra * - Enable CRC generation.
2445015a6ef6SSaurabh Misra *
2446015a6ef6SSaurabh Misra * Start with full-duplex/1000Mbps media. Actual reconfiguration
2447015a6ef6SSaurabh Misra * of MAC is followed after link establishment.
2448015a6ef6SSaurabh Misra */
2449015a6ef6SSaurabh Misra reg = (ATGE_CFG_TX_CRC_ENB | ATGE_CFG_TX_AUTO_PAD |
2450015a6ef6SSaurabh Misra ATGE_CFG_FULL_DUPLEX |
2451015a6ef6SSaurabh Misra ((ATGE_CFG_PREAMBLE_DEFAULT << ATGE_CFG_PREAMBLE_SHIFT) &
2452015a6ef6SSaurabh Misra ATGE_CFG_PREAMBLE_MASK));
2453015a6ef6SSaurabh Misra
24545e8715b9SGary Mills /*
24555e8715b9SGary Mills * AR813x/AR815x always does checksum computation regardless
24565e8715b9SGary Mills * of MAC_CFG_RXCSUM_ENB bit. Also the controller is known to
24575e8715b9SGary Mills * have bug in protocol field in Rx return structure so
24585e8715b9SGary Mills * these controllers can't handle fragmented frames. Disable
24595e8715b9SGary Mills * Rx checksum offloading until there is a newer controller
24605e8715b9SGary Mills * that has sane implementation.
24615e8715b9SGary Mills */
24625e8715b9SGary Mills switch (ATGE_DID(atgep)) {
24635e8715b9SGary Mills case ATGE_CHIP_AR8151V2_DEV_ID:
24645e8715b9SGary Mills case ATGE_CHIP_AR8151V1_DEV_ID:
24655e8715b9SGary Mills case ATGE_CHIP_AR8152V2_DEV_ID:
24665e8715b9SGary Mills reg |= ATGE_CFG_HASH_ALG_CRC32 | ATGE_CFG_SPEED_MODE_SW;
24675e8715b9SGary Mills break;
24685e8715b9SGary Mills }
24695e8715b9SGary Mills
2470015a6ef6SSaurabh Misra if ((atgep->atge_flags & ATGE_FLAG_FASTETHER) != 0) {
2471015a6ef6SSaurabh Misra reg |= ATGE_CFG_SPEED_10_100;
2472015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() Fast Ethernet", atgep->atge_name, __func__));
2473015a6ef6SSaurabh Misra } else {
2474015a6ef6SSaurabh Misra reg |= ATGE_CFG_SPEED_1000;
2475015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() 1G speed", atgep->atge_name, __func__));
2476015a6ef6SSaurabh Misra }
24775e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
24785e8715b9SGary Mills case ATGE_CHIP_L1C:
24795e8715b9SGary Mills reg |= L1C_CFG_SINGLE_PAUSE_ENB;
24805e8715b9SGary Mills break;
24815e8715b9SGary Mills }
2482015a6ef6SSaurabh Misra
2483015a6ef6SSaurabh Misra OUTL(atgep, ATGE_MAC_CFG, reg);
2484015a6ef6SSaurabh Misra
2485015a6ef6SSaurabh Misra atgep->atge_chip_state |= ATGE_CHIP_RUNNING;
2486015a6ef6SSaurabh Misra
2487015a6ef6SSaurabh Misra /*
2488015a6ef6SSaurabh Misra * Set up the receive filter.
2489015a6ef6SSaurabh Misra */
2490015a6ef6SSaurabh Misra atge_rxfilter(atgep);
2491015a6ef6SSaurabh Misra
24920eb090a7SSaurabh Misra /*
24930eb090a7SSaurabh Misra * Acknowledge all pending interrupts and clear it.
24940eb090a7SSaurabh Misra */
24955e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
24965e8715b9SGary Mills case ATGE_CHIP_L1E:
2497015a6ef6SSaurabh Misra OUTL(atgep, ATGE_INTR_MASK, L1E_INTRS);
2498015a6ef6SSaurabh Misra OUTL(atgep, ATGE_INTR_STATUS, 0xFFFFFFFF);
2499015a6ef6SSaurabh Misra OUTL(atgep, ATGE_INTR_STATUS, 0);
25005e8715b9SGary Mills break;
25015e8715b9SGary Mills case ATGE_CHIP_L1:
25025e8715b9SGary Mills case ATGE_CHIP_L1C:
25035e8715b9SGary Mills OUTL(atgep, ATGE_INTR_STATUS, 0);
25045e8715b9SGary Mills OUTL(atgep, ATGE_INTR_MASK, atgep->atge_intrs);
25055e8715b9SGary Mills break;
2506015a6ef6SSaurabh Misra }
2507015a6ef6SSaurabh Misra
25080eb090a7SSaurabh Misra atge_mac_config(atgep);
25090eb090a7SSaurabh Misra
2510015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() device started", atgep->atge_name, __func__));
2511015a6ef6SSaurabh Misra }
2512015a6ef6SSaurabh Misra
2513015a6ef6SSaurabh Misra /*
2514015a6ef6SSaurabh Misra * Generic functions.
2515015a6ef6SSaurabh Misra */
2516015a6ef6SSaurabh Misra
2517015a6ef6SSaurabh Misra #define CRC32_POLY_BE 0x04c11db7
2518015a6ef6SSaurabh Misra uint32_t
atge_ether_crc(const uint8_t * addr,int len)2519015a6ef6SSaurabh Misra atge_ether_crc(const uint8_t *addr, int len)
2520015a6ef6SSaurabh Misra {
2521015a6ef6SSaurabh Misra int idx;
2522015a6ef6SSaurabh Misra int bit;
2523015a6ef6SSaurabh Misra uint_t data;
2524015a6ef6SSaurabh Misra uint32_t crc;
2525015a6ef6SSaurabh Misra
2526015a6ef6SSaurabh Misra crc = 0xffffffff;
2527015a6ef6SSaurabh Misra for (idx = 0; idx < len; idx++) {
2528015a6ef6SSaurabh Misra for (data = *addr++, bit = 0; bit < 8; bit++, data >>= 1) {
2529015a6ef6SSaurabh Misra crc = (crc << 1)
2530015a6ef6SSaurabh Misra ^ ((((crc >> 31) ^ data) & 1) ? CRC32_POLY_BE : 0);
2531015a6ef6SSaurabh Misra }
2532015a6ef6SSaurabh Misra }
2533015a6ef6SSaurabh Misra
2534015a6ef6SSaurabh Misra return (crc);
2535015a6ef6SSaurabh Misra }
2536015a6ef6SSaurabh Misra
2537015a6ef6SSaurabh Misra
2538015a6ef6SSaurabh Misra /*
2539015a6ef6SSaurabh Misra * Programs RX filter. We use a link-list to keep track of all multicast
2540015a6ef6SSaurabh Misra * addressess.
2541015a6ef6SSaurabh Misra */
2542015a6ef6SSaurabh Misra void
atge_rxfilter(atge_t * atgep)2543015a6ef6SSaurabh Misra atge_rxfilter(atge_t *atgep)
2544015a6ef6SSaurabh Misra {
2545015a6ef6SSaurabh Misra uint32_t rxcfg;
2546015a6ef6SSaurabh Misra uint64_t mchash;
2547015a6ef6SSaurabh Misra
2548015a6ef6SSaurabh Misra rxcfg = INL(atgep, ATGE_MAC_CFG);
2549015a6ef6SSaurabh Misra rxcfg &= ~(ATGE_CFG_ALLMULTI | ATGE_CFG_PROMISC);
2550015a6ef6SSaurabh Misra
2551015a6ef6SSaurabh Misra /*
2552015a6ef6SSaurabh Misra * Accept broadcast frames.
2553015a6ef6SSaurabh Misra */
2554015a6ef6SSaurabh Misra rxcfg |= ATGE_CFG_BCAST;
2555015a6ef6SSaurabh Misra
2556015a6ef6SSaurabh Misra /*
2557015a6ef6SSaurabh Misra * We don't use Hardware VLAN tagging.
2558015a6ef6SSaurabh Misra */
2559015a6ef6SSaurabh Misra rxcfg &= ~ATGE_CFG_VLAN_TAG_STRIP;
2560015a6ef6SSaurabh Misra
2561015a6ef6SSaurabh Misra if (atgep->atge_filter_flags & (ATGE_PROMISC | ATGE_ALL_MULTICST)) {
2562015a6ef6SSaurabh Misra mchash = ~0ULL;
2563015a6ef6SSaurabh Misra
2564015a6ef6SSaurabh Misra if (atgep->atge_filter_flags & ATGE_PROMISC)
2565015a6ef6SSaurabh Misra rxcfg |= ATGE_CFG_PROMISC;
2566015a6ef6SSaurabh Misra
2567015a6ef6SSaurabh Misra if (atgep->atge_filter_flags & ATGE_ALL_MULTICST)
2568015a6ef6SSaurabh Misra rxcfg |= ATGE_CFG_ALLMULTI;
2569015a6ef6SSaurabh Misra } else {
2570015a6ef6SSaurabh Misra mchash = atgep->atge_mchash;
2571015a6ef6SSaurabh Misra }
2572015a6ef6SSaurabh Misra
2573015a6ef6SSaurabh Misra atge_program_ether(atgep);
2574015a6ef6SSaurabh Misra
2575015a6ef6SSaurabh Misra OUTL(atgep, ATGE_MAR0, (uint32_t)mchash);
2576015a6ef6SSaurabh Misra OUTL(atgep, ATGE_MAR1, (uint32_t)(mchash >> 32));
2577015a6ef6SSaurabh Misra OUTL(atgep, ATGE_MAC_CFG, rxcfg);
2578015a6ef6SSaurabh Misra
2579015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() mac_cfg is : %x, mchash : %llx",
2580015a6ef6SSaurabh Misra atgep->atge_name, __func__, rxcfg, mchash));
2581015a6ef6SSaurabh Misra }
2582015a6ef6SSaurabh Misra
2583015a6ef6SSaurabh Misra void
atge_device_stop(atge_t * atgep)2584015a6ef6SSaurabh Misra atge_device_stop(atge_t *atgep)
2585015a6ef6SSaurabh Misra {
2586015a6ef6SSaurabh Misra uint32_t reg;
2587015a6ef6SSaurabh Misra int t;
2588015a6ef6SSaurabh Misra
2589015a6ef6SSaurabh Misra /*
2590015a6ef6SSaurabh Misra * If the chip is being suspended, then don't touch the state. Caller
2591015a6ef6SSaurabh Misra * will take care of setting the correct state.
2592015a6ef6SSaurabh Misra */
2593015a6ef6SSaurabh Misra if (!(atgep->atge_chip_state & ATGE_CHIP_SUSPENDED)) {
2594015a6ef6SSaurabh Misra atgep->atge_chip_state |= ATGE_CHIP_STOPPED;
2595015a6ef6SSaurabh Misra atgep->atge_chip_state &= ~ATGE_CHIP_RUNNING;
2596015a6ef6SSaurabh Misra }
2597015a6ef6SSaurabh Misra
2598015a6ef6SSaurabh Misra /*
2599015a6ef6SSaurabh Misra * Collect stats for L1E. L1 chip's stats are collected by interrupt.
2600015a6ef6SSaurabh Misra */
26015e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
26025e8715b9SGary Mills case ATGE_CHIP_L1E:
2603015a6ef6SSaurabh Misra atge_l1e_gather_stats(atgep);
26045e8715b9SGary Mills break;
26055e8715b9SGary Mills case ATGE_CHIP_L1:
26065e8715b9SGary Mills case ATGE_CHIP_L1C:
26075e8715b9SGary Mills break;
2608015a6ef6SSaurabh Misra }
2609015a6ef6SSaurabh Misra
2610015a6ef6SSaurabh Misra /*
2611015a6ef6SSaurabh Misra * Disable interrupts.
2612015a6ef6SSaurabh Misra */
2613015a6ef6SSaurabh Misra atge_disable_intrs(atgep);
2614015a6ef6SSaurabh Misra
26155e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
26165e8715b9SGary Mills case ATGE_CHIP_L1E:
26175e8715b9SGary Mills /* Clear CTRL not required. */
26185e8715b9SGary Mills /* Stop DMA Engine not required. */
26195e8715b9SGary Mills /*
26205e8715b9SGary Mills * Disable queue processing.
26215e8715b9SGary Mills */
26225e8715b9SGary Mills /* Stop TxQ */
26235e8715b9SGary Mills reg = INL(atgep, ATGE_TXQ_CFG);
26245e8715b9SGary Mills reg = reg & ~TXQ_CFG_ENB;
26255e8715b9SGary Mills OUTL(atgep, ATGE_TXQ_CFG, reg);
26265e8715b9SGary Mills /* Stop RxQ */
26275e8715b9SGary Mills reg = INL(atgep, ATGE_RXQ_CFG);
26285e8715b9SGary Mills reg = reg & ~RXQ_CFG_ENB;
26295e8715b9SGary Mills OUTL(atgep, ATGE_RXQ_CFG, reg);
26305e8715b9SGary Mills /* Stop DMA */
26315e8715b9SGary Mills reg = INL(atgep, ATGE_DMA_CFG);
26325e8715b9SGary Mills reg = reg & ~(DMA_CFG_TXCMB_ENB | DMA_CFG_RXCMB_ENB);
26335e8715b9SGary Mills OUTL(atgep, ATGE_DMA_CFG, reg);
26345e8715b9SGary Mills drv_usecwait(1000);
26355e8715b9SGary Mills atge_l1e_stop_mac(atgep);
26365e8715b9SGary Mills OUTL(atgep, ATGE_INTR_STATUS, 0xFFFFFFFF);
26375e8715b9SGary Mills break;
26385e8715b9SGary Mills case ATGE_CHIP_L1:
26395e8715b9SGary Mills /* Clear CTRL. */
26400eb090a7SSaurabh Misra OUTL(atgep, L1_CSMB_CTRL, 0);
26415e8715b9SGary Mills /* Stop DMA Engine */
26420eb090a7SSaurabh Misra atge_l1_stop_tx_mac(atgep);
26430eb090a7SSaurabh Misra atge_l1_stop_rx_mac(atgep);
26440eb090a7SSaurabh Misra reg = INL(atgep, ATGE_DMA_CFG);
26450eb090a7SSaurabh Misra reg &= ~(DMA_CFG_RD_ENB | DMA_CFG_WR_ENB);
26460eb090a7SSaurabh Misra OUTL(atgep, ATGE_DMA_CFG, reg);
26475e8715b9SGary Mills /*
26485e8715b9SGary Mills * Disable queue processing.
26495e8715b9SGary Mills */
26505e8715b9SGary Mills /* Stop TxQ */
26515e8715b9SGary Mills reg = INL(atgep, ATGE_TXQ_CFG);
26525e8715b9SGary Mills reg = reg & ~TXQ_CFG_ENB;
26535e8715b9SGary Mills OUTL(atgep, ATGE_TXQ_CFG, reg);
26545e8715b9SGary Mills /* Stop RxQ */
26555e8715b9SGary Mills reg = INL(atgep, ATGE_RXQ_CFG);
26565e8715b9SGary Mills reg = reg & ~RXQ_CFG_ENB;
26575e8715b9SGary Mills OUTL(atgep, ATGE_RXQ_CFG, reg);
26585e8715b9SGary Mills break;
26595e8715b9SGary Mills case ATGE_CHIP_L1C:
26605e8715b9SGary Mills /* Clear CTRL not required. */
26615e8715b9SGary Mills /* Stop DMA Engine */
26625e8715b9SGary Mills atge_l1c_stop_tx_mac(atgep);
26635e8715b9SGary Mills atge_l1c_stop_rx_mac(atgep);
2664015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_DMA_CFG);
26655e8715b9SGary Mills reg &= ~(DMA_CFG_RD_ENB | DMA_CFG_WR_ENB);
2666015a6ef6SSaurabh Misra OUTL(atgep, ATGE_DMA_CFG, reg);
26675e8715b9SGary Mills /*
26685e8715b9SGary Mills * Disable queue processing.
26695e8715b9SGary Mills */
26705e8715b9SGary Mills /* Stop TxQ */
26715e8715b9SGary Mills reg = INL(atgep, L1C_TXQ_CFG);
26725e8715b9SGary Mills reg = reg & ~TXQ_CFG_ENB;
26735e8715b9SGary Mills OUTL(atgep, L1C_TXQ_CFG, reg);
26745e8715b9SGary Mills /* Stop RxQ */
26755e8715b9SGary Mills reg = INL(atgep, ATGE_RXQ_CFG);
26765e8715b9SGary Mills reg = reg & ~RXQ_CFG_ENB;
26775e8715b9SGary Mills OUTL(atgep, ATGE_RXQ_CFG, reg);
26785e8715b9SGary Mills break;
2679015a6ef6SSaurabh Misra }
2680015a6ef6SSaurabh Misra
2681015a6ef6SSaurabh Misra for (t = ATGE_RESET_TIMEOUT; t > 0; t--) {
2682015a6ef6SSaurabh Misra if ((reg = INL(atgep, ATGE_IDLE_STATUS)) == 0)
2683015a6ef6SSaurabh Misra break;
2684015a6ef6SSaurabh Misra drv_usecwait(10);
2685015a6ef6SSaurabh Misra }
2686015a6ef6SSaurabh Misra
2687015a6ef6SSaurabh Misra if (t == 0) {
2688015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "%s() stopping TX/RX MAC timeout",
2689015a6ef6SSaurabh Misra __func__);
2690015a6ef6SSaurabh Misra }
2691015a6ef6SSaurabh Misra }
2692015a6ef6SSaurabh Misra
2693015a6ef6SSaurabh Misra void
atge_disable_intrs(atge_t * atgep)2694015a6ef6SSaurabh Misra atge_disable_intrs(atge_t *atgep)
2695015a6ef6SSaurabh Misra {
2696015a6ef6SSaurabh Misra OUTL(atgep, ATGE_INTR_MASK, 0);
2697015a6ef6SSaurabh Misra OUTL(atgep, ATGE_INTR_STATUS, 0xFFFFFFFF);
2698015a6ef6SSaurabh Misra }
2699015a6ef6SSaurabh Misra
2700015a6ef6SSaurabh Misra void
atge_device_init(atge_t * atgep)2701015a6ef6SSaurabh Misra atge_device_init(atge_t *atgep)
2702015a6ef6SSaurabh Misra {
27035e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
27045e8715b9SGary Mills case ATGE_CHIP_L1E:
2705015a6ef6SSaurabh Misra atgep->atge_intrs = L1E_INTRS;
2706015a6ef6SSaurabh Misra atgep->atge_int_mod = ATGE_IM_TIMER_DEFAULT;
2707015a6ef6SSaurabh Misra
2708015a6ef6SSaurabh Misra atge_l1e_init_tx_ring(atgep);
2709015a6ef6SSaurabh Misra atge_l1e_init_rx_pages(atgep);
27105e8715b9SGary Mills break;
27115e8715b9SGary Mills case ATGE_CHIP_L1:
27120eb090a7SSaurabh Misra atgep->atge_intrs = L1_INTRS | INTR_GPHY | INTR_PHY_LINK_DOWN |
27130eb090a7SSaurabh Misra INTR_LINK_CHG;
27140eb090a7SSaurabh Misra atgep->atge_int_mod = ATGE_IM_TIMER_DEFAULT;
27150eb090a7SSaurabh Misra
27160eb090a7SSaurabh Misra atge_l1_init_tx_ring(atgep);
27170eb090a7SSaurabh Misra atge_l1_init_rx_ring(atgep);
27180eb090a7SSaurabh Misra atge_l1_init_rr_ring(atgep);
27190eb090a7SSaurabh Misra atge_l1_init_cmb(atgep);
27200eb090a7SSaurabh Misra atge_l1_init_smb(atgep);
27215e8715b9SGary Mills break;
27225e8715b9SGary Mills case ATGE_CHIP_L1C:
27235e8715b9SGary Mills atgep->atge_intrs = L1C_INTRS | L1C_INTR_GPHY |
27245e8715b9SGary Mills L1C_INTR_PHY_LINK_DOWN;
27255e8715b9SGary Mills atgep->atge_int_rx_mod = 400/2;
27265e8715b9SGary Mills atgep->atge_int_tx_mod = 2000/1;
27275e8715b9SGary Mills
27285e8715b9SGary Mills atge_l1c_init_tx_ring(atgep);
27295e8715b9SGary Mills atge_l1c_init_rx_ring(atgep);
27305e8715b9SGary Mills atge_l1c_init_rr_ring(atgep);
27315e8715b9SGary Mills atge_l1c_init_cmb(atgep);
27325e8715b9SGary Mills atge_l1c_init_smb(atgep);
27335e8715b9SGary Mills
27345e8715b9SGary Mills /* Enable all clocks. */
27355e8715b9SGary Mills OUTL(atgep, ATGE_CLK_GATING_CFG, 0);
27365e8715b9SGary Mills break;
2737015a6ef6SSaurabh Misra }
2738015a6ef6SSaurabh Misra }
2739015a6ef6SSaurabh Misra
2740015a6ef6SSaurabh Misra void
atge_device_restart(atge_t * atgep)2741015a6ef6SSaurabh Misra atge_device_restart(atge_t *atgep)
2742015a6ef6SSaurabh Misra {
2743015a6ef6SSaurabh Misra ASSERT(MUTEX_HELD(&atgep->atge_intr_lock));
2744015a6ef6SSaurabh Misra ASSERT(MUTEX_HELD(&atgep->atge_tx_lock));
2745015a6ef6SSaurabh Misra
2746015a6ef6SSaurabh Misra /*
2747015a6ef6SSaurabh Misra * Cancel any pending I/O.
2748015a6ef6SSaurabh Misra */
2749015a6ef6SSaurabh Misra atge_device_stop(atgep);
2750015a6ef6SSaurabh Misra
2751015a6ef6SSaurabh Misra /*
2752015a6ef6SSaurabh Misra * Reset the chip to a known state.
2753015a6ef6SSaurabh Misra */
2754015a6ef6SSaurabh Misra atge_device_reset(atgep);
2755015a6ef6SSaurabh Misra
2756015a6ef6SSaurabh Misra /*
2757015a6ef6SSaurabh Misra * Initialize the ring and other descriptor like CMB/SMB/Rx return.
2758015a6ef6SSaurabh Misra */
2759015a6ef6SSaurabh Misra atge_device_init(atgep);
2760015a6ef6SSaurabh Misra
2761015a6ef6SSaurabh Misra /*
2762015a6ef6SSaurabh Misra * Start the chip.
2763015a6ef6SSaurabh Misra */
2764015a6ef6SSaurabh Misra atge_device_start(atgep);
2765015a6ef6SSaurabh Misra
2766015a6ef6SSaurabh Misra }
2767015a6ef6SSaurabh Misra
2768015a6ef6SSaurabh Misra static int
atge_send_a_packet(atge_t * atgep,mblk_t * mp)2769015a6ef6SSaurabh Misra atge_send_a_packet(atge_t *atgep, mblk_t *mp)
2770015a6ef6SSaurabh Misra {
27710eb090a7SSaurabh Misra uchar_t *c;
27720eb090a7SSaurabh Misra uint32_t cflags = 0;
2773015a6ef6SSaurabh Misra atge_ring_t *r;
2774015a6ef6SSaurabh Misra size_t pktlen;
2775015a6ef6SSaurabh Misra uchar_t *buf;
2776015a6ef6SSaurabh Misra int start;
2777015a6ef6SSaurabh Misra
2778015a6ef6SSaurabh Misra ASSERT(MUTEX_HELD(&atgep->atge_tx_lock));
2779015a6ef6SSaurabh Misra ASSERT(mp != NULL);
2780015a6ef6SSaurabh Misra
2781015a6ef6SSaurabh Misra pktlen = msgsize(mp);
2782015a6ef6SSaurabh Misra if (pktlen > atgep->atge_tx_buf_len) {
2783015a6ef6SSaurabh Misra atgep->atge_macxmt_errors++;
2784015a6ef6SSaurabh Misra
2785015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() pktlen (%d) > rx_buf_len (%d)",
2786015a6ef6SSaurabh Misra atgep->atge_name, __func__,
2787015a6ef6SSaurabh Misra pktlen, atgep->atge_rx_buf_len));
2788015a6ef6SSaurabh Misra
2789015a6ef6SSaurabh Misra freemsg(mp);
27900eb090a7SSaurabh Misra return (DDI_SUCCESS);
2791015a6ef6SSaurabh Misra }
2792015a6ef6SSaurabh Misra
2793015a6ef6SSaurabh Misra r = atgep->atge_tx_ring;
2794015a6ef6SSaurabh Misra
2795015a6ef6SSaurabh Misra if (r->r_avail_desc <= 1) {
2796015a6ef6SSaurabh Misra atgep->atge_noxmtbuf++;
2797015a6ef6SSaurabh Misra atgep->atge_tx_resched = 1;
27980eb090a7SSaurabh Misra
27990eb090a7SSaurabh Misra ATGE_DB(("%s: %s() No transmit buf",
28000eb090a7SSaurabh Misra atgep->atge_name, __func__));
28010eb090a7SSaurabh Misra
28020eb090a7SSaurabh Misra return (DDI_FAILURE);
2803015a6ef6SSaurabh Misra }
2804015a6ef6SSaurabh Misra
2805015a6ef6SSaurabh Misra start = r->r_producer;
2806015a6ef6SSaurabh Misra
2807015a6ef6SSaurabh Misra /*
2808015a6ef6SSaurabh Misra * Get the DMA buffer to hold a packet.
2809015a6ef6SSaurabh Misra */
2810015a6ef6SSaurabh Misra buf = (uchar_t *)r->r_buf_tbl[start]->addr;
2811015a6ef6SSaurabh Misra
2812015a6ef6SSaurabh Misra /*
2813015a6ef6SSaurabh Misra * Copy the msg and free mp
2814015a6ef6SSaurabh Misra */
2815015a6ef6SSaurabh Misra mcopymsg(mp, buf);
2816015a6ef6SSaurabh Misra
2817015a6ef6SSaurabh Misra r->r_avail_desc--;
2818015a6ef6SSaurabh Misra
28190eb090a7SSaurabh Misra c = (uchar_t *)r->r_desc_ring->addr;
28205e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
28215e8715b9SGary Mills case ATGE_CHIP_L1C:
28225e8715b9SGary Mills {
28235e8715b9SGary Mills l1c_tx_desc_t *txd;
28245e8715b9SGary Mills
28255e8715b9SGary Mills c += (sizeof (l1c_tx_desc_t) * start);
28265e8715b9SGary Mills txd = (l1c_tx_desc_t *)c;
28275e8715b9SGary Mills
28285e8715b9SGary Mills ATGE_PUT64(r->r_desc_ring, &txd->addr,
28295e8715b9SGary Mills r->r_buf_tbl[start]->cookie.dmac_laddress);
28305e8715b9SGary Mills
28315e8715b9SGary Mills ATGE_PUT32(r->r_desc_ring, &txd->len, L1C_TX_BYTES(pktlen));
28325e8715b9SGary Mills
28335e8715b9SGary Mills cflags |= L1C_TD_EOP;
28345e8715b9SGary Mills ATGE_PUT32(r->r_desc_ring, &txd->flags, cflags);
28355e8715b9SGary Mills break;
28365e8715b9SGary Mills }
28375e8715b9SGary Mills default:
28385e8715b9SGary Mills {
28395e8715b9SGary Mills atge_tx_desc_t *txd;
28400eb090a7SSaurabh Misra
28415e8715b9SGary Mills c += (sizeof (atge_tx_desc_t) * start);
28425e8715b9SGary Mills txd = (atge_tx_desc_t *)c;
28430eb090a7SSaurabh Misra
28445e8715b9SGary Mills ATGE_PUT64(r->r_desc_ring, &txd->addr,
28455e8715b9SGary Mills r->r_buf_tbl[start]->cookie.dmac_laddress);
28460eb090a7SSaurabh Misra
28475e8715b9SGary Mills ATGE_PUT32(r->r_desc_ring, &txd->len, ATGE_TX_BYTES(pktlen));
28480eb090a7SSaurabh Misra
28495e8715b9SGary Mills cflags |= ATGE_TD_EOP;
28505e8715b9SGary Mills ATGE_PUT32(r->r_desc_ring, &txd->flags, cflags);
28515e8715b9SGary Mills break;
28525e8715b9SGary Mills }
28535e8715b9SGary Mills }
28540eb090a7SSaurabh Misra /*
28550eb090a7SSaurabh Misra * Sync buffer first.
28560eb090a7SSaurabh Misra */
28570eb090a7SSaurabh Misra DMA_SYNC(r->r_buf_tbl[start], 0, pktlen, DDI_DMA_SYNC_FORDEV);
28580eb090a7SSaurabh Misra
28590eb090a7SSaurabh Misra /*
28600eb090a7SSaurabh Misra * Increment TX producer count by one.
28610eb090a7SSaurabh Misra */
28620eb090a7SSaurabh Misra ATGE_INC_SLOT(r->r_producer, ATGE_TX_RING_CNT);
28630eb090a7SSaurabh Misra
28640eb090a7SSaurabh Misra /*
28650eb090a7SSaurabh Misra * Sync descriptor table.
28660eb090a7SSaurabh Misra */
28670eb090a7SSaurabh Misra DMA_SYNC(r->r_desc_ring, 0, ATGE_TX_RING_SZ, DDI_DMA_SYNC_FORDEV);
28680eb090a7SSaurabh Misra
2869015a6ef6SSaurabh Misra /*
2870015a6ef6SSaurabh Misra * Program TX descriptor to send a packet.
2871015a6ef6SSaurabh Misra */
28725e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
28735e8715b9SGary Mills case ATGE_CHIP_L1E:
28740eb090a7SSaurabh Misra atge_l1e_send_packet(r);
28755e8715b9SGary Mills break;
28765e8715b9SGary Mills case ATGE_CHIP_L1:
28770eb090a7SSaurabh Misra atge_l1_send_packet(r);
28785e8715b9SGary Mills break;
28795e8715b9SGary Mills case ATGE_CHIP_L1C:
28805e8715b9SGary Mills atge_l1c_send_packet(r);
28815e8715b9SGary Mills break;
2882015a6ef6SSaurabh Misra }
2883015a6ef6SSaurabh Misra
28840eb090a7SSaurabh Misra r->r_atge->atge_opackets++;
28850eb090a7SSaurabh Misra r->r_atge->atge_obytes += pktlen;
28860eb090a7SSaurabh Misra
28870eb090a7SSaurabh Misra ATGE_DB(("%s: %s() pktlen : %d, avail_desc : %d, producer :%d, "
28880eb090a7SSaurabh Misra "consumer : %d", atgep->atge_name, __func__, pktlen,
28890eb090a7SSaurabh Misra r->r_avail_desc, r->r_producer, r->r_consumer));
28900eb090a7SSaurabh Misra
28910eb090a7SSaurabh Misra return (DDI_SUCCESS);
2892015a6ef6SSaurabh Misra }
2893015a6ef6SSaurabh Misra
2894015a6ef6SSaurabh Misra /*
2895015a6ef6SSaurabh Misra * Stream Information.
2896015a6ef6SSaurabh Misra */
2897015a6ef6SSaurabh Misra DDI_DEFINE_STREAM_OPS(atge_devops, nulldev, nulldev, atge_attach, atge_detach,
2898015a6ef6SSaurabh Misra nodev, NULL, D_MP, NULL, atge_quiesce);
2899015a6ef6SSaurabh Misra
2900015a6ef6SSaurabh Misra /*
2901015a6ef6SSaurabh Misra * Module linkage information.
2902015a6ef6SSaurabh Misra */
2903015a6ef6SSaurabh Misra static struct modldrv atge_modldrv = {
2904015a6ef6SSaurabh Misra &mod_driverops, /* Type of Module */
2905015a6ef6SSaurabh Misra "Atheros/Attansic Gb Ethernet", /* Description */
2906015a6ef6SSaurabh Misra &atge_devops /* drv_dev_ops */
2907015a6ef6SSaurabh Misra };
2908015a6ef6SSaurabh Misra
2909015a6ef6SSaurabh Misra static struct modlinkage atge_modlinkage = {
2910015a6ef6SSaurabh Misra MODREV_1, /* ml_rev */
2911015a6ef6SSaurabh Misra (void *)&atge_modldrv,
2912015a6ef6SSaurabh Misra NULL
2913015a6ef6SSaurabh Misra };
2914015a6ef6SSaurabh Misra
2915015a6ef6SSaurabh Misra /*
2916015a6ef6SSaurabh Misra * DDI Entry points.
2917015a6ef6SSaurabh Misra */
2918015a6ef6SSaurabh Misra int
_init(void)2919015a6ef6SSaurabh Misra _init(void)
2920015a6ef6SSaurabh Misra {
2921015a6ef6SSaurabh Misra int r;
2922015a6ef6SSaurabh Misra mac_init_ops(&atge_devops, "atge");
2923015a6ef6SSaurabh Misra if ((r = mod_install(&atge_modlinkage)) != DDI_SUCCESS) {
2924015a6ef6SSaurabh Misra mac_fini_ops(&atge_devops);
2925015a6ef6SSaurabh Misra }
2926015a6ef6SSaurabh Misra
2927015a6ef6SSaurabh Misra return (r);
2928015a6ef6SSaurabh Misra }
2929015a6ef6SSaurabh Misra
2930015a6ef6SSaurabh Misra int
_fini(void)2931015a6ef6SSaurabh Misra _fini(void)
2932015a6ef6SSaurabh Misra {
2933015a6ef6SSaurabh Misra int r;
2934015a6ef6SSaurabh Misra
2935015a6ef6SSaurabh Misra if ((r = mod_remove(&atge_modlinkage)) == DDI_SUCCESS) {
2936015a6ef6SSaurabh Misra mac_fini_ops(&atge_devops);
2937015a6ef6SSaurabh Misra }
2938015a6ef6SSaurabh Misra
2939015a6ef6SSaurabh Misra return (r);
2940015a6ef6SSaurabh Misra }
2941015a6ef6SSaurabh Misra
2942015a6ef6SSaurabh Misra int
_info(struct modinfo * modinfop)2943015a6ef6SSaurabh Misra _info(struct modinfo *modinfop)
2944015a6ef6SSaurabh Misra {
2945015a6ef6SSaurabh Misra return (mod_info(&atge_modlinkage, modinfop));
2946015a6ef6SSaurabh Misra }
2947